lang-slide/draw-plain.ss
2012-04-23 21:53:53 -04:00

158 lines
5.1 KiB
Scheme

#lang scheme/gui
(provide lang-pict string->color)
(require scheme/runtime-path
slideshow)
(define-runtime-path lang.plain "lang.plain")
(define (parse-file)
(call-with-input-file lang.plain
(λ (port)
(for ([l (in-lines port)])
(parse-line l)))))
;; nodes : hash[string -o> node]
(define nodes (make-hash))
(define-struct node (x y w h type color) #:transparent)
;; parents : hash[string -o> string]
(define parents (make-hash))
(define graph-width 0)
(define graph-height 0)
(define (parse-line line)
(cond
[(regexp-match #rx"^node \"([^\"]*)\" +([0-9.]*) +([0-9.]*) +([0-9.]*) +([0-9.]*) +\"([^\"]*)\" +([^ ]*) +([^ ]*) +([^ ]*) +([^ ]*)"
line)
=>
(λ (m)
(let-values ([(id x y w h label type1 type2 color1 color2)
(apply values (cdr m))])
(hash-set! nodes id (make-node (string->number y)
(string->number x)
(string->number w)
(string->number h)
(string->symbol type2)
(string->color color1)))))]
[(regexp-match #rx"^edge \"([^\"]*)\" +\"([^\"]*)\""
line)
=>
(λ (m)
(let-values ([(src dest) (apply values (cdr m))])
(hash-set! parents dest src)))]
[(regexp-match #rx"^graph ([0-9.]*) ([0-9.]*) ([0-9.]*)" line)
=>
(λ (m)
(let-values ([(scale w h) (apply values (cdr m))])
(set! graph-width (string->number w))
(set! graph-height (string->number h))))]
[(regexp-match #rx"^stop" line) (void)]
[else
(error 'parse-line "unknown line ~s\n" line)]))
(define (string->color str)
(cond
[(regexp-match
#rx"#([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])"
str)
=>
(λ (m)
(let-values ([(r g b) (apply values (cdr m))])
(make-object color%
(string->number r 16)
(string->number g 16)
(string->number b 16))))]
[else
(let ([c (send the-color-database find-color str)])
(unless c
(error 'string->color "unknown color ~s" str))
c)]))
(define (draw-graph dc dx dy w h color?)
(let ([scale (min (/ w graph-width)
(/ h graph-height))])
(define (draw-node name node)
(case (node-type node)
[(circle)
(let-values ([(nx ny) (node->xy node)]
[(px py) (node->xy (hash-ref nodes (hash-ref parents name)))])
(let ([nw (* 1.8 (node-w node))]
[nh (* 1.8 (node-h node))])
(cond
[color?
(send dc set-pen "black" 1 'transparent)
(send dc set-brush (node-color node) 'solid)]
[else
(send dc set-pen "SlateGray" 1 'solid)
(send dc set-brush "LightSlateGray" 'solid)])
(send dc draw-ellipse
(+ dx (- nx (* scale (/ nw 2))))
(+ dy (- ny (* scale (/ nh 2))))
(* scale nw)
(* scale nh))))]
[else (void)]))
(define (draw-edge src dest)
(send dc set-pen "gray" 1 'solid)
(send dc set-brush "black" 'transparent)
(let-values ([(sx sy) (node->xy (hash-ref nodes src))]
[(tx ty) (node->xy (hash-ref nodes dest))])
(send dc draw-line
(+ dx sx)
(+ dy sy)
(+ dx tx)
(+ dy ty))))
(define (node->xy node)
(values (* scale (node-x node))
(- h (* scale (node-y node)))))
(let ([smoothing (send dc get-smoothing)]
[pen (send dc get-pen)]
[brush (send dc get-brush)])
(send dc set-smoothing 'aligned)
(hash-for-each
parents
(λ (dest src)
(draw-edge src dest)))
(for-each
(λ (name-node)
(draw-node (car name-node)
(cadr name-node)))
(sort (hash-map nodes list)
(compare-name-node-list w h)))
(send dc set-smoothing smoothing)
(send dc set-pen pen)
(send dc set-brush brush))))
(define ((compare-name-node-list w h) name-node1 name-node2)
(let* ([c (make-rectangular (/ w 2) (/ h 2))]
[x (make-rectangular (node-x (cadr name-node1))
(node-x (cadr name-node2)))]
[y (make-rectangular (node-y (cadr name-node1))
(node-y (cadr name-node2)))]
[ax (angle (- x c))]
[ay (angle (- y c))])
(cond
[(= ax ay)
(< (magnitude x) (magnitude y))]
[else
(< ax ay)])))
(parse-file)
#;
(begin
(define f (new frame% [label ""]))
(define c (new canvas%
[parent f]
[paint-callback
(λ (c dc)
(let-values ([(w h) (send c get-client-size)])
(draw-graph dc 0 0 w h)))]))
(send f show #t))
(define (lang-pict size color?)
(dc (λ (dc dx dy) (draw-graph dc dx dy size size color?))
size size))