added support for special-case drawing of individual edges to the graph library and support to be able to use that to redex

svn: r13226
This commit is contained in:
Robby Findler 2009-01-19 18:02:33 +00:00
parent 49fd5085d0
commit af810c8a6f
8 changed files with 120 additions and 33 deletions

View File

@ -1115,6 +1115,8 @@ profile todo:
(send src lock #f)))))) (send src lock #f))))))
sorted) sorted)
(printf "sorted ~s\n" sorted)
;; clear out old annotations (and thaw colorers) ;; clear out old annotations (and thaw colorers)
(when internal-clear-test-coverage-display (when internal-clear-test-coverage-display
(internal-clear-test-coverage-display) (internal-clear-test-coverage-display)

View File

@ -231,7 +231,8 @@
(mixin ((class->interface pasteboard%)) (graph-pasteboard<%>) (mixin ((class->interface pasteboard%)) (graph-pasteboard<%>)
(inherit find-first-snip find-next-selected-snip) (inherit find-first-snip find-next-selected-snip)
(init-field [edge-label-font #f]) (init-field [edge-label-font #f]
[edge-labels? #t])
(define draw-arrow-heads? #t) (define draw-arrow-heads? #t)
(inherit refresh get-admin) (inherit refresh get-admin)
@ -535,12 +536,12 @@
[(b45x b45y) (values s5x s4y)] [(b45x b45y) (values s5x s4y)]
[(b56x b56y) (values s5x s6y)]) [(b56x b56y) (values s5x s6y)])
(update-polygon s4x s4y sx s4y) (update-arrowhead-polygon s4x s4y sx s4y)
(send dc draw-spline (+ dx s1x) (+ dy s1y) (+ dx b12x) (+ dy b12y) (+ dx s2x) (+ dy s2y)) (send dc draw-spline (+ dx s1x) (+ dy s1y) (+ dx b12x) (+ dy b12y) (+ dx s2x) (+ dy s2y))
(send dc draw-spline (+ dx s2x) (+ dy s2y) (+ dx b23x) (+ dy b23y) (+ dx s3x) (+ dy s3y)) (send dc draw-spline (+ dx s2x) (+ dy s2y) (+ dx b23x) (+ dy b23y) (+ dx s3x) (+ dy s3y))
(send dc draw-line (+ dx s3x) (+ dy s3y) (+ dx s6x) (+ dy s6y)) (send dc draw-line (+ dx s3x) (+ dy s3y) (+ dx s6x) (+ dy s6y))
(when (link-label the-link) (when (and edge-labels? (link-label the-link))
(let* ((textlen (get-text-length (link-label the-link))) (let* ((textlen (get-text-length (link-label the-link)))
(linelen (- s6x s3x)) (linelen (- s6x s3x))
(offset (* 1/2 (- linelen textlen)))) (offset (* 1/2 (- linelen textlen))))
@ -606,19 +607,8 @@
;; the snips overlap, draw nothing ;; the snips overlap, draw nothing
(void)] (void)]
[else [else
(send dc draw-line (draw-single-edge dc dx dy from to from-x from-y to-x to-y arrow-point-ok?)
(+ dx from-x) (+ dy from-y) (when (and edge-labels? (link-label from-link))
(+ dx to-x) (+ dy to-y))
(update-polygon from-x from-y to-x to-y)
(when (and draw-arrow-heads?
(arrow-point-ok? (send point1 get-x) (send point1 get-y))
(arrow-point-ok? (send point2 get-x) (send point2 get-y))
(arrow-point-ok? (send point3 get-x) (send point3 get-y))
(arrow-point-ok? (send point4 get-x) (send point4 get-y)))
;; the arrowhead is not overlapping the snips, so draw it
;; (this is only an approximate test, but probably good enough)
(send dc draw-polygon points dx dy))
(when (named-link? from-link)
(let-values ([(text-len h d v) (send dc get-text-extent (link-label from-link))]) (let-values ([(text-len h d v) (send dc get-text-extent (link-label from-link))])
(let* ([arrow-end-x (send point3 get-x)] (let* ([arrow-end-x (send point3 get-x)]
[arrow-end-y (send point3 get-y)] [arrow-end-y (send point3 get-y)]
@ -628,15 +618,14 @@
(- (* 1/2 vec) (- (* 1/2 vec)
(make-polar (/ text-len 2) (angle vec))))]) (make-polar (/ text-len 2) (angle vec))))])
(when (> (sqrt (+ (sqr (- arrow-end-x from-x)) (when (> (sqrt (+ (sqr (- arrow-end-x from-x))
(sqr (- arrow-end-y from-y)))) (sqr (- arrow-end-y from-y))))
text-len) text-len)
(send dc draw-text (link-label from-link) (send dc draw-text (link-label from-link)
(+ dx (real-part middle)) (+ dx (real-part middle))
(+ dy (imag-part middle)) (+ dy (imag-part middle))
#f #f
0 0
(- (angle vec)))))))])))))))) (- (angle vec)))))))]))))))))
(define (named-link? l) (link-label l))
(define (set-pen/brush from-link dark-lines?) (define (set-pen/brush from-link dark-lines?)
(send dc set-brush (send dc set-brush
@ -678,6 +667,20 @@
(send dc set-text-foreground old-fg) (send dc set-text-foreground old-fg)
(send dc set-brush old-brush)))) (send dc set-brush old-brush))))
(define/public (draw-single-edge dc dx dy from to from-x from-y to-x to-y arrow-point-ok?)
(send dc draw-line
(+ dx from-x) (+ dy from-y)
(+ dx to-x) (+ dy to-y))
(update-arrowhead-polygon from-x from-y to-x to-y point1 point2 point3 point4)
(when (and draw-arrow-heads?
(arrow-point-ok? (send point1 get-x) (send point1 get-y))
(arrow-point-ok? (send point2 get-x) (send point2 get-y))
(arrow-point-ok? (send point3 get-x) (send point3 get-y))
(arrow-point-ok? (send point4 get-x) (send point4 get-y)))
;; the arrowhead is not overlapping the snips, so draw it
;; (this is only an approximate test, but probably good enough)
(send dc draw-polygon points dx dy)))
;; for-each-to-redraw : number number number number (link snip -> void) ;; for-each-to-redraw : number number number number (link snip -> void)
(define/private (for-each-to-redraw left top right bottom f) (define/private (for-each-to-redraw left top right bottom f)
(let () (let ()
@ -727,11 +730,11 @@
[point4 (make-object point% 0 0)] [point4 (make-object point% 0 0)]
[points (list point1 point2 point3 point4)]) [points (list point1 point2 point3 point4)])
;; update-polygon : number^4 -> void ;; update-arrowhead-polygon : number^4 -> void
;; updates points1, 2, and 3 with the arrow head's ;; updates points1, 2, and 3 with the arrow head's
;; points. Use a turtle-like movement to find the points. ;; points. Use a turtle-like movement to find the points.
;; point3 is the point where the line should end. ;; point3 is the point where the line should end.
(define/private (update-polygon from-x from-y to-x to-y) (define/public (update-arrowhead-polygon from-x from-y to-x to-y point1 point2 point3 point4)
(define (move tx ty ta d) (values (+ tx (* d (cos ta))) (define (move tx ty ta d) (values (+ tx (* d (cos ta)))
(+ ty (* d (sin ta))) (+ ty (* d (sin ta)))
ta)) ta))

View File

@ -60,5 +60,51 @@ different nodes.
is @scheme[#t]. is @scheme[#t].
} }
@defmethod[(draw-single-edge [dc (is-a?/c dc<%>)]
[dx real?]
[dy real?]
[from (is-a?/c graph-snip<%>)]
[to (is-a?/c graph-snip<%>)]
[from-x real?]
[from-y real?]
[to-x real?]
[to-y real?]
[arrow-point-ok? (-> real? real? boolean?)]) void?]{
This method is called to draw each edge in the graph, except
for the edges that connect a node to itself.
The @scheme[dc], @scheme[dx], and @scheme[dy] arguments are
the same as in @method[editor<%> on-paint].
The
@scheme[from-x], @scheme[from-y], @scheme[to-x], and
@scheme[to-y] arguments specify points on the source and
destination snip's bounding box where a straight line
between the centers of the snip would intersect.
The @scheme[arrow-point-ok?] function returns @scheme[#t]
when the point specified by its arguments is inside the the
smallest rectangle that covers both the source and
destination snips, but is outside of both of the rectangles
that surround the source and destination snips themselves.
This default implementation uses @scheme[update-polygon] to compute
the arrowheads and otherwise draws a straight line between the two
points and then the arrowheads, unless the arrowhead points
are not ok according to @scheme[arrow-point-ok?], in which case
it just draws the line.
}
@defmethod[(update-arrowhead-polygon [from-x real?] [from-y real?] [to-x real?] [to-y real?]
[point1 (is-a?/c point%)]
[point2 (is-a?/c point%)]
[point3 (is-a?/c point%)]
[point4 (is-a?/c point%)]) void?]{
Updates the arguments @scheme[point1], @scheme[point2], @scheme[point3], @scheme[point4] with the coordinates
of an arrowhead for a line that connects (@scheme[from-x],@scheme[from-y]) to (@scheme[to-x],@scheme[to-y]).
}
} }

View File

@ -3,7 +3,11 @@
@defmixin/title[graph-pasteboard-mixin (pasteboard%) (graph-pasteboard<%>)]{ @defmixin/title[graph-pasteboard-mixin (pasteboard%) (graph-pasteboard<%>)]{
@defconstructor/auto-super[([edge-label-font (or/c #f (is-a?/c font%)) #f])]{ @defconstructor/auto-super[([edge-labels? boolean? #t]
[edge-label-font (or/c #f (is-a?/c font%)) #f])]{
If @scheme[edge-labels?] is @scheme[#f], no edge labels are
drawn. Otherwise, they are.
If @scheme[edge-label-font] is supplied, it is used when drawing the If @scheme[edge-label-font] is supplied, it is used when drawing the
labels on the edges. Otherwise, the font is not set before drawing labels on the edges. Otherwise, the font is not set before drawing

View File

@ -9,6 +9,7 @@
"private/matcher.ss" "private/matcher.ss"
"private/reduction-semantics.ss" "private/reduction-semantics.ss"
"private/size-snip.ss" "private/size-snip.ss"
mrlib/graph
scheme/contract scheme/contract
scheme/class scheme/class
scheme/gui/base) scheme/gui/base)
@ -37,7 +38,9 @@
#:scheme-colors? boolean? #:scheme-colors? boolean?
#:layout (-> any/c any/c) #:layout (-> any/c any/c)
#:edge-label-font (or/c #f (is-a?/c font%)) #:edge-label-font (or/c #f (is-a?/c font%))
#:filter (-> any/c (or/c #f string?) any/c)) #:edge-labels? boolean?
#:filter (-> any/c (or/c #f string?) any/c)
#:graph-pasteboard-mixin (make-mixin-contract graph-pasteboard<%>))
any)] any)]
[traces/ps (->* (reduction-relation? [traces/ps (->* (reduction-relation?
any/c any/c
@ -50,7 +53,9 @@
#:colors (listof any/c) #:colors (listof any/c)
#:layout (-> any/c any/c) #:layout (-> any/c any/c)
#:edge-label-font (or/c #f (is-a?/c font%)) #:edge-label-font (or/c #f (is-a?/c font%))
#:filter (-> any/c (or/c #f string?) any/c)) #:edge-labels? boolean?
#:filter (-> any/c (or/c #f string?) any/c)
#:graph-pasteboard-mixin (make-mixin-contract graph-pasteboard<%>))
any)] any)]
[term-node? (-> any/c boolean?)] [term-node? (-> any/c boolean?)]

View File

@ -133,6 +133,8 @@
#:colors [colors '()] #:colors [colors '()]
#:layout [layout void] #:layout [layout void]
#:edge-label-font [edge-label-font #f] #:edge-label-font [edge-label-font #f]
#:edge-labels? [edge-labels? #t]
#:graph-pasteboard-mixin [extra-graph-pasteboard-mixin values]
#:filter [term-filter (lambda (x y) #t)]) #:filter [term-filter (lambda (x y) #t)])
(let-values ([(graph-pb canvas) (let-values ([(graph-pb canvas)
(traces reductions pre-exprs (traces reductions pre-exprs
@ -144,6 +146,8 @@
#:colors colors #:colors colors
#:layout layout #:layout layout
#:edge-label-font edge-label-font #:edge-label-font edge-label-font
#:edge-labels? edge-labels?
#:graph-pasteboard-mixin extra-graph-pasteboard-mixin
#:filter term-filter)]) #:filter term-filter)])
(print-to-ps graph-pb canvas filename))) (print-to-ps graph-pb canvas filename)))
@ -232,12 +236,14 @@
#:scheme-colors? [scheme-colors? #t] #:scheme-colors? [scheme-colors? #t]
#:layout [layout void] #:layout [layout void]
#:edge-label-font [edge-label-font #f] #:edge-label-font [edge-label-font #f]
#:edge-labels? [edge-labels? #t]
#:filter [term-filter (lambda (x y) #t)] #:filter [term-filter (lambda (x y) #t)]
#:graph-pasteboard-mixin [extra-graph-pasteboard-mixin values]
#:no-show-frame? [no-show-frame? #f]) #:no-show-frame? [no-show-frame? #f])
(define exprs (if multiple? pre-exprs (list pre-exprs))) (define exprs (if multiple? pre-exprs (list pre-exprs)))
(define main-eventspace (current-eventspace)) (define main-eventspace (current-eventspace))
(define saved-parameterization (current-parameterization)) (define saved-parameterization (current-parameterization))
(define graph-pb (new graph-pasteboard% [layout layout] [edge-label-font edge-label-font])) (define graph-pb (new (extra-graph-pasteboard-mixin graph-pasteboard%) [layout layout] [edge-label-font edge-label-font] [edge-labels? edge-labels?]))
(define user-char-width (initial-char-width)) (define user-char-width (initial-char-width))
(define f (instantiate red-sem-frame% () (define f (instantiate red-sem-frame% ()
(label "PLT Redex Reduction Graph") (label "PLT Redex Reduction Graph")

View File

@ -4,11 +4,12 @@
scribble/eval scribble/eval
(for-syntax scheme/base) (for-syntax scheme/base)
(for-label scheme/base (for-label scheme/base
scheme/gui scheme/gui
scheme/pretty scheme/pretty
scheme/contract scheme/contract
(only-in slideshow/pict pict? text dc-for-text-size) mrlib/graph
redex)) (only-in slideshow/pict pict? text dc-for-text-size)
redex))
@(define-syntax (defpattech stx) @(define-syntax (defpattech stx)
(syntax-case stx () (syntax-case stx ()
@ -378,7 +379,7 @@ stands for repetition unless otherwise indicated):
(in-hole term term) (in-hole term term)
hole hole
#t #f #t #f
string] string]
[term-sequence [term-sequence
term term
,@scheme-expression ,@scheme-expression
@ -1156,10 +1157,12 @@ exploring reduction sequences.
(and/c (listof (or/c string? (is-a?/c color%))) (and/c (listof (or/c string? (is-a?/c color%)))
(lambda (x) (member (length x) '(2 3 4 6))))))] (lambda (x) (member (length x) '(2 3 4 6))))))]
[#:scheme-colors? scheme-colors? boolean? #t] [#:scheme-colors? scheme-colors? boolean? #t]
[#:filter term-filter (-> any/c (or/c #f string?) any/c) (lambda (x y) #t)] [#:filter term-filter (-> any/c (or/c #f string?) any/c) (lambda (x y) #t)]
[#:layout layout (-> (listof term-node?) void) void] [#:layout layout (-> (listof term-node?) void) void]
[#:edge-label-font edge-label-font (or/c #f (is-a?/c font%)) #f]) [#:edge-labels? edge-label-font boolean? #t]
[#:edge-label-font edge-label-font (or/c #f (is-a?/c font%)) #f]
[#:graph-pasteboard-mixin graph-pasteboard-mixin (make-mixin-contract graph-pasteboard<%>) values])
void?]{ void?]{
This function opens a new window and inserts each expression This function opens a new window and inserts each expression
@ -1228,10 +1231,23 @@ after new terms are inserted in response to the user clicking on the
reduce button, and after the initial set of terms is inserted. reduce button, and after the initial set of terms is inserted.
See also @scheme[term-node-set-position!]. See also @scheme[term-node-set-position!].
If @scheme[edge-labels?] is @scheme[#t] (the default), then edge labels
are drawn; otherwise not.
The @scheme[edge-label-font] argument is used as the font on the edge The @scheme[edge-label-font] argument is used as the font on the edge
labels. If nothign is suppled, the @scheme[dc<%>] object's default labels. If @scheme[#f] is suppled, the @scheme[dc<%>] object's default
font is used. font is used.
The traces library an instance of the @schememodname[mrlib/graph]
library's @scheme[graph-pasteboard<%>] interface to layout
the graphs. Sometimes, overriding one of its methods can
help give finer-grained control over the layout, so the
@scheme[graph-pasteboard-mixin] is applied to the class
before it is instantiated. Also note that all of the snips
inserted into the editor by this library have a
@tt{get-term-node} method which returns the snip's
@scheme[term-node].
} }
@defproc[(traces/ps [reductions reduction-relation?] @defproc[(traces/ps [reductions reduction-relation?]
@ -1249,7 +1265,9 @@ font is used.
[#:colors colors (listof (list string string)) '()] [#:colors colors (listof (list string string)) '()]
[#:filter term-filter (-> any/c (or/c #f string?) any/c) (lambda (x y) #t)] [#:filter term-filter (-> any/c (or/c #f string?) any/c) (lambda (x y) #t)]
[#:layout layout (-> (listof term-node?) void) void] [#:layout layout (-> (listof term-node?) void) void]
[#:edge-label-font edge-label-font (or/c #f (is-a?/c font%)) #f]) [#:edge-labels? edge-label-font boolean? #t]
[#:edge-label-font edge-label-font (or/c #f (is-a?/c font%)) #f]
[#:graph-pasteboard-mixin graph-pasteboard-mixin (make-mixin-contract graph-pasteboard<%>) values])
void?]{ void?]{
The arguments behave just like the function @scheme[traces], but The arguments behave just like the function @scheme[traces], but

View File

@ -3,6 +3,9 @@ v4.1.4
- initial-char-width now accepts functions to give finer grained - initial-char-width now accepts functions to give finer grained
control of the initial widths of the terms. control of the initial widths of the terms.
- traces & traces/ps: added the ability to specify a mixin
to be mixed into the graph pasteboard
v4.1.3 v4.1.3
* added redex-check, a tool for automatically generating test cases * added redex-check, a tool for automatically generating test cases