Skip to content

Commit

Permalink
view: add add-hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
Bogdanp committed Aug 29, 2023
1 parent ddba619 commit 677840d
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 44 deletions.
26 changes: 26 additions & 0 deletions examples/hooks.rkt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#lang racket/gui/easy

(require racket/class)

(define/obs @choice 'a)

(render
(window
#:title "Lifecycle Hooks"
(choice
'(a b)
#:choice->label symbol->string
#:selection @choice
(λ:= @choice))
(dyn-view
@choice
(lambda (choice)
(case choice
[(a) (add-hooks
#:on-create (λ () (eprintf "a created~n"))
#:on-destroy (λ () (eprintf "a destroyed~n"))
(text "a"))]
[(b) (add-hooks
#:on-create (λ () (eprintf "b created~n"))
#:on-destroy (λ () (eprintf "b destroyed~n"))
(text "b"))])))))
1 change: 1 addition & 0 deletions gui-easy-lib/gui/easy/private/view.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"view/checkbox.rkt"
"view/choice.rkt"
"view/common.rkt"
"view/hooks.rkt"
"view/if.rkt"
"view/image.rkt"
"view/input.rkt"
Expand Down
32 changes: 32 additions & 0 deletions gui-easy-lib/gui/easy/private/view/hooks.rkt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#lang racket/base

(require racket/class
"view.rkt")

(provide
add-hooks)

(define proxy%
(class* object% (view<%>)
(init-field on-create-proc
on-destroy-proc
the-view)
(super-new)
(define/public (dependencies)
(send the-view dependencies))
(define/public (create parent)
(begin0 (send the-view create parent)
(on-create-proc)))
(define/public (update v what val)
(send the-view update v what val))
(define/public (destroy v)
(begin0 (send the-view destroy v)
(on-destroy-proc)))))

(define (add-hooks #:on-create [on-create-proc void]
#:on-destroy [on-destroy-proc void]
the-view)
(new proxy%
[on-create-proc on-create-proc]
[on-destroy-proc on-destroy-proc]
[the-view the-view]))
75 changes: 39 additions & 36 deletions gui-easy-lib/gui/easy/view.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,11 @@
[dialog (window/c gui:dialog% (listof (or/c 'no-caption 'no-sheet 'resize-border 'close-button)))]

;; Menus & Menu Items
[popup-menu (-> (is-a?/c view<%>) ...
(is-a?/c popup-menu-view<%>))]
[menu-bar (-> (is-a?/c view<%>) ...
(is-a?/c menu-bar-view<%>))]
[menu (-> (maybe-obs/c maybe-label/c)
(is-a?/c view<%>) ...
(is-a?/c menu-view<%>))]
[menu-item (->* ((maybe-obs/c maybe-label/c))
((-> any))
(is-a?/c view<%>))]
[menu-item-separator (-> (is-a?/c view<%>))]
[popup-menu (-> view/c ... (is-a?/c popup-menu-view<%>))]
[menu-bar (-> view/c ... (is-a?/c menu-bar-view<%>))]
[menu (-> (maybe-obs/c maybe-label/c) view/c ... (is-a?/c menu-view<%>))]
[menu-item (->* ((maybe-obs/c maybe-label/c)) ((-> any)) view/c)]
[menu-item-separator (-> view/c)]

;; Containers
[hpanel (panel/c)]
Expand All @@ -61,18 +55,18 @@
#:margin (maybe-obs/c margin/c)
#:min-size (maybe-obs/c size/c)
#:stretch (maybe-obs/c stretch/c))
#:rest (listof (is-a?/c view<%>))
(is-a?/c view<%>))]
#:rest (listof view/c)
view/c)]
[observable-view (->* (obs?)
((-> any/c (is-a?/c view<%>))
((-> any/c view/c)
#:equal? (-> any/c any/c any/c))
(is-a?/c view<%>))]
view/c)]
[rename observable-view dyn-view
(->* (obs? (-> any/c (is-a?/c view<%>)))
(->* (obs? (-> any/c view/c))
(#:equal? (-> any/c any/c any/c))
(is-a?/c view<%>))]
view/c)]
[list-view (->* ((maybe-obs/c any/c)
(-> any/c any/c (is-a?/c view<%>)))
(-> any/c any/c view/c))
(#:alignment (maybe-obs/c alignment/c)
#:enabled? (maybe-obs/c boolean?)
#:style (listof (or/c 'horizontal 'vertical 'border 'deleted
Expand All @@ -84,7 +78,7 @@
#:stretch (maybe-obs/c stretch/c)
#:key (-> any/c any/c)
#:mixin (make-mixin-contract gui:panel%))
(is-a?/c view<%>))]
view/c)]

;; Canvases & Snips
[canvas (canvas/c (-> (is-a?/c gui:dc<%>) any/c any))]
Expand All @@ -102,7 +96,7 @@
#:min-size (maybe-obs/c size/c)
#:stretch (maybe-obs/c stretch/c)
#:mixin (make-mixin-contract gui:snip-canvas%))
(is-a?/c view<%>))]
view/c)]

;; Widgets
[button (->* ((maybe-obs/c
Expand All @@ -118,12 +112,12 @@
#:margin (maybe-obs/c margin/c)
#:min-size (maybe-obs/c size/c)
#:stretch (maybe-obs/c stretch/c))
(is-a?/c view<%>))]
view/c)]
[checkbox (->* ((-> boolean? any))
(#:label (maybe-obs/c gui:label-string?)
#:checked? (maybe-obs/c boolean?)
#:enabled? (maybe-obs/c boolean?))
(is-a?/c view<%>))]
view/c)]
[choice (->* ((maybe-obs/c (listof any/c))
(-> (or/c #f any/c) any))
(#:choice->label (-> any/c gui:label-string?)
Expand All @@ -134,11 +128,11 @@
#:enabled? (maybe-obs/c boolean?)
#:min-size (maybe-obs/c size/c)
#:stretch (maybe-obs/c stretch/c))
(is-a?/c view<%>))]
view/c)]
[image (->* ((maybe-obs/c path-string?))
(#:size (maybe-obs/c size/c)
#:mode (maybe-obs/c (or/c 'fit 'fill)))
(is-a?/c view<%>))]
view/c)]
[input (->* ((maybe-obs/c any/c))
((-> (or/c 'input 'return) string? any)
#:label (maybe-obs/c maybe-label/c)
Expand All @@ -155,7 +149,7 @@
#:mixin (make-mixin-contract gui:text-field%)
#:value=? (-> any/c any/c boolean?)
#:value->text (-> any/c string?))
(is-a?/c view<%>))]
view/c)]
[progress (->* ((maybe-obs/c gui:position-integer?))
(#:label (maybe-obs/c gui:label-string?)
#:enabled? (maybe-obs/c boolean?)
Expand All @@ -165,7 +159,7 @@
#:range (maybe-obs/c gui:positive-dimension-integer?)
#:min-size (maybe-obs/c size/c)
#:stretch (maybe-obs/c stretch/c))
(is-a?/c view<%>))]
view/c)]
[radios (->* ((listof any/c)
(-> (or/c #f any/c) any))
(#:choice->label (-> any/c gui:label-string?)
Expand All @@ -178,7 +172,7 @@
#:enabled? (maybe-obs/c boolean?)
#:min-size (maybe-obs/c size/c)
#:stretch (maybe-obs/c stretch/c))
(is-a?/c view<%>))]
view/c)]
[slider (->* ((maybe-obs/c gui:position-integer?)
(-> gui:position-integer? any))
(#:label (maybe-obs/c (or/c #f gui:label-string?))
Expand All @@ -190,8 +184,8 @@
#:max-value gui:position-integer?
#:min-size (maybe-obs/c size/c)
#:stretch (maybe-obs/c stretch/c))
(is-a?/c view<%>))]
[spacer (-> (is-a?/c view<%>))]
view/c)]
[spacer (-> view/c)]
[table (->* ((listof gui:label-string?)
(maybe-obs/c vector?))
(table-action/c
Expand All @@ -213,11 +207,20 @@
(or/c (list/c exact-nonnegative-integer? gui:dimension-integer?)
(list/c exact-nonnegative-integer? gui:dimension-integer? gui:dimension-integer? gui:dimension-integer?))))
#:mixin (make-mixin-contract gui:list-box%))
(is-a?/c view<%>))]
view/c)]
[text (->* ((maybe-obs/c gui:label-string?))
(#:color (maybe-obs/c (or/c #f string? (is-a?/c gui:color%)))
#:font (is-a?/c gui:font%))
(is-a?/c view<%>))]))
view/c)]

;; Combinators
[add-hooks (->* (view/c)
(#:on-create (-> any)
#:on-destroy (-> any))
view/c)]))

(define view/c
(is-a?/c view<%>))

(define (canvas/c draw/c)
(->* ((maybe-obs/c any/c) draw/c)
Expand All @@ -231,7 +234,7 @@
#:min-size (maybe-obs/c size/c)
#:stretch (maybe-obs/c stretch/c)
#:mixin (make-mixin-contract gui:canvas%))
(is-a?/c view<%>)))
view/c))

(define-syntax-rule (panel/c arg/c ...)
(->* (arg/c ...)
Expand All @@ -245,8 +248,8 @@
#:min-size (maybe-obs/c size/c)
#:stretch (maybe-obs/c stretch/c)
#:mixin (make-mixin-contract gui:panel%))
#:rest (listof (is-a?/c view<%>))
(is-a?/c view<%>)))
#:rest (listof view/c)
view/c))

(define (window/c % style/c)
(->* ()
Expand All @@ -258,8 +261,8 @@
#:stretch (maybe-obs/c stretch/c)
#:style style/c
#:mixin (make-mixin-contract %))
#:rest (listof (is-a?/c view<%>))
(is-a?/c view<%>)))
#:rest (listof view/c)
view/c))

(define table-action/c
(-> (or/c 'select 'dclick 'column)
Expand Down
2 changes: 1 addition & 1 deletion gui-easy-lib/info.rkt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#lang info

(define license 'BSD-3-Clause)
(define version "0.13")
(define version "0.14")
(define collection "racket")
(define deps '("base"
"box-extra-lib"
Expand Down
25 changes: 18 additions & 7 deletions gui-easy/gui/easy/scribblings/reference.scrbl
Original file line number Diff line number Diff line change
Expand Up @@ -625,18 +625,29 @@
Returns a representation of a textual label.
}

@subsection{Combinators}

@defproc[(add-hooks [#:on-create create-proc (-> any) void]
[#:on-destroy destroy-proc (-> any) void]
[v (is-a?/c view<%>)]) (is-a?/c view<%>)]{
Returns a proxy of @racket[v] that calls @racket[create-proc] and
@racket[destroy-proc] when a GUI widget is created and destroyed,
respectively, from the view.

@history[#:added "0.14"]
}

@subsection{Interfaces}
@subsubsection{@tt{view<%>}}
@definterface[view<%> ()]{
A @racket[view<%>] object is a wrapper around a GUI object that
knows what its data dependecies are and how to respond to their
changes.
A @racket[view<%>] object is a wrapper around a GUI object that knows
what its data dependecies are and how to respond to their changes.

A single @racket[view<%>] object may be used to manage multiple GUI
widgets. Consequently, when implementing custom views, it's best
not to store any state within the view object itself. Instead,
associate any internal state with the GUI widgets returned by
@racket[create], possibly via @racket[context-mixin].
widgets. Consequently, when implementing custom views, it's best not
to store any state within the view object itself. Instead, associate
any internal state with the GUI widgets returned by @racket[create],
possibly via @racket[context-mixin].

@defmethod[(dependencies) (listof obs?)]{
Returns the set of observers that this view depends on.
Expand Down

0 comments on commit 677840d

Please sign in to comment.