chiark / gitweb /
Added manually defined slots to autogenerated class definitions
[clg] / gtk / gtkobject.lisp
CommitLineData
0d07716f 1;; Common Lisp bindings for GTK+ v2.0
6d27e76c 2;; Copyright (C) 1999-2001 Espen S. Johnsen <esj@stud.cs.uit.no>
0d07716f 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
6d27e76c 18;; $Id: gtkobject.lisp,v 1.9 2001/05/29 16:00:52 espen Exp $
0d07716f 19
20
21(in-package "GTK")
22
aa1ae3a5 23
0d07716f 24;;;; Misc utils
25
6d27e76c 26; (defun name-to-string (name)
27; (substitute #\_ #\- (string-downcase (string name))))
0d07716f 28
6d27e76c 29; (defun string-to-name (name &optional (package "KEYWORD"))
30; (intern (substitute #\- #\_ (string-upcase name)) package))
0d07716f 31
32
8df321c4 33;;; Argument stuff - to be removed soon
0d07716f 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
6d27e76c 42(defbinding arg-new () arg
0d07716f 43 (type type-number))
44
6d27e76c 45(defbinding %arg-free () nil
0d07716f 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
6d27e76c 56 (intern-destroy-function (type-from-number (arg-type arg)))
0d07716f 57 arg +arg-value-offset+))
58 (deallocate-memory arg)))))
59
6d27e76c 60(defbinding %arg-reset () nil
0d07716f 61 (arg arg))
62
63(defun arg-name (arg)
6d27e76c 64 (funcall (intern-reader-function 'string) arg +arg-name-offset+))
0d07716f 65
66(defun (setf arg-name) (name arg)
6d27e76c 67 (funcall (intern-writer-function 'string) name arg +arg-name-offset+)
0d07716f 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))))
6d27e76c 77 (funcall (intern-reader-function type) arg +arg-value-offset+))
0d07716f 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))))
6d27e76c 82 (funcall (intern-writer-function type) value arg +arg-value-offset+)
0d07716f 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
6d27e76c 88 (funcall (intern-writer-function type) value (arg-value arg 'pointer) 0)
0d07716f 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)
6d27e76c 98 (init-types-in-library "/opt/gnome/lib/libgtk-x11-1.3.so")
99
100 (defclass %object (gobject)
0d07716f 101 ()
0d07716f 102 (:metaclass gobject-class)
103 (:alien-name "GtkObject")))
104
105
6d27e76c 106(defmethod shared-initialize ((object %object) names &rest initargs
107 &key signals)
0d07716f 108 (declare (ignore initargs names))
109 (call-next-method)
6d27e76c 110 (%object-sink object)
0d07716f 111 (dolist (signal signals)
112 (apply #'signal-connect object signal)))
113
6d27e76c 114(defmethod initialize-proxy ((object %object) &rest initargs &key location)
0d07716f 115 (declare (ignore initargs))
116 (call-next-method)
6d27e76c 117 (%object-sink location))
0d07716f 118
6d27e76c 119(defbinding %object-sink () nil
120 (object %object))
0d07716f 121
0d07716f 122
13148f19 123;;;; Main loop, timeouts and idle functions
0d07716f 124
125(declaim (inline events-pending-p main-iteration))
126
6d27e76c 127(defbinding (events-pending-p "gtk_events_pending") () boolean)
0d07716f 128
6d27e76c 129(defbinding get-current-event () gdk:event)
13148f19 130
6d27e76c 131(defbinding main-do-event () nil
0d07716f 132 (event gdk:event))
133
6d27e76c 134(defbinding main () nil)
0d07716f 135
6d27e76c 136(defbinding main-level () int)
0d07716f 137
6d27e76c 138(defbinding main-quit () nil)
0d07716f 139
6d27e76c 140(defbinding main-iteration-do (&optional (blocking t)) boolean
0d07716f 141 (blocking boolean))
142
143(defun main-iterate-all (&rest args)
144 (declare (ignore args))
145 (when (events-pending-p)
6d27e76c 146 (main-iteration-do nil)
0d07716f 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
0d07716f 156;;;; Metaclass for child classes
6d27e76c 157
158(defvar *container-to-child-class-mappings* (make-hash-table))
0d07716f 159
160(eval-when (:compile-toplevel :load-toplevel :execute)
6d27e76c 161 (defclass child-class (virtual-slot-class))
0d07716f 162
6d27e76c 163 (defclass direct-child-slot-definition (direct-virtual-slot-definition)
164 ((arg-name :reader slot-definition-arg-name)))
0d07716f 165
166 (defclass effective-child-slot-definition
167 (effective-virtual-slot-definition)))
168
169
6d27e76c 170(defmethod shared-initialize ((class child-class) names &rest initargs
171 &key container)
0d07716f 172 (declare (ignore initargs))
173 (call-next-method)
6d27e76c 174 (setf
175 (gethash (find-class (first container)) *container-to-child-class-mappings*)
176 class))
0d07716f 177
6d27e76c 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")))
0d07716f 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
0d07716f 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))))
0d07716f 195
6d27e76c 196(defmethod compute-virtual-slot-accessor
0d07716f 197 ((class child-class) (slotd effective-child-slot-definition) direct-slotds)
198 (with-slots (type) slotd
6d27e76c 199 (let ((arg-name (slot-definition-arg-name (first direct-slotds)))
0d07716f 200 (type-number (find-type-number type))
6d27e76c 201; (reader (intern-reader-function type))
202; (writer (intern-writer-function type))
203; (destroy (intern-destroy-function type))
204 )
0d07716f 205 (list
206 #'(lambda (object)
207 (with-slots (parent child) object
208 (with-gc-disabled
209 (let ((arg (arg-new type-number)))
6d27e76c 210 (setf (arg-name arg) arg-name)
211 (%container-child-getv parent child arg)
0d07716f 212 (prog1
6d27e76c 213 (funcall
214 (intern-reader-function type)
215 arg +arg-value-offset+)
0d07716f 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)))
6d27e76c 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+)
0d07716f 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
6d27e76c 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)