Author: junrue
Date: Sat May 13 19:57:06 2006
New Revision: 130
Modified:
trunk/docs/manual/api.texinfo
trunk/src/packages.lisp
trunk/src/tests/uitoolkit/windlg.lisp
trunk/src/uitoolkit/system/system-constants.lisp
trunk/src/uitoolkit/system/user32.lisp
trunk/src/uitoolkit/widgets/button.lisp
trunk/src/uitoolkit/widgets/dialog.lisp
trunk/src/uitoolkit/widgets/event.lisp
trunk/src/uitoolkit/widgets/label.lisp
trunk/src/uitoolkit/widgets/panel.lisp
trunk/src/uitoolkit/widgets/widget-classes.lisp
trunk/src/uitoolkit/widgets/widget-generics.lisp
trunk/src/uitoolkit/widgets/widget-utils.lisp
trunk/src/uitoolkit/widgets/window.lisp
Log:
progress towards proper keyboard traversal in dialogs
Modified: trunk/docs/manual/api.texinfo
==============================================================================
--- trunk/docs/manual/api.texinfo (original)
+++ trunk/docs/manual/api.texinfo Sat May 13 19:57:06 2006
@@ -276,7 +276,7 @@
@anchor{file-dialog}
@deftp Class file-dialog open-mode
-This class provides a standard @ref{dialog} for navigating the file
+This class provides a standard dialog for navigating the file
system to select or enter file names. A variety of configurations are
possible; however, please note that the following behaviors are
implemented regardless of other style flags or initarg values:
@@ -290,9 +290,14 @@
steps manually, in which case the @ref{file-dialog-paths} function can
be used to obtain the user's selection(s). Unless the
@code{:multiple-select} style keyword is specified, there will at most
-be one selected file returned, and possibly zero if the user cancelled
-the dialog. Also, manual construction of an instance must be followed
-by an explicit call to @ref{dispose}.@*@*
+be one selected file returned. In either case, zero is returned if the
+user cancelled the dialog. Also, manual construction of an instance
+must be followed by an explicit call to @ref{dispose}.@*@*
+Like other system dialogs, @code{file-dialog} is derived from @ref{widget}
+rather than @ref{dialog} since the majority of its functionality is
+implemented by the system and is not directly extensible by applications.
+@strong{NOTE:} A future release of Graphic-Forms will provide a
+customization mechanism.@*@*
@deffn Initarg :default-extension
Specifies a default extension to be appended to a file name if
the user fails to provide one. Any embedded periods @samp{.} will
@@ -783,11 +788,12 @@
enclose the specified desired client area and this object's trim.
@end deffn
-@deffn GenericFunction default-button self button
-Returns the default @ref{button} set for a @ref{dialog}, or @sc{nil}
-if none has been set. If @code{button} is @sc{nil}, then no default
-button is set. The default button is the button that is selected when
-@code{self} is active and the user presses @sc{enter}.
+@deffn GenericFunction default-widget self
+Returns the default @ref{widget} set for a @ref{dialog}, or @sc{nil}
+if none has been set. If @sc{nil} is passed to the corresponding
+@sc{setf} function, then no default widget is set. The default widget
+is the one that is selected when @code{self} is active and the user
+presses @sc{enter}.
@end deffn
@deffn GenericFunction display-to-object self pnt
Modified: trunk/src/packages.lisp
==============================================================================
--- trunk/src/packages.lisp (original)
+++ trunk/src/packages.lisp Sat May 13 19:57:06 2006
@@ -341,8 +341,8 @@
#:current-font
#:cursor
#:cut
- #:default-item
#:default-message-filter
+ #:default-widget
#:defmenu
#:delay-of
#:disabled-image
Modified: trunk/src/tests/uitoolkit/windlg.lisp
==============================================================================
--- trunk/src/tests/uitoolkit/windlg.lisp (original)
+++ trunk/src/tests/uitoolkit/windlg.lisp Sat May 13 19:57:06 2006
@@ -164,6 +164,7 @@
:parent dlg))
(ok-btn (make-instance 'gfw:button
:callback #'btn-callback
+ :style '(:default-button)
:text "OK"
:parent btn-panel))
(cancel-btn (make-instance 'gfw:button
Modified: trunk/src/uitoolkit/system/system-constants.lisp
==============================================================================
--- trunk/src/uitoolkit/system/system-constants.lisp (original)
+++ trunk/src/uitoolkit/system/system-constants.lisp Sat May 13 19:57:06 2006
@@ -72,6 +72,15 @@
(defconstant +blt-captureblt+ #x40000000)
(defconstant +blt-nomirrorbitmap+ #x80000000)
+(defconstant +bm-getcheck+ #x00f0)
+(defconstant +bm-setcheck+ #x00f1)
+(defconstant +bm-getstate+ #x00f2)
+(defconstant +bm-setstate+ #x00f3)
+(defconstant +bm-setstyle+ #x00f4)
+(defconstant +bm-click+ #x00f5)
+(defconstant +bm-getimage+ #x00f6)
+(defconstant +bm-setimage+ #x00f7)
+
(defconstant +bs-solid+ 0)
(defconstant +bs-null+ 1)
(defconstant +bs-hollow+ 1)
@@ -113,6 +122,12 @@
(defconstant +bs-flat+ #x00008000)
(defconstant +bs-rightbutton+ #x00000020)
+(defconstant +bst-unchecked+ #x0000)
+(defconstant +bst-checked+ #x0001)
+(defconstant +bst-indeterminate+ #x0002)
+(defconstant +bst-pushed+ #x0004)
+(defconstant +bst-focus+ #x0008)
+
(defconstant +cbm-init+ #x04)
(defconstant +cchdevicename+ 32)
@@ -194,6 +209,10 @@
(defconstant +dib-rgb-colors+ 0)
(defconstant +dib-pal-colors+ 1)
+(defconstant +dm-getdefid+ #x0400)
+(defconstant +dm-setdefid+ #x0401)
+(defconstant +dm-reposition+ #x0402)
+
(defconstant +dt-top+ #x00000000)
(defconstant +dt-left+ #x00000000)
(defconstant +dt-center+ #x00000001)
@@ -292,6 +311,19 @@
(defconstant +hs-cross+ 4)
(defconstant +hs-diagcross+ 5)
+(defconstant +idok+ 1)
+(defconstant +idcancel+ 2)
+(defconstant +idabort+ 3)
+(defconstant +idretry+ 4)
+(defconstant +idignore+ 5)
+(defconstant +idyes+ 6)
+(defconstant +idno+ 7)
+(defconstant +idclose+ 8)
+(defconstant +idhelp+ 9)
+(defconstant +idtryagain+ 10)
+(defconstant +idcontinue+ 11)
+(defconstant +idtimeout+ 32000)
+
(defconstant +image-bitmap+ 0)
(defconstant +image-icon+ 1)
(defconstant +image-cursor+ 2)
@@ -766,6 +798,15 @@
(defconstant +wm-paint+ #x000F)
(defconstant +wm-close+ #x0010)
(defconstant +wm-getminmaxinfo+ #x0024)
+(defconstant +wm-painticon+ #x0026)
+(defconstant +wm-iconerasebkgnd+ #x0027)
+(defconstant +wm-nextdlgctl+ #x0028)
+(defconstant +wm-spoolerstatus+ #x002A)
+(defconstant +wm-drawitem+ #x002B)
+(defconstant +wm-measureitem+ #x002C)
+(defconstant +wm-deleteitem+ #x002D)
+(defconstant +wm-vkeytoitem+ #x002E)
+(defconstant +wm-chartoitem+ #x002F)
(defconstant +wm-setfont+ #x0030)
(defconstant +wm-getfont+ #x0031)
(defconstant +wm-ncmousemove+ #x00A0)
@@ -848,8 +889,10 @@
(defconstant +ws-hscroll+ #x00100000)
(defconstant +ws-sysmenu+ #x00080000)
(defconstant +ws-thickframe+ #x00040000)
+(defconstant +ws-group+ #x00020000)
(defconstant +ws-minimizebox+ #x00020000)
(defconstant +ws-maximizebox+ #x00010000)
+(defconstant +ws-tabstop+ #x00010000)
(defconstant +ws-popupwindow+ #x80880000)
(defconstant +ws-overlappedwindow+ #x00CF0000)
Modified: trunk/src/uitoolkit/system/user32.lisp
==============================================================================
--- trunk/src/uitoolkit/system/user32.lisp (original)
+++ trunk/src/uitoolkit/system/user32.lisp Sat May 13 19:57:06 2006
@@ -108,6 +108,14 @@
(flags UINT))
(defcfun
+ ("DefDlgProcA" def-dlg-proc)
+ LRESULT
+ (hwnd HANDLE)
+ (msg UINT)
+ (wp WPARAM)
+ (lp LPARAM))
+
+(defcfun
("DefWindowProcA" def-window-proc)
LRESULT
(hwnd HANDLE)
@@ -367,6 +375,13 @@
(monitor-info LPTR))
(defcfun
+ ("GetNextDlgTabItem" get-next-dlg-tab-item)
+ HANDLE
+ (hdlg HANDLE)
+ (hctl HANDLE)
+ (flag BOOL))
+
+(defcfun
("GetParent" get-parent)
HANDLE
(hwnd HANDLE))
Modified: trunk/src/uitoolkit/widgets/button.lisp
==============================================================================
--- trunk/src/uitoolkit/widgets/button.lisp (original)
+++ trunk/src/uitoolkit/widgets/button.lisp Sat May 13 19:57:06 2006
@@ -39,7 +39,8 @@
(defmethod compute-style-flags ((btn button) &rest extra-data)
(declare (ignore extra-data))
- (let ((std-flags (logior gfs::+ws-child+ gfs::+ws-visible+)))
+ (let ((std-flags (logior gfs::+ws-child+ gfs::+ws-visible+))
+ (style (style-of btn)))
(loop for sym in (style-of btn)
do (cond
;; primary button styles
@@ -54,6 +55,8 @@
(setf std-flags (logior std-flags gfs::+bs-radiobutton+)))
((eq sym :toggle-button)
(setf std-flags (logior std-flags gfs::+bs-pushbox+)))))
+ (if (null style)
+ (logior std-flags gfs::+bs-pushbutton+))
(values std-flags 0)))
(defmethod initialize-instance :after ((btn button) &key parent text &allow-other-keys)
@@ -63,9 +66,12 @@
(or text " ")
(gfs:handle parent)
std-style
- ex-style)))
+ ex-style
+ (increment-widget-id (thread-context)))))
(if (not hwnd)
(error 'gfs:win32-error :detail "create-window failed"))
+ (unless (zerop (logand std-style gfs::+bs-defpushbutton+))
+ (gfs::send-message (gfs:handle parent) gfs::+dm-setdefid+ (cffi:pointer-address hwnd) 0))
(setf (slot-value btn 'gfs:handle) hwnd)))
(init-control btn))
Modified: trunk/src/uitoolkit/widgets/dialog.lisp
==============================================================================
--- trunk/src/uitoolkit/widgets/dialog.lisp (original)
+++ trunk/src/uitoolkit/widgets/dialog.lisp Sat May 13 19:57:06 2006
@@ -34,6 +34,7 @@
(in-package :graphic-forms.uitoolkit.widgets)
(defconstant +default-dialog-title+ " ")
+(defconstant +dlgwindowextra+ 48)
;;;
;;; helper functions
@@ -45,7 +46,8 @@
(logior gfs::+cs-dblclks+
gfs::+cs-savebits+
gfs::+cs-bytealignwindow+)
- gfs::+color-btnface+))
+ gfs::+color-btnface+
+ +dlgwindowextra+))
;;;
;;; methods
@@ -63,7 +65,45 @@
(declare (ignore time))
(show dlg nil))
-(defmethod initialize-instance :after ((dlg dialog) &key owner text &allow-other-keys)
+(defmethod default-widget :before ((self dialog))
+ (if (gfs:disposed-p self)
+ (error 'gfs:disposed-error)))
+
+(defmethod default-widget ((self dialog))
+ (let ((def-widget nil))
+ (visit-child-widgets self (lambda (parent kid)
+ (declare (ignore parent))
+ (if (= (gfs::get-window-long (gfs:handle kid) gfs::+gwlp-id+)
+ gfs::+idok+)
+ (setf def-widget kid))))
+ def-widget))
+
+(defmethod (setf default-widget) :before ((def-widget widget) (self dialog))
+ (if (or (gfs:disposed-p self) (gfs:disposed-p def-widget))
+ (error 'gfs:disposed-error)))
+
+(defmethod (setf default-widget) ((def-widget widget) (self dialog))
+ (when (or (not (typep def-widget 'button))
+ (and (style-of def-widget)
+ (null (find :push-button (style-of def-widget)))))
+ (warn 'gfs:toolkit-warning :detail "only push buttons may serve as default widgets in a dialog")
+ (return-from default-widget nil))
+ (let ((old-def-widget (default-widget self)))
+ (if old-def-widget
+ (let* ((hwnd (gfs:handle old-def-widget))
+ (style (gfs::get-window-long hwnd gfs::+gwl-style+)))
+ (setf style (logand style (lognot gfs::+bs-defpushbutton+)))
+ (gfs::send-message (gfs:handle self) gfs::+dm-setdefid+ 0 0)
+ (gfs::send-message hwnd gfs::+bm-setstyle+ style 1))))
+ (let* ((hdlg (gfs:handle self))
+ (hwnd (gfs:handle def-widget))
+ (style (gfs::get-window-long hwnd gfs::+gwl-style+)))
+ (setf style (logior style gfs::+bs-defpushbutton+))
+ (gfs::send-message hdlg gfs::+dm-setdefid+ (cffi:pointer-address hwnd) 0)
+ (gfs::send-message hdlg gfs::+wm-nextdlgctl+ (cffi:pointer-address hwnd) 1)
+ (gfs::send-message hwnd gfs::+bm-setstyle+ style 1)))
+
+(defmethod initialize-instance :after ((self dialog) &key owner text &allow-other-keys)
(unless (null owner)
(if (gfs:disposed-p owner)
(error 'gfs:disposed-error)))
@@ -75,14 +115,19 @@
;;
(if (cffi:pointer-eq (gfs:handle owner) (gfs::get-desktop-window))
(setf owner nil))
- (init-window dlg +dialog-classname+ #'register-dialog-class owner text))
+ ;; FIXME: check if owner is actually a top-level or dialog, and if not,
+ ;; walk up the ancestors until one is found. Only top level hwnds can
+ ;; be owners.
+ ;;
+ (init-window self +dialog-classname+ #'register-dialog-class owner text))
-(defmethod show ((dlg dialog) flag)
- (let ((hutility (utility-hwnd (thread-context)))
- (app-modal (find :application-modal (style-of dlg)))
- (owner-modal (find :owner-modal (style-of dlg)))
- (owner (owner dlg))
- (hdlg (gfs:handle dlg)))
+(defmethod show ((self dialog) flag)
+ (let* ((tc (thread-context))
+ (hutility (utility-hwnd tc))
+ (app-modal (find :application-modal (style-of self)))
+ (owner-modal (find :owner-modal (style-of self)))
+ (owner (owner self))
+ (hdlg (gfs:handle self)))
(cond
((and app-modal owner)
;; FIXME: need to save and restore each window's prior
@@ -98,7 +143,7 @@
(when (and flag (or app-modal owner-modal))
(message-loop (lambda (gm-code msg-ptr)
(cond
- ((or (gfs:disposed-p dlg) (not (visible-p dlg)))
+ ((or (gfs:disposed-p self) (not (visible-p self)))
t) ; dialog closed, so exit loop
((zerop gm-code)
;; IMPORTANT: allow WM_QUIT to propagate back through
@@ -114,7 +159,7 @@
((= gm-code -1)
(warn 'gfs:win32-warning :detail "get-message failed")
t)
- ((/= (gfs::is-dialog-message (gfs:handle dlg) msg-ptr) 0)
+ ((/= (gfs::is-dialog-message (gfs:handle self) msg-ptr) 0)
;; It was a dialog message and has been processed,
;; so nothing else to do.
;;
Modified: trunk/src/uitoolkit/widgets/event.lisp
==============================================================================
--- trunk/src/uitoolkit/widgets/event.lisp (original)
+++ trunk/src/uitoolkit/widgets/event.lisp Sat May 13 19:57:06 2006
@@ -123,6 +123,9 @@
;;;
(defmethod process-message (hwnd msg wparam lparam)
+ (let ((w (get-widget (thread-context) hwnd)))
+ (if (typep w 'dialog)
+ (return-from process-message (gfs::def-dlg-proc hwnd msg wparam lparam))))
(gfs::def-window-proc hwnd msg wparam lparam))
(defmethod process-message (hwnd (msg (eql gfs::+wm-close+)) wparam lparam)
@@ -139,7 +142,6 @@
(wparam-hi (hi-word wparam))
(wparam-lo (lo-word wparam))
(owner (get-widget tc hwnd)))
-(format t "wparam-hi: ~x wparam-lo: ~x lparam: ~x~%" wparam-hi wparam-lo lparam)
(if owner
(cond
((zerop lparam)
@@ -152,7 +154,7 @@
(event-time tc)
(make-instance 'gfs:rectangle)))))) ; FIXME
((eq wparam-hi 1)
- (format t "accelerator wparam: ~x lparam: ~x~%" wparam lparam))
+ (format t "accelerator wparam: ~x lparam: ~x~%" wparam lparam)) ; FIXME: debug
(t
(let ((w (get-widget tc (cffi:make-pointer lparam))))
(if (null w)
@@ -186,8 +188,9 @@
0)
(defmethod process-message (hwnd (msg (eql gfs::+wm-create+)) wparam lparam)
- (declare (ignore wparam lparam))
- (get-widget (thread-context) hwnd) ; has side-effect of setting handle slot
+ (let ((w (get-widget (thread-context) hwnd))) ; has side-effect of setting handle slot
+ (if (typep w 'dialog)
+ (return-from process-message (gfs::def-dlg-proc hwnd msg wparam lparam))))
0)
(defmethod process-message (hwnd (msg (eql gfs::+wm-destroy+)) wparam lparam)
Modified: trunk/src/uitoolkit/widgets/label.lisp
==============================================================================
--- trunk/src/uitoolkit/widgets/label.lisp (original)
+++ trunk/src/uitoolkit/widgets/label.lisp Sat May 13 19:57:06 2006
@@ -160,7 +160,8 @@
(or text " ")
(gfs:handle parent)
(logior std-style)
- ex-style)))
+ ex-style
+ (increment-widget-id (thread-context)))))
(if (not hwnd)
(error 'gfs:win32-error :detail "create-window failed"))
(setf (slot-value label 'gfs:handle) hwnd)
Modified: trunk/src/uitoolkit/widgets/panel.lisp
==============================================================================
--- trunk/src/uitoolkit/widgets/panel.lisp (original)
+++ trunk/src/uitoolkit/widgets/panel.lisp Sat May 13 19:57:06 2006
@@ -59,7 +59,7 @@
((eq sym :border)
(setf std-flags (logior std-flags gfs::+ws-border+)))))
(style-of self))
- (values std-flags 0)))
+ (values std-flags gfs::+ws-ex-controlparent+)))
(defmethod initialize-instance :after ((self panel) &key parent &allow-other-keys)
(if (null parent)
Modified: trunk/src/uitoolkit/widgets/widget-classes.lisp
==============================================================================
--- trunk/src/uitoolkit/widgets/widget-classes.lisp (original)
+++ trunk/src/uitoolkit/widgets/widget-classes.lisp Sat May 13 19:57:06 2006
@@ -93,6 +93,12 @@
(defclass label (control) ()
(:documentation "This class represents non-selectable controls that display a string or image."))
+(defclass file-dialog (widget)
+ ((open-mode
+ :reader open-mode
+ :initform t))
+ (:documentation "This class represents the standard file open/save dialog."))
+
(defclass widget-with-items (widget)
((items
:accessor items
@@ -116,12 +122,6 @@
(defclass dialog (window) ()
(:documentation "The dialog class is the base class for both system-defined and application-defined dialogs."))
-(defclass file-dialog (dialog)
- ((open-mode
- :reader open-mode
- :initform t))
- (:documentation "This class represents the standard file open/save dialog."))
-
(defclass panel (window) ()
(:documentation "Base class for windows that are children of top-level windows (or other panels)."))
Modified: trunk/src/uitoolkit/widgets/widget-generics.lisp
==============================================================================
--- trunk/src/uitoolkit/widgets/widget-generics.lisp (original)
+++ trunk/src/uitoolkit/widgets/widget-generics.lisp Sat May 13 19:57:06 2006
@@ -120,8 +120,8 @@
(defgeneric cut (self)
(:documentation "Copies the current selection to the clipboard and removes it from the object."))
-(defgeneric default-item (self)
- (:documentation "Returns the item in this object that has the default emphasis."))
+(defgeneric default-widget (self)
+ (:documentation "Returns the child widget or item that has the default emphasis."))
(defgeneric disabled-image (self)
(:documentation "Returns the image used to render this item with a disabled look."))
Modified: trunk/src/uitoolkit/widgets/widget-utils.lisp
==============================================================================
--- trunk/src/uitoolkit/widgets/widget-utils.lisp (original)
+++ trunk/src/uitoolkit/widgets/widget-utils.lisp Sat May 13 19:57:06 2006
@@ -82,7 +82,7 @@
ex-style
cname-ptr
title-ptr
- std-style
+ (if child-id (logior std-style gfs::+ws-tabstop+) std-style)
gfs::+cw-usedefault+
gfs::+cw-usedefault+
gfs::+cw-usedefault+
Modified: trunk/src/uitoolkit/widgets/window.lisp
==============================================================================
--- trunk/src/uitoolkit/widgets/window.lisp (original)
+++ trunk/src/uitoolkit/widgets/window.lisp Sat May 13 19:57:06 2006
@@ -145,10 +145,10 @@
(defmacro with-children ((win var) &body body)
(let ((hwnd (gensym)))
`(let ((,var nil))
- (visit-child-widgets ,win #'(lambda (parent child)
- (let ((,hwnd (gfs::get-ancestor (gfs:handle child) gfs::+ga-parent+)))
- (if (cffi:pointer-eq (gfs:handle parent) ,hwnd)
- (push child ,var)))))
+ (visit-child-widgets ,win (lambda (parent child)
+ (let ((,hwnd (gfs::get-ancestor (gfs:handle child) gfs::+ga-parent+)))
+ (if (cffi:pointer-eq (gfs:handle parent) ,hwnd)
+ (push child ,var)))))
(setf ,var (reverse ,var))
,@body))))