chiark / gitweb /
Added manually defined slots to autogenerated class definitions
[clg] / gtk / gtkobject.lisp
CommitLineData
560af5c5 1;; Common Lisp bindings for GTK+ v2.0
f86d391e 2;; Copyright (C) 1999-2001 Espen S. Johnsen <esj@stud.cs.uit.no>
560af5c5 3;;
4;; This library is free software; you can redistribute it and/or
5;; modify it under the terms of the GNU Lesser General Public
6;; License as published by the Free Software Foundation; either
7;; version 2 of the License, or (at your option) any later version.
8;;
9;; This library is distributed in the hope that it will be useful,
10;; but WITHOUT ANY WARRANTY; without even the implied warranty of
11;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12;; Lesser General Public License for more details.
13;;
14;; You should have received a copy of the GNU Lesser General Public
15;; License along with this library; if not, write to the Free Software
16;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
f86d391e 18;; $Id: gtkobject.lisp,v 1.9 2001-05-29 16:00:52 espen Exp $
560af5c5 19
20
21(in-package "GTK")
22
8bf63d9f 23
560af5c5 24;;;; Misc utils
25
f86d391e 26; (defun name-to-string (name)
27; (substitute #\_ #\- (string-downcase (string name))))
560af5c5 28
f86d391e 29; (defun string-to-name (name &optional (package "KEYWORD"))
30; (intern (substitute #\- #\_ (string-upcase name)) package))
560af5c5 31
32
968da4bc 33;;; Argument stuff - to be removed soon
560af5c5 34
35(deftype arg () 'pointer)
36
37(defconstant +arg-type-offset+ 0)
38(defconstant +arg-name-offset+ 4)
39(defconstant +arg-value-offset+ 8)
40(defconstant +arg-size+ 16)
41
f86d391e 42(defbinding arg-new () arg
560af5c5 43 (type type-number))
44
f86d391e 45(defbinding %arg-free () nil
560af5c5 46 (arg arg)
47 (free-contents boolean))
48
49(defun arg-free (arg free-contents &optional alien)
50 (cond
51 (alien (%arg-free arg free-contents))
52 (t
53 (unless (null-pointer-p arg)
54 (when free-contents
55 (funcall
f86d391e 56 (intern-destroy-function (type-from-number (arg-type arg)))
560af5c5 57 arg +arg-value-offset+))
58 (deallocate-memory arg)))))
59
f86d391e 60(defbinding %arg-reset () nil
560af5c5 61 (arg arg))
62
63(defun arg-name (arg)
f86d391e 64 (funcall (intern-reader-function 'string) arg +arg-name-offset+))
560af5c5 65
66(defun (setf arg-name) (name arg)
f86d391e 67 (funcall (intern-writer-function 'string) name arg +arg-name-offset+)
560af5c5 68 name)
69
70(defun arg-type (arg)
71 (system:sap-ref-32 arg +arg-type-offset+))
72
73(defun (setf arg-type) (type arg)
74 (setf (system:sap-ref-32 arg +arg-type-offset+) type))
75
76(defun arg-value (arg &optional (type (type-from-number (arg-type arg))))
f86d391e 77 (funcall (intern-reader-function type) arg +arg-value-offset+))
560af5c5 78
79;; One should never call this function on an arg whose value is already set
80(defun (setf arg-value)
81 (value arg &optional (type (type-from-number (arg-type arg))))
f86d391e 82 (funcall (intern-writer-function type) value arg +arg-value-offset+)
560af5c5 83 value)
84
85(defun (setf return-arg-value)
86 (value arg &optional (type (type-from-number (arg-type arg))))
87 ; this is probably causing a memory leak
f86d391e 88 (funcall (intern-writer-function type) value (arg-value arg 'pointer) 0)
560af5c5 89 value)
90
91(defun arg-array-ref (arg0 index)
92 (system:sap+ arg0 (* index +arg-size+)))
93
94
95;;;; Superclass for the gtk class hierarchy
96
97(eval-when (:compile-toplevel :load-toplevel :execute)
f86d391e 98 (init-types-in-library "/opt/gnome/lib/libgtk-x11-1.3.so")
99
100 (defclass %object (gobject)
560af5c5 101 ()
560af5c5 102 (:metaclass gobject-class)
103 (:alien-name "GtkObject")))
104
105
f86d391e 106(defmethod shared-initialize ((object %object) names &rest initargs
107 &key signals)
560af5c5 108 (declare (ignore initargs names))
109 (call-next-method)
f86d391e 110 (%object-sink object)
560af5c5 111 (dolist (signal signals)
112 (apply #'signal-connect object signal)))
113
f86d391e 114(defmethod initialize-proxy ((object %object) &rest initargs &key location)
560af5c5 115 (declare (ignore initargs))
116 (call-next-method)
f86d391e 117 (%object-sink location))
560af5c5 118
f86d391e 119(defbinding %object-sink () nil
120 (object %object))
560af5c5 121
560af5c5 122
aace61f5 123;;;; Main loop, timeouts and idle functions
560af5c5 124
125(declaim (inline events-pending-p main-iteration))
126
f86d391e 127(defbinding (events-pending-p "gtk_events_pending") () boolean)
560af5c5 128
f86d391e 129(defbinding get-current-event () gdk:event)
aace61f5 130
f86d391e 131(defbinding main-do-event () nil
560af5c5 132 (event gdk:event))
133
f86d391e 134(defbinding main () nil)
560af5c5 135
f86d391e 136(defbinding main-level () int)
560af5c5 137
f86d391e 138(defbinding main-quit () nil)
560af5c5 139
f86d391e 140(defbinding main-iteration-do (&optional (blocking t)) boolean
560af5c5 141 (blocking boolean))
142
143(defun main-iterate-all (&rest args)
144 (declare (ignore args))
145 (when (events-pending-p)
f86d391e 146 (main-iteration-do nil)
560af5c5 147 (main-iterate-all)))
148
149(system:add-fd-handler (gdk:event-poll-fd) :input #'main-iterate-all)
150(setq lisp::*periodic-polling-function* #'main-iterate-all)
151(setq lisp::*max-event-to-sec* 0)
152(setq lisp::*max-event-to-usec* 1000)
153
154
155
560af5c5 156;;;; Metaclass for child classes
f86d391e 157
158(defvar *container-to-child-class-mappings* (make-hash-table))
560af5c5 159
160(eval-when (:compile-toplevel :load-toplevel :execute)
f86d391e 161 (defclass child-class (virtual-slot-class))
560af5c5 162
f86d391e 163 (defclass direct-child-slot-definition (direct-virtual-slot-definition)
164 ((arg-name :reader slot-definition-arg-name)))
560af5c5 165
166 (defclass effective-child-slot-definition
167 (effective-virtual-slot-definition)))
168
169
f86d391e 170(defmethod shared-initialize ((class child-class) names &rest initargs
171 &key container)
560af5c5 172 (declare (ignore initargs))
173 (call-next-method)
f86d391e 174 (setf
175 (gethash (find-class (first container)) *container-to-child-class-mappings*)
176 class))
560af5c5 177
f86d391e 178(defmethod initialize-instance ((slotd direct-child-slot-definition)
179 &rest initargs &key arg-name)
180 (declare (ignore initargs))
181 (call-next-method)
182 (if arg-name
183 (setf (slot-value slotd 'arg-name) arg-name)
184 (error "Need argument name for slot with allocation :arg")))
560af5c5 185
186(defmethod direct-slot-definition-class ((class child-class) initargs)
187 (case (getf initargs :allocation)
188 (:arg (find-class 'direct-child-slot-definition))
189 (t (call-next-method))))
190
560af5c5 191(defmethod effective-slot-definition-class ((class child-class) initargs)
192 (case (getf initargs :allocation)
193 (:arg (find-class 'effective-child-slot-definition))
194 (t (call-next-method))))
560af5c5 195
f86d391e 196(defmethod compute-virtual-slot-accessor
560af5c5 197 ((class child-class) (slotd effective-child-slot-definition) direct-slotds)
198 (with-slots (type) slotd
f86d391e 199 (let ((arg-name (slot-definition-arg-name (first direct-slotds)))
560af5c5 200 (type-number (find-type-number type))
f86d391e 201; (reader (intern-reader-function type))
202; (writer (intern-writer-function type))
203; (destroy (intern-destroy-function type))
204 )
560af5c5 205 (list
206 #'(lambda (object)
207 (with-slots (parent child) object
208 (with-gc-disabled
209 (let ((arg (arg-new type-number)))
f86d391e 210 (setf (arg-name arg) arg-name)
211 (%container-child-getv parent child arg)
560af5c5 212 (prog1
f86d391e 213 (funcall
214 (intern-reader-function type)
215 arg +arg-value-offset+)
560af5c5 216 (arg-free arg t t))))))
217 #'(lambda (value object)
218 (with-slots (parent child) object
219 (with-gc-disabled
220 (let ((arg (arg-new type-number)))
f86d391e 221 (setf (arg-name arg) arg-name)
222 (funcall
223 (intern-writer-function type)
224 value arg +arg-value-offset+)
225 (%container-child-setv parent child arg)
226 (funcall
227 (intern-destroy-function type)
228 arg +arg-value-offset+)
560af5c5 229 (arg-free arg nil)
230 value))))))))
231
232
233(defmethod pcl::add-reader-method ((class child-class) generic-function slot-name)
234 (add-method
235 generic-function
236 (make-instance 'standard-method
237 :specializers (list (find-class 'widget))
238 :lambda-list '(widget)
239 :function #'(lambda (args next-methods)
240 (declare (ignore next-methods))
241 (child-slot-value (first args) slot-name)))))
242
243(defmethod pcl::add-writer-method
244 ((class child-class) generic-function slot-name)
245 (add-method
246 generic-function
247 (make-instance 'standard-method
248 :specializers (list (find-class t) (find-class 'widget))
249 :lambda-list '(value widget)
250 :function #'(lambda (args next-methods)
251 (declare (ignore next-methods))
252 (destructuring-bind (value widget) args
253 (setf
254 (child-slot-value widget slot-name)
255 value))))))
256
257
258(defmethod validate-superclass ((class child-class) (super pcl::standard-class))
259 (subtypep (class-name super) 'container-child))
260
261
f86d391e 262(defclass container-child ()
263 ((parent :initarg :parent :type container)
264 (child :initarg :child :type widget)))
265
266
267;;;;
268
269(defbinding %container-query-child-args () arg
270 (type-number type-number)
271 (nil null)
272 (n-args unsigned-int :out))
273
274(defun query-container-type-dependencies (type-number)
275 (let ((child-slot-types ()))
276 (multiple-value-bind (args n-args)
277 (%container-query-child-args type-number)
278 (dotimes (i n-args)
279 (push (arg-type (arg-array-ref args i)) child-slot-types)))
280 (delete-duplicates
281 (append (query-object-type-dependencies type-number) child-slot-types))))
282
283(defun default-container-child-name (container-class)
284 (intern (format nil "~A-CHILD" container-class)))
285
286(defun expand-container-type (type-number &optional slots)
287 (let* ((class (type-from-number type-number))
288 (super (supertype type-number))
289 (child-class (default-container-child-name class))
290 (child-slots ()))
291 (multiple-value-bind (args n-args)
292 (%container-query-child-args type-number)
293 (dotimes (i n-args)
294 (let* ((arg (arg-array-ref args i))
295 (arg-name (arg-name arg))
296 (slot-name (default-slot-name
297 (subseq arg-name (+ (position #\: arg-name) 2))))
298 (type (type-from-number (arg-type arg) #|t|#)))
299 (push
300 `(,slot-name
301 :allocation :arg
302 :arg-name ,arg-name
303 :accessor ,(default-slot-accessor child-class slot-name type)
304 :initarg ,(intern (string slot-name) "KEYWORD")
305 :type ,type)
306 child-slots)))
307 `(progn
308 ,(expand-gobject-type type-number slots)
309 (defclass ,child-class
310 (,(default-container-child-name super))
311 ,child-slots
312 (:metaclass child-class)
313 (:container ,class))))))
314
315(register-derivable-type
316 'container "GtkContainer"
317 :query 'query-container-type-dependencies
318 :expand 'expand-container-type)