184 lines
8.1 KiB
Racket
184 lines
8.1 KiB
Racket
#lang racket/base
|
|
|
|
(require racket/gui/base racket/class racket/match racket/list racket/math unstable/parameter-group
|
|
"../common/snip.rkt"
|
|
"../common/plot-device.rkt"
|
|
"../common/math.rkt"
|
|
"../common/format.rkt"
|
|
"../common/ticks.rkt"
|
|
"../common/parameters.rkt")
|
|
|
|
(provide 2d-plot-snip% make-2d-plot-snip)
|
|
|
|
(define zoom-delay 16) ; about 60 fps (just over)
|
|
(define show-zoom-message? #t)
|
|
|
|
(define 2d-plot-snip%
|
|
(class plot-snip%
|
|
(init bm saved-plot-parameters)
|
|
(init-field make-plot plot-bounds-rect area-bounds-rect area-bounds->plot-bounds)
|
|
|
|
(inherit set-bitmap get-bitmap
|
|
get-saved-plot-parameters
|
|
refresh set-message reset-message-timeout get-admin)
|
|
|
|
(super-make-object bm saved-plot-parameters)
|
|
|
|
(define/override (copy)
|
|
(make-object this%
|
|
(get-bitmap) (get-saved-plot-parameters)
|
|
make-plot plot-bounds-rect area-bounds-rect area-bounds->plot-bounds))
|
|
|
|
(define left-click-x 0)
|
|
(define left-click-y 0)
|
|
(define left-drag-x 0)
|
|
(define left-drag-y 0)
|
|
|
|
(define plot-bounds-rects empty)
|
|
|
|
(define (get-area-bounds-rect)
|
|
(rect-meet area-bounds-rect
|
|
(rect-inexact->exact
|
|
(vector (ivl left-click-x left-drag-x) (ivl left-click-y left-drag-y)))))
|
|
|
|
(define dragging? #f)
|
|
(define left-down? #f) ; only #t if left-down happened on this snip
|
|
|
|
(define zoom-timer #f)
|
|
(define (set-zoom-timer)
|
|
(when (not zoom-timer)
|
|
(set! zoom-timer (make-object timer%
|
|
(λ ()
|
|
(set! zoom-timer #f)
|
|
(refresh))
|
|
zoom-delay #t))))
|
|
|
|
(define (set-click-message)
|
|
(when show-zoom-message?
|
|
(set-message "Click and drag to zoom\n Click to unzoom once")))
|
|
|
|
(define (update-plot new-plot-bounds-rect)
|
|
(define-values (new-bm new-area-bounds-rect new-area-bounds->plot-bounds)
|
|
(make-plot new-plot-bounds-rect))
|
|
(set! plot-bounds-rect new-plot-bounds-rect)
|
|
(set! area-bounds-rect new-area-bounds-rect)
|
|
(set! area-bounds->plot-bounds new-area-bounds->plot-bounds)
|
|
(set-bitmap new-bm))
|
|
|
|
(define/override (on-event dc x y editorx editory evt)
|
|
(define evt-type (send evt get-event-type))
|
|
(define mouse-x (- (send evt get-x) x))
|
|
(define mouse-y (- (send evt get-y) y))
|
|
(case evt-type
|
|
[(left-down) (set! left-click-x mouse-x)
|
|
(set! left-click-y mouse-y)
|
|
(set! left-drag-x mouse-x)
|
|
(set! left-drag-y mouse-y)
|
|
(set! dragging? #f)
|
|
(set! left-down? #t)
|
|
(set-message #f)
|
|
(set-zoom-timer)]
|
|
[(left-up) (set! left-drag-x mouse-x)
|
|
(set! left-drag-y mouse-y)
|
|
(set! left-down? #f)
|
|
(cond [dragging?
|
|
(set! dragging? #f)
|
|
(define new-rect (area-bounds->plot-bounds (get-area-bounds-rect)))
|
|
(cond [(and (rect-rational? new-rect) (not (rect-zero-area? new-rect)))
|
|
#;(printf "~a: new-plot-bounds-rect = ~v~n"
|
|
(current-milliseconds) new-rect)
|
|
(set! plot-bounds-rects (cons plot-bounds-rect plot-bounds-rects))
|
|
(update-plot new-rect)]
|
|
[else (refresh)])]
|
|
[(not (empty? plot-bounds-rects))
|
|
(define new-rect (first plot-bounds-rects))
|
|
(set! plot-bounds-rects (rest plot-bounds-rects))
|
|
(update-plot new-rect)
|
|
(set! show-zoom-message? #f)])]
|
|
[(motion) (cond [left-down? ; not event's left-down: only #t if clicked on snip
|
|
(when (not (and (= left-drag-x mouse-x)
|
|
(= left-drag-y mouse-y)))
|
|
(set! left-drag-x mouse-x)
|
|
(set! left-drag-y mouse-y)
|
|
(set! dragging? #t)
|
|
(set-zoom-timer))]
|
|
[(and (not (send evt get-left-down))
|
|
(<= 0 mouse-x (send (get-bitmap) get-width))
|
|
(<= 0 mouse-y (send (get-bitmap) get-height)))
|
|
(set-click-message)])])
|
|
(super on-event dc x y editorx editory evt))
|
|
|
|
(define/override (draw dc dc-x-min dc-y-min left top right bottom dx dy draw-caret)
|
|
;(printf "~a: drawing~n" (current-milliseconds))
|
|
(super draw dc dc-x-min dc-y-min left top right bottom dx dy draw-caret)
|
|
(when dragging?
|
|
(define new-rect (get-area-bounds-rect))
|
|
(when (and (rect-rational? new-rect) (not (rect-zero-area? new-rect)))
|
|
(define width (send (get-bitmap) get-width))
|
|
(define height (send (get-bitmap) get-height))
|
|
|
|
(define pd (make-object plot-device% dc dc-x-min dc-y-min width height))
|
|
(send pd reset-drawing-params #f)
|
|
|
|
(define select-color (get-highlight-background-color))
|
|
(define draw-rect (rect-translate new-rect (vector dc-x-min dc-y-min)))
|
|
|
|
;; inside of selection box
|
|
(send pd set-pen select-color 1 'transparent)
|
|
(send pd set-brush select-color 'solid)
|
|
(send pd set-alpha 1/4)
|
|
(send pd draw-rect draw-rect)
|
|
|
|
;; border of selection box
|
|
(send pd set-minor-pen)
|
|
(send pd set-brush select-color 'transparent)
|
|
(send pd set-alpha 3/4)
|
|
(send pd draw-rect draw-rect)
|
|
|
|
;; side labels
|
|
(parameterize/group ([plot-parameters (get-saved-plot-parameters)])
|
|
(match-define (vector (ivl x-min x-max) (ivl y-min y-max)) plot-bounds-rect)
|
|
(match-define (vector (ivl new-area-x-min new-area-x-max)
|
|
(ivl new-area-y-min new-area-y-max))
|
|
new-rect)
|
|
(match-define (vector (ivl new-x-min new-x-max) (ivl new-y-min new-y-max))
|
|
(area-bounds->plot-bounds new-rect))
|
|
|
|
(define new-area-x-mid (* 1/2 (+ new-area-x-min new-area-x-max)))
|
|
(define new-area-y-mid (* 1/2 (+ new-area-y-min new-area-y-max)))
|
|
|
|
;; format new-x-min and new-x-max
|
|
(match-define (list new-x-min-str new-x-max-str)
|
|
((ticks-format (plot-x-ticks))
|
|
x-min x-max (list (pre-tick new-x-min #t) (pre-tick new-x-max #t))))
|
|
;; draw new-x-min
|
|
(send pd draw-text new-x-min-str
|
|
(vector (+ dc-x-min new-area-x-min) (+ dc-y-min new-area-y-mid))
|
|
'center (* 1/2 pi) #:outline? #t)
|
|
;; draw new-x-max
|
|
(send pd draw-text new-x-max-str
|
|
(vector (+ dc-x-min new-area-x-max) (+ dc-y-min new-area-y-mid))
|
|
'center (* 1/2 pi) #:outline? #t)
|
|
|
|
;; format new-y-min and new-y-max
|
|
(match-define (list new-y-min-str new-y-max-str)
|
|
((ticks-format (plot-y-ticks))
|
|
y-min y-max (list (pre-tick new-y-min #t) (pre-tick new-y-max #t))))
|
|
;; draw new-y-min
|
|
(send pd draw-text new-y-min-str
|
|
(vector (+ dc-x-min new-area-x-mid) (+ dc-y-min new-area-y-max))
|
|
'center #:outline? #t)
|
|
;; draw new-y-max
|
|
(send pd draw-text new-y-max-str
|
|
(vector (+ dc-x-min new-area-x-mid) (+ dc-y-min new-area-y-min))
|
|
'center #:outline? #t))
|
|
|
|
(send pd restore-drawing-params))))
|
|
))
|
|
|
|
(define (make-2d-plot-snip bm saved-plot-parameters
|
|
make-plot plot-bounds-rect area-bounds-rect area-bounds->plot-bounds)
|
|
(make-object 2d-plot-snip%
|
|
bm saved-plot-parameters
|
|
make-plot plot-bounds-rect area-bounds-rect area-bounds->plot-bounds))
|