Accessors

Readers

output-pane-input-modeloutput-pane-graphics-options

Description

The class
output-pane
is a subclass of
gp:graphics-port-mixin
which means that it supports many of the graphics ports drawing operations. When the CAPI needs to redisplay a region of the output pane, the
display-callback
gets called with the
output-pane
and the
x
,
y
,
width
and
height
of the region that needs redrawing. The
display-callback
should then use graphics port operations to redisplay that area. To force an area to be re-displayed, use the function invalidate-rectangle.

The
input-model
provides a means to get callbacks on mouse and keyboard gestures. An
input-model
is a list of mappings from gesture to callback, where each mapping is a list

(
gesture
callback
.
extra-callback-args
)

gesture
specifies the type of gesture, which can be gesture spec, character, button, key, command or motion.

In a gesture spec mapping,
gesture
can be simply the keyword
:gesture-spec
, which matches any keyboard input. For specific mappings,
gesture
is a list

(:gesture-spec
data
[modifier]*
)

in which
data
is a character object or an integer between 0 and
char-code-limit
(interpreted as the character object obtained by
code-char
), or a keyword naming a function key, and each
modifier
is one of the keywords
:shift
,
:control
and
:meta
. Note that the
:meta
modifier is received only when the keys style is
:emacs
(see interface-keys-style). On Cocoa, the
modifer
value
:hyper
is interpreted as the
Command
key for mouse input in dialogs (though note that
Command
is reserved for menu accelerators in interfaces).

Also
data
can be a string which is interpreted as a gesture spec as if by
sys:coerce-to-gesture-spec
. See the
LispWorks Reference Manual
for a description of this and other functions for manipulating gesture spec objects.

In a character mapping,
gesture
can be simply the keyword
:character
, which matches any character input. For specific mappings,
gesture
can be a list containing a single character object
char
, or a list

(
char
)

Note:
where input would match both a gesture spec mapping and a character mapping, the gesture spec mapping takes precedence.

In a button mapping,
gesture
should be list

(
button
action
[modifiers]*
)

where
button
is one of
:button-1
,
:button-2
or
:button-3
denoting the mouse buttons.
action
is one of
:press
,
:release
,
:second-press
and
:motion
, and each
modifier
is one of the keywords
:shift
,
:control
and
:meta
.

In a key mapping,
gesture
should contain the key in question (or the keyword
:key
meaning any key) along with an optional action (one of
:press
or
:release
) and zero or more keyboard modifiers.

In a motion mapping,
gesture
can either be defined in terms of dragging a button (in which case it is defined as a button gesture with
action
:motion
), or it can be defined for motions whilst no button is down by just specifying the keyword
:motion
with no additional arguments.

In a command mapping, gesture should be a command which is defined using define-command, and provides an alias for a gesture. The following commands are predefined:

:post-menu

(:button-3 :release)
on Windows.

(:button-3 :press)
on Motif.

(:button-1 :press :control)
on Mac OS X.

:control-post-menu

(:button-3 :press :control)
on Windows, Motif and Mac OS X.

:keyboard-post-menu

(:gesture-spec :f10 :shift)
on Windows, Motif and Mac OS X.

Note that it is recommended you follow the style guidelines and conventions of the platform you are developing for when mapping gestures to results.

When user input matches
gesture
,
callback
is called with standard arguments and any
extra-callback-args
as extra arguments. The standard arguments are the
output-pane
, the x cursor position, the y cursor position, and in the case of gesture spec, character or key mappings, the input object that matched.

If
pane-can-scroll
is true then the pane is responsible for handling scrolling, by redrawing. It should draw into the visible area according to the scroll parameters. An example of this is editor-pane. If
pane-can-scroll
is
nil
, then the CAPI is responsible for scrolling over the data range. The default value is
nil
. See the example in
output-panes/scroll-test.lisp
.

When the output pane is scrolled, the CAPI calls the
scroll-callback
if this is non-
nil
. The arguments of the scroll callback are the
output-pane,
the direction (
:vertical
,
:horizontal
or
:pan
), the scroll operation (
:move
,
:drag
,
:step
or
:page
), the amount of scrolling (an integer), and a keyword argument
:interactive
. This has value
t
if the scroll was invoked interactively, and value
nil
if the scroll was programmatic, such as via the function scroll. In the Mac OS X Cocoa implementation the direction is always
:pan
. See the following CAPI example files:

output-panes/scroll-test.lisp

output-panes/scrolling-without-bar.lisp

graphics/scrolling-test.lisp

focus-callback
, if non-
nil
, is a function of two arguments. The first argument is the
output-pane
itself, and the second is a boolean. When the
output-pane
gets the focus,
focus-callback
is called with second argument
t
, and when the
output-pane
loses the focus,
focus-callback
is called with second argument
nil
.

resize-callback
, if non-
nil
, is a function of five arguments called when the
output-pane
is resized. The first argument is the
output-pane
itself, and the rest are its new geometry:
x
,
y
,
width
and
height
.

graphics-options
is currently only used by the Mac OS X Cocoa implementation. The single option defined is
:text-rendering
, with allowed values:

:glyph

Draw glyphs directly using Core Graphics. This only draws characters with glyphs in the chosen font.

:atsui

Draw using ATSUI APIs where possible.This is slower but can handle more characters.

Examples

Firstly, here is an example that draws a circle in an output pane.

(defun display-circle (self x y width height)

(declare (ignore x y width height))

(gp:draw-circle self 200 200 200 :filled t))

(capi:contain (make-instance

'capi:output-pane

:display-callback 'display-circle)

:best-width 200 :best-height 200)

Here is an example that shows how to use a button gesture.

(defun test-callback (self x y)

(capi:display-message

"Pressed button 1 at (~S,~S) in ~S" x y self))

(capi:contain

(make-instance

'capi:output-pane

:title "Press button 1:"

:input-model `(((:button-1 :press)

test-callback)))

:best-width 200 :best-height 200)

This example illustrates gesture spec mappings.

(defun draw-input (self x y gspec)

(let ((data (sys:gesture-spec-data gspec))

(mods (sys:gesture-spec-modifiers gspec)))

(gp:draw-string

self

(with-output-to-string (ss)

(sys:print-pretty-gesture-spec

gspec ss :force-shift-for-upcase nil))

x y)))

(capi:contain

(make-instance

'capi:output-pane

:title "Press keys in the pane..."

:input-model '((:gesture-spec

draw-input)))

:best-width 200 :best-height 200)

(capi:contain

(make-instance

'capi:output-pane

:title "Press Control-a in the pane..."

:input-model '(((:gesture-spec "Control-a")

draw-input)))

:best-width 200 :best-height 200)

Here is a simple example that draws the character typed at the cursor point.

(defun draw-character (self x y character)

(gp:draw-character self character x y))

(capi:contain

(make-instance

'capi:output-pane

:title "Press keys in the pane..."

:input-model '((:character draw-character)))

:best-width 200 :best-height 200)

This example shows how to use the motion gesture.

(defun draw-red-blob (self x y)

(gp:draw-circle self x y 3

:filled t

:foreground :red))

(capi:contain

(make-instance

'capi:output-pane

:title "Drag button-1 across this pane."

:input-model '(((:button-1 :motion)

gp:draw-point)

((:button-1 :motion :control)

draw-red-blob)))

:best-width 200 :best-height 200)

This example illustrates the use of
focus-callback
:

(capi:contain

(make-instance

'capi:output-pane

:focus-callback

#'(lambda (x y)

(format t

"Pane ~a ~:[lost~;got~] the focus~%"

x y))))

This example illustrates the use of
graphics-options
to specify ATSUI drawing on Cocoa:

(defvar *string*

(coerce (loop for i from 0 below 60

collect (code-char (* 5 i)))

'text-string))

(capi:contain

(make-instance 'capi:output-pane

:visible-min-width 400

:visible-max-height 50

:display-callback

#'(lambda (pane x y w h)

(gp:draw-string pane

*string*

10 10))

:graphics-options

'(:text-rendering :atsui)))

There are further examples in the directory
examples/capi/output-panes/
.