;;;; ;;;; M u l t i p a n e d . s t k ;;;; ;;;; Rewritten version of Paned.stk to allow an arbitrary number of panes. ;;;; Modified by Harvey J. Stein ;;;; Modified again by Erick Gallesio for allowing horizontal and vertical ;;;; placement ;;;; ;;;; Copyright © 1993-1999 Erick Gallesio - I3S-CNRS/ESSI ;;;; ;;;; Permission to use, copy, modify, distribute,and license this ;;;; software and its documentation for any purpose is hereby granted, ;;;; provided that existing copyright notices are retained in all ;;;; copies and that this notice is included verbatim in any ;;;; distributions. No written agreement, license, or royalty fee is ;;;; required for any of the authorized uses. ;;;; This software is provided ``AS IS'' without express or implied ;;;; warranty. ;;;; ;;;; Idea of this implementation was found in comp.lang.tcl. ;;;; Original author seems to be James Noble and the version from which this ;;;; stuff is derivated is Jay Schmidgall (shmdgljd@ghostwind.rchland.ibm.com). (require "Frame") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; ;;;; class definition ;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (define-class () (;; Public slots (frames :accessor frames-of) (grips :accessor grips-of) (ghost :accessor ghost-of) (panes :accessor panes-of :init-keyword :panes) (width :accessor width :init-keyword :width :allocation :propagated :propagate-to (frame)) (height :accessor height :init-keyword :height :allocation :propagated :propagate-to (frame)) ;; Virtual slot (orientation :accessor orientation :allocation :virtual :slot-ref (lambda (o) (extend-environment (environment o) (if vertical? "vertical" "horizontal"))) :slot-set! (lambda (o v) (extend-environment (environment o) (set! vertical? (equal? v "vertical")) (place-grips o)))) ;; Private slots (environment :accessor environment) (fractions :accessor fractions-of) (grip-number :accessor grip-number-of) (drag-start :accessor drag-start-of))) (define-method initialize-composite-widget ((self ) initargs frame) (let* ((panes (get-keyword :panes initargs 2)) (vertical? (equal? "vertical" (get-keyword :orientation initargs "vertical"))) (fractions (make-vector panes)) (frames (make-vector panes)) (grips (make-vector (- panes 1))) (ghost (make :parent frame :border-width 2 :relief "ridge"))) ;; Build the "container" frames (dotimes (i panes) (vector-set! fractions i (/ (+ i 1) panes)) (vector-set! frames i (make :parent frame :border-width 2 :relief "raised"))) ;; Build grips (dotimes (i (- panes 1)) (let ((G (make :parent frame :width 10 :height 10 :border-width 2 :relief "raised" :cursor "crosshair"))) (vector-set! grips i G) ;; Associate bindings to the newly created grip (bind G "" (lambda (|W| x y) (start-grip self x y |W|))) (bind G "" (lambda (x y) (motion-grip self x y))) (bind G "" (lambda (x y) (stop-grip self x y))))) ;; Initialize slots (slot-set! self 'environment (the-environment)) (slot-set! self 'panes panes) (slot-set! self 'frames frames) (slot-set! self 'grips grips) (slot-set! self 'fractions fractions) (slot-set! self 'ghost ghost) (slot-set! self 'Id (Id frame)) ;; Place grips (place-grips self))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; methods ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (define-method place-grips ((self )) (extend-environment (environment self) (let ((f 0) (fp 0)) ;; Place frames and grips (dotimes (i (- panes 1)) (set! f (vector-ref fractions i)) (if vertical? (begin (place (vector-ref grips i) :rely 0.95 :relx f :anchor "center") (place (vector-ref frames i) :y 0 :relh 1 :relx fp :relw (- f fp))) (begin (place (vector-ref grips i) :relx 0.95 :rely f :anchor "center") (place (vector-ref frames i) :x 0 :relw 1 :rely fp :relh (- f fp)))) (raise (vector-ref grips i)) (set! fp f)) ;; Last frame (if vertical? (place (vector-ref frames (- panes 1)) :y 0 :relx f :relheight 1 :relwidth (- 1.0 f)) (place (vector-ref frames (- panes 1)) :x 0 :rely f :relwidth 1 :relheight (- 1.0 f)))))) ;;; ;;; Methods for moving grips ;;; (define-method find-grip ((self ) w) (do ((i 0 (+ 1 i))) ((eq? w (slot-ref (vector-ref (grips-of self) i) 'id)) i))) (define-method start-grip ((self ) x y w) (extend-environment (environment self) (let* ((grip (find-grip self w)) (ghost (ghost-of self)) (fracts (fractions-of self)) (fr (vector-ref fracts grip))) (slot-set! self 'grip-number grip) (slot-set! self 'drag-start (cons x y)) ;; Raise ghost (place 'forget ghost) ; otherwise old constaints seems to stay valid (if vertical? (place ghost :rely 0 :relx fr :anchor "n" :relh 1) (place ghost :relx 0 :rely fr :anchor "w" :relw 1)) (raise ghost) ;; Raise current grip (raise (vector-ref (grips-of self) grip))))) (define-method motion-grip ((self ) x y) (extend-environment (environment self) (let ((fraction (fractions-of self)) (gn (grip-number-of self)) (ghost (ghost-of self))) (if vertical? (begin (vector-set! fraction gn (max 0.0001 (min .9999 (+ (vector-ref fraction gn) (/ (- x (car (drag-start-of self))) (+ 1 (winfo 'width (frame-of self)))))))) (place ghost :rely 0 :relheight 1 :relx (vector-ref fraction gn) :anchor "n") (place (vector-ref (grips-of self) gn) :rely 0.95 :relx (vector-ref fraction gn) :anchor "center")) (begin (vector-set! fraction gn (max 0.0001 (min .9999 (+ (vector-ref fraction gn) (/ (- y (cdr (drag-start-of self))) (+ 1 (winfo 'height (frame-of self)))))))) (place ghost :relx 0 :relwidth 1 :rely (vector-ref fraction gn) :anchor "w") (place (vector-ref (grips-of self) gn) :relx 0.95 :rely (vector-ref fraction gn) :anchor "center")))))) (define-method stop-grip ((self ) x y) (let* ((gn (grip-number-of self)) (fractions (fractions-of self)) (cp (vector-ref fractions gn))) (dotimes (i (- (panes-of self) 1)) (cond ((and (< i gn) (> (vector-ref fractions i) cp)) (vector-set! fractions i cp)) ((and (> i gn) (< (vector-ref fractions i) cp)) (vector-set! fractions i cp))))) (lower (ghost-of self)) (place-grips self)) (provide "Multipaned") ;;; ;;; Example of usage ;;; ;;; (define p (make ;;; :panes 4 ;;; :width 400 :height 400 ;;; :orientation "horizontal")) ;;; ;;; (define l0 (make