[racket] Custom GUI container

From: Kieron Hardy (kieron.hardy at gmail.com)
Date: Sat Feb 25 13:40:32 EST 2012

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.)



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
(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
(define (self-placeable-containee%% %)
  (class* % (self-placeable-containee<%>)

    (define preferred-x 0)
    (define preferred-y 0)

    (define/public (get-preferred-x)
    (define/public (get-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
(define placer-panel%
  (class panel%
    (inherit get-children min-width min-height)


    ; container-size is called with each child's dimensions and
    ; 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
    [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
    ; 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
;      (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)))

(define self-placeable-canvas%
  (class (self-placeable-containee%% canvas%)
    (inherit set-preferred-x-y)
    (init x y)
    (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)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20120225/c872adaf/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Capture-self-placeable.PNG
Type: image/png
Size: 67008 bytes
Desc: not available
URL: <http://lists.racket-lang.org/users/archive/attachments/20120225/c872adaf/attachment-0001.png>

Posted on the users mailing list.