[plt-scheme] A Square Canvas

Jens Axel Soegaard jensaxel at soegaard.net
Mon Jul 14 13:13:04 EDT 2008


Jens Axel Soegaard wrote:
> Robby Findler wrote:
>> Is the goal to have a stretchable canvas, but one that always stays
>> square? 
> Yes.
>> For that you'd need to make your own geometry manager, I'm
>> afraid. This is the relevant part of the docs:
>>
>> http://docs.plt-scheme.org/gui/windowing-overview.html#(part._new-containers) 
>>
>>   
> I'll take a look.

Here is a solution meant for the archives.

I have made an alternative to horizontal-panel%. The square-panel% 
behaves as a
horizon-panel% when respect to borders, margin, and vertical alignment.
The children all become quadratic. The stretchable children will be 
stretched
with the same magnification factor.

In my use case, where I needed a stretchable, quadratic canvas, all I 
need to do
is to place a single canvas as the only child of a square-panel%.

-- 
Jens Axel Søgaard

-------------- next part --------------
#lang scheme/gui

(require "square-panel.ss")

(let* ([frame (new frame% [label "Test of Square Canvas"])]
       [square-panel (new square-panel% [parent frame] [border 50] [spacing 20] 
                          [alignment '(left center)])])
  (define (build-canvas stretch? size-x size-y pen-color brush-color)
    (letrec ([pen   (make-object pen% pen-color 1 'solid)]
             [brush (make-object brush% brush-color 'solid)]
             [canvas (new canvas% 
                          [parent square-panel] [style '()]
                          [min-width size-x] [min-height size-y]
                          [stretchable-width stretch?] [stretchable-height stretch?]
                          [paint-callback (λ (b dc) 
                                            (let-values ([(w h) (send canvas get-size)])
                                              (let ([dc (send canvas get-dc)])
                                                (send dc set-pen pen)
                                                (send dc set-brush brush)
                                                (send dc draw-rectangle 0 0 w h)
                                                (send dc draw-line 0 0 w h)
                                                (send dc draw-line 0 h w 0))))])])
      canvas))
  (build-canvas #t 100 50  "red" "white")
  (build-canvas #f 200 100 "green" "black")
  (build-canvas #t 50  100 "white" "red")
  (build-canvas #f 150 100 "yellow" "green")
  (send frame show #t))


-------------- next part --------------
A non-text attachment was scrubbed...
Name: example.png
Type: image/png
Size: 11622 bytes
Desc: not available
Url : http://list.cs.brown.edu/pipermail/plt-scheme/attachments/20080714/dcf7263c/example.png
-------------- next part --------------
#lang scheme/gui

(provide square-panel%)

; Horizontal panel where all children are quadratic.
; All children are magnified with the same factor.
; That is, stretchability is ignored.
; And so is margins.

(define square-panel%
  (let ()
    (define-syntax with-info
      (syntax-rules ()
        [(with-info (w h hs vs) i body ...)
         (let ([w  (list-ref i 0)]
               [h  (list-ref i 1)]
               [hs (list-ref i 2)]
               [vs (list-ref i 3)])
           body ...)]))
    (class panel%
      (define/override (container-size infos)
        (let* ([c (foldl (λ (i a) 
                           (with-info (w h hs vs) i
                             (let ([m (max w h)])
                               (match a [(list aw ah) (list (+ aw m) (max ah m))]))))
                         '(0 0)
                         infos)]
               [b (send this border)]
               [s (send this spacing)]
               [n (length infos)])
          (match c 
            [(list w h) 
             (values (+ w (* 2 b) (* s (max 0 (- n 1))))
                     (+ h (* 2 b)))])))
      (define/override (place-children infos width height)
        ; place the children within an width x height area
        (let* ([border (send this border)]
               [spacing (send this spacing)]
               [n (length infos)]
               [width (- width (* 2 border) (* spacing (max 0 (- n 1))))]
               [height (- height (* 2 border))]
               [total-horiz  (foldl (λ (i a) (with-info (w h hs vs) i (+ a (max w h)))) 0 infos)]
               [total-stretchable-horiz 
                (foldl (λ (i a) (with-info (w h hs vs) i (if (and hs vs) (+ a (max w h)) a))) 0 infos)]
               [non-stretchable-horiz (- total-horiz total-stretchable-horiz)]
               [total-vert   (foldl (λ (i a) (with-info (w h hs vs) i (max a w h))) 0 infos)]
               [total-stretchable-vert   
                (foldl (λ (i a) (with-info (w h hs vs) i (if (and hs vs) (max a w h) a))) 0 infos)]
               [vert-factor  (/ height total-stretchable-vert)]
               [horiz-factor (/ (- width non-stretchable-horiz) total-stretchable-horiz)]
               [factor       (min vert-factor horiz-factor)]
               [b border]
               [s spacing])
          (let-values ([(horiz-alignment vert-alignment) (send this get-alignment)])
            (define (mag s) (inexact->exact (floor (* factor s))))
            (reverse 
             (first 
              (foldl (λ (i a)
                       (match a
                         [(list specs x)
                          (with-info (w h hs vs) i
                            (let* ([m (max w h)]
                                   [m (if (and hs vs) (mag m) m)]
                                   [y (case vert-alignment
                                        [(top)    b]
                                        [(center) (+ b (- (quotient height 2)
                                                          (quotient m 2)))]
                                        [(bottom) (+ b (- height m))]
                                        [else (error 'unknown-alignment)])])
                              (list (cons (list x y m m) specs)
                                    (+ x m s))))]))
                     (list '() b)
                     infos))))))
        (super-new))))


More information about the plt-scheme mailing list