Update of /project/mcclim/cvsroot/mcclim/Backends/Graphic-Forms
In directory clnet:/tmp/cvs-serv934
Modified Files:
gadgets.lisp medium.lisp port.lisp utils.lisp
Log Message:
More little clim-g-f fixes. demodemo still looks terrible but its buttons
work. The Quit menu in the address book works.
* Backends/Graphic-Forms/gadgets.lisp ((REALIZE-MIRROR
PUSH-BUTTON)): Set the dispatcher.
* Backends/Graphic-Forms/medium.lisp (add-medium-to-render): Do it
only if the double buffering image has been installed.
(RENDER-MEDIUM-BUFFER): Renamed from render-medium, since it is
only used for the buffering image. (RENDER-PENDING-MEDIUMS): Use
render-medium-buffer. (INK-TO-COLOR): New function. (TARGET-OF):
Return (and create if needed) image-of, or return the normal
mirror if no buffering has been requested. (TEXT-STYLE-TO-FONT):
New function, based on the old sync-text-style.
(SYNC-TEXT-STYLE): Use text-style-to-font. (MEDIUM-DRAW-POLYGON,
MEDIUM-DRAW-RECTANGLE*): Use the medium ink. Use target-of
instead of image-of. (TEXT-STYLE-*, MEDIUM-DRAW-TEXT*,
MEDIUM-CLEAR-AREA): Use target-of instead of image-of.
(TEXT-SIZE): Merge the text styles properly. (MEDIUM-DRAW-TEXT*):
At least make some effort to draw the text above the y coordinate,
not below it. Probably not correct yet. (MEDIUM-FINISH-OUTPUT,
MEDIUM-FORCE-OUTPUT): Only if image-of is set.
* Backends/Graphic-Forms/port.lisp (GFW-MENU-ITEM-PANE): New slot
callback, needed for those commands that sit directly in the menu
bar. (SHEET-DESIRED-INK): Copy&paste from CLX. (EVENT-PAINT):
Clear the affected area with the desired color when enqueing an
repaint, as expected by the frontend. (EVENT-RESIZE): Resize
image-of only if it exists. (GADGET-EVENT, BUTTON-PRESSED-EVENT):
New classes. (EVENT-SELECT): Handle push buttons. ((HANDLE-EVENT
PUSH-BUTTON BUTTON-PRESSED-EVENT)): New method.
(HANDLE-MENU-CLICKED-EVENT): Call the callback if present.
* Backends/Graphic-Forms/utils.lisp (COORDINATES->POINTS):
Rewritten to loop over the vector (it's not a list).
--- /project/mcclim/cvsroot/mcclim/Backends/Graphic-Forms/gadgets.lisp 2007/03/14 23:42:40 1.2
+++ /project/mcclim/cvsroot/mcclim/Backends/Graphic-Forms/gadgets.lisp 2007/03/16 14:42:49 1.3
@@ -123,7 +123,11 @@
(defmethod realize-mirror ((port graphic-forms-port) (gadget push-button))
(gfs::debug-format "realizing ~a~%" gadget)
(let* ((parent-mirror (sheet-mirror (sheet-parent gadget)))
- (mirror (make-instance 'gfw-button :parent parent-mirror :style '(:push-button))))
+ (mirror (make-instance 'gfw-button
+ :sheet gadget
+ :parent parent-mirror
+ :dispatcher *pane-dispatcher*
+ :style '(:push-button))))
(if (gadget-label gadget)
(setf (gfw:text mirror) (gadget-label gadget)))
(climi::port-register-mirror port gadget mirror)
--- /project/mcclim/cvsroot/mcclim/Backends/Graphic-Forms/medium.lisp 2007/03/14 23:49:05 1.3
+++ /project/mcclim/cvsroot/mcclim/Backends/Graphic-Forms/medium.lisp 2007/03/16 14:42:49 1.4
@@ -37,21 +37,45 @@
(defvar *mediums-to-render* nil)
(defun add-medium-to-render (medium)
- (pushnew medium *mediums-to-render* :test #'eql))
+ (when (image-of medium)
+ (pushnew medium *mediums-to-render* :test #'eql)))
(defun remove-medium-to-render (medium)
(setf *mediums-to-render* (remove medium *mediums-to-render*)))
-(defun render-medium (medium)
+(defun render-medium-buffer (medium)
(let ((mirror (climi::port-lookup-mirror (port-of medium) (medium-sheet medium))))
(gfw:with-graphics-context (gc mirror)
(gfg:draw-image gc (image-of medium) *medium-origin*))))
(defun render-pending-mediums ()
(loop for medium in *mediums-to-render*
- do (render-medium medium))
+ do (render-medium-buffer medium))
(setf *mediums-to-render* nil))
+(defun ink-to-color (medium ink)
+ (cond
+ ((eql ink +foreground-ink+)
+ (setf ink (medium-foreground medium)))
+ ((eql ink +background-ink+)
+ (setf ink (medium-background medium))))
+ (multiple-value-bind (red green blue) (clim:color-rgb ink)
+ (gfg:make-color :red (truncate (* red 256))
+ :green (truncate (* green 256))
+ :blue (truncate (* blue 256)))))
+
+(defun target-of (medium)
+ (let ((sheet (medium-sheet medium)))
+ (if (climi::pane-double-buffering sheet)
+ (or (image-of medium)
+ (let* ((region (climi::sheet-mirror-region sheet))
+ (width (floor (bounding-rectangle-max-x region)))
+ (height (floor (bounding-rectangle-max-y region))))
+ (setf (image-of medium)
+ (make-instance 'gfg:image
+ :size (gfs:make-size width height)))))
+ (sheet-mirror (medium-sheet medium)))))
+
(defun resize-medium-buffer (medium size)
(let ((old-image (image-of medium)))
(when old-image
@@ -81,6 +105,19 @@
(symbol (symbol-name text))))
(defun sync-text-style (medium text-style)
+ (gfw:with-graphics-context
+ (gc (climi::port-lookup-mirror (port-of medium) (medium-sheet medium)))
+ (let* ((old-data
+ (when (font-of medium)
+ (gfg:data-object (font-of medium) gc)))
+ (new-font (text-style-to-font gc text-style old-data)))
+ (when new-font
+ (when old-data
+ (gfs:dispose (font-of medium))
+ (setf (font-of medium) nil))
+ (setf (font-of medium) new-font)))))
+
+(defun text-style-to-font (gc text-style old-data)
(multiple-value-bind (family face size)
(text-style-components (merge-text-styles text-style *default-text-style*))
#+nil (gfs::debug-format "family: ~a face: ~a size: ~a~%" family face size)
@@ -90,53 +127,47 @@
;; FIXME: externalize these specific choices so that applications can
;; have better control over them
;;
- (gfw:with-graphics-context (gc (climi::port-lookup-mirror (port-of medium) (medium-sheet medium)))
- (let ((old-data (if (font-of medium) (gfg:data-object (font-of medium) gc)))
- (face-name (if (stringp family)
- family
- (ecase family
- ((:fix :fixed) "Lucida Console")
- (:serif "Times New Roman")
- (:sans-serif "Arial"))))
- (pnt-size (case size
- (:tiny 6)
- (:very-small 8)
- (:small 10)
- (:normal 12)
- (:large 14)
- (:very-large 16)
- (:huge 18)
- (otherwise 10)))
- (style nil))
- (pushnew (case face
- ((:bold :bold-italic :bold-oblique :italic-bold :oblique-bold)
- :bold)
- (otherwise
- :normal))
- style)
- (pushnew (case face
- ((:bold-italic :italic :italic-bold)
- :italic)
- (otherwise
- :normal))
- style)
- (pushnew (case family
- ((:fix :fixed) :fixed)
- (otherwise :normal))
- style)
- (when (or (null old-data)
- (not (eql pnt-size (gfg:font-data-point-size old-data)))
- (string-not-equal face-name (gfg:font-data-face-name old-data))
- (/= (length style)
- (length (intersection style (gfg:font-data-style old-data)))))
- (when old-data
- (gfs:dispose (font-of medium))
- (setf (font-of medium) nil))
- (let ((new-data (gfg:make-font-data :face-name face-name
- :point-size pnt-size
- :style style)))
- #+nil (gfs::debug-format "new font data: ~a~%" new-data)
- (setf (font-of medium) (make-instance 'gfg:font :gc gc :data new-data))))))))
+ (let ((face-name (if (stringp family)
+ family
+ (ecase family
+ ((:fix :fixed) "Lucida Console")
+ (:serif "Times New Roman")
+ (:sans-serif "Arial"))))
+ (pnt-size (case size
+ (:tiny 6)
+ (:very-small 8)
+ (:small 10)
+ (:normal 12)
+ (:large 14)
+ (:very-large 16)
+ (:huge 18)
+ (otherwise 10)))
+ (style nil))
+ (pushnew (case face
+ ((:bold :bold-italic :bold-oblique :italic-bold :oblique-bold)
+ :bold)
+ (otherwise
+ :normal))
+ style)
+ (pushnew (case face
+ ((:bold-italic :italic :italic-bold)
+ :italic)
+ (otherwise
+ :normal))
+ style)
+ (pushnew (case family
+ ((:fix :fixed) :fixed)
+ (otherwise :normal))
+ style)
+ (when (or (null old-data)
+ (not (eql pnt-size (gfg:font-data-point-size old-data)))
+ (string-not-equal face-name (gfg:font-data-face-name old-data))
+ (/= (length style)
+ (length (intersection style (gfg:font-data-style old-data)))))
+ (let ((new-data (gfg:make-font-data :face-name face-name
+ :point-size pnt-size
+ :style style)))
+ (make-instance 'gfg:font :gc gc :data new-data))))))
(defmethod (setf medium-text-style) :before (text-style (medium graphic-forms-medium))
(sync-text-style medium
@@ -190,11 +221,12 @@
(defmethod medium-draw-polygon* ((medium graphic-forms-medium) coord-seq closed filled)
#+nil (gfs::debug-format "draw-polygon ~a ~a ~a~%" coord-seq closed filled)
- (when (image-of medium)
- (gfw:with-graphics-context (gc (image-of medium))
- (setf (gfg:background-color gc) gfg:*color-white*
- (gfg:foreground-color gc) gfg:*color-black*)
- (let ((points-list (coordinates->points coord-seq)))
+ (when (target-of medium)
+ (gfw:with-graphics-context (gc (target-of medium))
+ (let ((points-list (coordinates->points coord-seq))
+ (color (ink-to-color medium (medium-ink medium))))
+ (setf (gfg:background-color gc) color
+ (gfg:foreground-color gc) color)
(if filled
(gfg:draw-filled-polygon gc points-list)
(gfg:draw-polygon gc points-list))))
@@ -202,11 +234,12 @@
(defmethod medium-draw-rectangle* ((medium graphic-forms-medium) left top right bottom filled)
#+nil (gfs::debug-format "draw-rectangle ~a ~a ~a ~a ~a~%" left top right bottom filled)
- (when (image-of medium)
- (gfw:with-graphics-context (gc (image-of medium))
- (setf (gfg:background-color gc) gfg:*color-white*
- (gfg:foreground-color gc) gfg:*color-black*)
- (let ((rect (coordinates->rectangle left top right bottom)))
+ (when (target-of medium)
+ (gfw:with-graphics-context (gc (target-of medium))
+ (let ((rect (coordinates->rectangle left top right bottom))
+ (color (ink-to-color medium (medium-ink medium))))
+ (setf (gfg:background-color gc) color
+ (gfg:foreground-color gc) color)
(if filled
(gfg:draw-filled-rectangle gc rect)
(gfg:draw-rectangle gc rect))))
@@ -229,21 +262,21 @@
(defmethod text-style-ascent (text-style (medium graphic-forms-medium))
(let ((font (font-of medium)))
(if font
- (gfw:with-graphics-context (gc (image-of medium))
+ (gfw:with-graphics-context (gc (target-of medium))
(gfg:ascent (gfg:metrics gc font)))
1)))
(defmethod text-style-descent (text-style (medium graphic-forms-medium))
(let ((font (font-of medium)))
(if font
- (gfw:with-graphics-context (gc (image-of medium))
+ (gfw:with-graphics-context (gc (target-of medium))
(gfg:descent (gfg:metrics gc font)))
1)))
(defmethod text-style-height (text-style (medium graphic-forms-medium))
(let ((font (font-of medium)))
(if font
- (gfw:with-graphics-context (gc (image-of medium))
+ (gfw:with-graphics-context (gc (target-of medium))
(gfg:height (gfg:metrics gc font)))
1)))
@@ -252,7 +285,7 @@
(width 1)
(text (normalize-text-data char)))
(if font
- (gfw:with-graphics-context (gc (image-of medium))
+ (gfw:with-graphics-context (gc (target-of medium))
(setf (gfg:font gc) font)
(setf width (gfs:size-width (gfg:text-extent gc text)))))
width))
@@ -260,34 +293,30 @@
(defmethod text-style-width (text-style (medium graphic-forms-medium))
(let ((font (font-of medium)))
(if font
- (gfw:with-graphics-context (gc (image-of medium))
+ (gfw:with-graphics-context (gc (target-of medium))
(gfg:average-char-width (gfg:metrics gc font)))
1)))
(defmethod text-size ((medium graphic-forms-medium) string &key text-style (start 0) end)
(setf string (normalize-text-data string))
-#|
- (setf text-style (merge-text-styles (or text-style (make-text-style nil nil nil))
- (medium-default-text-style medium)))
-|#
- ;; FIXME: handle embedded newlines
- ;;
- (let ((font (font-of medium)))
- (if font
- (gfw:with-graphics-context (gc (image-of medium))
- (let ((metrics (gfg:metrics gc font))
- (width (gfs:size-width (gfg:text-extent gc (subseq string
- start
- (or end (length string)))))))
- (values width
- (gfg:height metrics)
- width
- (gfg:height metrics)
- (gfg:ascent metrics))))
- (values 1 1 1 1 1))))
+ (setf text-style (or text-style (make-text-style nil nil nil)))
+ (setf text-style
+ (merge-text-styles text-style (medium-default-text-style medium)))
+ (gfw:with-graphics-context (gc (target-of medium))
+ (let* ((font (text-style-to-font gc text-style nil))
+ (metrics (gfg:metrics gc font))
+ (width (gfs:size-width (gfg:text-extent gc (subseq string
+ start
+ (or end (length string)))))))
+ (values width
+ (gfg:height metrics)
+ width
+ (gfg:height metrics)
+ (gfg:ascent metrics)))))
(defmethod climi::text-bounding-rectangle*
((medium graphic-forms-medium) string &key text-style (start 0) end)
+ ;; fixme, completely wrong
(text-size medium string :text-style text-style :start start :end end))
(defmethod medium-draw-text* ((medium graphic-forms-medium) string x y
@@ -295,15 +324,18 @@
align-x align-y
toward-x toward-y transform-glyphs)
#+nil (gfs::debug-format "medium-draw-text: ~d, ~d ~s~%" x y string)
- (when (image-of medium)
+ (when (target-of medium)
(setf string (normalize-text-data string))
- (gfw:with-graphics-context (gc (image-of medium))
+ (gfw:with-graphics-context (gc (target-of medium))
(let ((font (font-of medium)))
(if font
(setf (gfg:font gc) font))
- (gfg:draw-text gc
- (subseq string start (or end (length string)))
- (gfs:make-point :x x :y y))))
+ (let ((h (gfg:height (gfg:metrics gc font)))
+ (x (round-coordinate x))
+ (y (round-coordinate y)))
+ (gfg:draw-text gc
+ (subseq string start (or end (length string)))
+ (gfs:make-point :x x :y (- y h))))))
(add-medium-to-render medium)))
(defmethod medium-buffering-output-p ((medium graphic-forms-medium))
@@ -318,15 +350,17 @@
())
(defmethod medium-finish-output ((medium graphic-forms-medium))
- (render-medium medium))
+ (when (image-of medium)
+ (render-medium-buffer medium)))
(defmethod medium-force-output ((medium graphic-forms-medium))
- (render-medium medium))
+ (when (image-of medium)
+ (render-medium-buffer medium)))
(defmethod medium-clear-area ((medium graphic-forms-medium) left top right bottom)
- (when (image-of medium)
+ (when (target-of medium)
(let ((rect (coordinates->rectangle left top right bottom)))
- (gfw:with-graphics-context (gc (image-of medium))
+ (gfw:with-graphics-context (gc (target-of medium))
(setf (gfg:background-color gc) gfg:*color-white*
(gfg:foreground-color gc) gfg:*color-white*)
(gfg:draw-filled-rectangle gc rect)))
--- /project/mcclim/cvsroot/mcclim/Backends/Graphic-Forms/port.lisp 2007/03/14 23:49:05 1.3
+++ /project/mcclim/cvsroot/mcclim/Backends/Graphic-Forms/port.lisp 2007/03/16 14:42:49 1.4
@@ -59,6 +59,7 @@
:accessor item
:initarg :item
:initform nil)
+ (callback :initarg :value-changed-callback :accessor callback)
(command
:accessor command
:initarg :command
@@ -408,12 +409,35 @@
(setf (event (port self)) (make-instance 'window-manager-delete-event
:sheet (sheet mirror))))
+;; copy&paste from port.lisp|CLX:
+(defun sheet-desired-ink (sheet)
+ (typecase sheet
+ (sheet-with-medium-mixin
+ (medium-background sheet))
+ (basic-pane
+ ;; CHECKME [is this sensible?] seems to be
+ (let ((background (pane-background sheet)))
+ (if (typep background 'color)
+ background
+ +white+)))
+ (t
+ +white+)))
+
(defmethod gfw:event-paint ((self sheet-event-dispatcher) mirror gc rect)
(declare (ignore gc))
(let ((sheet (sheet mirror)))
- (setf (event (port self)) (make-instance 'window-repaint-event
- :sheet sheet
- :region (translate-rectangle rect)))))
+ (when (and (typep sheet 'sheet-with-medium-mixin)
+ (not (image-of (sheet-medium sheet))))
+ (gfw:with-graphics-context (gc mirror)
+ (let ((c (ink-to-color (sheet-medium sheet)
+ (sheet-desired-ink sheet))))
+ (setf (gfg:background-color gc) c
+ (gfg:foreground-color gc) c))
+ (gfg:draw-filled-rectangle gc rect)))
+ (setf (event (port self))
+ (make-instance 'window-repaint-event
+ :sheet sheet
+ :region (translate-rectangle rect)))))
(defun generate-configuration-event (mirror pnt size)
(make-instance 'window-configuration-event
@@ -431,15 +455,26 @@
(let ((sheet (sheet mirror)))
(if (and sheet (subtypep (class-of sheet) 'sheet-with-medium-mixin))
(let ((medium (climi::sheet-medium sheet)))
- (if medium
+ (if (and medium (image-of medium))
(resize-medium-buffer medium size))))
(setf (event (port self))
(generate-configuration-event mirror (gfw:location mirror) size))))
+(defclass gadget-event (window-event) ())
+(defclass button-pressed-event (gadget-event) ())
+
(defmethod gfw:event-select ((self pane-event-dispatcher) mirror)
- (setf (event (port self)) (make-instance 'menu-clicked-event
- :sheet (sheet (gfw:owner mirror))
- :item (sheet mirror))))
+ (setf (event (port self))
+ (typecase mirror
+ (gfw-button
+ (make-instance 'button-pressed-event :sheet (sheet mirror)))
+ (t
+ (make-instance 'menu-clicked-event
+ :sheet (sheet (gfw:owner mirror))
+ :item (sheet mirror))))))
+
+(defmethod handle-event ((pane push-button) (event button-pressed-event))
+ (activate-callback pane (gadget-client pane) (gadget-id pane)))
(defun translate-button-name (name)
(case name
@@ -553,8 +588,9 @@
(if pane
(let ((menu-item (item pane)))
(if menu-item
- (if (eql (command-menu-item-type menu-item) :command)
- (climi::throw-object-ptype menu-item 'menu-item)))))))
+ (if (eql (command-menu-item-type menu-item) :command)
+ (climi::throw-object-ptype menu-item 'menu-item))
+ (funcall (callback pane) pane nil))))))
(defmethod handle-event ((pane gfw-menu-pane) (event menu-clicked-event))
(handle-menu-clicked-event event))
--- /project/mcclim/cvsroot/mcclim/Backends/Graphic-Forms/utils.lisp 2007/03/14 23:33:25 1.1
+++ /project/mcclim/cvsroot/mcclim/Backends/Graphic-Forms/utils.lisp 2007/03/16 14:42:51 1.2
@@ -44,10 +44,8 @@
:width (round-coordinate (- right left))
:height (round-coordinate (- bottom top))))
-(defun coordinates->points (list)
- (cond
- ((null list) (values))
- ((and (car list) (cdr list))
- (concatenate 'list (list (gfs:make-point :x (round-coordinate (car list))
- :y (round-coordinate (car (cdr list)))))
- (coordinates->points (cdr (cdr list)))))))
+(defun coordinates->points (seq)
+ (loop for i from 2 below (length seq) by 2
+ collect
+ (gfs:make-point :x (round-coordinate (elt seq i))
+ :y (round-coordinate (elt seq (+ i 1))))))