308 lines
9.9 KiB
Racket
308 lines
9.9 KiB
Racket
#lang racket
|
|
|
|
(require slideshow/base slideshow/pict
|
|
racket/splicing racket/stxparam racket/gui/base
|
|
unstable/define)
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;
|
|
;; Font Controls
|
|
;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
(define-with-parameter with-size current-font-size)
|
|
(define-syntax-rule (with-scale scale expr)
|
|
(with-size (inexact->exact (ceiling (* scale (current-font-size)))) expr))
|
|
(define-syntax-rule (define-scale name scale)
|
|
(define-syntax-rule (name expr) (with-scale scale expr)))
|
|
(define-scale big 3/2)
|
|
(define-scale small 2/3)
|
|
|
|
(define-with-parameter with-font current-main-font)
|
|
(define-syntax-rule (with-style style expr)
|
|
(with-font (cons style (current-main-font)) expr))
|
|
(define-syntax-rule (define-style name style)
|
|
(define-syntax-rule (name expr) (with-style style expr)))
|
|
(define-style bold 'bold)
|
|
(define-style italic 'italic)
|
|
(define-style subscript 'subscript)
|
|
(define-style superscript 'superscript)
|
|
(define-style caps 'caps)
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;
|
|
;; Picture Manipulation
|
|
;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
(define (fill pict w h)
|
|
(cc-superimpose
|
|
pict
|
|
(blank (or w (pict-width pict))
|
|
(or h (pict-height pict)))))
|
|
|
|
(define (color c p) (colorize p c))
|
|
|
|
(define color/c
|
|
(or/c string? ;; might be faster
|
|
;;(and/c string? (lambda (s) (send the-color-database find-color s)))
|
|
(is-a?/c color%)
|
|
(list/c byte? byte? byte?)))
|
|
|
|
(define-syntax-rule (define-colors name ...)
|
|
(begin (define (name pict) (color (symbol->string 'name) pict)) ...))
|
|
|
|
(define-colors
|
|
red orange yellow green blue purple
|
|
black brown gray white cyan magenta)
|
|
|
|
(define (light c) (scale-color 2 c))
|
|
(define (dark c) (scale-color 1/2 c))
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;
|
|
;; Slide / Paragraph Manipulation
|
|
;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
(define-with-parameter column current-para-width)
|
|
|
|
(define (columns . picts)
|
|
(apply hc-append gap-size (map baseless picts)))
|
|
|
|
(define (column-size n [r (/ n)])
|
|
(* r (- (current-para-width) (* (sub1 n) gap-size))))
|
|
|
|
(define-syntax-rule (two-columns a b)
|
|
(columns (column (column-size 2) a)
|
|
(column (column-size 2) b)))
|
|
|
|
(define (mini-slide . picts)
|
|
(apply vc-append gap-size picts))
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;
|
|
;; Simple Tables
|
|
;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
(define =!
|
|
(case-lambda
|
|
[(n) n]
|
|
[(n . ns)
|
|
(if (apply = n ns)
|
|
n
|
|
(error '=! "not all equal: ~a" (cons n ns)))]))
|
|
|
|
(define (elem->pict elem)
|
|
(if (string? elem) (t elem) elem))
|
|
|
|
(define (tabular #:gap [gap gap-size]
|
|
#:vgap [vgap gap]
|
|
#:hgap [hgap gap]
|
|
#:align [align lbl-superimpose]
|
|
#:halign [halign align]
|
|
#:valign [valign align]
|
|
. cells)
|
|
(let* ([rows (length cells)]
|
|
[cols (apply =! (map length cells))]
|
|
[picts (map elem->pict (append* cells))]
|
|
[haligns (for/list ([i (in-range 0 cols)]) halign)]
|
|
[valigns (for/list ([i (in-range 0 rows)]) valign)]
|
|
[hseps (for/list ([i (in-range 1 cols)]) hgap)]
|
|
[vseps (for/list ([i (in-range 1 rows)]) vgap)])
|
|
(table cols picts haligns valigns hseps vseps)))
|
|
|
|
(define (matrixof c)
|
|
(and/c (listof (listof c))
|
|
(flat-named-contract "matrix"
|
|
(match-lambda
|
|
[(list) #t]
|
|
[(list _) #t]
|
|
[(list xs ...) (apply = (map length xs))]))))
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;
|
|
;; Space-smart picture selection
|
|
;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
(define-syntax-parameter pict-combine #'ltl-superimpose)
|
|
|
|
(define-syntax-rule (with-pict-combine combine body ...)
|
|
(splicing-syntax-parameterize
|
|
([pict-combine #'combine])
|
|
body ...))
|
|
|
|
(define-syntax (pict-if stx)
|
|
(syntax-case stx ()
|
|
[(_ #:combine combine test success failure)
|
|
(syntax/loc stx
|
|
(let* ([result test])
|
|
(combine (show success result)
|
|
(hide failure result))))]
|
|
[(_ test success failure)
|
|
(quasisyntax/loc stx
|
|
(pict-if #:combine #,(syntax-parameter-value #'pict-combine)
|
|
test success failure))]))
|
|
|
|
(define-syntax (pict-cond stx)
|
|
(syntax-case stx (else)
|
|
[(_ #:combine combine [test expr] ... [else default])
|
|
(with-syntax ([(pict ...) (generate-temporaries #'(expr ...))])
|
|
(syntax/loc stx
|
|
(let ([pict expr] ... [final default])
|
|
(combine (cond [test pict] ... [else final])
|
|
(ghost pict) ... (ghost final)))))]
|
|
[(_ #:combine combine [test pict] ...)
|
|
(syntax/loc stx
|
|
(pict-cond #:combine combine [test pict] ... [else (blank 0 0)]))]
|
|
[(_ [test expr] ...)
|
|
(quasisyntax/loc stx
|
|
(pict-cond #:combine #,(syntax-parameter-value #'pict-combine)
|
|
[test expr] ...))]))
|
|
|
|
(define-syntax (pict-case stx)
|
|
(syntax-case stx (else)
|
|
[(_ test #:combine combine [literals expr] ... [else default])
|
|
(with-syntax ([(pict ...) (generate-temporaries #'(expr ...))])
|
|
(syntax/loc stx
|
|
(let ([pict expr] ... [final default])
|
|
(combine (case test [literals pict] ... [else final])
|
|
(ghost pict) ... (ghost final)))))]
|
|
[(_ test #:combine combine [literals expr] ...)
|
|
(syntax/loc stx
|
|
(pict-case #:combine combine [literals expr] ... [else (blank 0 0)]))]
|
|
[(_ test [literals expr] ...)
|
|
(quasisyntax/loc stx
|
|
(pict-case test #:combine #,(syntax-parameter-value #'pict-combine)
|
|
[literals expr] ...))]))
|
|
|
|
(define-syntax (pict-match stx)
|
|
(syntax-case stx ()
|
|
[(_ test #:combine combine [pattern expr] ...)
|
|
(with-syntax ([(pict ...) (generate-temporaries #'(expr ...))])
|
|
(syntax/loc stx
|
|
(let ([pict expr] ...)
|
|
(combine (match test [pattern pict] ... [_ (blank 0 0)])
|
|
(ghost pict) ...))))]
|
|
[(_ test [pattern expr] ...)
|
|
(quasisyntax/loc stx
|
|
(pict-match test #:combine #,(syntax-parameter-value #'pict-combine)
|
|
[pattern expr] ...))]))
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;
|
|
;; Slide Staging
|
|
;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
(define-for-syntax (stage-keyword stx)
|
|
(raise-syntax-error #f "not in the body of a staged slide" stx))
|
|
|
|
(define-syntax-parameter stage stage-keyword)
|
|
(define-syntax-parameter stage-name stage-keyword)
|
|
|
|
(define-syntax (staged stx)
|
|
(syntax-case stx ()
|
|
[(_ [name ...] body ...)
|
|
(let* ([ids (syntax->list #'(name ...))])
|
|
|
|
(for ([id (in-list ids)] #:when (not (identifier? id)))
|
|
(raise-syntax-error #f "expected an identifier" stx id))
|
|
|
|
(with-syntax ([(num ...)
|
|
(for/list ([i (in-naturals 1)] [id (in-list ids)])
|
|
(datum->syntax #'here i id))])
|
|
|
|
(syntax/loc stx
|
|
(let* ([name num] ...)
|
|
(define (staged-computation number symbol)
|
|
(syntax-parameterize
|
|
([stage (make-rename-transformer #'number)]
|
|
[stage-name (make-rename-transformer #'symbol)])
|
|
(block body ...)))
|
|
(begin (staged-computation name 'name) ...)))))]))
|
|
|
|
(define-syntax-rule (slide/staged [name ...] body ...)
|
|
(staged [name ...] (slide body ...)))
|
|
|
|
(define-syntax-rule (before name) (< stage name))
|
|
(define-syntax-rule (before/at name) (<= stage name))
|
|
(define-syntax-rule (at/after name) (>= stage name))
|
|
(define-syntax-rule (after name) (> stage name))
|
|
(define-syntax-rule (before/after name) (not (= stage name)))
|
|
(define-syntax-rule (at name ...) (or (= stage name) ...))
|
|
|
|
(define (hide pict [hide? #t])
|
|
(if hide? (ghost pict) pict))
|
|
|
|
(define (show pict [show? #t])
|
|
(if show? pict (ghost pict)))
|
|
|
|
(define (shade pict [shade? #t] #:ratio [ratio 0.5])
|
|
(if shade? (cellophane pict ratio) pict))
|
|
|
|
(define (strike pict [strike? #t])
|
|
(if strike?
|
|
(pin-over pict
|
|
0
|
|
(/ (pict-height pict) 2)
|
|
(pip-line (pict-width pict) 0 0))
|
|
pict))
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;
|
|
;; Exports
|
|
;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
(provide with-size with-scale big small
|
|
with-font with-style bold italic subscript superscript caps)
|
|
|
|
(provide/contract
|
|
[color/c flat-contract?]
|
|
[red (-> pict? pict?)]
|
|
[orange (-> pict? pict?)]
|
|
[yellow (-> pict? pict?)]
|
|
[green (-> pict? pict?)]
|
|
[blue (-> pict? pict?)]
|
|
[purple (-> pict? pict?)]
|
|
[black (-> pict? pict?)]
|
|
[brown (-> pict? pict?)]
|
|
[gray (-> pict? pict?)]
|
|
[white (-> pict? pict?)]
|
|
[cyan (-> pict? pict?)]
|
|
[magenta (-> pict? pict?)]
|
|
[light (-> color/c color/c)]
|
|
[dark (-> color/c color/c)]
|
|
[color (-> color/c pict? pict?)]
|
|
[fill
|
|
(-> pict?
|
|
(or/c (real-in 0 +inf.0) #f)
|
|
(or/c (real-in 0 +inf.0) #f)
|
|
pict?)])
|
|
|
|
(provide column columns column-size two-columns mini-slide)
|
|
|
|
(provide/contract
|
|
[tabular (->* []
|
|
[#:gap natural-number/c
|
|
#:hgap natural-number/c
|
|
#:vgap natural-number/c
|
|
#:align (->* [] [] #:rest (listof pict?) pict?)
|
|
#:halign (->* [] [] #:rest (listof pict?) pict?)
|
|
#:valign (->* [] [] #:rest (listof pict?) pict?)]
|
|
#:rest (matrixof (or/c string? pict?))
|
|
pict?)])
|
|
|
|
(provide/contract
|
|
[hide (->* [pict?] [any/c] pict?)]
|
|
[show (->* [pict?] [any/c] pict?)]
|
|
[strike (->* [pict?] [any/c] pict?)]
|
|
[shade (->* [pict?] [any/c #:ratio (real-in 0 1)] pict?)])
|
|
(provide staged slide/staged stage stage-name
|
|
before at after before/at at/after except
|
|
pict-if pict-cond pict-case pict-match
|
|
pict-combine with-pict-combine)
|