There are a variety of ways in which an application can display text, accept text input or allow editing of text by the user:
Display panes | Show non-editable text. |
Text input panes | Used for entering short pieces of text. |
Editor panes | Used for dealing with large amounts of text such as files. Also offer full configurable editor functionality. |
Rich text panes | Support formatted text. Available on Cocoa and Microsoft Windows only. |
You can use a display-pane to display text messages on the screen. The text in these messages cannot be edited, so they can be used by the application to present a message to the user. The :text
initarg can be used to specify the message that is to appear in the pane.
(setq display (make-instance 'display-pane :text "This is a message")) (contain display)
A display pane
Note that the window title, which defaults to "Container" for windows created by contain, may appear truncated.
You can access the text (get and set) of a display-pane by the accessor display-pane-text. You can access the selection by display-pane-selection-p, display-pane-selection, set-display-pane-selection and display-pane-selected-text.
When you want the user to enter a line of text, such as a search string, use a text-input-pane.
(setq text (make-instance 'text-input-pane :title "Search: " :callback 'test-callback)) (contain text)
A text input pane
Notice that the default title position for text input panes is :left
.
You can place text programmatically in the text input pane by supplying a string for the :text
initarg, or later by calling (setf text-input-pane-text)
in the appropriate process.
You can use set-text-input-pane-selection to control the selection in the text input pane:
(setq tip (make-instance 'capi:text-input-pane :title "Search: " :text "Foo Bar Baz")) (capi:set-text-input-pane-selection tip (length "Foo ") (+ (length "Foo ") (length "Bar"))) (capi:contain tip)
text-input-pane has many callbacks which allow the program to perform various tasks as the user changes the text, the selection or the caret position, or enters/leaves the pane. It is possible to respond to specific keyboard gestures, characters or otherwise (like Up
arrow). text-input-pane has also options for performing completion on the user input.
You can add toolbar buttons for easier user input in a text-input-pane via the :buttons
initarg. This example allows the user to enter the filename of an existing Lisp source file, either directly or by selecting the file in a dialog raised by the Browse File button. There is also a Cancel button, but the default OK button is not displayed:
(capi:contain (make-instance 'capi:text-input-pane :buttons (list :cancel t :ok nil :browse-file (list :operation :open :filter "*.LISP;*.LSP"))))
For a larger quantity of text use multi-line-text-input-pane.
On Cocoa, text-input-pane can also be made to look like a search field, using the initarg :search-field
and related initargs.
For entering passwords use the subclass password-pane, which does not display the actual characters that the user types.
An editor-pane is a pane which displays text and allows the user to edit it. The text is held and manipulated in a separate module, the Editor, which is implemented in the "EDITOR" package.
The Editor is optimized to deal with large amounts of text, whether that is because a single document contains large amount of text or because the user wants to edit many texts at the same time. It has a large set of commands that the user can invoke to perform a variety of tasks, including many kinds of editing and search operations, integration with the LispWorks IDE, and various other tasks. It also has a programmatic interface to manipulate the text, which is exported from the package "EDITOR". The user interface and the programmatic interface are both documented in the Editor User Guide, and the LispWorks IDE uses editor-pane for editing.
The interaction of the Editor emulates either Emacs style or the native style of macOS, Microsoft Windows or KDE/Gnome as appropriate. There is a global default setting (native on Windows, Emacs elsewhere), which can be set in a runtime image by the Delivery keyword :editor-style
. In particular, you fix the style for editor-pane in your interfaces by defining your method for interface-keys-style. See the chapter "Emulation" in the Editor User Guide for more detail about the different styles.
From the CAPI side you can access the editor structures that hold the text by using editor-pane-buffer, which returns an editor:buffer
object which holds the text. You can then use the programmatic Editor interface to access and manipulate the text.
For example, the following code inserts the string "foo"
in the end of the editor pane (really in the end of the buffer):
(let ((buffer (capi:editor-pane-buffer editor-pane))) (let ((point (editor:buffers-end buffer))) (editor:insert-string point "foo")))
Above, point
is an editor:point
object.
Alternatively, editor commands can be executed by passing the name of an editor command to call-editor.
Note that the editor objects can be accessed from any process (as opposed to the CAPI elements), because they use locks. Programmers can use the locks to group several editor operations so that they happen "atomically".
It is possible to specify that an editor-pane has an attached Echo Area which is where non-editing interactions (for example entering a command name or filename) occur. To add an Echo Area, use the :echo-area
initarg. Otherwise, a special window pops up when such interaction needs to occur.
The variables *editor-cursor-active-style*, *editor-cursor-color*, *editor-cursor-drag-style* and *editor-cursor-inactive-style* can be used to control the appearance of the cursor. When adding an echo area, the inactive cursor style can be controlled separately by *editor-cursor-inactive-style*.
An editor-pane can have input callbacks (before and after) and a change callback. These are described in 3.5.3.1 Editor pane callbacks.
On the CAPI side there are few additional functions that can be used on an editor-pane. These are described in 3.5.3.2 Additional editor-pane functions.
You can use the initarg :change-callback
to specify a function which is called whenever the editor buffer under the editor-pane changes. The value change-callback can be set either by:
(make-instance 'capi:editor-pane :change-callback ...)
or:
(setf capi:editor-pane-change-callback)
The current value can be queried by the accessor editor-pane-change-callback.
The change-callback function must have signature:
change-callback pane point old-length new-length
pane is the editor-pane itself.
point is an editor:point
object where the modification to the underlying buffer starts. point is a temporary point, and is not valid outside the scope of the change callback. For more information about editor:point
objects, see "Points" in the Editor User Guide.
old-length is the length of the affected text following point, prior to the modification.
new-length is the length of the affected text following point, after the modification has occurred.
Typical calls to the change-callback occur on insertion of text (when old-length is 0) and on deletion of text (when new-length is 0). There can be other combinations, for example, after executing the Uppercase Region editor command, change-callback be called with both old-length and new-length being the length of the region. The same is true for changing editor text properties.
The change-callback is always executed in the process of pane (as if by apply-in-pane-process).
The change-callback is permitted to modify the buffer of pane, and other editor buffers. The callback is disabled inside the dynamic scope of the call, so there are no recursive calls to the change-callback of pane. However, changes done by the callback may trigger change-callback calls on other editor-panes, whether in the same process or in another process.
There is an example illustrating the use of change-callback in:
(example-edit-file "capi/editor/change-callback")
You can use the initargs :before-input-callback
and :after-input-callback
to add input callbacks which are called when call-editor is called. Note that the default input-model also generates calls to call-editor, so unless you override the default input-model these input callbacks are called for all keyboard and mouse gestures (other than gestures that are processed by a non-focus completer window).
In both cases (before-input-callback and after-input-callback) the argument is a function that takes two arguments: the editor pane itself and the input gesture (the second argument to call-editor).
call-editor may redirect gestures to another pane. For example, gestures to an editor-pane are redirected to the echo area while it is used. In this case before-input-callback is called more than once for the same gesture, but after-input-callback is called only once for each gesture, on the pane that actually processed the gesture.
The contents of the buffer can be retrieved and set by the accessor editor-pane-text.
modify-editor-pane-buffer can be used to change the text and the filling at the same time.
editor-pane-line-wrap-marker, editor-pane-line-wrap-face and *default-editor-pane-line-wrap-marker* control the appearance of the marker that indicates wrapping of lines that are too long.
The function editor-pane-selected-text returns the selected text (if any), and editor-pane-selected-text-p checks if there is a selection.
You can call set-default-editor-pane-blink-rate to set the default blink rate of the cursor on all editor panes. You can specialize editor-pane-blink-rate to control the blink rate of specific panes, and use editor-pane-native-blink-rate to query the blink rate of the underlying GUI system. Note that the underlying system will normally allow the user to change this value.
The function print-editor-buffer can be used to print the contents of the editor buffer.
The function set-editor-parenthesis-colors can be used to control parenthesis coloring in Lisp mode.
Editor panes support composition of characters using input methods (see composition-callback in output-pane) by having a default callback editor-pane-default-composition-callback, which handles it mostly right. You can specify your own callback, which can also call editor-pane-default-composition-callback to do the actual work.
The editor-pane is geared towards editing files, and in particular it tries to guard against loss of work by keeping backup files and auto-save files, and asking the user before closing an unsaved buffer. When you use an editor-pane for other purposes, and therefore do not need all of this functionality, you should use temporary buffers. Create a temporary buffer by supplying the initarg :buffer-name :temp
, or create your own temporary buffer explicitly by (editor:make-buffer ... :temporary t)
.
You can make an editor-pane be non-editable by users by supplying the initarg :enabled :read-only
, or completely disable it with :enabled nil
.
CAPI User Guide and Reference Manual (Macintosh version) - 01 Dec 2021 19:31:17