[mcclim-cvs] CVS mcclim/Backends/Graphic-Forms

dlichteblau dlichteblau at common-lisp.net
Fri Mar 16 14:42:51 UTC 2007


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))))))




More information about the Mcclim-cvs mailing list