Update of /project/mcclim/cvsroot/mcclim/Backends/gtkairo In directory clnet:/tmp/cvs-serv1773/Backends/gtkairo
Modified Files: event.lisp ffi.lisp frame-manager.lisp gadgets.lisp port.lisp Log Message:
Added the tab layout.
* Extensions/tab-layout.lisp: New file. * Examples/tabdemo.lisp: New file. * mcclim.asd (CLIM): Added Extensions/tab-layout.lisp. (CLIM-EXAMPLES): Add tabdemo.lisp * package.lisp (CLIM-TAB-LAYOUT): New package. * Examples/demodemo.lisp: Added a button for the tabdemo. * Doc/make-docstrings.lisp: Process the clim-tab-layout package. * Doc/mcclim.texi: New chapter about the tab-layout. * Backends/CLX/frame-manager.lisp (GENERATE-STANDARD-PANE-SPECS, FIND-CONCRETE-PANE-CLASS): Obey define-abstract-pane-mapping even for names not the internal packages. * Backends/gtkairo/event.lisp (TAB-BUTTON-HANDLER): New. * Backends/gtkairo/frame-manager.lisp ((MAKE-PANE-2 TAB-LAYOUT-PANE)): New. (RESOLVE-ABSTRACT-PANE-NAME): Renamed. * Backends/gtkairo/gadgets.lisp (TAB-BUTTON-EVENT, TAB-PRESS-EVENT, TAB-RELEASE-EVENT, GTK-TAB-LAYOUT): New classes. (REALIZE-NATIVE-WIDGET, CONTAINER-PUT, (SETF CLIM-TAB-LAYOUT:TAB-LAYOUT-PAGES), REORDER-NOTEBOOK-PAGES, CONTAINER-MOVE, ALLOCATE-SPACE, (SETF CLIM-TAB-LAYOUT:TAB-LAYOUT-ENABLED-PAGE), CONNECT-NATIVE-SIGNALS, CLIM-TAB-LAYOUT:NOTE-TAB-PAGE-CHANGED, SET-TAB-PAGE-ATTRIBUTES, HANDLE-EVENT): New functions and methods on gtk-tab-layout. (PARENT-AD-HOC-PRESENTATION): New class. * Backends/gtkairo/port.lisp (GTK-WIDGET-MODIFY-FG): New function. * Backends/gtkairo/ffi.lisp: Regenerated.
--- /project/mcclim/cvsroot/mcclim/Backends/gtkairo/event.lisp 2006/12/27 14:47:24 1.18 +++ /project/mcclim/cvsroot/mcclim/Backends/gtkairo/event.lisp 2007/02/04 12:55:43 1.19 @@ -307,6 +307,28 @@ (t 0)))))
+(define-signal (tab-button-handler :return-type :int) (widget event) + (cffi:with-foreign-slots + ((type time button state x y x_root y_root) event gdkeventbutton) + (when (eql type GDK_BUTTON_PRESS) + ;; Hack alert: Menus don't work without this. + (gdk_pointer_ungrab GDK_CURRENT_TIME)) + (setf *last-seen-button* button) + (let ((page (widget->sheet widget *port*))) + (enqueue (make-instance + (if (eql type GDK_BUTTON_PRESS) + 'tab-press-event + 'tab-release-event) + :button (ecase button + (1 +pointer-left-button+) + (2 +pointer-middle-button+) + (3 +pointer-right-button+) + (4 +pointer-wheel-up+) + (5 +pointer-wheel-down+)) + :page page + :sheet (clim-tab-layout:tab-page-tab-layout page))))) + 1) + (define-signal enter-handler (widget event) (cffi:with-foreign-slots ((time state x y x_root y_root) event gdkeventcrossing) --- /project/mcclim/cvsroot/mcclim/Backends/gtkairo/ffi.lisp 2006/12/26 16:44:46 1.15 +++ /project/mcclim/cvsroot/mcclim/Backends/gtkairo/ffi.lisp 2007/02/04 12:55:44 1.16 @@ -677,11 +677,6 @@ (arg0 :pointer) ;cairo_t * )
-(defcfun "cairo_stroke_preserve" - :void - (arg0 :pointer) ;cairo_t * - ) - (defcfun "cairo_stroke_extents" :void (arg0 :pointer) ;cairo_t * @@ -691,6 +686,11 @@ (arg4 :pointer) ;double * )
+(defcfun "cairo_stroke_preserve" + :pointer + (arg0 :pointer) ;cairo_t * + ) + (defcfun "cairo_surface_create_similar" :pointer (arg0 :pointer) ;cairo_surface_t * @@ -1115,6 +1115,11 @@ (value :double) ;gdouble )
+(defcfun "gtk_bin_get_child" + :pointer + (bin :pointer) ;GtkBin * + ) + (defcfun "gtk_button_new_with_label" :pointer (label :string) ;const gchar * @@ -1152,6 +1157,20 @@ (widget :pointer) ;GtkWidget * )
+(defcfun "gtk_event_box_new" :pointer) + +(defcfun "gtk_event_box_set_above_child" + :void + (event_box :pointer) ;GtkEventBox * + (above_child :int) ;gboolean + ) + +(defcfun "gtk_event_box_set_visible_window" + :void + (event_box :pointer) ;GtkEventBox * + (visible_window :int) ;gboolean + ) + (defcfun "gtk_events_pending" :int)
(defcfun "gtk_fixed_move" @@ -1203,6 +1222,17 @@ (argv :pointer) ;char *** )
+(defcfun "gtk_label_new" + :pointer + (str :string) ;const gchar * + ) + +(defcfun "gtk_label_set_text" + :void + (label :pointer) ;GtkLabel * + (str :string) ;const gchar * + ) + (defcfun "gtk_list_store_append" :void (list_store :pointer) ;GtkListStore * @@ -1265,6 +1295,53 @@ (child :pointer) ;GtkWidget * )
+(defcfun "gtk_notebook_append_page" + :int + (notebook :pointer) ;GtkNotebook * + (child :pointer) ;GtkWidget * + (tab_label :pointer) ;GtkWidget * + ) + +(defcfun "gtk_notebook_get_current_page" + :int + (notebook :pointer) ;GtkNotebook * + ) + +(defcfun "gtk_notebook_get_tab_label" + :pointer + (notebook :pointer) ;GtkNotebook * + (child :pointer) ;GtkWidget * + ) + +(defcfun "gtk_notebook_insert_page" + :int + (notebook :pointer) ;GtkNotebook * + (child :pointer) ;GtkWidget * + (tab_label :pointer) ;GtkWidget * + (position :int) ;gint + ) + +(defcfun "gtk_notebook_new" :pointer) + +(defcfun "gtk_notebook_remove_page" + :void + (notebook :pointer) ;GtkNotebook * + (page_num :int) ;gint + ) + +(defcfun "gtk_notebook_reorder_child" + :void + (notebook :pointer) ;GtkNotebook * + (child :pointer) ;GtkWidget * + (position :int) ;gint + ) + +(defcfun "gtk_notebook_set_current_page" + :void + (notebook :pointer) ;GtkNotebook * + (page_num :int) ;gint + ) + (defcfun "gtk_radio_button_get_group" :pointer (radio_button :pointer) ;GtkRadioButton * @@ -1454,6 +1531,11 @@ (widget :pointer) ;GtkWidget * )
+(defcfun "gtk_widget_get_parent" + :pointer + (widget :pointer) ;GtkWidget * + ) + (defcfun "gtk_widget_get_pointer" :void (widget :pointer) ;GtkWidget * @@ -1490,6 +1572,18 @@ (color :pointer) ;const GdkColor * )
+(defcfun "gtk_widget_modify_fg" + :void + (widget :pointer) ;GtkWidget * + (state GtkStateType) + (color :pointer) ;const GdkColor * + ) + +(defcfun "gtk_widget_queue_draw" + :void + (widget :pointer) ;GtkWidget * + ) + (defcfun "gtk_widget_set_double_buffered" :void (widget :pointer) ;GtkWidget * --- /project/mcclim/cvsroot/mcclim/Backends/gtkairo/frame-manager.lisp 2006/12/10 19:33:05 1.10 +++ /project/mcclim/cvsroot/mcclim/Backends/gtkairo/frame-manager.lisp 2007/02/04 12:55:44 1.11 @@ -24,7 +24,9 @@ (defclass gtkairo-frame-manager (frame-manager) ())
-(defun frob-stupid-type-spec (type) +;; fixme! we're supposed to dispatch on the abstract name, not resolve +;; it to the (incorrect) concrete generic class name and dispatch on that. +(defun resolve-abstract-pane-name (type) (when (get type 'climi::concrete-pane-class-name) (setf type (get type 'climi::concrete-pane-class-name))) (class-name @@ -38,7 +40,7 @@ (defmethod make-pane-1 ((fm gtkairo-frame-manager) (frame application-frame) type &rest initargs) (apply #'make-pane-2 - (frob-stupid-type-spec type) + (resolve-abstract-pane-name type) :frame frame :manager fm :port (port frame) @@ -99,6 +101,10 @@ (defmethod make-pane-2 ((type (eql 'clim:generic-list-pane)) &rest initargs) (apply #'make-instance 'gtk-list initargs))
+(defmethod make-pane-2 + ((type (eql 'clim-tab-layout:tab-layout-pane)) &rest initargs) + (apply #'make-instance 'gtk-tab-layout initargs)) + (defmethod make-pane-2 ((type (eql 'clim:label-pane)) &rest initargs) (apply #'make-instance 'gtk-label-pane initargs))
--- /project/mcclim/cvsroot/mcclim/Backends/gtkairo/gadgets.lisp 2006/12/27 14:47:24 1.20 +++ /project/mcclim/cvsroot/mcclim/Backends/gtkairo/gadgets.lisp 2007/02/04 12:55:44 1.21 @@ -37,6 +37,13 @@
(defclass list-selection-event (gadget-event) ())
+(defclass tab-button-event (gadget-event) + ((page :initarg :page :accessor event-page) + (button :initarg :button :accessor event-button))) + +(defclass tab-press-event (tab-button-event) ()) +(defclass tab-release-event (tab-button-event) ()) +
;;;; Classes
@@ -80,6 +87,11 @@ (label-pane-extra-width :accessor label-pane-extra-width) (label-pane-extra-height :accessor label-pane-extra-height)))
+(defclass gtk-tab-layout (native-widget-mixin clim-tab-layout:tab-layout) + ((tab-layout-extra-width :accessor tab-layout-extra-width) + (tab-layout-extra-height :accessor tab-layout-extra-height))) + + ;;;; Constructors
(defmethod realize-native-widget ((sheet gtk-button)) @@ -277,6 +289,97 @@ ((pane gtk-list) (event pointer-button-release-event)) nil)
+(defmethod realize-native-widget ((sheet gtk-tab-layout)) + (let ((result (gtk_notebook_new)) + (dummy-child (gtk_fixed_new)) + (dummy-label (gtk_label_new "foo"))) + (gtk_notebook_append_page result dummy-child dummy-label) + (gtk_widget_show dummy-child) + (let* ((q + (reduce (lambda (x y) + (space-requirement-combine #'max x y)) + (mapcar #'compose-space (sheet-children sheet)) + :initial-value + (make-space-requirement + :width 0 :min-width 0 :max-width 0 + :height 0 :min-height 0 :max-height 0))) + (width1 (space-requirement-width q)) + (height1 (space-requirement-height q))) + (gtk_widget_set_size_request dummy-child width1 height1) + (cffi:with-foreign-object (r 'gtkrequisition) + (gtk_widget_size_request result r) + (cffi:with-foreign-slots ((width height) r gtkrequisition) + (setf (tab-layout-extra-width sheet) (- width width1)) + (setf (tab-layout-extra-height sheet) (- height height1)))) + (gtk_notebook_remove_page result 0)) + result)) + +(defmethod container-put ((parent gtk-tab-layout) parent-widget child x y) + (declare (ignore x y)) + (let* ((page (clim-tab-layout:sheet-to-page + (widget->sheet child (port parent)))) + (index (position page (clim-tab-layout:tab-layout-pages parent))) + (label (gtk_label_new (clim-tab-layout:tab-page-title page))) + (box (gtk_event_box_new))) + (gtk_event_box_set_visible_window box 0) + (gtk_container_add box label) + (gtk_widget_show_all box) + ;; naja, ein sheet ist das nicht + (setf (widget->sheet box (port parent)) page) + (connect-signal box "button-press-event" 'tab-button-handler) + (gtk_widget_show child) + (gtk_notebook_insert_page parent-widget child box index) + (set-tab-page-attributes page label) + ;; fixme: + (reorder-notebook-pages parent) + (setf (clim-tab-layout:tab-layout-enabled-page parent) + (clim-tab-layout:tab-layout-enabled-page parent)))) + +(defmethod (setf clim-tab-layout:tab-layout-pages) + :after + (newval (parent gtk-tab-layout)) + (declare (ignore newval)) + (reorder-notebook-pages parent)) + +(defun reorder-notebook-pages (parent) + (loop + for page in (clim-tab-layout:tab-layout-pages parent) + for i from 0 + do + (let* ((pane (clim-tab-layout:tab-page-pane page)) + (mirror (climi::port-lookup-mirror (port parent) pane))) + (when mirror + (gtk_notebook_reorder_child + (native-widget parent) + (mirror-widget mirror) + i))))) + +(defmethod container-move ((parent gtk-tab-layout) parent-widget child x y) + (declare (ignore parent-widget child x y))) + +(defmethod allocate-space ((pane gtk-tab-layout) width height) + (dolist (page (clim-tab-layout:tab-layout-pages pane)) + (let ((child (clim-tab-layout:tab-page-pane page))) + (move-sheet child 0 0) ;dummy + (allocate-space child + (- width (tab-layout-extra-width pane)) + (- height (tab-layout-extra-height pane)))))) + +(defmethod allocate-space :around ((pane gtk-tab-layout) width height) + ;; ARGH! Force the around method in panes.lisp to c-n-m. + (setf (climi::pane-current-width pane) nil) + (call-next-method)) + +(defmethod (setf clim-tab-layout:tab-layout-enabled-page) + :after + (newval (parent gtk-tab-layout)) + (when (and (native-widget parent) newval) + ;; fixme: + (reorder-notebook-pages parent) + (gtk_notebook_set_current_page + (native-widget parent) + (position newval (clim-tab-layout:tab-layout-pages parent))))) + (defun option-pane-set-active (sheet widget) (gtk_combo_box_set_active widget @@ -458,6 +561,10 @@ ;; no signals )
+(defmethod connect-native-signals ((sheet gtk-tab-layout) widget) + ;; no signals + ) + (defmethod connect-native-signals ((sheet gtk-option-pane) widget) (connect-signal widget "changed" 'magic-clicked-handler))
@@ -510,6 +617,66 @@ (:command (climi::throw-object-ptype item 'menu-item)))))
+;;;(defmethod handle-event +;;; ((pane gtk-tab-layout) (event tab-release-event)) +;;; ) + +(defclass parent-ad-hoc-presentation (climi::ad-hoc-presentation) + ((ad-hoc-children :initarg :ad-hoc-children + :reader output-record-children))) + +(defmethod clim-tab-layout:note-tab-page-changed ((layout gtk-tab-layout) page) + (with-gtk () + (let* ((pane (clim-tab-layout:tab-page-pane page)) + (mirror (climi::port-lookup-mirror (port layout) pane))) + (when mirror + (let ((box (gtk_notebook_get_tab_label (native-widget layout) + (mirror-widget mirror)))) + (set-tab-page-attributes page (gtk_bin_get_child box))))))) + +(defun set-tab-page-attributes (page label) + ;; fixme: wieso funktioniert das in der tabdemo, nicht aber in beirc? + (let ((ink (getf (clim-tab-layout:tab-page-drawing-options page) :ink))) + (when ink + (gtk-widget-modify-fg label ink))) + (gtk_label_set_text label (clim-tab-layout:tab-page-title page)) + (gtk_widget_queue_draw label)) + +(defmethod handle-event + ((pane gtk-tab-layout) (event tab-press-event)) + (let* ((page (event-page event)) + (ptype (clim-tab-layout:tab-page-presentation-type page)) + (inner-presentation + (make-instance 'climi::ad-hoc-presentation + :object page + :single-box t + :type 'clim-tab-layout:tab-page)) + (presentation + (make-instance 'parent-ad-hoc-presentation + :ad-hoc-children (vector inner-presentation) + :object page + :single-box t + :type ptype))) + (case (event-button event) + (#.+pointer-right-button+ + (call-presentation-menu + presentation + *input-context* + *application-frame* + pane + 42 42 + :for-menu t + :label (format nil "Operation on ~A" ptype))) + (#.+pointer-left-button+ + (throw-highlighted-presentation + presentation + *input-context* + (make-instance 'pointer-button-press-event + :sheet pane + :x 42 :y 42 + :modifier-state 0 + :button (event-button event))))))) + (defmethod handle-event ((pane gtk-nonmenu) (event magic-gadget-event)) (funcall (gtk-nonmenu-callback pane) pane nil)) --- /project/mcclim/cvsroot/mcclim/Backends/gtkairo/port.lisp 2006/12/25 21:34:57 1.15 +++ /project/mcclim/cvsroot/mcclim/Backends/gtkairo/port.lisp 2007/02/04 12:55:44 1.16 @@ -244,6 +244,10 @@ (with-gdkcolor (c color) (gtk_widget_modify_bg widget 0 c)))
+(defun gtk-widget-modify-fg (widget color) + (with-gdkcolor (c color) + (gtk_widget_modify_fg widget 0 c))) + ;; copy&paste from port.lisp|CLX: (defun sheet-desired-color (sheet) (typecase sheet