|
Ultralight C++ API 2.0.0
|
#include <Ultralight/Editor.h>
Text-editing interface for a View.
The editor executes editing commands and manages composition state for the focused element in a View.
Standard keyboard shortcuts like Ctrl+C and Ctrl+V run automatically when you forward key events to a View. You use the editor to connect native UI controls like Edit menus and on-screen keyboards directly to the page, and to relay text from an OS input method.
This example updates native Edit menu items before display and runs the command the user picks:
Call View::editor() to obtain the View's Editor instance. Commands target the focused element in the active frame.
Calling Execute() runs an EditorCommand on that element. It returns false when the command can't run, such as copying without an active selection or undoing with an empty history.
Call CanExecute() to test whether a command would succeed right now, which lets you enable or disable native menu items before presenting them.
Call InsertText() to insert text at the caret, such as when forwarding input from an on-screen keyboard. The text replaces any active selection, exactly as if the user typed it.
This callback forwards tapped keys to the focused element:
AppCore windows run the OS input method automatically for their panels. When you host a View directly, you implement EditorListener and pass it to View::set_editor_listener() to coordinate the input method with the page.
In EditorListener::OnChangeEditableState(), turn on the OS input method only while both view_has_focus and is_mutable are true in EditableState (turn it off whenever either property is false).
Pass in-progress composition text from the OS to SetComposition(). The initial call starts the composition and replaces any active selection on the page– later calls replace the previous in-progress text.
Implement EditorListener::OnUpdateComposition() to reposition the candidate window whenever the composition updates.
Query GetCompositionCharacterBounds() at index 0 to anchor the candidate window to the composition's first character, or GetCaretBounds() when no composition is active. Anchoring to the first character prevents the candidate window from jumping as candidate words change length.
Both methods return rectangles in viewport CSS pixels. Multiply their coordinates by View::device_scale() to convert them to device pixels.
Call the matching editor method when the input method completes or cancels:
When the page terminates an active composition on its own (such as during navigation or when a click focuses a different element), the library calls EditorListener::OnDiscardComposition(). The page keeps the in-progress text as final text, so cancel the OS input method without recommitting or inserting the text again.
OS input methods sometimes inspect or replace text surrounding the caret, such as when showing an accent palette.
Call GetSelectionOffsets() to locate the selection. The editor's offset methods measure character positions in UTF-16 code units from the start of the focused editable element, matching the DOM selectionStart and selectionEnd properties.
Public Member Functions | |
| virtual bool | Execute (EditorCommand command)=0 |
| Run an editing command. | |
| virtual bool | CanExecute (EditorCommand command) const =0 |
| Whether or not a command would do anything right now. | |
| virtual bool | InsertText (const String &text)=0 |
| Insert text at the caret, replacing the selection (the same as typing it). | |
| virtual Rect | GetCaretBounds ()=0 |
| Get the bounds of the caret. | |
| virtual bool | SetComposition (const String &text, const CompositionSegment *segments, size_t num_segments, const CompositionRange &selection)=0 |
| Set or update the in-progress text of an input method's composition. | |
| virtual bool | CommitComposition (const String &text)=0 |
| Replace the active composition with the input method's final text. | |
| virtual bool | FinishComposition ()=0 |
| Keep the active composition's in-progress text as final text. | |
| virtual bool | CancelComposition ()=0 |
| Cancel the active composition and remove its text. | |
| virtual bool | HasComposition () const =0 |
| Whether or not a composition is active. | |
| virtual Rect | GetCompositionBounds ()=0 |
| Get the bounds of the active composition's text, in viewport CSS pixels. | |
| virtual uint32_t | GetCompositionCharacterCount ()=0 |
| Get the length of the active composition's text, in UTF-16 code units (0 when none is active). | |
| virtual Rect | GetCompositionCharacterBounds (uint32_t index)=0 |
| Get the bounds of one character of the active composition's text, in viewport CSS pixels. | |
| virtual bool | GetSelectionOffsets (uint32_t &start, uint32_t &end)=0 |
| Get the selection's offsets within the focused element's text. | |
| virtual String | GetTextInRange (uint32_t start, uint32_t end)=0 |
| Get part of the focused element's text (see GetSelectionOffsets() for the offsets). | |
| virtual bool | ReplaceTextInRange (uint32_t start, uint32_t end, const String &text)=0 |
| Replace part of the focused element's text (see GetSelectionOffsets() for the offsets). | |
| virtual bool | GetCompositionOffsets (uint32_t &start, uint32_t &end)=0 |
| Get the active composition's offsets within the focused element's text (see GetSelectionOffsets() for the offsets). | |
Protected Member Functions | |
| virtual | ~Editor ()=default |
|
protectedvirtualdefault |
|
pure virtual |
Cancel the active composition and remove its text.
|
nodiscardpure virtual |
Whether or not a command would do anything right now.
You can use this to grey out items in a native menu.
| command | The command to check. |
|
pure virtual |
Replace the active composition with the input method's final text.
With no active composition, this inserts text at the caret.
| text | The final text. |
|
pure virtual |
Run an editing command.
| command | The command to run. |
|
pure virtual |
Keep the active composition's in-progress text as final text.
Call this when the input method closes without committing or cancelling (eg, focus moves away mid-composition).
|
nodiscardpure virtual |
Get the bounds of the caret.
The rect is in viewport CSS pixels (the same space as View::FireMouseEvent()). Multiply by View::device_scale() for device pixels.
|
nodiscardpure virtual |
Get the bounds of the active composition's text, in viewport CSS pixels.
You can use this as the area a candidate window shouldn't cover.
|
nodiscardpure virtual |
Get the bounds of one character of the active composition's text, in viewport CSS pixels.
You can use this to place a candidate window. Anchor it on the composition's first character (index 0) so it doesn't move as the candidates change.
| index | The character's offset within the composition's text, in UTF-16 code units. |
|
nodiscardpure virtual |
Get the length of the active composition's text, in UTF-16 code units (0 when none is active).
|
nodiscardpure virtual |
Get the active composition's offsets within the focused element's text (see GetSelectionOffsets() for the offsets).
You can use this to report the input method's marked range.
| start | Set to the composition's start. |
| end | Set to the composition's end (exclusive). |
|
nodiscardpure virtual |
Get the selection's offsets within the focused element's text.
The offset methods (this, GetTextInRange(), ReplaceTextInRange(), and GetCompositionOffsets()) use UTF-16 code units into the text of the focused text field or editable region. For <input> and <textarea>, they match the element's selectionStart and selectionEnd.
| start | Set to the selection's start. |
| end | Set to the selection's end (the same as start for a caret). |
|
nodiscardpure virtual |
Get part of the focused element's text (see GetSelectionOffsets() for the offsets).
Offsets past the end of the text are clamped to it.
| start | The start offset. |
| end | The end offset (exclusive). |
|
nodiscardpure virtual |
Whether or not a composition is active.
|
pure virtual |
Insert text at the caret, replacing the selection (the same as typing it).
| text | The text to insert. |
|
pure virtual |
Replace part of the focused element's text (see GetSelectionOffsets() for the offsets).
This edits the same way typing does. The edit is one undo step, and the caret ends up after the new text. You can use this for an input method's replacement ranges (eg, the macOS accent picker replaces the character it targets).
Offsets past the end of the text are clamped to it.
| start | The start offset. |
| end | The end offset (exclusive). |
| text | The new text (an empty string deletes the range). |
|
pure virtual |
Set or update the in-progress text of an input method's composition.
The first call starts a composition and replaces the selection. Later calls replace the previous in-progress text.
| text | The full in-progress text. Pass an empty string to remove it (the same as CancelComposition()). |
| segments | Underline styles for parts of the text (eg, one per clause). Pass a nullptr to underline all of it. |
| num_segments | The number of entries in segments. |
| selection | The caret or selection within text, in UTF-16 code units. |