#lang scheme/gui
(require "class-diagrams.ss"
(lib "mrpict.ss" "texpict")
(lib "utils.ss" "texpict")
scheme/system)
(define (mk-ps-diagram)
(linewidth .8 (mk-diagram)))
(define (mk-diagram)
(define part-name (class-name "part"))
(define part-blocks-field (field-spec #f "blocks"))
(define part-subparts-field (field-spec #f "subparts"))
(define part-title-field (field-spec #f "title"))
(define part-box (class-box part-name (list part-title-field part-blocks-field part-subparts-field) #f))
(define block-name (class-name "block"))
(define block-box (class-box block-name #f #f))
(define para-name (class-name "paragraph"))
(define para-style (field-spec #f "style"))
(define para-content (field-spec #f "content"))
(define para-box (class-box para-name (list para-style para-content) #f))
(define table-name (class-name "table"))
(define table-style (field-spec #f "style"))
(define table-cells (field-spec #f "cells")) (define table-box (class-box table-name (list table-style table-cells) #f))
(define itemization-name (class-name "itemization"))
(define itemization-style (field-spec #f "style"))
(define itemization-items (field-spec #f "items")) (define itemization-box (class-box itemization-name (list itemization-style itemization-items) #f))
(define nested-flow-name (class-name "nested-flow"))
(define nested-flow-style (field-spec #f "style"))
(define nested-flow-blocks (field-spec #f "blocks"))
(define nested-flow-box (class-box nested-flow-name (list nested-flow-style nested-flow-blocks) #f))
(define delayed-block-name (class-name "delayed-block"))
(define delayed-block-block (field-spec #f "block"))
(define delayed-block-box (class-box delayed-block-name (list delayed-block-block) #f))
(define content-name (class-name "content"))
(define content-box (class-box content-name #f #f))
(define element-name (class-name "element"))
(define element-style (field-spec #f "style"))
(define element-box (class-box element-name (list element-style) #f))
(define string-name (class-name "string"))
(define string-box (class-box string-name #f #f))
(define list-name (class-name "list"))
(define list-box (class-box list-name #f #f))
(define target-element-name (class-name "target-element"))
(define target-tag (field-spec #f "tag"))
(define target-content (field-spec #f "content"))
(define target-element-box (class-box target-element-name
(list target-tag target-content)
#f))
(define link-element-name (class-name "link-element"))
(define link-tag (field-spec #f "tag"))
(define link-content (field-spec #f "content"))
(define link-element-box (class-box link-element-name
(list link-tag link-content)
#f))
(define delayed-element-name (class-name "delayed-element"))
(define delayed-content (field-spec #f "content"))
(define delayed-element-box (class-box delayed-element-name (list delayed-content) #f))
(define collect-element-name (class-name "collect-element"))
(define collect-content (field-spec #f "content"))
(define collect-element-box (class-box collect-element-name (list collect-content) #f))
(define block-hierarchy
(hierarchy
(vc-append block-box
(blank 0 50)
(ht-append 20 para-box
(vc-append (blank 0 30) itemization-box)
delayed-block-box)
(blank 0 25)
(ht-append nested-flow-box
(blank 45 0)
table-box
(blank 45 0)))
(list block-box)
(list para-box
nested-flow-box
itemization-box
table-box
delayed-block-box)))
(define target-element-box/right
(inset target-element-box -40 0 0 0))
(define link-element-box/left
(inset link-element-box 0 0 -40 0))
(define element-hierarchy
(hierarchy
(vc-append element-box
(blank 0 50)
(ht-append 110
collect-element-box
delayed-element-box)
(blank 0 20)
(ht-append 10
target-element-box/right
link-element-box/left))
(list element-box)
(list collect-element-box
target-element-box/right
link-element-box/left
delayed-element-box)))
(define content-hierarchy
(hierarchy
(vc-append content-box
(blank 0 50)
(ht-append 10
string-box
(inset element-hierarchy -110 0)
list-box))
(list content-box)
(list string-box
element-box
list-box)))
(define raw
(vc-append part-box
(blank 0 20)
(vc-append block-hierarchy
(blank 0 20)
content-hierarchy)))
(define w/connections
(double
right-right-reference
(double
left-left-reference
(double
right-right-reference
(double
left-left-reference
(double
left-left-reference
(triple
right-right-reference
(triple
right-right-reference
(double
left-left-reference
(double
right-right-reference
(double
left-left-reference
(double
left-left-reference
raw
part-box part-title-field content-box content-name 18)
part-box part-blocks-field block-box block-name)
part-box part-subparts-field part-box part-name 2)
para-box para-content content-box content-name 2)
table-box table-cells block-box block-name 11)
itemization-box itemization-items block-box block-name 15)
nested-flow-box nested-flow-blocks block-box block-name 8)
target-element-box target-content content-box content-name 10)
link-element-box link-content content-box content-name 8)
collect-element-box collect-content content-box content-name 1)
list-box list-box content-box content-name))
(define w/delayed-connections
(dotted-right-right-reference
(dotted-right-right-reference
w/connections
delayed-block-box delayed-block-block block-box block-name)
delayed-element-box delayed-content content-box content-name))
w/delayed-connections)
(define (double f p0 a b c d [count 1])
(let ([arrows1 (launder (f (ghost p0) a b c d count #:dot-delta 1))]
[arrows2 (launder (f (ghost p0) a b c d count #:dot-delta -1))])
(cc-superimpose p0
arrows1
arrows2)))
(define (triple f p0 a b c d [count 1])
(let ([arrows (launder (f (ghost p0) a b c d count))]
[up-arrows (launder (f (ghost p0) a b c d count #:dot-delta 2))]
[down-arrows (launder (f (ghost p0) a b c d count #:dot-delta -2))])
(cc-superimpose p0
arrows
up-arrows
down-arrows)))
(define (connect-circly-dots show-arrowhead? main dot1 . dots)
(let loop ([prev-dot dot1]
[dots dots]
[pict main])
(cond
[(null? dots) pict]
[else
(loop (car dots)
(cdr dots)
(connect-two-circly-dots pict prev-dot (car dots) (null? (cdr dots))))])))
(define (connect-two-circly-dots pict dot1 dot2 arrowhead?)
(let ([base
(let*-values ([(sx sy) (cc-find pict dot1)]
[(raw-ex ey) (cc-find pict dot2)]
[(ex) (if arrowhead?
(+ raw-ex 2)
raw-ex)])
(cc-superimpose
(dc
(λ (dc dx dy)
(let ([pen (send dc get-pen)])
(send dc set-pen
(send pen get-color)
(if (is-a? dc post-script-dc%)
4
2)
'dot)
(send dc draw-line
(+ dx sx) (+ dy sy)
(+ dx ex) (+ dy ey))
(send dc set-pen pen)))
(pict-width pict)
(pict-height pict))
pict))])
(if arrowhead?
(pin-arrow-line field-arrowhead-size
base
dot1 (λ (ignored1 ignored2)
(let-values ([(x y) (cc-find pict dot2)])
(values (+ x 2) y)))
dot2 cc-find
#f #f #f #f)
base)))
(define (dotted-right-right-reference p0 a b c d)
(right-right-reference p0 a b c d #:connect-dots connect-circly-dots))
(define (save-ps mk-pict filename)
(let ([ps-setup (make-object ps-setup%)])
(send ps-setup copy-from (current-ps-setup))
(send ps-setup set-file filename)
(let ([ps-dc (parameterize ([current-ps-setup ps-setup])
(make-object post-script-dc% #f #f #f #t))])
(send ps-dc start-doc "")
(send ps-dc start-page)
(parameterize ([dc-for-text-size ps-dc])
(draw-pict (mk-pict) ps-dc 0 0))
(send ps-dc end-page)
(send ps-dc end-doc))))
(define (save-png mk-pict filename)
(let* ([pict (parameterize ([dc-for-text-size (make-object bitmap-dc% (make-object bitmap% 1 1))])
(panorama (mk-pict)))]
[bm (make-object bitmap%
(+ (ceiling (inexact->exact (pict-width pict))) 1)
(+ (ceiling (inexact->exact (pict-height pict))) 1))]
[bdc (make-object bitmap-dc% bm)])
(send bdc set-smoothing 'aligned)
(send bdc clear)
(draw-pict pict bdc 0 0)
(send bdc set-bitmap #f)
(send bm save-file filename 'png)
(void)))
(save-png mk-diagram "struct-hierarchy.png")
(save-ps mk-ps-diagram "struct-hierarchy.ps")
(void (system "epstopdf struct-hierarchy.ps"))
(require (only-in slideshow slide)) (slide (mk-diagram))