Author: junrue Date: Sun Apr 30 02:08:25 2006 New Revision: 114
Added: trunk/src/uitoolkit/widgets/heap-layout.lisp Modified: trunk/docs/manual/api.texinfo trunk/graphic-forms-uitoolkit.asd trunk/src/packages.lisp trunk/src/uitoolkit/system/system-constants.lisp trunk/src/uitoolkit/widgets/flow-layout.lisp trunk/src/uitoolkit/widgets/layout-classes.lisp trunk/src/uitoolkit/widgets/layout-generics.lisp trunk/src/uitoolkit/widgets/layout.lisp trunk/src/uitoolkit/widgets/top-level.lisp trunk/src/uitoolkit/widgets/window.lisp Log: initial implementation of heap-layout, possible container cleanup issues needing investigation; also made some layout-related doc enhancements
Modified: trunk/docs/manual/api.texinfo ============================================================================== --- trunk/docs/manual/api.texinfo (original) +++ trunk/docs/manual/api.texinfo Sun Apr 30 02:08:25 2006 @@ -502,7 +502,7 @@ @end deffn @deffn Initarg :layout @end deffn -@deffn Accessor layout +@deffn Accessor layout-of @end deffn @end deftp
@@ -513,17 +513,59 @@ @strong{NOTE:} A future release will provide additional layout manager classes.
-@anchor{layout-manager} -@deftp Class layout-manager style -Subclasses implement layout strategies on behalf of window objects. +@anchor{flow-layout} +@deftp Class flow-layout spacing +This @ref{layout-manager} subclass arranges dialog or window children +in a row or column, with optional spacing (specified in pixels) +between children. +@deffn Initarg :style +This initarg accepts a list containing one of the following +style keywords: +@table @code +@item :horizontal +Specifies arrangement in a horizontal row. This style is the default. +@item :vertical +Specifies arrangement in a vertical column. +@item :wrap +This style keyword enables the arrangement of children to be +wrapped if the available horizontal (or vertical) space within +the container is less than the layout requests for a full +row (or column). The default behavior is unwrapped. +@end table +@end deffn @end deftp
-@anchor{flow-layout} -@deftp Class flow-layout spacing left-margin top-margin right-margin bottom-margin -This @ref{layout-manager} subclass arranges window children in a row -or column, with optional margins around the row/column and spacing in -between children. The layout can wrap the window children if desired -and the available horizontal (or vertical) space is constrained. +@anchor{heap-layout} +@deftp Class heap-layout top-child +This @ref{layout-manager} subclass resizes all children to the same +size and stacks them on top of each other. +@deffn Initarg :top-child +Use this initarg to specify the child widget that should be visible. +The corresponding accessor @code{top-child-of} can be set +subsequently, followed by calling @ref{layout} on the container, in +order to make a different child visible. +@end deffn +@end deftp + +@anchor{layout-manager} +@deftp Class layout-manager style left-margin top-margin right-margin bottom-margin +Subclasses implement layout strategies on behalf of window +objects. Every layout manager allows optional margins (specified in +pixels) within the perimeter of the container being managed.@*@* The +values accepted by the @code{:style} initarg vary depending on the +actual @code{layout-manager} subclass being used. +@deffn Initarg :horizontal-margins +This initarg accepts a horizontal margin value that is applied to both +the left and right sides of the container. +@end deffn +@deffn Initarg :margins +This initarg accepts a margin value that is applied to all sides of +the container. +@end deffn +@deffn Initarg :vertical-margins +This initarg accepts a vertical margin value that is applied to both +the top and bottom of the container. +@end deffn @end deftp
@@ -709,6 +751,7 @@ Return the zero-based index of the location of the other object in this object. @end deffn
+@anchor{layout} @deffn GenericFunction layout self Set the size and location of this object's children. @end deffn @@ -861,19 +904,42 @@ @node layout functions @section layout functions
-@deffn GenericFunction compute-layout layout window width-hint height-hint -Returns a list of conses @code{(window . rectangle)} describing the +These functions comprise the protocol for @ref{layout-manager}s. As +such, they are not normally called by application code, but instead +are the concern of layout-manager implementers. + +The @code{width-hint} and @code{height-hint} parameters are a +mechanism to express the @emph{what-if} scenario where the total width +or height of the container is fixed; the proper response is to +calculate the container's desired dimension on the opposite +axis. While this behavior is primarily the concern of child windows +and/or controls, layout manager implementations should look for +non-negative values for either @code{width-hint} or +@code{height-hint}, indicating that the container's size is +constrained. + +@anchor{compute-layout} +@deffn GenericFunction compute-layout layout container width-hint height-hint +Returns a list of conses @code{(child . rectangle)} describing the new bounds of each child window or control. A @ref{layout-manager} subclass implements this method based on its particular layout strategy, taking into account attributes set by the user. Certain Graphic-Forms functions -call this method to accomplish layout within a window. +call this method to accomplish layout within a container. @end deffn
-@deffn GenericFunction compute-size layout window width-hint height-hint -Computes and returns the new @ref{size} of the window's client area. A -@ref{layout-manager} subclass implements this method based on its -particular layout strategy, taking into account attributes set by the -user. The @ref{pack} function ultimately calls this method. +@deffn GenericFunction compute-size layout container width-hint height-hint +Computes and returns the new @ref{size} of the @code{container}'s +client area. A @ref{layout-manager} subclass implements this method +based on its particular layout strategy, taking into account +attributes set by the user. The @ref{pack} function ultimately calls +this method. +@end deffn + +@deffn GenericFunction perform layout container width-hint height-hint +Calls @ref{compute-layout} for @code{container} and then moves and +resizes @code{container}'s children. Layout subclasses may override +this method -- most derivations should call @sc{CALL-NEXT-METHOD} to +allow the base implementation to execute. @end deffn
Modified: trunk/graphic-forms-uitoolkit.asd ============================================================================== --- trunk/graphic-forms-uitoolkit.asd (original) +++ trunk/graphic-forms-uitoolkit.asd Sun Apr 30 02:08:25 2006 @@ -112,4 +112,5 @@ (:file "dialog") (:file "file-dialog") (:file "layout") + (:file "heap-layout") (:file "flow-layout")))))))))
Modified: trunk/src/packages.lisp ============================================================================== --- trunk/src/packages.lisp (original) +++ trunk/src/packages.lisp Sun Apr 30 02:08:25 2006 @@ -222,6 +222,7 @@ #:event-source #:file-dialog #:flow-layout + #:heap-layout #:item #:layout-manager #:menu @@ -463,6 +464,7 @@ #:text-limit #:thumb-size #:tooltip-text + #:top-child-of #:top-index #:top-margin-of #:traverse
Modified: trunk/src/uitoolkit/system/system-constants.lisp ============================================================================== --- trunk/src/uitoolkit/system/system-constants.lisp (original) +++ trunk/src/uitoolkit/system/system-constants.lisp Sun Apr 30 02:08:25 2006 @@ -33,6 +33,14 @@
(in-package :graphic-forms.uitoolkit.system)
+;;; +;;; The following variables are used with set-window-pos +;;; +(defvar *hwnd-top* (cffi:null-pointer)) +(defvar *hwnd-bottom* (cffi:make-pointer #x00000001)) +(defvar *hwnd-topmost* (cffi:make-pointer #xFFFFFFFF)) +(defvar *hwnd-notopmost* (cffi:make-pointer #xFFFFFFFE)) + (defconstant +button-classname+ "button") (defconstant +static-classname+ "static")
Modified: trunk/src/uitoolkit/widgets/flow-layout.lisp ============================================================================== --- trunk/src/uitoolkit/widgets/flow-layout.lisp (original) +++ trunk/src/uitoolkit/widgets/flow-layout.lisp Sun Apr 30 02:08:25 2006 @@ -134,22 +134,6 @@ #+gf-debug-widgets (format t "compute-layout: ~a~%~a~%" win kids) (flow-container-layout layout (visible-p win) kids width-hint height-hint)))
-(defmethod initialize-instance :after ((layout flow-layout) - &key style margins horz-margins vert-margins - &allow-other-keys) - (unless (listp style) - (setf style (list style))) - (if (and (null (find :horizontal style)) (null (find :vertical style))) - (push :horizontal style)) - (setf (style-of layout) style) - (unless (null margins) - (setf (left-margin-of layout) margins) - (setf (right-margin-of layout) margins) - (setf (top-margin-of layout) margins) - (setf (bottom-margin-of layout) margins)) - (unless (null horz-margins) - (setf (left-margin-of layout) horz-margins) - (setf (right-margin-of layout) horz-margins)) - (unless (null vert-margins) - (setf (top-margin-of layout) vert-margins) - (setf (bottom-margin-of layout) vert-margins))) +(defmethod initialize-instance :after ((layout flow-layout) &key) + (unless (intersection (style-of layout) '(:horizontal :vertical)) + (setf (style-of layout) (list :horizontal))))
Added: trunk/src/uitoolkit/widgets/heap-layout.lisp ============================================================================== --- (empty file) +++ trunk/src/uitoolkit/widgets/heap-layout.lisp Sun Apr 30 02:08:25 2006 @@ -0,0 +1,104 @@ +;;;; +;;;; heap-layout.lisp +;;;; +;;;; Copyright (C) 2006, Jack D. Unrue +;;;; All rights reserved. +;;;; +;;;; Redistribution and use in source and binary forms, with or without +;;;; modification, are permitted provided that the following conditions +;;;; are met: +;;;; +;;;; 1. Redistributions of source code must retain the above copyright +;;;; notice, this list of conditions and the following disclaimer. +;;;; +;;;; 2. Redistributions in binary form must reproduce the above copyright +;;;; notice, this list of conditions and the following disclaimer in the +;;;; documentation and/or other materials provided with the distribution. +;;;; +;;;; 3. Neither the names of the authors nor the names of its contributors +;;;; may be used to endorse or promote products derived from this software +;;;; without specific prior written permission. +;;;; +;;;; THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS "AS IS" AND ANY +;;;; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +;;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DIS- +;;;; CLAIMED. IN NO EVENT SHALL THE AUTHORS AND CONTRIBUTORS BE LIABLE FOR ANY +;;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +;;;; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +;;;; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +;;;; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +;;;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +;;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;; + +(in-package :graphic-forms.uitoolkit.widgets) + +;;; +;;; methods +;;; + +(defmethod compute-size ((self heap-layout) win width-hint height-hint) + (let ((size (gfs:make-size))) + (with-children (win kids) + (loop for kid in kids + do (let ((kid-size (preferred-size kid width-hint height-hint))) + (setf (gfs:size-width size) (max (gfs:size-width size) + (gfs:size-width kid-size)) + (gfs:size-height size) (max (gfs:size-height size) + (gfs:size-height kid-size)))))) + (incf (gfs:size-width size) (+ (left-margin-of self) (right-margin-of self))) + (incf (gfs:size-height size) (+ (top-margin-of self) (bottom-margin-of self))) + size)) + +(defmethod compute-layout ((self heap-layout) win width-hint height-hint) + (let* ((size (client-size win)) + (horz-margin (+ (left-margin-of self) (right-margin-of self))) + (vert-margin (+ (top-margin-of self) (bottom-margin-of self))) + (new-size (gfs:make-size :width (- (if (> width-hint horz-margin) + width-hint + (gfs:size-width size)) + horz-margin) + :height (- (if (> height-hint vert-margin) + height-hint + (gfs:size-height size)) + vert-margin))) + (new-pnt (gfs:make-point :x (left-margin-of self) :y (top-margin-of self))) + (bounds (make-instance 'gfs:rectangle :size new-size :location new-pnt))) + (with-children (win kids) + (loop for kid in kids collect (cons kid bounds))))) + +(defmethod perform ((self heap-layout) win width-hint height-hint) + (let ((kids nil) + (hdwp (cffi:null-pointer)) + (top (top-child-of self))) + (when (layout-p win) + (setf kids (compute-layout self win width-hint height-hint)) + (setf hdwp (gfs::begin-defer-window-pos (length kids))) + (loop for k in kids + do (let* ((rect (cdr k)) + (sz (gfs:size rect)) + (pnt (gfs:location rect)) + (kid-win (car k)) + (hwnd-after (cffi:null-pointer)) + (flags (logior +window-pos-flags+ gfs::+swp-hidewindow+))) + (when (cffi:pointer-eq (gfs:handle kid-win) (gfs:handle top)) + (setf hwnd-after gfs::*hwnd-top* + flags (logior +window-pos-flags+ gfs::+swp-showwindow+))) + (if (gfs:null-handle-p hdwp) + (gfs::set-window-pos (gfs:handle kid-win) + hwnd-after + (gfs:point-x pnt) + (gfs:point-y pnt) + (gfs:size-width sz) + (gfs:size-height sz) + flags) + (setf hdwp (gfs::defer-window-pos hdwp + (gfs:handle kid-win) + hwnd-after + (gfs:point-x pnt) + (gfs:point-y pnt) + (gfs:size-width sz) + (gfs:size-height sz) + flags))))) + (unless (gfs:null-handle-p hdwp) + (gfs::end-defer-window-pos hdwp)))))
Modified: trunk/src/uitoolkit/widgets/layout-classes.lisp ============================================================================== --- trunk/src/uitoolkit/widgets/layout-classes.lisp (original) +++ trunk/src/uitoolkit/widgets/layout-classes.lisp Sun Apr 30 02:08:25 2006 @@ -37,14 +37,7 @@ ((style :accessor style-of :initarg :style - :initform nil)) - (:documentation "Subclasses implement layout strategies on behalf of window objects.")) - -(defclass flow-layout (layout-manager) - ((spacing - :accessor spacing-of - :initarg :spacing - :initform 0) + :initform nil) (left-margin :accessor left-margin-of :initarg :left-margin @@ -61,4 +54,18 @@ :accessor bottom-margin-of :initarg :bottom-margin :initform 0)) + (:documentation "Subclasses implement layout strategies on behalf of window objects.")) + +(defclass flow-layout (layout-manager) + ((spacing + :accessor spacing-of + :initarg :spacing + :initform 0)) (:documentation "Window children are arranged in a row or column.")) + +(defclass heap-layout (layout-manager) + ((top-child + :accessor top-child-of + :initarg :top-child + :initform nil)) + (:documentation "Window children are stacked one on top of the other."))
Modified: trunk/src/uitoolkit/widgets/layout-generics.lisp ============================================================================== --- trunk/src/uitoolkit/widgets/layout-generics.lisp (original) +++ trunk/src/uitoolkit/widgets/layout-generics.lisp Sun Apr 30 02:08:25 2006 @@ -38,3 +38,6 @@
(defgeneric compute-layout (layout win width-hint height-hint) (:documentation "Returns a list of conses (window . rectangle) describing the new bounds of each child window.")) + +(defgeneric perform (layout window widget-hint height-hint) + (:documentation "Moves and resizes window children based on layout strategy."))
Modified: trunk/src/uitoolkit/widgets/layout.lisp ============================================================================== --- trunk/src/uitoolkit/widgets/layout.lisp (original) +++ trunk/src/uitoolkit/widgets/layout.lisp Sun Apr 30 02:08:25 2006 @@ -38,12 +38,31 @@ gfs::+swp-noactivate+ gfs::+swp-nocopybits+))
-(defun perform-layout (win width-hint height-hint) +;;; +;;; methods +;;; + +(defmethod initialize-instance :after ((layout layout-manager) + &key style margins horizontal-margins vertical-margins + &allow-other-keys) + (setf (style-of layout) (if (listp style) style (list style))) + (unless (null margins) + (setf (left-margin-of layout) margins) + (setf (right-margin-of layout) margins) + (setf (top-margin-of layout) margins) + (setf (bottom-margin-of layout) margins)) + (unless (null horizontal-margins) + (setf (left-margin-of layout) horizontal-margins) + (setf (right-margin-of layout) horizontal-margins)) + (unless (null vertical-margins) + (setf (top-margin-of layout) vertical-margins) + (setf (bottom-margin-of layout) vertical-margins))) + +(defmethod perform ((layout layout-manager) win width-hint height-hint) "Calls compute-layout for a window and then handles the actual moving and resizing of its children." - (let ((layout (layout-of win)) - (kids nil) - (hdwp nil)) - (when (and (layout-p win) layout) + (let ((kids nil) + (hdwp (cffi:null-pointer))) + (when (layout-p win) (setf kids (compute-layout layout win width-hint height-hint)) (setf hdwp (gfs::begin-defer-window-pos (length kids))) (loop for k in kids
Modified: trunk/src/uitoolkit/widgets/top-level.lisp ============================================================================== --- trunk/src/uitoolkit/widgets/top-level.lisp (original) +++ trunk/src/uitoolkit/widgets/top-level.lisp Sun Apr 30 02:08:25 2006 @@ -156,10 +156,10 @@ m)))
(defmethod (setf maximum-size) :after (max-size (win top-level)) - (unless (gfs:disposed-p win) + (unless (or (gfs:disposed-p win) (null (layout-of win))) (let ((size (constrain-new-size max-size (size win) #'min))) (setf (size win) size) - (perform-layout win (gfs:size-width size) (gfs:size-height size))))) + (perform (layout-of win) win (gfs:size-width size) (gfs:size-height size)))))
(defmethod (setf menu-bar) :before ((m menu) (win top-level)) (declare (ignore m)) @@ -178,10 +178,10 @@ (gfs::draw-menu-bar hwnd)))
(defmethod (setf minimum-size) :after (min-size (win top-level)) - (unless (gfs:disposed-p win) + (unless (or (gfs:disposed-p win) (null (layout-of win))) (let ((size (constrain-new-size min-size (size win) #'max))) (setf (size win) size) - (perform-layout win (gfs:size-width size) (gfs:size-height size))))) + (perform (layout-of win) win (gfs:size-width size) (gfs:size-height size)))))
(defmethod print-object ((self top-level) stream) (print-unreadable-object (self stream :type t)
Modified: trunk/src/uitoolkit/widgets/window.lisp ============================================================================== --- trunk/src/uitoolkit/widgets/window.lisp (original) +++ trunk/src/uitoolkit/widgets/window.lisp Sun Apr 30 02:08:25 2006 @@ -174,14 +174,15 @@
(defmethod enable-layout ((win window) flag) (setf (slot-value win 'layout-p) flag) - (if flag + (if (and flag (layout-of win)) (let ((sz (client-size win))) - (perform-layout win (gfs:size-width sz) (gfs:size-height sz))))) + (perform (layout-of win) win (gfs:size-width sz) (gfs:size-height sz)))))
(defmethod event-resize ((d event-dispatcher) (win window) time size type) (declare (ignorable d time size type)) - (let ((sz (client-size win))) - (perform-layout win (gfs:size-width sz) (gfs:size-height sz)))) + (unless (null (layout-of win)) + (let ((sz (client-size win))) + (perform (layout-of win) win (gfs:size-width sz) (gfs:size-height sz)))))
(defmethod focus-p :before ((win window)) (if (gfs:disposed-p win) @@ -207,11 +208,13 @@ pnt))
(defmethod layout ((win window)) - (let ((sz (client-size win))) - (perform-layout win (gfs:size-width sz) (gfs:size-height sz)))) + (unless (null (layout-of win)) + (let ((sz (client-size win))) + (perform (layout-of win) win (gfs:size-width sz) (gfs:size-height sz)))))
(defmethod pack ((win window)) - (perform-layout win -1 -1) + (unless (null (layout-of win)) + (perform (layout-of win) win -1 -1)) (call-next-method))
(defmethod preferred-size ((win window) width-hint height-hint)