- (bind (((&optional g-name c-name) (ensure-list g-name-and-c-name))
- ((&optional superclass dispatch-slot dispatch-values) superclass-and-dispatch)
- (superclass-slots (get superclass 'boxed-combined-slots))
- (combined-slots (append superclass-slots slots)))
- (setf c-name (or c-name (gensym "C-UNION-")))
- `(progn ,(cstruct-definition name combined-slots)
- ,(struct-definition name superclass slots)
- ,(parse-method-definition name combined-slots)
- ,(unparse-method-definition name combined-slots)
- (eval-when (:load-toplevel :compile-toplevel :execute)
- (setf (get ',name 'boxed-slots) ',slots
- (get ',name 'boxed-combined-slots) ',combined-slots
- (get ',name 'superclass) ',superclass
- (get ',name 'c-name) (or (get ',name 'c-name) ',c-name))
- ,@(when superclass
- (list `(pushnew '(,name ,dispatch-slot ,(ensure-list dispatch-values)) (get ',superclass 'boxed-dispatch) :test 'equalp))))
- (update-g-boxed-root-c-class ,name)
- ,@(when g-name
- (list `(register-boxed-type ,g-name ',name)))
- ,@(when export
- (append (list `(export ',name (symbol-package ',name))
- `(export ',(struct-constructor-name name) (symbol-package ',(struct-constructor-name name))))
- (mapcar (lambda (slot) (slot->export-accessor name slot)) slots))))))
+ "Defines the class corresponding to GBoxed type. Used only for structures that are passed (semantically) by value. E.g., GdkEvent.
+Single inheritance of classes is supported (and is used for definining different sub-types of GdkEvent). Decision of which class to use for a given C structure is made based on values of certain slots (see arguments @code{dispatch-slot} and @code{dispatch-values}).
+
+Example:
+
+@begin{pre}
+\(define-g-boxed-class (\"GdkEvent\" event-struct) event ()
+ (type event-type)
+ (window (g-object gdk-window))
+ (send-event (:boolean :int8)))
+
+\(define-g-boxed-class nil event-button ((event type (:button-press :2button-press :3button-press :button-release)))
+ (time :uint32)
+ (x :double)
+ (y :double)
+ (axes (fixed-array :double 2))
+ (state :uint)
+ (button :uint)
+ (device (g-object device))
+ (x-root :double)
+ (y-root :double))
+
+\(define-g-boxed-class \"GdkColor\" color ()
+ (pixel :uint32 :initform 0)
+ (red :uint16 :initform 0)
+ (green :uint16 :initform 0)
+ (blue :uint16 :initform 0))
+@end{pre}
+@arg[g-name-and-c-name]{@code{NIL} or list @code{(&optional g-name c-name)}; g-name is the GObject type name and c-name is the name of generated CFFI C structure.}
+@arg[name]{a symbol; name of the structure (defstruct) that is defined}
+@arg[superclass-and-dispatch]{@code{NIL} or list @code{(&optional superclass dispatch-slot dispatch-values)}}
+@arg[superclass]{a symbol denoting the superclass of the class being defined}
+@arg[dispatch-slot]{a symbol denoting the slot of the superclass that identifies the \"real\" class}
+@arg[dispatch-values]{a value or a list of values of @code{dispatch-slot} of @code{superclass} that correspond to the class being defined}
+@arg[export]{a boolean; defines whether all related symbols (@code{name} and generated slot accessors) should be exported from the current package}
+@arg[slots]{a list of slots; each slot is defined by list @code{(name type &key initform parser unparser)}.
+@begin{itemize}
+@item{@code{name} is the name of a slot}
+@item{@code{type} is a CFFI type of a slot}
+@item{@code{initform} is an expression that is the iniform of a slot in generated @code{defstruct}; used when the lisp code creates the object.}
+@item{@code{parser} is a function designator for a slot parser function (if a slot parsing depends on other slots of a structure; custom slot parsing is better implemented with CFFI foreign types). Slot parser function is a function that accepts two arguments: name of a slot and a pointer to C structure and returns the value of a slot}
+@item{@code{unparser} is a function designator for a slot unparser function. Slot unparsing function is a function that accepts three arguments: name of a slot, pointer to a C structure and a value of a slot. It should assign the slot value to a C structure.}
+@end{itemize}}"
+ (destructuring-bind (&optional g-name c-name) (ensure-list g-name-and-c-name)
+ (destructuring-bind (&optional superclass dispatch-slot dispatch-values) superclass-and-dispatch
+ (let* ((superclass-slots (get superclass 'boxed-combined-slots))
+ (combined-slots (append superclass-slots slots)))
+
+ (setf c-name (or c-name (gensym "C-UNION-")))
+ `(progn ,(cstruct-definition name combined-slots)
+ ,(struct-definition name superclass slots)
+ ,(parse-method-definition name combined-slots)
+ ,(unparse-method-definition name combined-slots)
+ (eval-when (:load-toplevel :compile-toplevel :execute)
+ (setf (get ',name 'boxed-slots) ',slots
+ (get ',name 'boxed-combined-slots) ',combined-slots
+ (get ',name 'superclass) ',superclass
+ (get ',name 'c-name) (or (get ',name 'c-name) ',c-name))
+ ,@(when superclass
+ (list `(pushnew '(,name ,dispatch-slot ,(ensure-list dispatch-values)) (get ',superclass 'boxed-dispatch) :test 'equalp))))
+ (update-g-boxed-root-c-class ,name)
+ ,@(when g-name
+ (list `(register-boxed-type ,g-name ',name)))
+ ,@(when export
+ (append (list `(export ',name (symbol-package ',name))
+ `(export ',(struct-constructor-name name) (symbol-package ',(struct-constructor-name name))))
+ (mapcar (lambda (slot) (slot->export-accessor name slot)) slots))))))))