draw-plain.rkt (5217B)
1 #lang racket ;scheme/gui 2 (provide lang-pict string->color) 3 4 (require scheme/runtime-path 5 slideshow/pict 6 racket/draw) 7 8 (define-runtime-path lang.plain "lang.plain") 9 10 (define (parse-file) 11 (call-with-input-file lang.plain 12 (λ (port) 13 (for ([l (in-lines port)]) 14 (parse-line l))))) 15 16 ;; nodes : hash[string -o> node] 17 (define nodes (make-hash)) 18 (define-struct node (x y w h type color) #:transparent) 19 20 ;; parents : hash[string -o> string] 21 (define parents (make-hash)) 22 23 (define graph-width 0) 24 (define graph-height 0) 25 26 (define (parse-line line) 27 (cond 28 [(regexp-match #rx"^node \"([^\"]*)\" +([0-9.]*) +([0-9.]*) +([0-9.]*) +([0-9.]*) +\"([^\"]*)\" +([^ ]*) +([^ ]*) +([^ ]*) +([^ ]*)" 29 line) 30 => 31 (λ (m) 32 (let-values ([(id x y w h label type1 type2 color1 color2) 33 (apply values (cdr m))]) 34 (hash-set! nodes id (make-node (string->number y) 35 (string->number x) 36 (string->number w) 37 (string->number h) 38 (string->symbol type2) 39 (string->color color1)))))] 40 [(regexp-match #rx"^edge \"([^\"]*)\" +\"([^\"]*)\"" 41 line) 42 => 43 (λ (m) 44 (let-values ([(src dest) (apply values (cdr m))]) 45 (hash-set! parents dest src)))] 46 [(regexp-match #rx"^graph ([0-9.]*) ([0-9.]*) ([0-9.]*)" line) 47 => 48 (λ (m) 49 (let-values ([(scale w h) (apply values (cdr m))]) 50 (set! graph-width (string->number w)) 51 (set! graph-height (string->number h))))] 52 [(regexp-match #rx"^stop" line) (void)] 53 [else 54 (error 'parse-line "unknown line ~s\n" line)])) 55 56 (define (string->color str) 57 (cond 58 [(regexp-match 59 #rx"#([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])" 60 str) 61 => 62 (λ (m) 63 (let-values ([(r g b) (apply values (cdr m))]) 64 (make-object color% 65 (string->number r 16) 66 (string->number g 16) 67 (string->number b 16))))] 68 [else 69 (let ([c (send the-color-database find-color str)]) 70 (unless c 71 (error 'string->color "unknown color ~s" str)) 72 c)])) 73 74 (define (draw-graph dc dx dy w h color?) 75 (let ([scale (min (/ w graph-width) 76 (/ h graph-height))]) 77 (define (draw-node name node) 78 (case (node-type node) 79 [(circle) 80 (let-values ([(nx ny) (node->xy node)] 81 [(px py) (node->xy (hash-ref nodes (hash-ref parents name)))]) 82 (let ([nw (* 1.8 (node-w node))] 83 [nh (* 1.8 (node-h node))]) 84 (cond 85 [color? 86 (send dc set-pen "black" 1 'transparent) 87 (send dc set-brush (node-color node) 'solid)] 88 [else 89 (send dc set-pen "SlateGray" 1 'solid) 90 (send dc set-brush "LightSlateGray" 'solid)]) 91 (send dc draw-ellipse 92 (+ dx (- nx (* scale (/ nw 2)))) 93 (+ dy (- ny (* scale (/ nh 2)))) 94 (* scale nw) 95 (* scale nh))))] 96 [else (void)])) 97 (define (draw-edge src dest) 98 (send dc set-pen "gray" 1 'solid) 99 (send dc set-brush "black" 'transparent) 100 (let-values ([(sx sy) (node->xy (hash-ref nodes src))] 101 [(tx ty) (node->xy (hash-ref nodes dest))]) 102 (send dc draw-line 103 (+ dx sx) 104 (+ dy sy) 105 (+ dx tx) 106 (+ dy ty)))) 107 108 (define (node->xy node) 109 (values (* scale (node-x node)) 110 (- h (* scale (node-y node))))) 111 (let ([smoothing (send dc get-smoothing)] 112 [pen (send dc get-pen)] 113 [brush (send dc get-brush)]) 114 (send dc set-smoothing 'aligned) 115 (hash-for-each 116 parents 117 (λ (dest src) 118 (draw-edge src dest))) 119 (for-each 120 (λ (name-node) 121 (draw-node (car name-node) 122 (cadr name-node))) 123 (sort (hash-map nodes list) 124 (compare-name-node-list w h))) 125 (send dc set-smoothing smoothing) 126 (send dc set-pen pen) 127 (send dc set-brush brush)))) 128 129 (define ((compare-name-node-list w h) name-node1 name-node2) 130 (let* ([c (make-rectangular (/ w 2) (/ h 2))] 131 [x (make-rectangular (node-x (cadr name-node1)) 132 (node-x (cadr name-node2)))] 133 [y (make-rectangular (node-y (cadr name-node1)) 134 (node-y (cadr name-node2)))] 135 [ax (angle (- x c))] 136 [ay (angle (- y c))]) 137 (cond 138 [(= ax ay) 139 (< (magnitude x) (magnitude y))] 140 [else 141 (< ax ay)]))) 142 143 (parse-file) 144 145 #; 146 (begin 147 (define f (new frame% [label ""])) 148 (define c (new canvas% 149 [parent f] 150 [paint-callback 151 (λ (c dc) 152 (let-values ([(w h) (send c get-client-size)]) 153 (draw-graph dc 0 0 w h)))])) 154 (send f show #t)) 155 156 (define (lang-pict size color?) 157 (dc (λ (dc dx dy) (draw-graph dc dx dy size size color?)) 158 size size))