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