109 std::string
get_text()
const override {
return text_; }
119 return static_cast<int>(text_.size());
230 invalidate_layout_cache();
241 has_own_insets_ =
true;
242 invalidate_layout_cache();
267 const std::string&
text()
const {
return text_; }
340 if (font_size_ == size)
return;
342 invalidate_layout_cache();
351 font_family_ = std::move(family);
352 invalidate_layout_cache();
360 if (content_inset_left_ ==
px)
return;
361 content_inset_left_ =
px;
362 invalidate_layout_cache();
372 int selected_byte_offset,
373 int selected_byte_length);
378 int selected_utf16_offset,
379 int selected_utf16_length);
388 std::pair<int, int>
marked_range()
const {
return {marked_start_,
static_cast<int>(marked_text_.size())}; }
400 caret_blink_.set_config(config);
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;
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_;
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;
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;
459 struct UndoSnapshot {
461 int caret_position = 0;
462 int selection_start = 0;
463 int selection_end = 0;
466 enum class UndoCoalesce {
472 std::vector<UndoSnapshot> undo_history_;
473 std::vector<UndoSnapshot> redo_history_;
474 UndoCoalesce last_undo_coalesce_ = UndoCoalesce::none;
481 struct LayoutSnapshot {
495 std::vector<Line> lines;
496 bool multi_line =
false;
497 float fallback_char_w = 0.f;
499 mutable LayoutSnapshot last_layout_;
505 struct LayoutCacheKey {
506 std::size_t text_hash = 0;
508 float bounds_width = 0.f;
509 float bounds_height = 0.f;
513 bool placeholder_visible =
false;
514 bool operator==(
const LayoutCacheKey&
o)
const noexcept {
515 return text_hash ==
o.text_hash
517 && bounds_width ==
o.bounds_width
518 && bounds_height ==
o.bounds_height
522 && placeholder_visible ==
o.placeholder_visible;
525 mutable LayoutCacheKey last_layout_key_;
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;
546 bool clipboard_import_allowed()
const;
547 bool clipboard_export_allowed()
const;
548 bool password_contents_allowed()
const;
549 void invalidate_layout_cache()
const;
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();
572 void notify_change();
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
bool paste_from_clipboard()
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
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