The class
document-frame
is used to implement Multiple-Document Interface (MDI) which is a standard technique on Microsoft Windows (see the MSDN for documentation).
To use MDI in the CAPI, define an interface class that inherits from
document-frame
, and use the two special slots
capi:container
and
capi:windows-menu
as described below.
In your interface's layouts, use the symbol
capi:container
in the
description
to denote the pane inside the MDI interface in which child interfaces are added.
document-frame-container
is a reader which returns the document-container of the
document-frame
.
Interfaces of any type other than subclasses of
document-frame
may be added as children. To add a child interface in your MDI interface, call display on the child interface and pass the MDI interface as the
screen
argument. This will display the child interface inside the container pane. To obtain a list of the child interfaces, call the screen reader function
screen-interfaces
, passing the frame's document-container as the
screen
argument.
You can use most of the normal CAPI window operations such as top-level-interface-geometry and activate-pane on windows displayed as children of a
document-frame
.
The
capi:windows-menu
slot contains the Windows Menu, which allows the user to manipulate child interfaces. The standard functionality of the Windows Menu is handled by the system and normally you will not need to modify it. However, you will want to specify its position in the menu bar. Do this by adding the symbol
capi:windows-menu
in the
:menu-bar
option of your define-interface form.
Note:
capi:windows-menu
is a special slot in
document-frame
and this symbol should not appear elsewhere in the define-interface form.
By default the menu bar is made by effectively appending the menu bar of the
document-frame
interface with the menu bar of the current child. You can customize this behavior with merge-menu-bars.
This example uses
document-frame
to create a primitive
apropos
browser.
Firstly we define an interface that lists symbols. There is nothing special about this in itself.
(capi:define-interface symbols-listing ()
((symbols :initarg :symbols))
(:panes
( symbols-pane capi:list-panel
:items symbols
:print-function
'symbol-name))
(:default-initargs
:best-width '(character 40)
:best-height '(character 10)))
Next we define the MDI interface. Note:
document-frame
.
capi:container
is used in the layout description.
capi:windows-menu
is in the
:menu-bar
list.Otherwise, this example uses standard Common Lisp and CAPI functionality.
(capi:define-interface my-apropos-browser
(capi:document-frame)
((string :initarg :string))
(:panes
(package-list
capi:list-panel
:items
(loop for package in (list-all-packages)
when
(let ((al (apropos-list string package)))
(when al
(cons (package-name package) al)))
collect it)
:print-function 'car
:action-callback
#'(lambda (mdi-interface name-and-symbols)
(capi:display
(make-instance
'symbols-listing
:symbols (cdr name-and-symbols)
:title (car name-and-symbols))
:screen mdi-interface))
:callback-type :interface-data)
)
(:menu-bar capi:windows-menu)
(:layouts
(main
capi:row-layout
'(package-list :divider capi:container)
:ratios '(1 nil 4)))
(:default-initargs
:visible-min-height '(character 20)
:visible-min-width '(character 100)))
To browse apropos of a specific string
(capi:display
(make-instance 'my-apropos-browser
:string "EDITOR"))