24#include <boost/pool/pool_alloc.hpp>
77 return static_cast<text_edit_caps>(
static_cast<uint32_t
>(aLhs) &
static_cast<uint32_t
>(aRhs));
82 return static_cast<text_edit_caps>(
static_cast<uint32_t
>(aLhs) |
static_cast<uint32_t
>(aRhs));
90 define_event(CanAcceptText, can_accept_text, i_string
const&,
bool&)
92 define_event(TextFilter, text_filter, i_string
const&,
bool&)
100 typedef text_edit property_context_type;
106 button<> showPassword;
108 password_bits(text_edit& aParent);
113 typedef std::optional<string> optional_password_mask;
115 class character_style
119 character_style(character_style
const& aOther);
121 optional_font
const& aFont,
122 const color_or_gradient& aTextColor = color_or_gradient{},
124 const optional_text_effect& aTextEffect = optional_text_effect{});
126 optional_font
const& font()
const;
130 bool smart_underline()
const;
131 bool ignore_emoji()
const;
132 const optional_text_effect& text_effect()
const;
133 text_format as_text_format()
const;
134 character_style& set_font(optional_font
const& aFont = optional_font{});
135 character_style& set_font_if_none(neogfx::font
const& aFont);
136 character_style& set_glyph_color(
const color_or_gradient& aColor = color_or_gradient{});
137 character_style& set_text_color(
const color_or_gradient& aColor = color_or_gradient{});
138 character_style& set_paper_color(
const color_or_gradient& aColor = color_or_gradient{});
139 character_style& set_text_effect(
const optional_text_effect& aEffect = optional_text_effect{});
140 character_style& set_from_text_format(
const text_format& aTextFormat);
142 character_style& merge(
const character_style& aRhs);
144 bool operator==(
const character_style& aRhs)
const;
145 bool operator!=(
const character_style& aRhs)
const;
146 bool operator<(
const character_style& aRhs)
const;
152 bool iSmartUnderline;
154 optional_text_effect iTextEffect;
157 class paragraph_style
161 paragraph_style(paragraph_style
const& aOther);
162 paragraph_style(optional_alignment
const& aAlignment, optional_padding
const& aPadding = {}, optional<double>
const& aLineSpacing = {});
165 paragraph_style& set_alignment(optional_alignment
const& aALignment = {});
167 paragraph_style& set_padding(optional_padding
const& aPadding = {});
168 optional<double>
const& line_spacing()
const;
169 paragraph_style& set_line_spacing(optional<double>
const& aLineSpacing = {});
171 paragraph_style& merge(
const paragraph_style& aRhs);
173 bool operator==(
const paragraph_style& aRhs)
const;
174 bool operator!=(
const paragraph_style& aRhs)
const;
175 bool operator<(
const paragraph_style& aRhs)
const;
179 optional<double> iLineSpacing;
186 style(character_style
const& aCharacter);
187 style(character_style
const& aCharacter, paragraph_style
const& aParagraph);
188 style(paragraph_style
const& aParagraph);
189 style(text_edit& aParent,
const style& aOther);
191 void add_ref()
const;
192 void release()
const;
194 style& merge(
const style& aOverridingStyle);
200 character_style
const& character()
const;
201 character_style& character();
202 paragraph_style
const& paragraph()
const;
203 paragraph_style& paragraph();
206 mutable uint32_t iUseCount;
207 character_style iCharacter;
208 paragraph_style iParagraph;
211 typedef std::set<style> style_list;
213 typedef std::function<std::tuple<const style&, std::ptrdiff_t> (std::ptrdiff_t)> style_callback;
215 typedef std::variant<std::monostate, style, style_callback, ansi>
format;
223 char32_t delimiter()
const;
224 void set_delimiter(
char32_t aDelimiter);
226 void set_min_width(
const optional_dimension& aMinWidth);
228 void set_max_width(
const optional_dimension& aMaxWidth);
231 const std::optional<text_edit::style>& style()
const;
232 void set_style(
const std::optional<text_edit::style>& aStyle);
235 bool operator==(
const column_info& aRhs)
const;
236 bool operator!=(
const column_info& aRhs)
const;
243 std::optional<text_edit::style> iStyle;
247 class multiple_text_changes;
249 struct unknown_node {};
251 template <
typename Node = unknown_node>
255 static constexpr std::size_t SMALL_OPTIMIZATION_FONT_COUNT = 4;
257 typedef std::variant<std::monostate, style_list::const_iterator, nullptr_t> tag_style;
264 return style == rhs.style;
268 template <
typename Node2>
269 struct rebind {
typedef tag<Node2> type; };
271 typedef Node node_type;
273 tag(
const tag_data& aContents) :
274 iNode(nullptr), iContents(aContents)
276 if (std::holds_alternative<style_list::const_iterator>(style()))
277 static_variant_cast<style_list::const_iterator>(style())->add_ref();
279 template <
typename Node2>
280 tag(node_type& aNode,
const tag<Node2>& aTag) :
281 iNode(&aNode), iContents(aTag.iContents)
283 if (std::holds_alternative<style_list::const_iterator>(style()))
284 static_variant_cast<style_list::const_iterator>(style())->add_ref();
286 tag(
const tag& aOther) :
287 iNode(aOther.iNode), iContents(aOther.iContents)
289 if (std::holds_alternative<style_list::const_iterator>(style()))
290 static_variant_cast<style_list::const_iterator>(style())->add_ref();
294 if (std::holds_alternative<style_list::const_iterator>(style()))
295 static_variant_cast<style_list::const_iterator>(style())->release();
300 return contents() == aOther.contents();
304 return !(*
this == aOther);
307 const tag_style& style()
const
309 return contents().style;
312 const tag_data& contents()
const
329 typedef basic_glyph_text_content<glyph_container_type> document_glyphs;
331 class glyph_paragraph;
332 class glyph_paragraph_index;
335 glyph_paragraph_index,
336 boost::fast_pool_allocator<std::pair<glyph_paragraph, const glyph_paragraph_index>, boost::default_user_allocator_new_delete, boost::details::pool::null_mutex>> glyph_paragraphs;
339 typedef std::vector<glyph_line> glyph_lines;
342 typedef std::vector<glyph_column> glyph_columns;
344 struct position_info;
350 typedef document_text::size_type position_type;
354 struct not_implemented : std::logic_error { not_implemented() :
std::logic_error(
"neogfx::text_edit::not_implemented") {} };
355 struct bad_column_index : std::logic_error { bad_column_index() :
std::logic_error(
"neogfx::text_edit::bad_column_index") {} };
359 text_edit(text_edit_caps aType = text_edit_caps::MultiLine, frame_style aFrameStyle = frame_style::SolidFrame);
360 text_edit(i_widget& aParent, text_edit_caps aType = text_edit_caps::MultiLine, frame_style aFrameStyle = frame_style::SolidFrame);
361 text_edit(i_layout& aLayout, text_edit_caps aType = text_edit_caps::MultiLine, frame_style aFrameStyle = frame_style::SolidFrame);
365 void moved()
override;
366 void resized()
override;
367 void layout_items(
bool aDefer)
override;
369 size minimum_size(optional_size
const& aAvailableSpace = optional_size{})
const override;
370 size maximum_size(optional_size
const& aAvailableSpace = optional_size{})
const override;
373 void paint(i_graphics_context& aGc)
const override;
375 color palette_color(color_role aColorRole)
const override;
377 const neogfx::font& font()
const override;
378 void set_font(optional_font
const& aFont)
override;
380 void focus_gained(focus_reason aFocusReason)
override;
381 void focus_lost(focus_reason aFocusReason)
override;
383 void mouse_button_pressed(mouse_button aButton,
const point& aPosition, key_modifiers_e aKeyModifiers)
override;
384 void mouse_button_double_clicked(mouse_button aButton,
const point& aPosition, key_modifiers_e aKeyModifiers)
override;
385 void mouse_button_released(mouse_button aButton,
const point& aPosition)
override;
386 void mouse_moved(
const point& aPosition, key_modifiers_e aKeyModifiers)
override;
387 void mouse_entered(
const point& aPosition)
override;
388 void mouse_left()
override;
391 bool key_pressed(scan_code_e aScanCode, key_code_e aKeyCode, key_modifiers_e aKeyModifiers)
override;
392 bool key_released(scan_code_e aScanCode, key_code_e aKeyCode, key_modifiers_e aKeyModifiers)
override;
393 bool text_input(i_string
const& aText)
override;
398 rect scroll_area()
const override;
399 size scroll_page()
const override;
401 bool use_scrollbar_container_updater()
const override;
402 using framed_scrollable_widget::update_scrollbar_visibility;
403 bool update_scrollbar_visibility(usv_stage_e aStage)
override;
404 void scroll_page_updated()
override;
406 color frame_color()
const override;
409 bool can_undo()
const override;
410 bool can_redo()
const override;
411 bool can_cut()
const override;
412 bool can_copy()
const override;
413 bool can_paste()
const override;
414 bool can_delete_selected()
const override;
415 bool can_select_all()
const override;
416 void undo(i_clipboard& aClipboard)
override;
417 void redo(i_clipboard& aClipboard)
override;
418 void cut(i_clipboard& aClipboard)
override;
419 void copy(i_clipboard& aClipboard)
override;
420 void paste(i_clipboard& aClipboard)
override;
421 void delete_selected()
override;
422 void select_all()
override;
425 std::size_t document_length()
const override;
426 void move_cursor(cursor::move_operation_e aMoveOperation,
bool aMoveAnchor =
true)
override;
428 i_string
const& plain_text()
const override;
429 bool set_plain_text(i_string
const& aPlainText)
override;
430 i_string
const& rich_text(rich_text_format aFormat = rich_text_format::Html)
const override;
431 bool set_rich_text(i_string
const& aRichText, rich_text_format aFormat = rich_text_format::Html)
override;
433 void paste_plain_text()
override;
434 void paste_rich_text(rich_text_format aFormat = rich_text_format::Html)
override;
436 void begin_update()
override;
437 void end_update()
override;
440 bool read_only()
const;
441 void set_read_only(
bool aReadOnly =
true);
442 bool word_wrap()
const;
443 void set_word_wrap(
bool aWordWrap =
true);
444 uint32_t grow_lines()
const;
445 void set_grow_lines(uint32_t aGrowLines = 5u);
446 bool password()
const;
447 i_string
const& password_mask()
const;
448 void set_password(
bool aPassword, i_string
const& aMask =
string{
"\xE2\x97\x8F" });
449 const style& default_style()
const;
450 void set_default_style(style
const& aDefaultStyle,
bool aPersist =
false);
451 color default_text_color()
const;
455 style current_style()
const;
456 void apply_style(style
const& aStyle);
457 void apply_style(position_type aStart, position_type aEnd, style
const& aStyle);
458 style next_style()
const;
461 std::size_t paragraph_count()
const;
462 void delete_paragraph(std::size_t aParagraphIndex);
463 i_string
const& text()
const;
464 std::size_t set_text(i_string
const& aText);
465 std::size_t set_text(i_string
const& aText, format
const& aFormat);
466 std::size_t append_text(i_string
const& aText,
bool aMoveCursor =
false);
467 std::size_t append_text(i_string
const& aText, format
const& aFormat,
bool aMoveCursor =
false);
468 std::size_t insert_text(i_string
const& aText,
bool aMoveCursor =
false);
469 std::size_t insert_text(i_string
const& aText, format
const& aFormat,
bool aMoveCursor =
false);
470 std::size_t insert_text(position_type aPosition, i_string
const& aText,
bool aMoveCursor =
false);
471 std::size_t insert_text(position_type aPosition, i_string
const& aText, format
const& aFormat,
bool aMoveCursor =
false);
472 std::size_t set_text(std::string
const& aText) {
return set_text(
string{ aText }); }
473 std::size_t set_text(std::string
const& aText, format
const& aFormat) {
return set_text(
string{ aText }, aFormat); }
474 std::size_t append_text(std::string
const& aText,
bool aMoveCursor =
false) {
return append_text(
string{ aText }, aMoveCursor); }
475 std::size_t append_text(std::string
const& aText, format
const& aFormat,
bool aMoveCursor =
false) {
return append_text(
string{ aText }, aFormat, aMoveCursor); }
476 std::size_t insert_text(std::string
const& aText,
bool aMoveCursor =
false) {
return insert_text(
string{ aText }, aMoveCursor); }
477 std::size_t insert_text(std::string
const& aText, format
const& aFormat,
bool aMoveCursor =
false) {
return insert_text(
string{ aText }, aFormat, aMoveCursor); }
478 std::size_t insert_text(position_type aPosition, std::string
const& aText,
bool aMoveCursor =
false) {
return insert_text(aPosition,
string{ aText }, aMoveCursor); }
479 std::size_t insert_text(position_type aPosition, std::string
const& aText, format
const& aFormat,
bool aMoveCursor =
false) {
return insert_text(aPosition,
string{ aText }, aFormat, aMoveCursor); }
480 void delete_text(position_type aStart, position_type aEnd);
481 std::size_t columns()
const;
482 void set_columns(std::size_t aColumnCount);
483 void remove_columns();
484 const column_info& column(std::size_t aColumnIndex)
const;
485 void set_column(std::size_t aColumnIndex,
const column_info& aColumn);
486 const style& column_style(std::size_t aColumnIndex)
const;
487 const style& column_style(
const column_info& aColumn)
const;
489 const neogfx::size_hint& size_hint()
const;
490 void set_size_hint(
const neogfx::size_hint& aSizeHint);
491 void set_tab_stop_hint(i_string
const& aTabStopHint =
string{
"0000" });
493 void set_tab_stops(std::optional<neogfx::tab_stops>
const& aTabStops);
495 position_type document_hit_test(
const point& aPosition,
bool aAdjustForScrollPosition =
true)
const;
496 virtual bool same_word(position_type aTextPositionLeft, position_type aTextPositionRight)
const;
497 virtual std::pair<position_type, position_type> word_at(position_type aTextPosition,
bool aWordBreakIsWhitespace =
false)
const;
500 void set_cursor_position(
const point& aPosition,
bool aMoveAnchor =
true,
bool aEnableDragger =
false);
502 std::size_t column_index(
const column_info& aColumn)
const;
503 rect column_rect(std::size_t aColumnIndex,
bool aExtendIntoPadding =
false)
const;
504 std::size_t column_hit_test(
const point& aPosition,
bool aAdjustForScrollPosition =
true)
const;
506 std::pair<glyph_columns::const_iterator, glyph_lines::const_iterator> glyph_column_line(position_type aGlyphPosition)
const;
507 position_info glyph_position(position_type aGlyphPosition,
bool aForCursor =
false)
const;
508 position_type cursor_glyph_position()
const;
509 position_type cursor_glyph_anchor()
const;
510 void set_cursor_glyph_position(position_type aGlyphPosition,
bool aMoveAnchor =
true);
513 document_glyphs
const& glyphs()
const;
514 document_glyphs& glyphs();
515 std::size_t do_insert_text(position_type aPosition, i_string
const& aText, format
const& aFormat,
bool aMoveCursor,
bool aClearFirst);
516 void delete_any_selection();
517 void notify_text_changed();
518 std::pair<position_type, position_type> related_glyphs(position_type aGlyphPosition)
const;
519 bool same_paragraph(position_type aFirstGlyphPos, position_type aSecondGlyphPos)
const;
520 glyph_paragraphs::const_iterator character_to_paragraph(position_type aCharacterPos)
const;
521 glyph_paragraphs::const_iterator glyph_to_paragraph(position_type aGlyphPos)
const;
522 document_glyphs::const_iterator to_glyph(document_text::const_iterator aWhere)
const;
523 std::pair<document_text::size_type, document_text::size_type> from_glyph(document_glyphs::const_iterator aWhere)
const;
524 void refresh_paragraph(document_text::const_iterator aWhere, ptrdiff_t aDelta);
525 void refresh_columns();
526 void refresh_lines();
528 void update_cursor();
529 void make_cursor_visible(
bool aForcePreviewScroll =
false);
530 void make_visible(position_info
const& aGlyphPosition, point
const& aPreview = {});
531 style glyph_style(document_glyphs::const_iterator aGlyphChar,
const glyph_column& aColumn)
const;
532 void draw_glyphs(i_graphics_context
const& aGc,
const point& aPosition,
const glyph_column& aColumn, glyph_lines::const_iterator aLine)
const;
533 void draw_cursor(i_graphics_context
const& aGc)
const;
534 rect cursor_rect()
const;
535 double calc_padding_adjust(style
const& aStyle)
const;
536 double padding_adjust()
const;
537 static std::pair<document_glyphs::iterator, document_glyphs::iterator> word_break(document_glyphs::iterator aBegin, document_glyphs::iterator aFrom, document_glyphs::iterator aEnd);
538 static std::pair<document_glyphs::reverse_iterator, document_glyphs::reverse_iterator> word_break(document_glyphs::reverse_iterator aBegin, document_glyphs::reverse_iterator aFrom, document_glyphs::reverse_iterator aEnd);
543 mutable std::optional<style> iNextStyle;
544 bool iPersistDefaultStyle;
545 font_info iDefaultFont;
548 bool iUpdatingDocument;
549 document_text iPreviousText;
551 mutable std::optional<string> iUtf8TextCache;
552 mutable std::optional<document_glyphs> iGlyphs;
553 glyph_paragraphs iGlyphParagraphs;
554 glyph_columns iGlyphColumns;
556 uint64_t iCursorAnimationStartTime;
557 typedef std::pair<position_type, position_type> find_span;
560 glyph_paragraphs::const_iterator,
561 std::less<find_span>,
562 boost::fast_pool_allocator<std::pair<const find_span, glyph_paragraphs::const_iterator>, boost::default_user_allocator_new_delete, boost::details::pool::null_mutex>> find_in_paragraph_cache;
563 mutable find_in_paragraph_cache iCharacterToParagraphCache;
564 mutable std::optional<find_in_paragraph_cache::iterator> iCharacterToParagraphCacheLastAccess;
565 mutable find_in_paragraph_cache iGlyphToParagraphCache;
566 mutable std::optional<find_in_paragraph_cache::iterator> iGlyphToParagraphCacheLastAccess;
567 neogfx::size_hint iSizeHint;
568 mutable std::optional<std::pair<neogfx::font, size>> iHintedSize;
569 std::optional<neogfx::tab_stops> iTabStops;
571 mutable std::optional<std::pair<neogfx::font, neogfx::tab_stops>> iCalculatedTabStops;
572 basic_point<std::optional<dimension>> iCursorHint;
573 widget_timer iAnimator;
574 std::unique_ptr<dragger> iDragger;
575 std::unique_ptr<neogfx::context_menu> iMenu;
576 uint32_t iSuppressTextChangedNotification;
577 uint32_t iWantedToNotfiyTextChanged;
578 std::optional<std::pair<text_edit::position_type, text_edit::position_type>> iSelectedUri;
579 std::optional<password_bits> iPasswordBits;
582 define_property(property_category::other,
bool, ReadOnly, read_only,
false)
583 define_property(property_category::other,
bool, WordWrap, word_wrap, (iCaps & text_edit_caps::MultiLine) == text_edit_caps::MultiLine)
584 define_property(property_category::other, uint32_t, GrowLines, grow_lines, 5u)
585 define_property(property_category::other,
bool, Password, password, false)
586 define_property(property_category::other,
string, PasswordMask, password_mask)
589 extern template class basic_glyph_text_content<text_edit::glyph_container_type>;
#define end_declare_enum(enumName)
#define declare_enum_string(enumName, enumEnumerator)
#define begin_declare_enum(enumName)
constexpr style_aspect operator&(style_aspect aLhs, style_aspect aRhs)
bool operator!=(color_or_gradient const &lhs, color const &rhs) noexcept
audio_channel operator~(audio_channel lhs)
optional< padding > optional_padding
basic_padding< dimension > padding
bool operator<(const basic_rect< CoordinateType, CoordinateSystem > &left, const basic_rect< CoordinateType, CoordinateSystem > &right)
neolib::variant< color, gradient > color_or_gradient
bool operator==(const basic_rect< CoordinateType, CoordinateSystem > &left, const basic_rect< CoordinateType, CoordinateSystem > &right)
optional< dimension > optional_dimension
constexpr style_aspect operator|(style_aspect aLhs, style_aspect aRhs)
optional< size > optional_size
optional< alignment > optional_alignment
scrollable_widget< framed_widget< widget<> > > framed_scrollable_widget
basic_size< coordinate > size
format_result format(std::string_view const &aFormat, Args &&... aArgs)
#define define_event(name, declName,...)
#define define_property(category, type, name, calculator,...)