[racket] Custom GUI container

From: Vincent St-Amour (stamourv at ccs.neu.edu)
Date: Sat Feb 25 13:42:28 EST 2012

Neat!

That would make a great planet package,

Vincent


At Sat, 25 Feb 2012 11:40:32 -0700,
Kieron Hardy wrote:
> 
> Hi all,
> 
> I needed a GUI container that allows the contained components to choose
> where they are placed in the container.  i.e. A container that doesn't try
> to stretch and re-'place' its containees, instead letting the containees
> figure out where they want to be.
> 
> I was surprised that this particular container/containee use-case wasn't
> readily available in Racket (since it is 'the' fundamental layout
> elsewhere), so I implemented a version and post it here in case it is
> useful to others. (If I'm going about it wrong, then please do let me know.)
> 
> Cheers,
> 
> Kieron.
> 
> p.s. I notice the canvas border is actually painted only on the top and
> left (see capture-self-placeable). Should the border also be painted on the
> bottom and right?
> 
> ****
> 
> #lang racket/gui
> 
> ; Specify in an interface the methods that a containee needs to make it
> self-placeable.
> (define self-placeable-containee<%>
>   (interface ()
>     get-preferred-x get-preferred-y get-preferred-x-y
>     set-preferred-x set-preferred-y set-preferred-x-y))
> 
> ; Define in a mixin the default implementations for a self-placeable
> containee.
> (define (self-placeable-containee%% %)
>   (class* % (self-placeable-containee<%>)
>     (super-new)
> 
>     (define preferred-x 0)
>     (define preferred-y 0)
> 
>     (define/public (get-preferred-x)
>       preferred-x)
>     (define/public (get-preferred-y)
>       preferred-y)
>     (define/public (get-preferred-x-y)
>       (values preferred-x preferred-y))
> 
>     (define/public (set-preferred-x x)
>       (set! preferred-x x))
>     (define/public (set-preferred-y y)
>       (set! preferred-y y))
>     (define/public (set-preferred-x-y x y)
>       (set! preferred-x x)
>       (set! preferred-y y))
>     ))
> 
> ; Define a custom container panel that can place the self-placeable
> containees.
> (define placer-panel%
>   (class panel%
>     (inherit get-children min-width min-height)
> 
>     (super-new)
> 
>     ; container-size is called with each child's dimensions and
> strechability,
>     ; and returns the container's required minimum dimensions.
>     ; In this case, the containee size's are ignored,
>     ; and the container's (previously set) minimum width and height are
> returned.
>     [define/override (container-size containee-sizes)
> ;      (printf "container-size:~a\n" containee-sizes)
>       (values (min-width) (min-height))]
> 
>     ; place-children is called with each child's dimensions and
> strechability,
>     ; and returns each child's location and dimensions.
>     ; In this case, each containee is simply asked where it wants to be
> (previously set).
>     ; No adustments are made to a containee's size so as to use any empty
> space in the container.
>     ; i.e. A containee's strechability is ignored, and each containee
> remains the (previously set) minimum width and height.
>     [define/override (place-children containee-sizes container-width
> container-height)
> ;      (printf "place-children:~a\n" containee-sizes)
>       (map (lambda (containee-size containee)
>              (let*-values ([(min-width min-height h-stretch? v-stretch?)
>                             (apply values containee-size)]
>                            [(x y)
>                             (send containee get-preferred-x-y)]
>                            )
>                (list x y min-width min-height)))
>            containee-sizes
>            (get-children))]
>     ))
> 
> (define self-placeable-canvas%
>   (class (self-placeable-containee%% canvas%)
>     (inherit set-preferred-x-y)
>     (init x y)
>     (super-new)
>     (set-preferred-x-y x y)
>     ))
> 
> (define frame-1 (new frame%
>                      [label "Self Placeable Containees"]
>                      [x 30]
>                      [y 30]
>                      [min-width 800]
>                      [min-height 600]))
> 
> (define panel-1 (new placer-panel%
>                      [parent frame-1]
>                      ))
> 
> (define canvas-1 (new self-placeable-canvas%
>                       [parent panel-1]
>                       [style (list 'border)]
>                       [x 25]
>                       [y 25]
>                       [min-width 500]
>                       [min-height 75]))
> 
> (define canvas-2 (new self-placeable-canvas%
>                       [parent panel-1]
>                       [style (list 'border)]
>                       [x 275]
>                       [y 275]
>                       [min-width 100]
>                       [min-height 100]))
> 
> (define canvas-3 (new self-placeable-canvas%
>                       [parent panel-1]
>                       [style (list 'border)]
>                       [x 600]
>                       [y 125]
>                       [min-width 100]
>                       [min-height 400]))
> 
> (send frame-1 show #t)

Posted on the users mailing list.