Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
text_editor.hpp
Go to the documentation of this file.
1#pragma once
2
6
7#include <cstddef>
8#include <functional>
11#include <pulp/view/caret.hpp>
14#include <pulp/view/view.hpp>
17#include <string>
18#include <string_view>
19#include <utility>
20#include <vector>
21
22namespace pulp::view {
23
48 public:
51 set_focusable(true);
53 on_context_menu = [this](Point pos) { show_default_context_menu(pos); };
54 }
55 ~TextEditor() override;
56
57 bool accepts_text_input() const override { return enabled() && !read_only; }
58
59 // ── SelectableText ───────────────────────────────────────────────────
60 //
61 // Only a READ-ONLY editor joins a document-level selection. An editable
62 // field owns its own selection the way an HTML `<input>` does: a document
63 // selection that swallowed a live text field would fight the field's caret
64 // over the same range, and Cmd-C would then be ambiguous between the two.
65 // Read-only is exactly the case where the field is prose rather than a
66 // control, and it is already the mode `copy_to_clipboard()` supports —
67 // that gate is `has_selection()`, never `can_edit()`.
69 return read_only ? this : nullptr;
70 }
71 std::string_view selectable_text() const override {
72 return text_;
73 }
75 void set_selection_highlight(int start_utf8, int end_utf8) override;
76 bool selection_highlight(int& start_utf8, int& end_utf8) const override;
77 View* selectable_view() override {
78 return this;
79 }
80
96 int char_index_at_point(float x, float y) const;
97 int char_index_at_x(float x) const;
98
99 // ── AccessibilityTextInterface ───────────────────────────────────────
100 //
101 // Without this, `AccessRole::text_field` is a lie by omission: the role
102 // says "edit field", and then macOS -accessibilityValue returns nil and
103 // the Windows IValueProvider::get_Value returns a NULL BSTR, so VoiceOver
104 // and Narrator announce "text field" and read NOTHING. The bridges resolve
105 // an element's value through accessibility_value_string() (accessibility.
106 // hpp), which finds this interface by dynamic_cast; the Windows provider
107 // also routes IValueProvider::SetValue back through set_text() so
108 // IsReadOnly and "editing works" finally agree.
109 std::string get_text() const override { return text_; }
110 void set_text(std::string_view t) override { set_text(std::string(t)); }
114 void set_text(const char* t) { set_text(std::string(t ? t : "")); }
115 bool is_editable() const override { return enabled() && !read_only; }
116 std::pair<int, int> get_selection() const override { return selection_range(); }
117 void set_selection(int start, int end) override;
118 int get_character_count() const override {
119 return static_cast<int>(text_.size());
120 }
121
122 static constexpr int kMaxUndoHistory = 1000;
123
130
136
142
148
149 // ── Configuration ────────────────────────────────────────────────────
150
152 bool multi_line = false;
153
155 bool numeric_only = false;
156
159 bool read_only = false;
160
162 bool password_mode = false;
163 char password_char = '*';
164
166 bool select_on_focus = false;
167
169 std::string placeholder;
170
173
176
181
184
186 std::size_t max_length = 0;
187
190 std::function<std::string(std::string_view)> input_filter;
191
194 std::function<std::string(std::string_view)> paste_sanitizer;
195
198 std::function<bool(std::string_view)> validator;
199
202
203 // ── Callbacks ─────────────────────────────────────────────────────────
204
206 std::function<void(const std::string& text)> on_return;
207
209 std::function<void(const std::string& text)> on_tab_commit;
210
212 std::function<void()> on_escape;
213
215 std::function<void(const std::string& text)> on_change;
216
222 std::function<void(const std::string& text)> on_focus_lost;
223
224 // ── Frame geometry ───────────────────────────────────────────────────
225
229 text_align_ = a;
230 invalidate_layout_cache();
232 }
233 canvas::TextAlign text_align() const { return text_align_; }
234
240 insets_ = insets;
241 has_own_insets_ = true;
242 invalidate_layout_cache();
244 }
245 EdgeInsets insets() const { return insets_; }
246
250 void set_caret_width(float px) {
251 caret_width_ = px;
253 }
254 float caret_width() const;
255
259 void set_caret_visible(bool v) {
260 caret_visible_ = v;
262 }
263 bool caret_visible() const { return caret_visible_; }
264
265 // ── Text access ──────────────────────────────────────────────────────
266
267 const std::string& text() const { return text_; }
270 void set_text(const std::string& t);
271
273 std::string selected_text() const;
274
275 bool has_selection() const { return selection_start_ != selection_end_; }
276 bool is_empty() const { return text_.empty(); }
277
278 // ── Selection ─────────────────────────────────────────────────────────
279
282 void set_caret_pos(int byte_offset);
283 // set_selection(anchor, active) is declared above as the
284 // AccessibilityTextInterface override — same contract, one definition.
285 int selection_anchor() const { return selection_start_; }
286 int selection_active() const { return selection_end_; }
287 std::pair<int, int> selection_range() const;
288
289 // ── Clipboard ─────────────────────────────────────────────────────────
290
294
295 // ── Undo/Redo ────────────────────────────────────────────────────────
296
297 bool undo();
298 bool redo();
299
300 // ── Layout ────────────────────────────────────────────────────────────
301
313 float intrinsic_height() const override;
314
315 // ── Painting ──────────────────────────────────────────────────────────
316
317 void paint(canvas::Canvas& canvas) override;
318
319 // ── Event handling ────────────────────────────────────────────────────
320
321 void on_mouse_event(const MouseEvent& event) override;
322 void on_mouse_down(Point pos) override;
323 void on_mouse_drag(Point pos) override;
324 void on_mouse_up(Point pos) override;
325 bool on_key_event(const KeyEvent& event) override;
326 void on_text_input(const TextInputEvent& event) override;
327 void on_focus_changed(bool gained) override;
328 bool wants_mouse_input() const override { return true; }
329 void on_attached() override;
334 void on_frame_clock_changed() override;
335 void on_resized() override { invalidate_layout_cache(); }
336
337 // ── Style ─────────────────────────────────────────────────────────────
338
339 void set_font_size(float size) {
340 if (font_size_ == size) return;
341 font_size_ = size;
342 invalidate_layout_cache();
343 }
344 float font_size() const { return font_size_; }
345
350 void set_font_family(std::string family) {
351 font_family_ = std::move(family);
352 invalidate_layout_cache();
354 }
355 const std::string& font_family() const { return font_family_; }
356
360 if (content_inset_left_ == px) return;
361 content_inset_left_ = px;
362 invalidate_layout_cache();
363 }
364 float content_inset_left() const { return content_inset_left_; }
365
366 // ── IME composition (marked text) ────────────────────────────────────
367
371 void set_marked_text(const std::string& marked,
372 int selected_byte_offset,
373 int selected_byte_length);
374
377 void set_marked_text_utf16(const std::string& marked,
378 int selected_utf16_offset,
379 int selected_utf16_length);
380
383
385 bool has_marked_text() const { return !marked_text_.empty(); }
386
388 std::pair<int, int> marked_range() const { return {marked_start_, static_cast<int>(marked_text_.size())}; }
389
391 int caret_pos() const { return caret_position_; }
392
394 void set_caret_style(CaretStyle style) { caret_style_ = style; request_repaint(); }
395 CaretStyle caret_style() const { return caret_style_; }
396
399 void set_caret_blink(const CaretBlinkConfig& config) {
400 caret_blink_.set_config(config);
402 }
403 const CaretBlinkConfig& caret_blink() const { return caret_blink_.config(); }
404
413
417 float scroll_offset() const { return scroll_offset_; }
418
419private:
420 std::string text_;
421 int caret_position_ = 0;
422 int selection_start_ = 0;
423 int selection_end_ = 0;
424 float font_size_ = 13.0f;
425 std::string font_family_;
426 float content_inset_left_ = 0.0f;
428 EdgeInsets insets_{};
429 bool has_own_insets_ = false;
430 float caret_width_ = 0.0f;
431 bool caret_visible_ = true;
432 float scroll_offset_ = 0.0f;
433 CaretBlink caret_blink_;
434 CaretStyle caret_style_ = default_caret_style();
435 bool has_preferred_horizontal_ = false;
436 float preferred_visual_x_ = 0.0f;
437 int preferred_text_column_ = 0;
438 int caret_blink_sub_ = -1;
439 FrameClock* caret_blink_clock_ = nullptr;
443
444 // IME composition state
445 std::string marked_text_;
446 int marked_start_ = 0;
447 int marked_selected_pos_ = 0;
448 int marked_selected_len_ = 0;
449 bool marked_undo_active_ = false;
450 bool drag_selecting_ = false;
451 bool drag_selecting_words_ = false;
452 int drag_anchor_ = 0;
453 int drag_word_start_ = 0;
454 int drag_word_end_ = 0;
455 int drag_pointer_id_ = 0;
456 bool has_drag_pointer_capture_ = false;
457 bool suppress_next_legacy_mouse_down_ = false;
458
459 struct UndoSnapshot {
460 std::string text;
461 int caret_position = 0;
462 int selection_start = 0;
463 int selection_end = 0;
464 float scroll_offset = 0.0f;
465 };
466 enum class UndoCoalesce {
467 none,
468 typing,
469 backspace,
470 delete_forward,
471 };
472 std::vector<UndoSnapshot> undo_history_;
473 std::vector<UndoSnapshot> redo_history_;
474 UndoCoalesce last_undo_coalesce_ = UndoCoalesce::none;
475
481 struct LayoutSnapshot {
482 struct Line {
483 int start = 0;
484 int end = 0;
485 float baseline_y = 0.f;
486 float top_y = 0.f;
487 float inner_x = 0.f;
488 float line_height = 0.f;
491 std::vector<float> x_offsets;
493 std::vector<int> byte_offsets;
494 };
495 std::vector<Line> lines;
496 bool multi_line = false;
497 float fallback_char_w = 0.f;
498 };
499 mutable LayoutSnapshot last_layout_;
500
505 struct LayoutCacheKey {
506 std::size_t text_hash = 0;
507 float font_size = 0.f;
508 float bounds_width = 0.f;
509 float bounds_height = 0.f;
510 float scroll_offset = 0.f;
511 bool multi_line = false;
512 bool password_mode = false;
513 bool placeholder_visible = false;
514 bool operator==(const LayoutCacheKey& o) const noexcept {
515 return text_hash == o.text_hash
516 && font_size == o.font_size
517 && bounds_width == o.bounds_width
518 && bounds_height == o.bounds_height
519 && scroll_offset == o.scroll_offset
520 && multi_line == o.multi_line
521 && password_mode == o.password_mode
522 && placeholder_visible == o.placeholder_visible;
523 }
524 };
525 mutable LayoutCacheKey last_layout_key_;
526
527 void push_undo(UndoCoalesce coalesce = UndoCoalesce::none);
528 void break_undo_coalescing();
529 UndoSnapshot snapshot() const;
530 void restore_snapshot(const UndoSnapshot& snapshot);
531 void insert_text(const std::string& t);
532 void delete_selection();
533 void delete_char_before_caret();
534 void delete_char_after_caret();
535 void delete_word_before_caret();
536 void delete_word_after_caret();
537 void delete_to_line_start();
538 void delete_to_line_end();
539 bool replace_selection_or_insert(std::string text,
540 UndoCoalesce coalesce = UndoCoalesce::none,
541 bool from_paste = false);
542 bool replace_marked_text(std::string text);
543 bool delete_range(int start, int end, UndoCoalesce coalesce = UndoCoalesce::none);
544 bool candidate_is_valid(int replace_start, int replace_end, std::string_view insertion) const;
545 bool can_edit() const { return enabled() && !read_only; }
546 bool clipboard_import_allowed() const;
547 bool clipboard_export_allowed() const;
548 bool password_contents_allowed() const;
549 void invalidate_layout_cache() const;
550
551 void move_caret(int delta, bool extend_selection);
552 void move_word(int direction, bool extend_selection);
553 void move_visual_line(int direction, bool extend_selection);
554 void move_page(int direction, bool extend_selection);
555 void move_paragraph(int direction, bool extend_selection);
556 void move_to_line_start(bool extend_selection);
557 void move_to_line_end(bool extend_selection);
558 void move_to_start(bool extend_selection);
559 void move_to_end(bool extend_selection);
560
561 std::pair<int, int> word_range_at_position(int position) const;
562 std::pair<int, int> line_range_at_position(int position) const;
563 void show_default_context_menu(Point local_pos);
564 void cancel_drag_selection(int pointer_id);
565 void reset_preferred_horizontal();
566 void keep_caret_solid();
567 void advance_caret_blink(float dt);
568 bool should_paint_caret() const;
569 void ensure_caret_blink_subscription();
570 void clear_caret_blink_subscription();
571
572 void notify_change();
573};
574
575} // namespace pulp::view
Text-caret appearance and blink policy, shared by every editable widget.
Definition canvas.hpp:240
Interface for accessible text content (text editors, labels).
Definition accessibility.hpp:43
A widget whose painted text can join a document-level selection.
Definition selectable_text.hpp:58
bool caret_visible() const
Definition text_editor.hpp:263
LineEndingPolicy line_ending_policy
Line-ending normalization for typed input, paste, and IME composition.
Definition text_editor.hpp:183
void on_frame_clock_changed() override
Re-home the caret-blink subscription when the tree's FrameClock changes.
ClipboardPolicy
Definition text_editor.hpp:137
@ disabled
Disable copy, cut, and paste through this control.
Definition text_editor.hpp:139
@ allow_password_contents
Allow selected password text to leave the control.
Definition text_editor.hpp:140
@ standard
Native behavior; password contents are protected.
Definition text_editor.hpp:138
const std::string & font_family() const
Definition text_editor.hpp:355
std::size_t max_length
Maximum accepted length in grapheme clusters. 0 means unlimited.
Definition text_editor.hpp:186
static constexpr int kMaxUndoHistory
Definition text_editor.hpp:122
int char_index_at_point(float x, float y) const
Multi-line aware hit-test: local point -> UTF-8 byte offset.
bool read_only
Read-only mode — allow focus, caret navigation, selection, and copy, but reject typed input,...
Definition text_editor.hpp:159
void on_attached() override
bool password_mode
Password mode — display mask character instead of actual text.
Definition text_editor.hpp:162
float caret_width() const
float content_inset_left() const
Definition text_editor.hpp:364
void set_marked_text_utf16(const std::string &marked, int selected_utf16_offset, int selected_utf16_length)
Convenience for native IME APIs that report marked-text selection ranges as UTF-16 code-unit offsets,...
void set_text(const char *t)
Disambiguator: set_text("literal") would otherwise be ambiguous between the std::string and std::stri...
Definition text_editor.hpp:114
int selection_active() const
Definition text_editor.hpp:286
std::function< void(const std::string &text)> on_change
Called whenever the text content changes.
Definition text_editor.hpp:215
bool has_marked_text() const
Whether there is active IME composition text.
Definition text_editor.hpp:385
bool is_empty() const
Definition text_editor.hpp:276
TabBehavior tab_behavior
Tab policy. Defaults to native text-field behavior: let focus move.
Definition text_editor.hpp:172
void on_resized() override
Definition text_editor.hpp:335
std::pair< int, int > marked_range() const
The marked text range relative to the full text (start, length).
Definition text_editor.hpp:388
bool multi_line
Multi-line mode (default: single-line).
Definition text_editor.hpp:152
void set_insets(EdgeInsets insets)
The gap between the field's frame and its text, per side.
Definition text_editor.hpp:239
void on_mouse_up(Point pos) override
void set_caret_pos(int byte_offset)
bool allow_password_clipboard
Password fields do not copy/cut their hidden contents by default.
Definition text_editor.hpp:201
TextEditor()
Definition text_editor.hpp:49
float font_size() const
Definition text_editor.hpp:344
std::string_view selectable_text() const override
The widget's text, in UTF-8.
Definition text_editor.hpp:71
void set_selection(int start, int end) override
Set selection range.
SelectableLayout selectable_layout() const override
Where the glyphs landed at the last paint. See SelectableLayout.
int get_character_count() const override
Number of characters.
Definition text_editor.hpp:118
char password_char
Definition text_editor.hpp:163
float intrinsic_height() const override
The field's natural height: one line of text plus the frame insets.
void set_font_size(float size)
Definition text_editor.hpp:339
std::function< void(const std::string &text)> on_return
Called when Return/Enter is pressed (single-line) or Cmd+Return (multi-line).
Definition text_editor.hpp:206
TabBehavior
Definition text_editor.hpp:124
@ move_focus
Return false from Tab so the host/focus system can advance focus.
Definition text_editor.hpp:125
@ ignore
Consume Tab without mutating text or moving focus.
Definition text_editor.hpp:128
@ insert_tab
Insert a literal tab character into the editor.
Definition text_editor.hpp:126
@ commit
Consume Tab and call on_tab_commit (or on_return when unset).
Definition text_editor.hpp:127
void set_text_align(canvas::TextAlign a)
Horizontal alignment of the text inside the field.
Definition text_editor.hpp:228
int caret_pos() const
Caret position in the text, for IME cursor rect queries.
Definition text_editor.hpp:391
std::function< std::string(std::string_view)> input_filter
Optional input filter.
Definition text_editor.hpp:190
bool accepts_text_input() const override
Does this widget consume printable character keys for text entry?
Definition text_editor.hpp:57
MultiLineReturnBehavior multi_line_return_behavior
Multi-line Return policy. Defaults to native text-area behavior.
Definition text_editor.hpp:175
bool wants_mouse_input() const override
True if this widget handles mouse down/drag through virtual methods even when it does not expose JS p...
Definition text_editor.hpp:328
void set_content_inset_left(float px)
Extra left inset (px) for the text / placeholder / caret — used to clear a leading icon (an imported ...
Definition text_editor.hpp:359
SelectableText * as_selectable_text() override
This view's painted text can join a cross-widget selection; null for the vast majority of views,...
Definition text_editor.hpp:68
std::pair< int, int > get_selection() const override
Get selected text range.
Definition text_editor.hpp:116
std::pair< int, int > selection_range() const
bool is_editable() const override
Whether the text is editable.
Definition text_editor.hpp:115
std::function< void(const std::string &text)> on_focus_lost
Called when the field loses keyboard focus.
Definition text_editor.hpp:222
EdgeInsets insets() const
Definition text_editor.hpp:245
void set_selection_highlight(int start_utf8, int end_utf8) override
Paint this byte range as selected. start >= end clears the highlight.
void on_text_input(const TextInputEvent &event) override
Text input from keyboard/IME (separate from key events).
std::string selected_text() const
Get the currently selected text (empty if no selection).
bool has_selection() const
Definition text_editor.hpp:275
void on_mouse_event(const MouseEvent &event) override
Mouse down with full event context.
bool select_on_focus
Automatically select all text when this editor gains focus.
Definition text_editor.hpp:166
LineEndingPolicy
Definition text_editor.hpp:143
@ normalize
CRLF/CR/LF become ' ' in multi-line fields, spaces in single-line fields.
Definition text_editor.hpp:144
@ strip
Remove CR/LF during insertion and paste.
Definition text_editor.hpp:145
@ preserve
Keep inserted CR/LF bytes in multi-line fields; single-line fields still flatten.
Definition text_editor.hpp:146
const std::string & text() const
Definition text_editor.hpp:267
std::function< std::string(std::string_view)> paste_sanitizer
Optional paste-specific sanitizer.
Definition text_editor.hpp:194
int selection_anchor() const
Definition text_editor.hpp:285
int char_index_at_x(float x) const
bool numeric_only
Numeric-only mode — only digits, decimal point, minus sign allowed.
Definition text_editor.hpp:155
std::string placeholder
Placeholder text when empty.
Definition text_editor.hpp:169
void set_marked_text(const std::string &marked, int selected_byte_offset, int selected_byte_length)
Set composition text from an input method.
float scroll_offset() const
Current horizontal scroll offset (single-line) or vertical scroll (multi-line).
Definition text_editor.hpp:417
Rect caret_rect() const
Caret bounding rect in local view coordinates.
void set_text(const std::string &t)
Programmatically replace the text.
std::function< void()> on_escape
Called when Escape is pressed.
Definition text_editor.hpp:212
void on_mouse_drag(Point pos) override
std::function< bool(std::string_view)> validator
Optional whole-buffer validator.
Definition text_editor.hpp:198
const CaretBlinkConfig & caret_blink() const
Definition text_editor.hpp:403
void unmark_text()
Commit composition (clear marked text, the final text was already inserted via on_text_input).
std::string get_text() const override
Get the full text.
Definition text_editor.hpp:109
CaretStyle caret_style() const
Definition text_editor.hpp:395
ClipboardPolicy clipboard_policy
Clipboard policy.
Definition text_editor.hpp:180
void set_text(std::string_view t) override
Set the text (if editable).
Definition text_editor.hpp:110
void on_focus_changed(bool gained) override
Called when this view gains or loses focus.
void set_caret_blink(const CaretBlinkConfig &config)
Blink timing.
Definition text_editor.hpp:399
void set_caret_style(CaretStyle style)
Caret shape. Defaults to the process-wide style (CaretStyle::ibeam).
Definition text_editor.hpp:394
bool selection_highlight(int &start_utf8, int &end_utf8) const override
The current highlight. Returns false when nothing is highlighted.
void set_font_family(std::string family)
Typeface family.
Definition text_editor.hpp:350
void paint(canvas::Canvas &canvas) override
MultiLineReturnBehavior
Definition text_editor.hpp:131
@ insert_newline
Return inserts a newline; main modifier commits.
Definition text_editor.hpp:132
@ shift_inserts_newline
Return commits; Shift+Return inserts a newline.
Definition text_editor.hpp:134
std::function< void(const std::string &text)> on_tab_commit
Called when TabBehavior::commit is selected. Falls back to on_return.
Definition text_editor.hpp:209
void set_caret_width(float px)
Caret stroke width in pixels.
Definition text_editor.hpp:250
void set_caret_visible(bool v)
Force the caret hidden even while focused.
Definition text_editor.hpp:259
canvas::TextAlign text_align() const
Definition text_editor.hpp:233
View * selectable_view() override
The View this capability is mixed into. Never null.
Definition text_editor.hpp:77
bool on_key_event(const KeyEvent &event) override
Key event with modifiers and up/down state.
void on_mouse_down(Point pos) override
std::function< void(Point position)> on_context_menu
Right-click context menu callback.
Definition view.hpp:1496
WritingDirection direction() const
Definition view.hpp:2681
Position position() const
Definition view.hpp:1767
void request_repaint()
Request that this view's host invalidate and schedule a repaint.
void set_cursor(CursorStyle c)
Definition view.hpp:2760
@ text_field
Definition view.hpp:990
@ text
Definition view.hpp:2742
void set_access_role(AccessRole role)
Definition view.hpp:995
bool enabled() const
CSS :disabled equivalent — blocks input, reduces opacity.
Definition view.hpp:715
void set_focusable(bool f)
Definition view.hpp:669
Input event types with modifier keys and pointer IDs.
Definition affine_transform.hpp:24
TextAlign
Definition canvas.hpp:221
@ left
Definition canvas.hpp:221
Hover-cursor tracking for platform window hosts.
Definition fwd.hpp:27
CaretStyle default_caret_style() noexcept
Process-wide caret defaults.
@ px
Absolute pixels.
Definition geometry.hpp:393
CaretStyle
Caret shape. All three anchor at the same caret x.
Definition caret.hpp:63
@ extend_selection
Definition waveform_editor_primitives.hpp:226
@ a
Definition input_events.hpp:39
@ y
Definition input_events.hpp:42
@ x
Definition input_events.hpp:41
@ v
Definition input_events.hpp:41
@ o
Definition input_events.hpp:40
@ t
Definition input_events.hpp:41
@ end
Definition geometry.hpp:370
@ start
Definition geometry.hpp:370
bool operator==(const WaveformGpuUploadKey &a, const WaveformGpuUploadKey &b) noexcept
Blink timing. The defaults are the values Pulp has always used.
Definition caret.hpp:78
Per-side insets in pixels.
Definition widget_metrics.hpp:63
Rich key event with key code, modifiers, and repeat state.
Definition input_events.hpp:193
Rich mouse/pointer event with position, modifiers, button state, pointer ID, and stylus properties.
Definition input_events.hpp:104
Definition geometry.hpp:20
Axis-aligned rectangle in continuous (float) coordinates.
Definition geometry.hpp:52
The painted line geometry of one widget.
Definition selectable_text.hpp:52
Definition text_editor.hpp:482
float top_y
Definition text_editor.hpp:486
float line_height
Definition text_editor.hpp:488
std::vector< int > byte_offsets
UTF-8 byte offset in text_ for each x_offsets entry.
Definition text_editor.hpp:493
int start
Definition text_editor.hpp:483
int end
Definition text_editor.hpp:484
float baseline_y
Definition text_editor.hpp:485
float inner_x
Definition text_editor.hpp:487
std::vector< float > x_offsets
Cumulative x of each char start; size = (end-start)+1.
Definition text_editor.hpp:491
Text input from IME or keyboard composition (separate from KeyEvent).
Definition input_events.hpp:210
A pluggable sizing delegate for Pulp's stock widgets — the sibling of WidgetPainter (widget_painter....
A pluggable paint delegate for Pulp's stock widgets.