Author: junrue Date: Sun Jul 2 14:32:26 2006 New Revision: 168
Added: trunk/src/uitoolkit/widgets/font-dialog.lisp Modified: trunk/docs/manual/api.texinfo trunk/graphic-forms-uitoolkit.asd trunk/src/packages.lisp trunk/src/tests/uitoolkit/image-unit-tests.lisp trunk/src/tests/uitoolkit/windlg.lisp trunk/src/uitoolkit/graphics/font-data.lisp trunk/src/uitoolkit/graphics/font.lisp trunk/src/uitoolkit/graphics/graphics-generics.lisp trunk/src/uitoolkit/graphics/image.lisp trunk/src/uitoolkit/system/comdlg32.lisp trunk/src/uitoolkit/system/system-constants.lisp trunk/src/uitoolkit/system/system-types.lisp trunk/src/uitoolkit/widgets/file-dialog.lisp trunk/src/uitoolkit/widgets/widget-classes.lisp trunk/src/uitoolkit/widgets/widget-utils.lisp Log: implemented font-dialog, refactored font-data and font classes, implemented show-common-dialog to centralize system dialog invocation
Modified: trunk/docs/manual/api.texinfo ============================================================================== --- trunk/docs/manual/api.texinfo (original) +++ trunk/docs/manual/api.texinfo Sun Jul 2 14:32:26 2006 @@ -377,18 +377,17 @@ @end itemize The @ref{with-file-dialog} macro wraps the creation of a @code{file-dialog} and subsequent retrieval of the file paths selected -by the user. However, applications may choose to implements these +by the user. However, applications may choose to implement these 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. In either case, zero is returned if the -user cancelled the dialog. Also, manual construction of an instance +user cancelled the dialog. 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.@*@* +Like other system dialogs in Graphic-Forms, @code{file-dialog} is +derived from @ref{widget} rather than @ref{dialog} since the majority +of its functionality is implemented by the system. @strong{NOTE:} A +future release 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 @@ -424,8 +423,7 @@ @end deffn @deffn Initarg :owner A value is required for this initarg, and it may be either a -@ref{window} or a @ref{dialog}. The file dialog will remain above the -specified @code{owner} in the window system Z-order. +@ref{window} or a @ref{dialog}. @end deffn @deffn Initarg :style This initarg accepts a list of keyword symbols, as follows: @@ -448,7 +446,7 @@ for data to be saved. @item :show-hidden This keyword enables the dialog to display files marked @sc{hidden} by -the system. @strong{Note:} files marked both @sc{hidden} and +the system. @strong{NOTE:} files marked both @sc{hidden} and @sc{system} will not be displayed in any case. Also, be aware that using this keyword effectively overrides the user's preference settings. @@ -462,8 +460,73 @@ @end deffn @end deftp
+@anchor{font-dialog} +@deftp Class font-dialog +This class provides a standard dialog for choosing attributes +of a @ref{font}, either from scratch or relative to an existing font. +A variety of style options may be selected, including strikeout +and font color.@*@* +The @ref{with-font-dialog} macro wraps the creation of a @code{font-dialog} +and provides a new font object based on the user's selections. However, +applications may choose to implement these steps manually, in which case +the @ref{font-dialog-results} function can be called to obtain the results +of the user's selections. Manual construction of an instance must be followed +by an explicit call to @ref{dispose}.@*@* +Like other system dialogs in Graphic-Forms, @code{font-dialog} is derived +from @ref{widget} rather than @ref{dialog} since the majority of its +functionality is implemented by the system. @strong{NOTE:} A future release +will provide a customization mechanism.@* +@deffn Initarg :gc +This required initarg accepts a @ref{graphics-context} object providing +context for the font selection, such as when the set of fonts to be offered +depends on a printer device. +@end deffn +@deffn Initarg :initial-color +This initarg accepts a @ref{color} object which the font dialog +will use for its initial color selection (as long as the @code{:no-effects} +style is @strong{not} set). +@end deffn +@deffn Initarg :initial-font +This initarg accepts a @ref{font} object which the font dialog +will use for its initial font attribute selections. If not +specified, the dialog will be set to the system font's attributes. +@end deffn +@deffn Initarg :owner +A value is required for this initarg, and it may be either a +@ref{window} or a @ref{dialog}. +@end deffn +@deffn Initarg :style +This initarg accepts a list of keyword symbols, as follows: +@table @code +@item :all-fonts +This is a convenience style, used by default if no other font +criteria are specified, that enables the dialog to offer all +possible fonts. +@item :fixed-pitch-fonts +Enables the dialog to offer fixed pitch fonts. +@item :no-effects +Causes the font dialog to hide the controls that +allow the user to specify strikeout, underline, and text color +attributes. +@item :printer-fonts +Enables the dialog to offer fonts supported by the printer associated +with the graphics-context supplied via the @code{:gc} initarg. +@item :screen-fonts +Enables the dialog to offer screen fonts supported by the system. +@item :truetype-fonts +Enables the dialog to offer TrueType fonts. +@item :wysiwyg-fonts +Enables the dialog to offer the intersection of the sets of fonts +available on the screen and the printer associated with the +graphics-context specified by the @code{:gc} initarg. +@end table +@end deffn +@end deftp + @anchor{group} @deftp Class group layout children location size style +@strong{NOTE:} this class is not yet fully implemented +and does not yet participate in the layout protocol.@*@* A @code{group} represents a logical rectangular aggregation of @ref{window} children which has the following properties and behaviors: @@ -970,11 +1033,12 @@ @end deffn
@anchor{file-dialog-paths} -@deffn Function file-dialog-paths dlg +@deffn Function file-dialog-paths dlg => @sc{list} Interrogates the data structure associated with an instance of @ref{file-dialog} to obtain the paths for selected files. This return value is either @sc{nil} if the user cancelled the dialog, or a list -of file @sc{namestring}s. +of file @sc{namestring}s. Use this function when manually constructing +a file dialog. @xref{with-file-dialog}. @end deffn
@deffn GenericFunction focus-p self @@ -982,6 +1046,19 @@ otherwise. @end deffn
+@anchor{font-dialog-results} +@deffn Function font-dialog-results dlg gc => @ref{font}, @ref{color} +Interrogates the data structure associated with an instance of +@ref{font-dialog} to obtain the @ref{font} and @ref{color} +corresponding to selections made by the user, and returns +them via @sc{values}. The @code{gc} parameter should be the same +@ref{graphics-context} object with which the dialog was created. +If the user cancelled the dialog, the font value will be @sc{nil}. +Also, the color value will be @sc{nil} if the dialog was created with +the @code{:no-effects} style keyword. Use this function when manually +constructing a font dialog. @xref{with-font-dialog}. +@end deffn + @deffn GenericFunction give-focus self Places keyboard focus on @code{self}. @end deffn @@ -1173,8 +1250,18 @@ @anchor{with-file-dialog} @deffn Macro with-file-dialog (owner style paths &key default-extension filters initial-directory initial-filename text) &body body This macro wraps the instantiation of a standard file open/save dialog -and the subsequent retrieval of the user's file -selections. @xref{file-dialog}. +and the subsequent retrieval of the user's file selections (supplied to @code{body} +via @code{paths}). @xref{file-dialog}. +@end deffn + +@anchor{with-font-dialog} +@deffn Macro with-font-dialog (owner style font color &key gc initial-color initial-font) &body body +This macro wraps the instantiation of a standard font dialog and binds +@code{font} to a font object, and @code{color} to a @ref{color} object, +corresponding to the attributes selected by the user. If the user cancels +the dialog, @code{font} will be @sc{nil}. In addition, @code{color} will also +be @sc{nil} if the dialog was created with the @code{:no-effects} style +keyword. @xref{font-dialog}. @end deffn
@@ -1226,6 +1313,7 @@ @strong{NOTE:} A future release will provide additional graphics classes.
+@anchor{color} @deftp Structure color red green blue This is a structure representing a color using three bytes in the RGB colorspace. @end deftp @@ -1304,6 +1392,7 @@ may use to position graphical elements. @xref{font}. @end deftp
+@anchor{graphics-context} @deftp Class graphics-context This subclass of @ref{native-object} wraps a native device context, hence instances of this class are used to perform drawing operations. @@ -1425,8 +1514,11 @@ Returns a color object corresponding to the current background color. @end deffn
-@deffn GenericFunction data-obj self -Returns the data structure representing the raw form of the object. +@deffn GenericFunction data-object self &optional gc => object +Returns the data structure representing the raw data form of the +object. The @code{gc} argument must be supplied when calling this +function on a @ref{font}, and the value must be a +@ref{graphics-context}. @end deffn
@deffn GenericFunction depth self
Modified: trunk/graphic-forms-uitoolkit.asd ============================================================================== --- trunk/graphic-forms-uitoolkit.asd (original) +++ trunk/graphic-forms-uitoolkit.asd Sun Jul 2 14:32:26 2006 @@ -113,6 +113,7 @@ (:file "panel") (:file "dialog") (:file "file-dialog") + (:file "font-dialog") (:file "layout") (:file "heap-layout") (:file "flow-layout")))))))))
Modified: trunk/src/packages.lisp ============================================================================== --- trunk/src/packages.lisp (original) +++ trunk/src/packages.lisp Sun Jul 2 14:32:26 2006 @@ -140,7 +140,7 @@ #:copy-color #:copy-font-data #:copy-font-metrics - #:data-obj + #:data-object #:depth #:descent #:draw-arc @@ -231,6 +231,7 @@ #:event-dispatcher #:event-source #:file-dialog + #:font-dialog #:flow-layout #:heap-layout #:item @@ -393,6 +394,7 @@ #:file-dialog-paths #:focus-index #:focus-p + #:font-dialog-results #:foreground-color #:give-focus #:grid-line-width @@ -492,6 +494,7 @@ #:visible-p #:with-children #:with-file-dialog + #:with-font-dialog
;; conditions ))
Modified: trunk/src/tests/uitoolkit/image-unit-tests.lisp ============================================================================== --- trunk/src/tests/uitoolkit/image-unit-tests.lisp (original) +++ trunk/src/tests/uitoolkit/image-unit-tests.lisp Sun Jul 2 14:32:26 2006 @@ -58,7 +58,7 @@ (assert-equal (gfs:size-width size1) (gfs:size-width size2) path) (assert-equal (gfs:size-height size1) (gfs:size-height size2) path)) (gfg:load im path) - (setf d3 (gfg:data-obj im)) + (setf d3 (gfg:data-object im)) (assert-equal (gfg:depth d1) (gfg:depth d3) path) (let ((size1 (gfg:size d1)) (size2 (gfg:size d3)))
Modified: trunk/src/tests/uitoolkit/windlg.lisp ============================================================================== --- trunk/src/tests/uitoolkit/windlg.lisp (original) +++ trunk/src/tests/uitoolkit/windlg.lisp Sun Jul 2 14:32:26 2006 @@ -118,6 +118,17 @@ :initial-directory #P"c:/") (print paths)))
+(defun choose-font-dlg (disp item time rect) + (declare (ignore disp item time rect)) + (let ((gc (make-instance 'gfg:graphics-context :widget *main-win*))) + (unwind-protect + (gfw:with-font-dialog (*main-win* nil font color :gc gc) + (if color + (print color)) + (if font + (print (gfg:data-object font gc)))) + (gfs:dispose gc)))) + (defclass dialog-events (gfw:event-dispatcher) ())
(defmethod gfw:event-close ((disp dialog-events) (dlg gfw:dialog) time) @@ -231,16 +242,17 @@ :style '(:workspace))) (setf menubar (gfw:defmenu ((:item "&File" :submenu ((:item "E&xit" :callback #'windlg-exit-fn))) + (:item "&Custom Dialogs" + :submenu ((:item "&Modal" :callback #'open-modal-dlg) + (:item "&Modeless" :callback #'open-modeless-dlg))) (:item "&System Dialogs" - :submenu ((:item "&Open File" :callback #'open-file-dlg) - (:item "&Save File" :callback #'save-file-dlg))) - (:item "&User Dialogs" - :submenu ((:item "&Modal" :callback #'open-modal-dlg) - (:item "&Modeless" :callback #'open-modeless-dlg))) + :submenu ((:item "&Choose Font" :callback #'choose-font-dlg) + (:item "&Open File" :callback #'open-file-dlg) + (:item "&Save File" :callback #'save-file-dlg))) (:item "&Windows" - :submenu ((:item "&Borderless" :callback #'create-borderless-win) - (:item "&Mini Frame" :callback #'create-miniframe-win) - (:item "&Palette" :callback #'create-palette-win)))))) + :submenu ((:item "&Borderless" :callback #'create-borderless-win) + (:item "&Mini Frame" :callback #'create-miniframe-win) + (:item "&Palette" :callback #'create-palette-win)))))) (setf (gfw:menu-bar *main-win*) menubar) (gfw:show *main-win* t)))
Modified: trunk/src/uitoolkit/graphics/font-data.lisp ============================================================================== --- trunk/src/uitoolkit/graphics/font-data.lisp (original) +++ trunk/src/uitoolkit/graphics/font-data.lisp Sun Jul 2 14:32:26 2006 @@ -33,50 +33,99 @@
(in-package :graphic-forms.uitoolkit.graphics)
-(defun compute-font-weight (style) - (if (null (find :bold style)) - gfs::+fw-normal+ - gfs::+fw-bold+)) - -(defun compute-font-precis (style) - (if (find :truetype-only style) - (return-from compute-font-precis gfs::+out-tt-only-precis+)) - (if (find :outline style) - (return-from compute-font-precis gfs::+out-outline-precis+)) - gfs::+out-default-precis+) - -(defun compute-font-pitch (style) - (if (find :fixed style) - (return-from compute-font-pitch gfs::+fixed-pitch+)) - (if (find :variable style) - (return-from compute-font-pitch gfs::+variable-pitch+)) - gfs::+default-pitch+) +(defun pntsize->lfheight (hdc pntsize) + (let ((log-height (gfs::get-device-caps hdc gfs::+logpixelsy+))) + (- (floor (+ (/ (* pntsize log-height) 72) 0.5)))))
-(defun data->font (hdc data) - (let ((hfont (cffi:null-pointer)) +(defun lfheight->pntsize (hdc lfheight) + (let ((log-height (gfs::get-device-caps hdc gfs::+logpixelsy+))) + (floor (* (+ (- lfheight) 0.5) 72) log-height))) + +(defun style->logfont (style lf-ptr) + (cffi:with-foreign-slots ((gfs::lfweight gfs::lfitalic gfs::lfunderline + gfs::lfstrikeout gfs::lfoutprec gfs::lfpitchandfamily) + lf-ptr gfs::logfont) + (setf gfs::lfweight (if (find :bold style) gfs::+fw-bold+ gfs::+fw-normal+)) + (setf gfs::lfitalic (if (find :italic style) 1 0)) + (setf gfs::lfunderline (if (find :underline style) 1 0)) + (setf gfs::lfstrikeout (if (find :strikeout style) 1 0)) + (setf gfs::lfoutprec (cond + ((find :truetype-only style) gfs::+out-tt-only-precis+) + ((find :outline style) gfs::+out-outline-precis+) + (t gfs::+out-default-precis+))) + (setf gfs::lfpitchandfamily (cond + ((find :fixed style) gfs::+fixed-pitch+) + ((find :variable style) gfs::+variable-pitch+) + (t gfs::+default-pitch+))))) + +(defun logfont->style (lf-ptr) + (let ((style nil)) + (cffi:with-foreign-slots ((gfs::lfweight gfs::lfitalic gfs::lfunderline + gfs::lfstrikeout gfs::lfoutprec gfs::lfpitchandfamily) + lf-ptr gfs::logfont) + (if (= gfs::lfweight gfs::+fw-bold+) + (push :bold style)) + (unless (zerop gfs::lfitalic) + (push :italic style)) + (unless (zerop gfs::lfunderline) + (push :underline style)) + (unless (zerop gfs::lfstrikeout) + (push :strikeout style)) + (case gfs::lfoutprec + (#.gfs::+out-tt-only-precis+ (push :truetype-only style)) + (#.gfs::+out-outline-precis+ (push :outline style))) + (case gfs::lfpitchandfamily + (#.gfs::+fixed-pitch+ (push :fixed style)) + (#.gfs::+variable-pitch+ (push :variable style)))) + style)) + +(defun data->logfont (hdc data) + (let ((lf-ptr (cffi:foreign-alloc 'gfs::logfont)) (style (font-data-style data))) - (cffi:with-foreign-object (lf-ptr 'gfs::logfont) - (gfs:zero-mem lf-ptr gfs::logfont) - (cffi:with-foreign-slots ((gfs::lfheight gfs::lfweight gfs::lfitalic gfs::lfunderline - gfs::lfstrikeout gfs::lfcharset gfs::lfoutprec - gfs::lfpitchandfamily gfs::lffacename) - lf-ptr gfs::logfont) - (setf gfs::lfheight (- (floor (+ (/ (* (font-data-point-size data) - (gfs::get-device-caps hdc gfs::+logpixelsy+)) - 72) - 0.5)))) - (setf gfs::lfweight (compute-font-weight style)) - (setf gfs::lfitalic (if (null (find :italic style)) 0 1)) - (setf gfs::lfunderline (if (null (find :underline style)) 0 1)) - (setf gfs::lfstrikeout (if (null (find :strikeout style)) 0 1)) - (setf gfs::lfcharset (font-data-char-set data)) - (setf gfs::lfoutprec (compute-font-precis style)) - (setf gfs::lfpitchandfamily (compute-font-pitch style)) - (cffi:with-foreign-string (str (font-data-face-name data)) - (let ((lffacename-ptr (cffi:foreign-slot-pointer lf-ptr 'gfs::logfont 'gfs::lffacename))) - (gfs::strncpy lffacename-ptr str (1- gfs::+lf-facesize+)) - (setf (cffi:mem-aref lffacename-ptr :char (1- gfs::+lf-facesize+)) 0)))) - (setf hfont (gfs::create-font-indirect lf-ptr)) - (if (gfs:null-handle-p hfont) - (error 'gfs:win32-error :detail "create-font-indirect failed"))) + (gfs:zero-mem lf-ptr gfs::logfont) + (cffi:with-foreign-slots ((gfs::lfheight gfs::lfcharset gfs::lffacename) lf-ptr gfs::logfont) + (setf gfs::lfheight (pntsize->lfheight hdc (font-data-point-size data))) + (setf gfs::lfcharset (font-data-char-set data)) + (style->logfont style lf-ptr) + (cffi:with-foreign-string (str (font-data-face-name data)) + (let ((lffacename-ptr (cffi:foreign-slot-pointer lf-ptr 'gfs::logfont 'gfs::lffacename))) + (gfs::strncpy lffacename-ptr str (1- gfs::+lf-facesize+)) + (setf (cffi:mem-aref lffacename-ptr :char (1- gfs::+lf-facesize+)) 0)))) + lf-ptr)) + +(defun logfont->data (hdc lf-ptr) + (let ((char-set 0) + (face-name "") + (point-size 0) + (style nil)) + (cffi:with-foreign-slots ((gfs::lfheight gfs::lfcharset gfs::lffacename) lf-ptr gfs::logfont) + (setf point-size (lfheight->pntsize hdc gfs::lfheight)) + (setf char-set gfs::lfcharset) + (setf style (logfont->style lf-ptr)) + (let ((lffacename-ptr (cffi:foreign-slot-pointer lf-ptr 'gfs::logfont 'gfs::lffacename))) + (setf face-name (cffi:foreign-string-to-lisp lffacename-ptr)))) + (gfg:make-font-data :char-set char-set + :face-name face-name + :point-size point-size + :style style))) + +(defun data->font (hdc data) + (let ((hfont (cffi:null-pointer))) + (setf hfont (gfs::create-font-indirect (data->logfont hdc data))) + (if (gfs:null-handle-p hfont) + (error 'gfs:win32-error :detail "create-font-indirect failed")) hfont)) + +(defun font->data (hdc hfont) + (cffi:with-foreign-object (lf-ptr 'gfs::logfont) + (gfs:zero-mem lf-ptr gfs::logfont) + (if (zerop (gfs::get-object hfont (cffi:foreign-type-size 'gfs::logfont) lf-ptr)) + (error 'gfs:win32-error :detail "get-object failed")) + (logfont->data hdc lf-ptr))) + +(defmethod print-object ((self font-data) stream) + (print-unreadable-object (self stream :type t) + (format stream "face name: ~a " (font-data-face-name self)) + (format stream "point size: ~d " (font-data-point-size self)) + (format stream "style: ~a " (font-data-style self)) + (format stream "char-set: ~d" (font-data-char-set self))))
Modified: trunk/src/uitoolkit/graphics/font.lisp ============================================================================== --- trunk/src/uitoolkit/graphics/font.lisp (original) +++ trunk/src/uitoolkit/graphics/font.lisp Sun Jul 2 14:32:26 2006 @@ -37,12 +37,17 @@ ;;; methods ;;;
-(defmethod gfs:dispose ((fn font)) - (let ((hgdi (gfs:handle fn))) +(defmethod data-object ((self font) &optional gc) + (if (or (gfs:disposed-p self) (gfs:disposed-p gc)) + (error 'gfs:disposed-error)) + (font->data (gfs:handle gc) (gfs:handle self))) + +(defmethod gfs:dispose ((self font)) + (let ((hgdi (gfs:handle self))) (unless (gfs:null-handle-p hgdi) (gfs::delete-object hgdi))) - (setf (slot-value fn 'gfs:handle) nil)) + (setf (slot-value self 'gfs:handle) nil))
-(defmethod initialize-instance :after ((font font) &key gc data &allow-other-keys) +(defmethod initialize-instance :after ((self font) &key gc data &allow-other-keys) (if gc - (setf (slot-value font 'gfs:handle) (data->font (gfs:handle gc) data)))) + (setf (slot-value self 'gfs:handle) (data->font (gfs:handle gc) data))))
Modified: trunk/src/uitoolkit/graphics/graphics-generics.lisp ============================================================================== --- trunk/src/uitoolkit/graphics/graphics-generics.lisp (original) +++ trunk/src/uitoolkit/graphics/graphics-generics.lisp Sun Jul 2 14:32:26 2006 @@ -36,7 +36,7 @@ (defgeneric background-color (self) (:documentation "Returns a color object corresponding to the current background color."))
-(defgeneric data-obj (self) +(defgeneric data-object (self &optional gc) (:documentation "Returns the data structure representing the raw form of the object."))
(defgeneric depth (self)
Modified: trunk/src/uitoolkit/graphics/image.lisp ============================================================================== --- trunk/src/uitoolkit/graphics/image.lisp (original) +++ trunk/src/uitoolkit/graphics/image.lisp Sun Jul 2 14:32:26 2006 @@ -72,15 +72,16 @@ (gfs::delete-object hgdi))) (setf (slot-value im 'gfs:handle) nil))
-(defmethod data-obj ((im image)) - (when (gfs:disposed-p im) +(defmethod data-object ((self image) &optional gc) + (declare (ignore gc)) + (when (gfs:disposed-p self) (error 'gfs:disposed-error)) - (image->data (gfs:handle im))) + (image->data (gfs:handle self)))
-(defmethod (setf data-obj) ((id image-data) (im image)) - (unless (gfs:disposed-p im) - (gfs:dispose im)) - (setf (slot-value im 'gfs:handle) (data->image id))) +(defmethod (setf data-object) ((id image-data) (self image)) + (unless (gfs:disposed-p self) + (gfs:dispose self)) + (setf (slot-value self 'gfs:handle) (data->image id)))
(defmethod initialize-instance :after ((image image) &key file size &allow-other-keys) (cond @@ -108,7 +109,7 @@ (defmethod load ((im image) path) (let ((data (make-instance 'image-data))) (load data path) - (setf (data-obj im) data) + (setf (data-object im) data) data))
(defmethod size ((image image))
Modified: trunk/src/uitoolkit/system/comdlg32.lisp ============================================================================== --- trunk/src/uitoolkit/system/comdlg32.lisp (original) +++ trunk/src/uitoolkit/system/comdlg32.lisp Sun Jul 2 14:32:26 2006 @@ -39,6 +39,11 @@ (load-foreign-library "comdlg32.dll")
(defcfun + ("ChooseFontA" choose-font) + BOOL + (struct LPTR)) + +(defcfun ("CommDlgExtendedError" comm-dlg-extended-error) DWORD)
Modified: trunk/src/uitoolkit/system/system-constants.lisp ============================================================================== --- trunk/src/uitoolkit/system/system-constants.lisp (original) +++ trunk/src/uitoolkit/system/system-constants.lisp Sun Jul 2 14:32:26 2006 @@ -142,6 +142,35 @@ (defconstant +cderr-nohook+ #x000b) (defconstant +cderr-registermsgfail+ #x000C)
+(defconstant +cf-screenfonts+ #x00000001) +(defconstant +cf-printerfonts+ #x00000002) +(defconstant +cf-both+ #x00000003) +(defconstant +cf-showhelp+ #x00000004) +(defconstant +cf-enablehook+ #x00000008) +(defconstant +cf-enabletemplate+ #x00000010) +(defconstant +cf-enabletemplatehandle+ #x00000020) +(defconstant +cf-inittologfontstruct+ #x00000040) +(defconstant +cf-usestyle+ #x00000080) +(defconstant +cf-effects+ #x00000100) +(defconstant +cf-apply+ #x00000200) +(defconstant +cf-ansionly+ #x00000400) +(defconstant +cf-scriptsonly+ #x00000400) +(defconstant +cf-novectorfonts+ #x00000800) +(defconstant +cf-nooemfonts+ #x00000800) +(defconstant +cf-nosimulations+ #x00001000) +(defconstant +cf-limitsize+ #x00002000) +(defconstant +cf-fixedpitchonly+ #x00004000) +(defconstant +cf-wysiwyg+ #x00008000) +(defconstant +cf-forcefontexist+ #x00010000) +(defconstant +cf-scalableonly+ #x00020000) +(defconstant +cf-ttonly+ #x00040000) +(defconstant +cf-nofacesel+ #x00080000) +(defconstant +cf-nostylesel+ #x00100000) +(defconstant +cf-nosizesel+ #x00200000) +(defconstant +cf-selectscript+ #x00400000) +(defconstant +cf-noscriptsel+ #x00800000) +(defconstant +cf-novertfonts+ #x01000000) + (defconstant +cferr-choosefontcodes+ #x2000) (defconstant +cferr-nofonts+ #x2001) (defconstant +cferr-maxlessthanmin+ #x2002)
Modified: trunk/src/uitoolkit/system/system-types.lisp ============================================================================== --- trunk/src/uitoolkit/system/system-types.lisp (original) +++ trunk/src/uitoolkit/system/system-types.lisp Sun Jul 2 14:32:26 2006 @@ -127,6 +127,23 @@ (biclrused DWORD) (biclrimp DWORD))
+(defcstruct choosefont + (structsize DWORD) + (howner HANDLE) + (hdc HANDLE) + (logfont LPTR) + (pointsize INT) + (flags DWORD) + (color COLORREF) + (data LPARAM) + (hookfn LPTR) ; FIXME: not yet used, but eventually should be CFHookProc + (templname :string) + (hinstance HANDLE) + (style :string) + (fonttype WORD) + (minsize INT) + (maxsize INT)) + (defcstruct drawtextparams (cbsize UINT) (tablength INT)
Modified: trunk/src/uitoolkit/widgets/file-dialog.lisp ============================================================================== --- trunk/src/uitoolkit/widgets/file-dialog.lisp (original) +++ trunk/src/uitoolkit/widgets/file-dialog.lisp Sun Jul 2 14:32:26 2006 @@ -74,12 +74,12 @@ ;;; methods ;;;
-(defmethod compute-style-flags ((dlg file-dialog) &rest extra-data) +(defmethod compute-style-flags ((self file-dialog) &rest extra-data) (declare (ignore extra-data)) (let ((std-flags (logior gfs::+ofn-dontaddtorecent+ gfs::+ofn-hidereadonly+ gfs::+ofn-notestfilecreate+ gfs::+ofn-overwriteprompt+ gfs::+ofn-explorer+))) - (loop for sym in (style-of dlg) + (loop for sym in (style-of self) do (cond ((eq sym :add-to-recent) (setf std-flags (logand std-flags (lognot gfs::+ofn-dontaddtorecent+)))) @@ -91,8 +91,8 @@ (setf std-flags (logior std-flags gfs::+ofn-forceshowhidden+))))) (values std-flags 0)))
-(defmethod gfs:dispose ((dlg file-dialog)) - (let ((ofn-ptr (gfs:handle dlg))) +(defmethod gfs:dispose ((self file-dialog)) + (let ((ofn-ptr (gfs:handle self))) (unless (cffi:null-pointer-p ofn-ptr) (cffi:with-foreign-slots ((gfs::ofnfile gfs::ofnfilter gfs::ofntitle gfs::ofninitialdir gfs::ofndefext) @@ -106,9 +106,9 @@ (unless (cffi:null-pointer-p gfs::ofndefext) (cffi:foreign-free gfs::ofndefext))) (cffi:foreign-free ofn-ptr) - (setf (slot-value dlg 'gfs:handle) (cffi:null-pointer))))) + (setf (slot-value self 'gfs:handle) (cffi:null-pointer)))))
-(defmethod initialize-instance :after ((dlg file-dialog) &key default-extension filters initial-directory initial-filename owner style text) +(defmethod initialize-instance :after ((self file-dialog) &key default-extension filters initial-directory initial-filename owner style text) ;; FIXME: implement an OFNHookProc to process CDN_SELCHANGE ;; so that the file buffer can be resized as needed for ;; multi-select mode. @@ -137,7 +137,7 @@ (gfs::strncpy file-buffer tmp-str 1023)) (setf (cffi:mem-ref file-buffer :char) 0)) (multiple-value-bind (std-style ex-style) - (compute-style-flags dlg) + (compute-style-flags self) (cffi:with-foreign-slots ((gfs::ofnsize gfs::ofnhwnd gfs::ofnhinst gfs::ofnfilter gfs::ofncustomfilter gfs::ofnmaxcustfilter gfs::ofnfilterindex gfs::ofnfile gfs::ofnmaxfile gfs::ofnfiletitle gfs::ofnmaxfiletitle @@ -168,12 +168,11 @@ gfs::ofnpvreserved (cffi:null-pointer) gfs::ofndwreserved 0 gfs::ofnexflags ex-style))) - (setf (slot-value dlg 'gfs:handle) ofn-ptr) - (setf (slot-value dlg 'open-mode) (find :open style)))) + (setf (slot-value self 'gfs:handle) ofn-ptr) + (setf (slot-value self 'open-mode) (find :open style))))
-(defmethod show ((dlg file-dialog) flag) +(defmethod show ((self file-dialog) flag) (declare (ignore flag)) - (let ((ofn-ptr (gfs:handle dlg)) - (fn (if (open-mode dlg) #'gfs::get-open-filename #'gfs::get-save-filename))) - (if (and (zerop (funcall fn ofn-ptr)) (/= (gfs::comm-dlg-extended-error) 0)) - (error 'gfs:comdlg-error :detail "file dialog function failed")))) + (if (open-mode self) + (show-common-dialog self #'gfs::get-open-filename) + (show-common-dialog self #'gfs::get-save-filename)))
Added: trunk/src/uitoolkit/widgets/font-dialog.lisp ============================================================================== --- (empty file) +++ trunk/src/uitoolkit/widgets/font-dialog.lisp Sun Jul 2 14:32:26 2006 @@ -0,0 +1,144 @@ +;;;; +;;;; font-dialog.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) + +(defconstant +font-dialog-flags+ (logior gfs::+cf-effects+ gfs::+cf-inittologfontstruct+)) + +;;; +;;; helper functions +;;; + +(defun font-dialog-results (dlg gc) + (if (or (gfs:disposed-p dlg) (gfs:disposed-p gc)) + (error 'gfs:disposed-error)) + (cffi:with-foreign-slots ((gfs::logfont gfs::color) (gfs:handle dlg) gfs::choosefont) + (values (make-instance 'gfg:font :handle (gfs::create-font-indirect gfs::logfont)) + (gfg::rgb->color gfs::color)))) + +(defun lookup-default-font () + (let ((lf-ptr (cffi:foreign-alloc 'gfs::logfont))) + (gfs:zero-mem lf-ptr gfs::logfont) + (gfs::get-object (gfs::get-stock-object gfs::+system-font+) + (cffi:foreign-type-size 'gfs::logfont) + lf-ptr) + lf-ptr)) + +(defmacro with-font-dialog ((owner style font color &key gc initial-color initial-font) &body body) + (let ((dlg (gensym))) + `(let ((,font nil) + (,color nil) + (,dlg (make-instance 'font-dialog + :gc ,gc + :initial-color ,initial-color + :initial-font ,initial-font + :owner ,owner + :style ,style))) + (unwind-protect + (progn + (unless (zerop (show ,dlg t)) + (multiple-value-bind (f c) (font-dialog-results ,dlg ,gc) + (setf ,font f) + (setf ,color c)) + ,@body)) + (gfs:dispose ,dlg))))) + +;;; +;;; methods +;;; + +(defmethod compute-style-flags ((self font-dialog) &rest extra-data) + (declare (ignore extra-data)) + (let ((std-flags (logior gfs::+cf-both+ +font-dialog-flags+))) + (loop for sym in (style-of self) + do (ecase sym + ;; primary styles + ;; + (:all-fonts + (setf std-flags (logior gfs::+cf-both+ +font-dialog-flags+))) + (:fixed-pitch-fonts + (setf std-flags (logior gfs::+cf-fixedpitchonly+ +font-dialog-flags+))) + (:printer-fonts + (setf std-flags (logior gfs::+cf-printerfonts+ +font-dialog-flags+))) + (:screen-fonts + (setf std-flags (logior gfs::+cf-screenfonts+ +font-dialog-flags+))) + (:truetype-fonts + (setf std-flags (logior gfs::+cf-ttonly+ +font-dialog-flags+))) + (:wsyiwyg-fonts + (setf std-flags (logior gfs::+cf-both+ + gfs::+cf-scalableonly+ + gfs::+cf-wysiwyg+ + +font-dialog-flags+))) + + ;; styles that can be combined + ;; + (:no-effects + (setf std-flags (logand std-flags (lognot gfs::+cf-effects+)))))) + (values std-flags 0))) + +(defmethod gfs:dispose ((self font-dialog)) + (let ((cf-ptr (gfs:handle self))) + (unless (cffi:null-pointer-p cf-ptr) + (cffi:with-foreign-slots ((gfs::logfont) cf-ptr gfs::choosefont) + (unless (cffi:null-pointer-p gfs::logfont) + (cffi:foreign-free gfs::logfont))) + (cffi:foreign-free cf-ptr))) + (setf (slot-value self 'gfs:handle) (cffi:null-pointer))) + +(defmethod initialize-instance :after ((self font-dialog) &key gc initial-color initial-font owner &allow-other-keys) + (if (null gc) + (error 'gfs:toolkit-error :detail ":gc initarg is required")) + (if (null owner) + (error 'gfs:toolkit-error :detail ":owner initarg is required")) + (if (gfs:disposed-p owner) + (error 'gfs:disposed-error)) + (let ((cf-ptr (cffi:foreign-alloc 'gfs::choosefont)) + (lf-ptr (if initial-font + (gfg::data->logfont (gfs:handle gc) (gfg:data-object initial-font gc)) + (lookup-default-font)))) + (multiple-value-bind (std-style ex-style) (compute-style-flags self) + (declare (ignore ex-style)) + (cffi:with-foreign-slots ((gfs::structsize gfs::howner gfs::hdc gfs::logfont + gfs::flags gfs::color) + cf-ptr gfs::choosefont) + (setf gfs::structsize (cffi:foreign-type-size 'gfs::choosefont) + gfs::howner (gfs:handle owner) + gfs::hdc (gfs:handle gc) + gfs::logfont lf-ptr + gfs::flags std-style + gfs::color (if initial-color (gfg:color->rgb initial-color) 0)))) + (setf (slot-value self 'gfs:handle) cf-ptr))) + +(defmethod show ((self font-dialog) flag) + (declare (ignore flag)) + (show-common-dialog self #'gfs::choose-font))
Modified: trunk/src/uitoolkit/widgets/widget-classes.lisp ============================================================================== --- trunk/src/uitoolkit/widgets/widget-classes.lisp (original) +++ trunk/src/uitoolkit/widgets/widget-classes.lisp Sun Jul 2 14:32:26 2006 @@ -130,6 +130,9 @@ :initform t)) (:documentation "This class represents the standard file open/save dialog."))
+(defclass font-dialog (widget) () + (:documentation "This class represents the standard font dialog.")) + (defclass widget-with-items (widget) ((items :accessor items
Modified: trunk/src/uitoolkit/widgets/widget-utils.lisp ============================================================================== --- trunk/src/uitoolkit/widgets/widget-utils.lisp (original) +++ trunk/src/uitoolkit/widgets/widget-utils.lisp Sun Jul 2 14:32:26 2006 @@ -107,6 +107,13 @@ (error 'gfs:win32-error :detail "create-window failed")) hwnd))))
+(defun show-common-dialog (dlg dlg-func) + (let* ((struct-ptr (gfs:handle dlg)) + (retval (funcall dlg-func struct-ptr))) + (if (and (zerop retval) (not (zerop (gfs::comm-dlg-extended-error)))) + (error 'gfs:comdlg-error :detail (format nil "~a failed" (symbol-name dlg-func)))) + retval)) + (defun get-widget-text (w) (if (gfs:disposed-p w) (error 'gfs:disposed-error))