From a1881efb58fb14d7b796de075edef1fdcf6a5e08 Mon Sep 17 00:00:00 2001 From: "D. Ben Knoble" Date: Mon, 6 Jan 2025 12:18:12 -0500 Subject: [PATCH 1/2] list-view: avoid more work when keys don't change According to existing discussion: - The removal loop does not trigger the inner conditional when the keys haven't changed anyway, because (member old-k new-keys) should always be true. - The call to change-children is redundant when the keys haven't changed because the list of children should also be the same. Thus we perform some work (looping, conditionals, and importantly a call to change-children) that is unnecessary: for performance, skip it. Close https://github.com/Bogdanp/racket-gui-easy/issues/57 Best-viewed-with: --ignore-space-change --- gui-easy-lib/gui/easy/private/view/list.rkt | 42 +++++++++++---------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/gui-easy-lib/gui/easy/private/view/list.rkt b/gui-easy-lib/gui/easy/private/view/list.rkt index 426fb00..1a8c0a1 100644 --- a/gui-easy-lib/gui/easy/private/view/list.rkt +++ b/gui-easy-lib/gui/easy/private/view/list.rkt @@ -96,9 +96,11 @@ [stretchable-height h-s?])) (define keys-to-children (get-keys-to-children the-panel)) + (define entries (peek @entries)) + (send the-panel set-context 'current-keys (map key-proc entries)) (begin0 the-panel (with-container-sequence the-panel - (for ([e (in-list (peek @entries))]) + (for ([e (in-list entries)]) (define k (key-proc e)) (define v (make-view k (make-keyed-obs k e))) (define w (send v create the-panel)) @@ -122,24 +124,26 @@ (add-child-handlers! v child-v) (add-child v child-v child-w) (hash-set! keys-to-children k child-v))))) - (for ([(old-k old-v) (in-hash keys-to-children)]) - (unless (member old-k new-keys) - (define old-w (get-child v old-v)) - (define focused? (send old-w has-focus?)) - (send old-v destroy old-w) - (send v delete-child old-w) - (remove-child-handlers! v old-v) - (remove-child v old-v) - (hash-remove! keys-to-children old-k) - (when focused? - (define children (send v get-children)) - (cond - [(null? children) (send v focus)] - [else (send (last children) focus)])))) - (send v change-children - (λ (_) - (for/list ([k (in-list new-keys)]) - (get-child v (hash-ref keys-to-children k))))))] + (unless (equal? new-keys (send v get-context 'current-keys null)) + (for ([(old-k old-v) (in-hash keys-to-children)]) + (unless (member old-k new-keys) + (define old-w (get-child v old-v)) + (define focused? (send old-w has-focus?)) + (send old-v destroy old-w) + (send v delete-child old-w) + (remove-child-handlers! v old-v) + (remove-child v old-v) + (hash-remove! keys-to-children old-k) + (when focused? + (define children (send v get-children)) + (cond + [(null? children) (send v focus)] + [else (send (last children) focus)])))) + (send v change-children + (λ (_) + (for/list ([k (in-list new-keys)]) + (get-child v (hash-ref keys-to-children k))))) + (send v set-context 'current-keys new-keys)))] [@alignment (send/apply v set-alignment val)] [@enabled? From f5c2c7de7863312c4b82cfcc534b42d01ab2b1b7 Mon Sep 17 00:00:00 2001 From: Bogdan Popa Date: Wed, 8 Jan 2025 09:33:41 +0200 Subject: [PATCH 2/2] list: avoid computing keys twice --- gui-easy-lib/gui/easy/private/view/list.rkt | 41 +++++++++++---------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/gui-easy-lib/gui/easy/private/view/list.rkt b/gui-easy-lib/gui/easy/private/view/list.rkt index 1a8c0a1..d050579 100644 --- a/gui-easy-lib/gui/easy/private/view/list.rkt +++ b/gui-easy-lib/gui/easy/private/view/list.rkt @@ -97,13 +97,14 @@ (define keys-to-children (get-keys-to-children the-panel)) (define entries (peek @entries)) - (send the-panel set-context 'current-keys (map key-proc entries)) + (define keys (map key-proc entries)) + (send the-panel set-context 'current-keys keys) (begin0 the-panel (with-container-sequence the-panel - (for ([e (in-list entries)]) - (define k (key-proc e)) + (for ([e (in-list entries)] + [k (in-list keys)]) (define v (make-view k (make-keyed-obs k e))) - (define w (send v create the-panel)) + (define w (send v create the-panel)) ;; noqa (add-child-handlers! the-panel v) (add-child the-panel v w) (hash-set! keys-to-children k v))))) @@ -125,25 +126,25 @@ (add-child v child-v child-w) (hash-set! keys-to-children k child-v))))) (unless (equal? new-keys (send v get-context 'current-keys null)) - (for ([(old-k old-v) (in-hash keys-to-children)]) - (unless (member old-k new-keys) - (define old-w (get-child v old-v)) - (define focused? (send old-w has-focus?)) - (send old-v destroy old-w) - (send v delete-child old-w) - (remove-child-handlers! v old-v) - (remove-child v old-v) - (hash-remove! keys-to-children old-k) - (when focused? - (define children (send v get-children)) - (cond - [(null? children) (send v focus)] - [else (send (last children) focus)])))) + (send v set-context 'current-keys new-keys) + (for ([(old-k old-v) (in-hash keys-to-children)] + #:unless (member old-k new-keys)) + (define old-w (get-child v old-v)) + (define focused? (send old-w has-focus?)) + (send old-v destroy old-w) + (send v delete-child old-w) + (remove-child-handlers! v old-v) + (remove-child v old-v) + (hash-remove! keys-to-children old-k) + (when focused? + (define children (send v get-children)) + (cond + [(null? children) (send v focus)] + [else (send (last children) focus)]))) (send v change-children (λ (_) (for/list ([k (in-list new-keys)]) - (get-child v (hash-ref keys-to-children k))))) - (send v set-context 'current-keys new-keys)))] + (get-child v (hash-ref keys-to-children k)))))))] [@alignment (send/apply v set-alignment val)] [@enabled?