chiark / gitweb /
Bug fix
[clg] / gtk / gtkcontainer.lisp
1 ;; Common Lisp bindings for GTK+ v2.x
2 ;; Copyright 2000-2005 Espen S. Johnsen <espen@users.sf.net>
3 ;;
4 ;; Permission is hereby granted, free of charge, to any person obtaining
5 ;; a copy of this software and associated documentation files (the
6 ;; "Software"), to deal in the Software without restriction, including
7 ;; without limitation the rights to use, copy, modify, merge, publish,
8 ;; distribute, sublicense, and/or sell copies of the Software, and to
9 ;; permit persons to whom the Software is furnished to do so, subject to
10 ;; the following conditions:
11 ;;
12 ;; The above copyright notice and this permission notice shall be
13 ;; included in all copies or substantial portions of the Software.
14 ;;
15 ;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 ;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 ;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 ;; IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 ;; CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 ;; TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 ;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
23 ;; $Id: gtkcontainer.lisp,v 1.23 2007-01-14 23:18:17 espen Exp $
24
25 (in-package "GTK")
26
27 (defgeneric container-add (container widget &rest args))
28 (defgeneric container-remove (container widget))
29 (defgeneric container-all-children (container))
30 (defgeneric container-internal-children (container))
31 (defgeneric (setf container-children) (children container))
32
33
34 (defun initial-add (object function initargs key pkey)
35   (loop 
36    as (initarg value . rest) = initargs then rest
37    do (cond
38        ((eq initarg key) (funcall function object value))
39        ((eq initarg pkey) (mapc #'(lambda (value)
40                                     (funcall function object value))
41                                 value)))
42        while rest))
43
44 (defun initial-apply-add (object function initargs key pkey)
45   (initial-add object #'(lambda (object value)
46                           (apply function object (mklist value)))
47                initargs key pkey))
48
49
50 (defmethod shared-initialize ((container container) names &rest initargs 
51                               &key child children child-args 
52                               (show-children nil show-children-p))
53   (declare (ignore names child children))
54   (when show-children-p
55     (if (not show-children)
56         (setf (user-data container 'show-recursive-p) nil)
57       (signal-connect container 'show #'container-show-recursive 
58        :object t :remove t)))
59
60   (call-next-method)
61   (initial-add container 
62    #'(lambda (container args) 
63        (apply #'container-add container (append (mklist args) child-args)))
64    initargs :child :children))
65
66
67 (defmethod compute-signal-function ((container container) signal function object args)
68   (declare (ignore signal))
69   (if (eq object :children)
70       #'(lambda (&rest emission-args)
71           (let ((all-args (nconc (rest emission-args) args)))
72             (container-foreach container
73              #'(lambda (child)
74                  (apply function child all-args)))))
75     (call-next-method)))
76
77
78 (defbinding %container-add () nil
79   (container container)
80   (widget widget))
81
82 (defmethod container-add ((container container) (widget widget) &rest args)
83   (%container-add container widget)
84   (when args
85     (setf
86      (slot-value widget 'child-properties)
87      (apply
88       #'make-instance
89       (gethash (class-of container) *container-to-child-class-mappings*)
90       :parent container :child widget args))))
91
92 (defmethod container-add ((container container) (widgets list) &rest args)
93   (dolist (widget widgets)
94     (apply #'container-add container widget args)))
95
96 (defbinding %container-remove () nil
97   (container container)
98   (widget widget))
99
100 (defmethod container-remove ((container container) (widget widget))
101   (%container-remove container widget)
102   (slot-makunbound widget 'child-properties))
103
104
105 (defbinding %container-child-get-property () nil
106   (container container)
107   (child widget)
108   (property-name string)
109   (value gvalue))
110
111 (defbinding %container-child-set-property () nil
112   (container container)
113   (child widget)
114   (property-name string)
115   (value gvalue))
116   
117
118 (defbinding container-check-resize () nil
119   (container container))
120
121 (define-callback-marshal %foreach-callback nil (widget))
122
123 (defbinding %container-foreach (container callback-id) nil
124   (container container)
125   (%foreach-callback callback)
126   (callback-id unsigned-int))
127
128 (defun container-foreach (container function)
129   (with-callback-function (id function)
130     (%container-foreach container id)))
131
132 (defbinding %container-forall (container callback-id) nil
133   (container container)
134   (%foreach-callback callback)
135   (callback-id unsigned-int))
136
137 (defun container-forall (container function)
138   (with-callback-function (id function)
139     (%container-forall container id)))
140
141 (defun map-container (seqtype func container)
142   (case seqtype
143     ((nil)
144      (container-foreach container func)
145      nil)
146     (list
147      (let ((list nil))
148        (container-foreach container
149         #'(lambda (child)
150             (push (funcall func child) list)))
151        (nreverse list)))
152     (t
153      (let ((seq (make-sequence seqtype (container-length container)))
154            (index 0))
155        (container-foreach container
156         #'(lambda (child)
157             (setf (elt seq index) (funcall func child))
158             (incf index)))
159        seq))))
160
161 (defmethod container-all-children ((container container))
162   (let ((internal ()))
163     (container-forall container 
164      #'(lambda (child)
165          (push child internal)))
166     (nreverse internal)))
167
168 (defmethod container-internal-children ((container container))
169   (let ((external-children (container-children container))
170         (all-children (container-all-children container)))
171     (loop
172      for child in all-children
173      unless (find child external-children)
174      collect child)))
175
176 (defmethod (setf container-children) (children (container container))
177   (dolist (child (container-children container))
178     (container-remove container child))
179   (dolist (child children)
180     (apply #'container-add container (mklist child)))
181   children)
182
183 (defun container-length (container)
184   (let ((n 0))
185     (container-foreach container
186      #'(lambda (child)
187          (declare (ignore child))
188          (incf n)))
189     n))
190
191 (defbinding container-resize-children () nil
192   (container container))
193
194 (defbinding container-propagate-expose () nil
195   (container container)
196   (child widget)
197   (event gdk:expose-event))
198
199
200 (defbinding %container-get-focus-chain () boolean
201   (container container)
202   (focusable-widgets (glist widget) :out))
203
204 (defun container-focus-chain (container)
205   (multiple-value-bind (chain-set-p focusable-widgets)
206       (%container-get-focus-chain container)
207     (and chain-set-p focusable-widgets)))
208
209 (defbinding %container-set-focus-chain () nil
210   (container container)
211   (focusable-widgets (glist widget)))
212
213 (defbinding %container-unset-focus-chain () nil
214   (container container))
215
216 (defun (setf container-focus-chain) (focusable-widgets container)
217   (if (null focusable-widgets)
218       (%container-unset-focus-chain container)
219     (%container-set-focus-chain container focusable-widgets)))
220
221 (defgeneric container-show-recursive (container))
222
223 (defmethod container-show-recursive ((container container))
224   "Recursively show any child widgets except widgets explicit hidden during construction."
225   (labels ((recursive-show (widget)
226              (when (typep widget 'container)
227                (if (not (user-data-p widget 'show-recursive-p))
228                    (container-foreach widget #'recursive-show)
229                  (unset-user-data widget 'show-recursive-p)))
230              (unless (widget-hidden-p widget)
231                (widget-show widget))))
232     (container-foreach container #'recursive-show)))