macro-stepper: faster step rendering

- lazily build on-click mapping
  - more precise un-styling on refresh

original commit: 199450dd0cacb2d8c3e5290b68d9b2d0aa1650fe
This commit is contained in:
Ryan Culpepper 2010-11-09 00:04:14 -07:00
parent 0cad27438d
commit 847c0c67a7
3 changed files with 136 additions and 117 deletions

View File

@ -3,6 +3,7 @@
racket/gui/base racket/gui/base
racket/list racket/list
racket/pretty racket/pretty
racket/promise
data/interval-map data/interval-map
framework framework
unstable/class-iop unstable/class-iop
@ -71,42 +72,68 @@
(define base-style (define base-style
(code-style text (send/i config config<%> get-syntax-font-size))) (code-style text (send/i config config<%> get-syntax-font-size)))
;; on-next-refresh : (listof (cons stx style-delta))
;; Styles to be applied on next refresh only. (eg, underline)
(define on-next-refresh null)
;; extra-styles : hash[stx => (listof style-delta)]
;; Styles to be re-applied on every refresh.
(define extra-styles (make-hasheq)) (define extra-styles (make-hasheq))
(define auto-refresh? #f) ;; FIXME: delete or make init arg ;; to-undo-styles : (listof (cons nat nat))
;; Ranges to unbold or unhighlight when selection changes.
;; FIXME: ought to be managed by text:region-data (to auto-update ranges)
;; until then, positions are relative
(define to-undo-styles null)
;; initialize : -> void ;; initialize : -> void
(define/private (initialize) (define/private (initialize)
(uninterruptible (uninterruptible
(send text change-style base-style start-position end-position #f)) (send text change-style base-style start-position end-position #f))
(uninterruptible (apply-primary-partition-styles)) (uninterruptible (apply-primary-partition-styles))
(uninterruptible (add-clickbacks)) (uninterruptible (add-clickbacks)))
(when auto-refresh? (refresh)))
;; add-clickbacks : -> void ;; add-clickbacks : -> void
(define/private (add-clickbacks) (define/private (add-clickbacks)
(define mapping (send text get-region-mapping 'syntax)) (define mapping (send text get-region-mapping 'syntax))
(define lazy-interval-map-init
(delay
(uninterruptible
(for ([range (send/i range range<%> all-ranges)])
(let ([stx (range-obj range)]
[start (range-start range)]
[end (range-end range)])
(interval-map-set! mapping (+ start-position start) (+ start-position end) stx))))))
(define (the-callback position) (define (the-callback position)
(force lazy-interval-map-init)
(send/i controller selection-manager<%> set-selected-syntax (send/i controller selection-manager<%> set-selected-syntax
(interval-map-ref mapping position #f))) (interval-map-ref mapping position #f)))
(for ([range (send/i range range<%> all-ranges)])
(let ([stx (range-obj range)]
[start (range-start range)]
[end (range-end range)])
(interval-map-set! mapping (+ start-position start) (+ start-position end) stx)))
(send text set-clickregion start-position end-position the-callback)) (send text set-clickregion start-position end-position the-callback))
;; refresh : -> void ;; refresh : -> void
;; Clears all highlighting and reapplies all non-foreground styles. ;; Clears all highlighting and reapplies all non-foreground styles.
(define/public (refresh) (define/public (refresh)
(uninterruptible (with-unlock text
(with-unlock text (uninterruptible
(send text change-style (unhighlight-d) start-position end-position) (let ([undo-select/highlight-d (get-undo-select/highlight-d)])
(apply-extra-styles) (for ([r (in-list to-undo-styles)])
(let ([selected-syntax (send text change-style undo-select/highlight-d
(send/i controller selection-manager<%> (relative->text-position (car r))
get-selected-syntax)]) (relative->text-position (cdr r)))))
(apply-secondary-relation-styles selected-syntax) (set! to-undo-styles null))
(uninterruptible
(for ([stx+delta (in-list on-next-refresh)])
(for ([r (in-list (send/i range range<%> get-ranges (car stx+delta)))])
(restyle-range r (cdr stx+delta) #f)))
(set! on-next-refresh null))
(uninterruptible
(apply-extra-styles))
(let ([selected-syntax
(send/i controller selection-manager<%>
get-selected-syntax)])
(uninterruptible
(apply-secondary-relation-styles selected-syntax))
(uninterruptible
(apply-selection-styles selected-syntax))))) (apply-selection-styles selected-syntax)))))
;; get-range : -> range<%> ;; get-range : -> range<%>
@ -120,22 +147,16 @@
;; highlight-syntaxes : (list-of syntax) string -> void ;; highlight-syntaxes : (list-of syntax) string -> void
(define/public (highlight-syntaxes stxs hi-color) (define/public (highlight-syntaxes stxs hi-color)
(let ([style-delta (highlight-style-delta hi-color #f)]) (let ([delta (highlight-style-delta hi-color)])
(for ([stx stxs]) (for ([stx (in-list stxs)])
(add-extra-styles stx (list style-delta)))) (hash-set! extra-styles stx
(when auto-refresh? (refresh))) (cons delta (hash-ref extra-styles stx null))))))
;; underline-syntaxes : (listof syntax) -> void ;; underline-syntaxes : (listof syntax) -> void
(define/public (underline-syntaxes stxs) (define/public (underline-syntaxes stxs)
(for ([stx stxs]) (for ([stx (in-list stxs)])
(add-extra-styles stx (list underline-style-delta))) (set! on-next-refresh
(when auto-refresh? (refresh))) (cons (cons stx underline-d) on-next-refresh))))
;; add-extra-styles : syntax (listof style) -> void
(define/public (add-extra-styles stx styles)
(hash-set! extra-styles stx
(append (hash-ref extra-styles stx null)
styles)))
;; Primary styles ;; Primary styles
;; (Done once on initialization, never repeated) ;; (Done once on initialization, never repeated)
@ -187,10 +208,16 @@
;; apply-extra-styles : -> void ;; apply-extra-styles : -> void
;; Applies externally-added styles (such as highlighting) ;; Applies externally-added styles (such as highlighting)
(define/private (apply-extra-styles) (define/private (apply-extra-styles)
(for ([(stx style-deltas) extra-styles]) (for ([(stx deltas) (in-hash extra-styles)])
(for ([r (send/i range range<%> get-ranges stx)]) (for ([r (in-list (send/i range range<%> get-ranges stx))])
(for ([style-delta style-deltas]) (for ([delta (in-list deltas)])
(restyle-range r style-delta))))) (restyle-range r delta #t)))))
;; apply-selection-styles : syntax -> void
;; Styles subterms eq to the selected syntax
(define/private (apply-selection-styles selected-syntax)
(for ([r (in-list (send/i range range<%> get-ranges selected-syntax))])
(restyle-range r select-d #t)))
;; apply-secondary-relation-styles : selected-syntax -> void ;; apply-secondary-relation-styles : selected-syntax -> void
;; If the selected syntax is an identifier, then styles all identifiers ;; If the selected syntax is an identifier, then styles all identifiers
@ -200,25 +227,17 @@
(let* ([name+relation (let* ([name+relation
(send/i controller secondary-relation<%> (send/i controller secondary-relation<%>
get-identifier=?)] get-identifier=?)]
[relation (and name+relation (cdr name+relation))]) [relation (and name+relation (cdr name+relation))]
[secondary-highlight-d (get-secondary-highlight-d)])
(when relation (when relation
(for ([id (send/i range range<%> get-identifier-list)]) (for ([id (in-list (send/i range range<%> get-identifier-list))])
(when (relation selected-syntax id) (when (relation selected-syntax id)
(draw-secondary-connection id))))))) (for ([r (in-list (send/i range range<%> get-ranges id))])
(restyle-range r secondary-highlight-d #t))))))))
;; apply-selection-styles : syntax -> void ;; restyle-range : (cons num num) style-delta% boolean -> void
;; Styles subterms eq to the selected syntax (define/private (restyle-range r style need-undo?)
(define/private (apply-selection-styles selected-syntax) (when need-undo? (set! to-undo-styles (cons r to-undo-styles)))
(for ([r (send/i range range<%> get-ranges selected-syntax)])
(restyle-range r (select-highlight-d))))
;; draw-secondary-connection : syntax -> void
(define/private (draw-secondary-connection stx2)
(for ([r (send/i range range<%> get-ranges stx2)])
(restyle-range r (select-sub-highlight-d))))
;; restyle-range : (cons num num) style-delta% -> void
(define/private (restyle-range r style)
(send text change-style style (send text change-style style
(relative->text-position (car r)) (relative->text-position (car r))
(relative->text-position (cdr r)))) (relative->text-position (cdr r))))
@ -352,34 +371,38 @@
;; Styles ;; Styles
(define (highlight-style-delta raw-color em? (define select-d
#:translate-color? [translate-color? #t]) (make-object style-delta% 'change-weight 'bold))
(let* ([sd (new style-delta%)])
(unless em? (define underline-d
(send sd set-delta-background (make-object style-delta% 'change-underline #t))
(if translate-color? (translate-color raw-color) raw-color)))
(when em? (send sd set-weight-on 'bold)) (define (highlight-style-delta raw-color #:translate-color? [translate-color? #t])
(unless em? (let ([sd (new style-delta%)]
;; (send sd set-underlined-off #t) [color (if translate-color? (translate-color raw-color) raw-color)])
(send sd set-weight-off 'bold)) (send sd set-delta-background color)
sd)) sd))
(define underline-style-delta (define (mk-2-constant-style bow-color [wob-color (translate-color bow-color)])
(let ([sd (new style-delta%)]) (let ([wob-version (highlight-style-delta wob-color #:translate-color? #f)]
(send sd set-underlined-on #t) [bow-version (highlight-style-delta bow-color #:translate-color? #f)])
sd))
(define (mk-2-constant-style bow-color em? [wob-color (translate-color bow-color)])
(let ([wob-version (highlight-style-delta wob-color em? #:translate-color? #f)]
[bow-version (highlight-style-delta bow-color em? #:translate-color? #f)])
(λ () (λ ()
(if (pref:invert-colors?) (if (pref:invert-colors?)
wob-version wob-version
bow-version)))) bow-version))))
(define select-highlight-d (define get-secondary-highlight-d
(mk-2-constant-style "yellow" #t "darkgoldenrod")) (mk-2-constant-style "yellow" "darkgoldenrod"))
(define select-sub-highlight-d
(mk-2-constant-style "yellow" #f "darkgoldenrod"))
(define unhighlight-d (mk-2-constant-style "white" #f #|"black"|#)) #|
(define undo-select-d
(make-object style-delta% 'change-weight 'normal))
(define get-undo-highlight-d
(mk-2-constant-style "white" "black"))
|#
(define (get-undo-select/highlight-d)
(let ([sd (make-object style-delta% 'change-weight 'normal)]
[bg (if (pref:invert-colors?) "black" "white")])
(send sd set-delta-background bg)
sd))

View File

@ -67,6 +67,12 @@
(send dc set-text-background old-background) (send dc set-text-background old-background)
(send dc set-text-mode old-mode)))) (send dc set-text-mode old-mode))))
;; Interfaces
(define text:region-data<%>
(interface (text:basic<%>)
get-region-mapping))
(define text:hover<%> (define text:hover<%>
(interface (text:basic<%>) (interface (text:basic<%>)
update-hover-position)) update-hover-position))
@ -74,8 +80,7 @@
(define text:hover-drawings<%> (define text:hover-drawings<%>
(interface (text:basic<%>) (interface (text:basic<%>)
add-hover-drawing add-hover-drawing
get-position-drawings get-position-drawings))
delete-all-drawings))
(define text:arrows<%> (define text:arrows<%>
(interface (text:hover-drawings<%>) (interface (text:hover-drawings<%>)
@ -83,9 +88,27 @@
add-question-arrow add-question-arrow
add-billboard)) add-billboard))
(define text:region-data<%> ;; Mixins
(interface (text:basic<%>)
get-region-mapping)) (define text:region-data-mixin
(mixin (text:basic<%>) (text:region-data<%>)
(define table (make-hasheq))
(define/public (get-region-mapping key)
(hash-ref! table key (lambda () (make-interval-map))))
(define/augment (after-delete start len)
(for ([im (in-hash-values table)])
(interval-map-contract! im start (+ start len)))
(inner (void) after-delete))
(define/augment (after-insert start len)
(for ([im (in-hash-values table)])
(interval-map-expand! im start (+ start len)))
(inner (void) after-insert))
(super-new)))
(define text:hover-mixin (define text:hover-mixin
(mixin (text:basic<%>) (text:hover<%>) (mixin (text:basic<%>) (text:hover<%>)
@ -108,13 +131,15 @@
(super-new))) (super-new)))
(define text:hover-drawings-mixin (define text:hover-drawings-mixin
(mixin (text:hover<%>) (text:hover-drawings<%>) (mixin (text:hover<%> text:region-data<%>) (text:hover-drawings<%>)
(inherit dc-location-to-editor-location (inherit dc-location-to-editor-location
find-position find-position
invalidate-bitmap-cache) invalidate-bitmap-cache
get-region-mapping)
(super-new)
;; interval-map of Drawings ;; interval-map of Drawings
(define drawings-list (make-interval-map)) (define drawings-list (get-region-mapping 'hover-drawings))
(field [hover-position #f]) (field [hover-position #f])
@ -132,9 +157,6 @@
drawing drawing
null))) null)))
(define/public (delete-all-drawings)
(interval-map-remove! drawings-list -inf.0 +inf.0))
(define/override (on-paint before? dc left top right bottom dx dy draw-caret) (define/override (on-paint before? dc left top right bottom dx dy draw-caret)
(super on-paint before? dc left top right bottom dx dy draw-caret) (super on-paint before? dc left top right bottom dx dy draw-caret)
(unless before? (unless before?
@ -147,9 +169,7 @@
(define/private (same-drawings? old-pos pos) (define/private (same-drawings? old-pos pos)
;; relies on order drawings added & list-of-eq?-struct equality ;; relies on order drawings added & list-of-eq?-struct equality
(equal? (get-position-drawings old-pos) (equal? (get-position-drawings old-pos)
(get-position-drawings pos))) (get-position-drawings pos)))))
(super-new)))
(define text:tacking-mixin (define text:tacking-mixin
(mixin (text:basic<%> text:hover-drawings<%>) () (mixin (text:basic<%> text:hover-drawings<%>) ()
@ -303,28 +323,6 @@
(super-new))) (super-new)))
(define text:region-data-mixin
(mixin (text:basic<%>) (text:region-data<%>)
(define table (make-hasheq))
(define/public (get-region-mapping key)
(hash-ref! table key (lambda () (make-interval-map))))
(define/augment (after-delete start len)
(for ([im (in-hash-values table)])
(interval-map-contract! im start (+ start len)))
(inner (void) after-delete))
(define/augment (after-insert start len)
(for ([im (in-hash-values table)])
(interval-map-expand! im start (+ start len)))
(inner (void) after-insert))
(super-new)))
(define clickregion-key (gensym 'text:clickregion))
#| #|
text:clickregion-mixin text:clickregion-mixin
@ -335,7 +333,6 @@ Like clickbacks, but:
- different rules for removal - different rules for removal
- TODO: extend to double-click - TODO: extend to double-click
|# |#
(define text:clickregion-mixin (define text:clickregion-mixin
(mixin (text:region-data<%>) () (mixin (text:region-data<%>) ()
(inherit get-admin (inherit get-admin
@ -344,7 +341,7 @@ Like clickbacks, but:
find-position) find-position)
(super-new) (super-new)
(define clickbacks (get-region-mapping clickregion-key)) (define clickbacks (get-region-mapping 'clickregion))
(define tracking #f) (define tracking #f)
(define/public (set-clickregion start end callback) (define/public (set-clickregion start end callback)

View File

@ -203,8 +203,7 @@
(define/public (erase-all) (define/public (erase-all)
(with-unlock -text (with-unlock -text
(send -text erase) (send -text erase))
(send -text delete-all-drawings))
(send/i controller displays-manager<%> remove-all-syntax-displays)) (send/i controller displays-manager<%> remove-all-syntax-displays))
(define/public (get-text) -text) (define/public (get-text) -text)
@ -245,11 +244,11 @@
(define browser-text% (define browser-text%
(let ([browser-text-default-style-name "widget.rkt::browser-text% basic"]) (let ([browser-text-default-style-name "widget.rkt::browser-text% basic"])
(class (text:clickregion-mixin (class (text:clickregion-mixin
(text:region-data-mixin (text:arrows-mixin
(text:arrows-mixin (text:tacking-mixin
(text:tacking-mixin (text:hover-drawings-mixin
(text:hover-drawings-mixin (text:hover-mixin
(text:hover-mixin (text:region-data-mixin
(text:hide-caret/selection-mixin (text:hide-caret/selection-mixin
(text:foreground-color-mixin (text:foreground-color-mixin
(editor:standard-style-list-mixin text:basic%))))))))) (editor:standard-style-list-mixin text:basic%)))))))))