




The 
define-interface
 macro defines subclasses of 
interface.
The macro 
define-interface
 is used to define subclasses of interface, which when created with 
make-instance
 has the specified panes, layouts and menus created automatically. If non-
nil
, 
superclasses
 must include interface or a subclass of it. 
define-interface
 is essentially a version of 
defclass
 which accepts the following extra options: 
Descriptions of the interface's panes.
Descriptions of the interface's layouts.
Descriptions of the interface's menus.
A list of menus for the interface's menu bar.
Options to alter 
define-interface
.
The class options 
:panes
, 
:layouts
 and 
:menus
 add extra slots to the class that will contain the CAPI object described in their description. Within the scope of the extra options, the slots themselves are available by referencing the name of the slot, and the interface itself is available with the variable 
capi:interface
. Each of the slots can be made to have readers, writers or accessors by passing the appropriate 
defclass
 keyword as one of the optional arguments in the description. Therefore, if you need to  find a pane within an interface instance, you can provide an accessor, or simply use 
with-slots
.
The 
:panes
 option is a list of pane descriptions of the following form
(:panes
(slot-name pane-class initargs )
...
(slot-name pane-class initargs )
)
where slot-name is a name for the slot, pane-class is the class of the pane being included in the interface, and initargs are the initialization arguments for the pane - the allowed forms are described below.
The 
:layouts
 option is a list of layout descriptions of the following form
(:layouts
(slot-name layout-class children initargs )
...
(slot-name layout-class children initargs )
)
where 
slot-name
 is a name for the slot, 
layout-class
 specifies the type of layout, 
children
 is a list of children for the layout, and 
initargs
 are the initialization arguments for the layout - the allowed forms are described below. The primary layout for the interface defaults to the first layout described, but can be specified as the 
:layout
 initarg to the interface. If no layouts are specified, then the CAPI will place all of the defined panes into a column layout and make that the primary layout.
The 
:menus
 option is a list of menu and menu component descriptions of the following form
(:menus
(slot-name title descriptions initargs )
...
(slot-name title descriptions initargs )
)
slot-name is the slot name for each menu or menu component.
title
 is the menu's title, the keyword 
:menu
, or the keyword 
:component
.
descriptions is a list of menu item descriptions. Each menu item description is either a title, a slot name for a menu, or a list of items containing a title, descriptions, and a list of initialization arguments for the menu item.
initargs are the initialization arguments for the menu.
The values given in 
initargs
 under 
:panes
, 
:layouts
 and 
:menus
 can be lists of the form
(:initarg keyword-name )
(:initarg key-spec )
(:initarg key-spec initarg-value )
key-spec := var | (var ) | (var initform ) | ((keyword-name var )) | ((keyword-name var ) initform )
keyword-name := any keyword
key-spec
 is interpreted as in the 
&key
 symbol of ordinary Common Lisp lambda lists. When this form of value is used, the specified 
keyword-name
 is added as an extra initarg to the class defined by the 
define-interface
 form.
If key-spec is followed by initarg-value , then its value is used as the initarg of the pane. Otherwise the value from key-spec is used.
Additionally 
initargs
 may contain the keyword argument 
:make-instance-extra-apply-args
 which is useful when you want to supply initargs to the pane 
slot-name
 when the interface is initialized. The value 
make-instance-extra-apply-args
 should be a keyword which becomes an extra initarg to the interface class 
name
. The value of that initarg should be a list of pane initargs and values which is passed when the pane is initialized. For an example, see 
examples/capi/applications/argument-passing.lisp
.
The 
:menu-bar
 option is a list of slot names, where each slot referred to contains a menu that should appear on the menu bar. 
The 
:definition
 option is a property list of arguments which 
define-interface
 uses to change the way that it behaves. Currently there is only one definition option: 
Firstly, a couple of pane examples:
(capi:define-interface test1 ()
()
(:panes
(text capi:text-input-pane))
(:default-initargs :title "Test1"))
(capi:display (make-instance 'test1))
(capi:define-interface test2 ()
()
(:panes
(text capi:text-input-pane)
(buttons capi:button-panel :items '(1 2 3)
:reader test2-buttons))
(:layouts
(main-layout capi:column-layout '(text buttons)))
(:default-initargs :title "Test2"))
(test2-buttons
(capi:display (make-instance 'test2)))
Here are a couple of menu examples:
(capi:define-interface test3 ()
()
(:menus
(color-menu "Colors" (:red :green :blue)
:print-function 'string-capitalize))
(:menu-bar color-menu)
(:default-initargs :title "Test3"))
(capi:display (make-instance 'test3))
(capi:define-interface test4 ()
()
(:menus
(colors-menu "Colors"
((:component
(:red :green :blue)
:interaction :single-selection
:print-function
'string-capitalize)
more-colors-menu))
(more-colors-menu "More Colors"
(:pink :yellow :cyan)
:print-function
'string-capitalize))
(:menu-bar colors-menu)
(:default-initargs :title "Test4"))
(capi:display (make-instance 'test4))
This example demonstrates inheritance amongst subclasses of 
interface
:
(capi:define-interface test5 (test4 test1)
()
(:default-initargs :title "Test5"))
(capi:display (make-instance 'test5))
The next three examples illustrate the use of 
:initarg
 in initarg specifications for 
:panes
.
Here we initialize the 
:selected-items
 initarg of the pane 
foo
 to the value passed by 
:select
 when making the interface object, or 
nil
 otherwise:
(capi:define-interface init1 () ()
(:panes
(foo
capi:list-panel
:items '(0 1 2 3 4)
:visible-min-height '(:character 5)
:interaction :multiple-selection
:selected-items (:initarg select))))
(capi:contain (make-instance 'init1
:select '(1 3)))
(capi:contain (make-instance 'init1))
Here we  initialize the 
:selected-items
  initarg of pane 
foo
 to the value passed by 
:select
 initarg when making the interface object, or 
(1 3)
 otherwise:
(capi:define-interface init2 () ()
(:panes
(foo
capi:list-panel
:items '(0 1 2 3 4)
:visible-min-height '(:character 5)
:interaction :multiple-selection
:selected-items
(:initarg (select '(1 3))))))
(capi:contain (make-instance 'init2))
Here we increment the indices passed in the interface's 
:select
 initarg before passing them in the 
:selected-items
 initarg of pane 
foo
:
(capi:define-interface init3 () ()
(:panes
(foo
capi:list-panel
:items '(0 1 2 3 4)
:visible-min-height '(:character 5)
:interaction :multiple-selection
:selected-items
(:initarg select
(mapcar '1+ select)))))
(capi:contain (make-instance 'init3
:select '(1 3)))
There are many more examples in the directory 
examples/capi/
.