| 1 | /**************************************************************************/ |
| 2 | /* rich_text_label.h */ |
| 3 | /**************************************************************************/ |
| 4 | /* This file is part of: */ |
| 5 | /* GODOT ENGINE */ |
| 6 | /* https://godotengine.org */ |
| 7 | /**************************************************************************/ |
| 8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
| 9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
| 10 | /* */ |
| 11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
| 12 | /* a copy of this software and associated documentation files (the */ |
| 13 | /* "Software"), to deal in the Software without restriction, including */ |
| 14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
| 15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
| 16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
| 17 | /* the following conditions: */ |
| 18 | /* */ |
| 19 | /* The above copyright notice and this permission notice shall be */ |
| 20 | /* included in all copies or substantial portions of the Software. */ |
| 21 | /* */ |
| 22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
| 23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
| 24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
| 25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
| 26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
| 27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
| 28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
| 29 | /**************************************************************************/ |
| 30 | |
| 31 | #ifndef RICH_TEXT_LABEL_H |
| 32 | #define RICH_TEXT_LABEL_H |
| 33 | |
| 34 | #include "core/object/worker_thread_pool.h" |
| 35 | #include "scene/gui/popup_menu.h" |
| 36 | #include "scene/gui/rich_text_effect.h" |
| 37 | #include "scene/gui/scroll_bar.h" |
| 38 | #include "scene/resources/text_paragraph.h" |
| 39 | |
| 40 | class RichTextLabel : public Control { |
| 41 | GDCLASS(RichTextLabel, Control); |
| 42 | |
| 43 | public: |
| 44 | enum ListType { |
| 45 | LIST_NUMBERS, |
| 46 | LIST_LETTERS, |
| 47 | LIST_ROMAN, |
| 48 | LIST_DOTS |
| 49 | }; |
| 50 | |
| 51 | enum ItemType { |
| 52 | ITEM_FRAME, |
| 53 | ITEM_TEXT, |
| 54 | ITEM_IMAGE, |
| 55 | ITEM_NEWLINE, |
| 56 | ITEM_FONT, |
| 57 | ITEM_FONT_SIZE, |
| 58 | ITEM_FONT_FEATURES, |
| 59 | ITEM_COLOR, |
| 60 | ITEM_OUTLINE_SIZE, |
| 61 | ITEM_OUTLINE_COLOR, |
| 62 | ITEM_UNDERLINE, |
| 63 | ITEM_STRIKETHROUGH, |
| 64 | ITEM_PARAGRAPH, |
| 65 | ITEM_INDENT, |
| 66 | ITEM_LIST, |
| 67 | ITEM_TABLE, |
| 68 | ITEM_FADE, |
| 69 | ITEM_SHAKE, |
| 70 | ITEM_WAVE, |
| 71 | ITEM_TORNADO, |
| 72 | ITEM_RAINBOW, |
| 73 | ITEM_PULSE, |
| 74 | ITEM_BGCOLOR, |
| 75 | ITEM_FGCOLOR, |
| 76 | ITEM_META, |
| 77 | ITEM_HINT, |
| 78 | ITEM_DROPCAP, |
| 79 | ITEM_CUSTOMFX, |
| 80 | ITEM_CONTEXT, |
| 81 | ITEM_LANGUAGE, |
| 82 | }; |
| 83 | |
| 84 | enum { |
| 85 | , |
| 86 | , |
| 87 | |
| 88 | }; |
| 89 | |
| 90 | enum DefaultFont { |
| 91 | NORMAL_FONT, |
| 92 | BOLD_FONT, |
| 93 | ITALICS_FONT, |
| 94 | BOLD_ITALICS_FONT, |
| 95 | MONO_FONT, |
| 96 | CUSTOM_FONT, |
| 97 | }; |
| 98 | |
| 99 | protected: |
| 100 | virtual void _update_theme_item_cache() override; |
| 101 | |
| 102 | void _notification(int p_what); |
| 103 | static void _bind_methods(); |
| 104 | |
| 105 | private: |
| 106 | struct Item; |
| 107 | |
| 108 | struct Line { |
| 109 | Item *from = nullptr; |
| 110 | |
| 111 | Ref<TextParagraph> text_buf; |
| 112 | Color dc_color; |
| 113 | int dc_ol_size = 0; |
| 114 | Color dc_ol_color; |
| 115 | |
| 116 | Vector2 offset; |
| 117 | int char_offset = 0; |
| 118 | int char_count = 0; |
| 119 | |
| 120 | Line() { text_buf.instantiate(); } |
| 121 | |
| 122 | _FORCE_INLINE_ float get_height(float line_separation) const { |
| 123 | return offset.y + text_buf->get_size().y + text_buf->get_line_count() * line_separation; |
| 124 | } |
| 125 | }; |
| 126 | |
| 127 | struct Item { |
| 128 | int index = 0; |
| 129 | int char_ofs = 0; |
| 130 | Item *parent = nullptr; |
| 131 | ItemType type = ITEM_FRAME; |
| 132 | List<Item *> subitems; |
| 133 | List<Item *>::Element *E = nullptr; |
| 134 | int line = 0; |
| 135 | |
| 136 | void _clear_children() { |
| 137 | while (subitems.size()) { |
| 138 | memdelete(subitems.front()->get()); |
| 139 | subitems.pop_front(); |
| 140 | } |
| 141 | } |
| 142 | |
| 143 | virtual ~Item() { _clear_children(); } |
| 144 | }; |
| 145 | |
| 146 | struct ItemFrame : public Item { |
| 147 | bool cell = false; |
| 148 | |
| 149 | LocalVector<Line> lines; |
| 150 | std::atomic<int> first_invalid_line; |
| 151 | std::atomic<int> first_invalid_font_line; |
| 152 | std::atomic<int> first_resized_line; |
| 153 | |
| 154 | ItemFrame *parent_frame = nullptr; |
| 155 | |
| 156 | Color odd_row_bg = Color(0, 0, 0, 0); |
| 157 | Color even_row_bg = Color(0, 0, 0, 0); |
| 158 | Color border = Color(0, 0, 0, 0); |
| 159 | Size2 min_size_over = Size2(-1, -1); |
| 160 | Size2 max_size_over = Size2(-1, -1); |
| 161 | Rect2 padding; |
| 162 | |
| 163 | ItemFrame() { |
| 164 | type = ITEM_FRAME; |
| 165 | first_invalid_line.store(0); |
| 166 | first_invalid_font_line.store(0); |
| 167 | first_resized_line.store(0); |
| 168 | } |
| 169 | }; |
| 170 | |
| 171 | struct ItemText : public Item { |
| 172 | String text; |
| 173 | ItemText() { type = ITEM_TEXT; } |
| 174 | }; |
| 175 | |
| 176 | struct ItemDropcap : public Item { |
| 177 | String text; |
| 178 | Ref<Font> font; |
| 179 | int font_size = 0; |
| 180 | Color color; |
| 181 | int ol_size = 0; |
| 182 | Color ol_color; |
| 183 | Rect2 dropcap_margins; |
| 184 | ItemDropcap() { type = ITEM_DROPCAP; } |
| 185 | }; |
| 186 | |
| 187 | struct ItemImage : public Item { |
| 188 | Ref<Texture2D> image; |
| 189 | InlineAlignment inline_align = INLINE_ALIGNMENT_CENTER; |
| 190 | Size2 size; |
| 191 | Color color; |
| 192 | ItemImage() { type = ITEM_IMAGE; } |
| 193 | }; |
| 194 | |
| 195 | struct ItemFont : public Item { |
| 196 | DefaultFont def_font = CUSTOM_FONT; |
| 197 | Ref<Font> font; |
| 198 | bool variation = false; |
| 199 | bool def_size = false; |
| 200 | int font_size = 0; |
| 201 | ItemFont() { type = ITEM_FONT; } |
| 202 | }; |
| 203 | |
| 204 | struct ItemFontSize : public Item { |
| 205 | int font_size = 16; |
| 206 | ItemFontSize() { type = ITEM_FONT_SIZE; } |
| 207 | }; |
| 208 | |
| 209 | struct ItemColor : public Item { |
| 210 | Color color; |
| 211 | ItemColor() { type = ITEM_COLOR; } |
| 212 | }; |
| 213 | |
| 214 | struct ItemOutlineSize : public Item { |
| 215 | int outline_size = 0; |
| 216 | ItemOutlineSize() { type = ITEM_OUTLINE_SIZE; } |
| 217 | }; |
| 218 | |
| 219 | struct ItemOutlineColor : public Item { |
| 220 | Color color; |
| 221 | ItemOutlineColor() { type = ITEM_OUTLINE_COLOR; } |
| 222 | }; |
| 223 | |
| 224 | struct ItemUnderline : public Item { |
| 225 | ItemUnderline() { type = ITEM_UNDERLINE; } |
| 226 | }; |
| 227 | |
| 228 | struct ItemStrikethrough : public Item { |
| 229 | ItemStrikethrough() { type = ITEM_STRIKETHROUGH; } |
| 230 | }; |
| 231 | |
| 232 | struct ItemMeta : public Item { |
| 233 | Variant meta; |
| 234 | ItemMeta() { type = ITEM_META; } |
| 235 | }; |
| 236 | |
| 237 | struct ItemHint : public Item { |
| 238 | String description; |
| 239 | ItemHint() { type = ITEM_HINT; } |
| 240 | }; |
| 241 | |
| 242 | struct ItemLanguage : public Item { |
| 243 | String language; |
| 244 | ItemLanguage() { type = ITEM_LANGUAGE; } |
| 245 | }; |
| 246 | |
| 247 | struct ItemParagraph : public Item { |
| 248 | HorizontalAlignment alignment = HORIZONTAL_ALIGNMENT_LEFT; |
| 249 | String language; |
| 250 | Control::TextDirection direction = Control::TEXT_DIRECTION_AUTO; |
| 251 | TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT; |
| 252 | BitField<TextServer::JustificationFlag> jst_flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_SKIP_LAST_LINE | TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE; |
| 253 | PackedFloat32Array tab_stops; |
| 254 | ItemParagraph() { type = ITEM_PARAGRAPH; } |
| 255 | }; |
| 256 | |
| 257 | struct ItemIndent : public Item { |
| 258 | int level = 0; |
| 259 | ItemIndent() { type = ITEM_INDENT; } |
| 260 | }; |
| 261 | |
| 262 | struct ItemList : public Item { |
| 263 | ListType list_type = LIST_DOTS; |
| 264 | bool capitalize = false; |
| 265 | int level = 0; |
| 266 | String bullet = U"•" ; |
| 267 | ItemList() { type = ITEM_LIST; } |
| 268 | }; |
| 269 | |
| 270 | struct ItemNewline : public Item { |
| 271 | ItemNewline() { type = ITEM_NEWLINE; } |
| 272 | }; |
| 273 | |
| 274 | struct ItemTable : public Item { |
| 275 | struct Column { |
| 276 | bool expand = false; |
| 277 | int expand_ratio = 0; |
| 278 | int min_width = 0; |
| 279 | int max_width = 0; |
| 280 | int width = 0; |
| 281 | }; |
| 282 | |
| 283 | LocalVector<Column> columns; |
| 284 | LocalVector<float> rows; |
| 285 | LocalVector<float> rows_baseline; |
| 286 | |
| 287 | int align_to_row = -1; |
| 288 | int total_width = 0; |
| 289 | int total_height = 0; |
| 290 | InlineAlignment inline_align = INLINE_ALIGNMENT_TOP; |
| 291 | ItemTable() { type = ITEM_TABLE; } |
| 292 | }; |
| 293 | |
| 294 | struct ItemFade : public Item { |
| 295 | int starting_index = 0; |
| 296 | int length = 0; |
| 297 | |
| 298 | ItemFade() { type = ITEM_FADE; } |
| 299 | }; |
| 300 | |
| 301 | struct ItemFX : public Item { |
| 302 | double elapsed_time = 0.f; |
| 303 | bool connected = true; |
| 304 | }; |
| 305 | |
| 306 | struct ItemShake : public ItemFX { |
| 307 | int strength = 0; |
| 308 | float rate = 0.0f; |
| 309 | uint64_t _current_rng = 0; |
| 310 | uint64_t _previous_rng = 0; |
| 311 | Vector2 prev_off; |
| 312 | |
| 313 | ItemShake() { type = ITEM_SHAKE; } |
| 314 | |
| 315 | void reroll_random() { |
| 316 | _previous_rng = _current_rng; |
| 317 | _current_rng = Math::rand(); |
| 318 | } |
| 319 | |
| 320 | uint64_t offset_random(int p_index) { |
| 321 | return (_current_rng >> (p_index % 64)) | |
| 322 | (_current_rng << (64 - (p_index % 64))); |
| 323 | } |
| 324 | |
| 325 | uint64_t offset_previous_random(int p_index) { |
| 326 | return (_previous_rng >> (p_index % 64)) | |
| 327 | (_previous_rng << (64 - (p_index % 64))); |
| 328 | } |
| 329 | }; |
| 330 | |
| 331 | struct ItemWave : public ItemFX { |
| 332 | float frequency = 1.0f; |
| 333 | float amplitude = 1.0f; |
| 334 | Vector2 prev_off; |
| 335 | |
| 336 | ItemWave() { type = ITEM_WAVE; } |
| 337 | }; |
| 338 | |
| 339 | struct ItemTornado : public ItemFX { |
| 340 | float radius = 1.0f; |
| 341 | float frequency = 1.0f; |
| 342 | Vector2 prev_off; |
| 343 | |
| 344 | ItemTornado() { type = ITEM_TORNADO; } |
| 345 | }; |
| 346 | |
| 347 | struct ItemRainbow : public ItemFX { |
| 348 | float saturation = 0.8f; |
| 349 | float value = 0.8f; |
| 350 | float frequency = 1.0f; |
| 351 | |
| 352 | ItemRainbow() { type = ITEM_RAINBOW; } |
| 353 | }; |
| 354 | |
| 355 | struct ItemPulse : public ItemFX { |
| 356 | Color color = Color(1.0, 1.0, 1.0, 0.25); |
| 357 | float frequency = 1.0f; |
| 358 | float ease = -2.0f; |
| 359 | |
| 360 | ItemPulse() { type = ITEM_PULSE; } |
| 361 | }; |
| 362 | |
| 363 | struct ItemBGColor : public Item { |
| 364 | Color color; |
| 365 | ItemBGColor() { type = ITEM_BGCOLOR; } |
| 366 | }; |
| 367 | |
| 368 | struct ItemFGColor : public Item { |
| 369 | Color color; |
| 370 | ItemFGColor() { type = ITEM_FGCOLOR; } |
| 371 | }; |
| 372 | |
| 373 | struct ItemCustomFX : public ItemFX { |
| 374 | Ref<CharFXTransform> char_fx_transform; |
| 375 | Ref<RichTextEffect> custom_effect; |
| 376 | |
| 377 | ItemCustomFX() { |
| 378 | type = ITEM_CUSTOMFX; |
| 379 | char_fx_transform.instantiate(); |
| 380 | } |
| 381 | |
| 382 | virtual ~ItemCustomFX() { |
| 383 | _clear_children(); |
| 384 | |
| 385 | char_fx_transform.unref(); |
| 386 | custom_effect.unref(); |
| 387 | } |
| 388 | }; |
| 389 | |
| 390 | struct ItemContext : public Item { |
| 391 | ItemContext() { type = ITEM_CONTEXT; } |
| 392 | }; |
| 393 | |
| 394 | ItemFrame *main = nullptr; |
| 395 | Item *current = nullptr; |
| 396 | ItemFrame *current_frame = nullptr; |
| 397 | |
| 398 | WorkerThreadPool::TaskID task = WorkerThreadPool::INVALID_TASK_ID; |
| 399 | Mutex data_mutex; |
| 400 | bool threaded = false; |
| 401 | std::atomic<bool> stop_thread; |
| 402 | std::atomic<bool> updating; |
| 403 | std::atomic<bool> validating; |
| 404 | std::atomic<double> loaded; |
| 405 | |
| 406 | uint64_t loading_started = 0; |
| 407 | int progress_delay = 1000; |
| 408 | |
| 409 | VScrollBar *vscroll = nullptr; |
| 410 | |
| 411 | TextServer::AutowrapMode autowrap_mode = TextServer::AUTOWRAP_WORD_SMART; |
| 412 | |
| 413 | bool scroll_visible = false; |
| 414 | bool scroll_follow = false; |
| 415 | bool scroll_following = false; |
| 416 | bool scroll_active = true; |
| 417 | int scroll_w = 0; |
| 418 | bool scroll_updated = false; |
| 419 | bool updating_scroll = false; |
| 420 | int current_idx = 1; |
| 421 | int current_char_ofs = 0; |
| 422 | int visible_paragraph_count = 0; |
| 423 | int visible_line_count = 0; |
| 424 | |
| 425 | int tab_size = 4; |
| 426 | bool underline_meta = true; |
| 427 | bool underline_hint = true; |
| 428 | bool use_selected_font_color = false; |
| 429 | |
| 430 | HorizontalAlignment default_alignment = HORIZONTAL_ALIGNMENT_LEFT; |
| 431 | BitField<TextServer::JustificationFlag> default_jst_flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_SKIP_LAST_LINE | TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE; |
| 432 | |
| 433 | ItemMeta *meta_hovering = nullptr; |
| 434 | Variant current_meta; |
| 435 | |
| 436 | Array custom_effects; |
| 437 | |
| 438 | void _invalidate_current_line(ItemFrame *p_frame); |
| 439 | |
| 440 | void _thread_function(void *p_userdata); |
| 441 | void _thread_end(); |
| 442 | void _stop_thread(); |
| 443 | bool _validate_line_caches(); |
| 444 | void _process_line_caches(); |
| 445 | _FORCE_INLINE_ float _update_scroll_exceeds(float p_total_height, float p_ctrl_height, float p_width, int p_idx, float p_old_scroll, float p_text_rect_height); |
| 446 | |
| 447 | void _add_item(Item *p_item, bool p_enter = false, bool p_ensure_newline = false); |
| 448 | void _remove_item(Item *p_item, const int p_line, const int p_subitem_line); |
| 449 | |
| 450 | String language; |
| 451 | TextDirection text_direction = TEXT_DIRECTION_AUTO; |
| 452 | TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT; |
| 453 | Array st_args; |
| 454 | |
| 455 | struct Selection { |
| 456 | ItemFrame *click_frame = nullptr; |
| 457 | int click_line = 0; |
| 458 | Item *click_item = nullptr; |
| 459 | int click_char = 0; |
| 460 | |
| 461 | ItemFrame *from_frame = nullptr; |
| 462 | int from_line = 0; |
| 463 | Item *from_item = nullptr; |
| 464 | int from_char = 0; |
| 465 | |
| 466 | ItemFrame *to_frame = nullptr; |
| 467 | int to_line = 0; |
| 468 | Item *to_item = nullptr; |
| 469 | int to_char = 0; |
| 470 | |
| 471 | bool active = false; // anything selected? i.e. from, to, etc. valid? |
| 472 | bool enabled = false; // allow selections? |
| 473 | bool drag_attempt = false; |
| 474 | }; |
| 475 | |
| 476 | Selection selection; |
| 477 | bool deselect_on_focus_loss_enabled = true; |
| 478 | bool drag_and_drop_selection_enabled = true; |
| 479 | |
| 480 | bool = false; |
| 481 | bool shortcut_keys_enabled = true; |
| 482 | |
| 483 | // Context menu. |
| 484 | PopupMenu * = nullptr; |
| 485 | void (); |
| 486 | void (); |
| 487 | Key (const String &p_action); |
| 488 | |
| 489 | int visible_characters = -1; |
| 490 | float visible_ratio = 1.0; |
| 491 | TextServer::VisibleCharactersBehavior visible_chars_behavior = TextServer::VC_CHARS_BEFORE_SHAPING; |
| 492 | |
| 493 | bool _is_click_inside_selection() const; |
| 494 | void _find_click(ItemFrame *p_frame, const Point2i &p_click, ItemFrame **r_click_frame = nullptr, int *r_click_line = nullptr, Item **r_click_item = nullptr, int *r_click_char = nullptr, bool *r_outside = nullptr, bool p_meta = false); |
| 495 | |
| 496 | String _get_line_text(ItemFrame *p_frame, int p_line, Selection p_sel) const; |
| 497 | bool _search_line(ItemFrame *p_frame, int p_line, const String &p_string, int p_char_idx, bool p_reverse_search); |
| 498 | bool _search_table(ItemTable *p_table, List<Item *>::Element *p_from, const String &p_string, bool p_reverse_search); |
| 499 | |
| 500 | float _shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> &p_base_font, int p_base_font_size, int p_width, float p_h, int *r_char_offset); |
| 501 | float _resize_line(ItemFrame *p_frame, int p_line, const Ref<Font> &p_base_font, int p_base_font_size, int p_width, float p_h); |
| 502 | |
| 503 | void _update_line_font(ItemFrame *p_frame, int p_line, const Ref<Font> &p_base_font, int p_base_font_size); |
| 504 | int _draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_ofs, int p_width, const Color &p_base_color, int p_outline_size, const Color &p_outline_color, const Color &p_font_shadow_color, int p_shadow_outline_size, const Point2 &p_shadow_ofs, int &r_processed_glyphs); |
| 505 | float _find_click_in_line(ItemFrame *p_frame, int p_line, const Vector2 &p_ofs, int p_width, const Point2i &p_click, ItemFrame **r_click_frame = nullptr, int *r_click_line = nullptr, Item **r_click_item = nullptr, int *r_click_char = nullptr, bool p_table = false, bool p_meta = false); |
| 506 | |
| 507 | String _roman(int p_num, bool p_capitalize) const; |
| 508 | String _letters(int p_num, bool p_capitalize) const; |
| 509 | |
| 510 | Item *_find_indentable(Item *p_item); |
| 511 | Item *_get_item_at_pos(Item *p_item_from, Item *p_item_to, int p_position); |
| 512 | void _find_frame(Item *p_item, ItemFrame **r_frame, int *r_line); |
| 513 | ItemFontSize *_find_font_size(Item *p_item); |
| 514 | ItemFont *_find_font(Item *p_item); |
| 515 | int _find_outline_size(Item *p_item, int p_default); |
| 516 | ItemList *_find_list_item(Item *p_item); |
| 517 | ItemDropcap *_find_dc_item(Item *p_item); |
| 518 | int _find_list(Item *p_item, Vector<int> &r_index, Vector<ItemList *> &r_list); |
| 519 | int _find_margin(Item *p_item, const Ref<Font> &p_base_font, int p_base_font_size); |
| 520 | PackedFloat32Array _find_tab_stops(Item *p_item); |
| 521 | HorizontalAlignment _find_alignment(Item *p_item); |
| 522 | BitField<TextServer::JustificationFlag> _find_jst_flags(Item *p_item); |
| 523 | TextServer::Direction _find_direction(Item *p_item); |
| 524 | TextServer::StructuredTextParser _find_stt(Item *p_item); |
| 525 | String _find_language(Item *p_item); |
| 526 | Color _find_color(Item *p_item, const Color &p_default_color); |
| 527 | Color _find_outline_color(Item *p_item, const Color &p_default_color); |
| 528 | bool _find_underline(Item *p_item); |
| 529 | bool _find_strikethrough(Item *p_item); |
| 530 | bool _find_meta(Item *p_item, Variant *r_meta, ItemMeta **r_item = nullptr); |
| 531 | bool _find_hint(Item *p_item, String *r_description); |
| 532 | Color _find_bgcolor(Item *p_item); |
| 533 | Color _find_fgcolor(Item *p_item); |
| 534 | bool _find_layout_subitem(Item *from, Item *to); |
| 535 | void _fetch_item_fx_stack(Item *p_item, Vector<ItemFX *> &r_stack); |
| 536 | void _normalize_subtags(Vector<String> &subtags); |
| 537 | |
| 538 | void _update_fx(ItemFrame *p_frame, double p_delta_time); |
| 539 | void _scroll_changed(double); |
| 540 | int _find_first_line(int p_from, int p_to, int p_vofs) const; |
| 541 | |
| 542 | _FORCE_INLINE_ float _calculate_line_vertical_offset(const Line &line) const; |
| 543 | |
| 544 | virtual void gui_input(const Ref<InputEvent> &p_event) override; |
| 545 | virtual String get_tooltip(const Point2 &p_pos) const override; |
| 546 | Item *_get_next_item(Item *p_item, bool p_free = false) const; |
| 547 | Item *_get_prev_item(Item *p_item, bool p_free = false) const; |
| 548 | |
| 549 | Rect2 _get_text_rect(); |
| 550 | Ref<RichTextEffect> _get_custom_effect_by_code(String p_bbcode_identifier); |
| 551 | virtual Dictionary parse_expressions_for_values(Vector<String> p_expressions); |
| 552 | |
| 553 | void _draw_fbg_boxes(RID p_ci, RID p_rid, Vector2 line_off, Item *it_from, Item *it_to, int start, int end, int fbg_flag); |
| 554 | #ifndef DISABLE_DEPRECATED |
| 555 | // Kept for compatibility from 3.x to 4.0. |
| 556 | bool _set(const StringName &p_name, const Variant &p_value); |
| 557 | #endif |
| 558 | bool use_bbcode = false; |
| 559 | String text; |
| 560 | void _apply_translation(); |
| 561 | |
| 562 | bool fit_content = false; |
| 563 | |
| 564 | struct ThemeCache { |
| 565 | Ref<StyleBox> normal_style; |
| 566 | Ref<StyleBox> focus_style; |
| 567 | Ref<StyleBox> progress_bg_style; |
| 568 | Ref<StyleBox> progress_fg_style; |
| 569 | |
| 570 | int line_separation; |
| 571 | |
| 572 | Ref<Font> normal_font; |
| 573 | int normal_font_size; |
| 574 | |
| 575 | Color default_color; |
| 576 | Color font_selected_color; |
| 577 | Color selection_color; |
| 578 | Color font_outline_color; |
| 579 | Color font_shadow_color; |
| 580 | int shadow_outline_size; |
| 581 | int shadow_offset_x; |
| 582 | int shadow_offset_y; |
| 583 | int outline_size; |
| 584 | Color outline_color; |
| 585 | |
| 586 | Ref<Font> bold_font; |
| 587 | int bold_font_size; |
| 588 | Ref<Font> bold_italics_font; |
| 589 | int bold_italics_font_size; |
| 590 | Ref<Font> italics_font; |
| 591 | int italics_font_size; |
| 592 | Ref<Font> mono_font; |
| 593 | int mono_font_size; |
| 594 | |
| 595 | int text_highlight_h_padding; |
| 596 | int text_highlight_v_padding; |
| 597 | |
| 598 | int table_h_separation; |
| 599 | int table_v_separation; |
| 600 | Color table_odd_row_bg; |
| 601 | Color table_even_row_bg; |
| 602 | Color table_border; |
| 603 | |
| 604 | float base_scale = 1.0; |
| 605 | } theme_cache; |
| 606 | |
| 607 | public: |
| 608 | String get_parsed_text() const; |
| 609 | void add_text(const String &p_text); |
| 610 | void add_image(const Ref<Texture2D> &p_image, const int p_width = 0, const int p_height = 0, const Color &p_color = Color(1.0, 1.0, 1.0), InlineAlignment p_alignment = INLINE_ALIGNMENT_CENTER, const Rect2 &p_region = Rect2(0, 0, 0, 0)); |
| 611 | void add_newline(); |
| 612 | bool remove_paragraph(const int p_paragraph); |
| 613 | void push_dropcap(const String &p_string, const Ref<Font> &p_font, int p_size, const Rect2 &p_dropcap_margins = Rect2(), const Color &p_color = Color(1, 1, 1), int p_ol_size = 0, const Color &p_ol_color = Color(0, 0, 0, 0)); |
| 614 | void _push_def_font(DefaultFont p_def_font); |
| 615 | void _push_def_font_var(DefaultFont p_def_font, const Ref<Font> &p_font, int p_size = -1); |
| 616 | void push_font(const Ref<Font> &p_font, int p_size = 0); |
| 617 | void push_font_size(int p_font_size); |
| 618 | void push_outline_size(int p_font_size); |
| 619 | void push_normal(); |
| 620 | void push_bold(); |
| 621 | void push_bold_italics(); |
| 622 | void push_italics(); |
| 623 | void push_mono(); |
| 624 | void push_color(const Color &p_color); |
| 625 | void push_outline_color(const Color &p_color); |
| 626 | void push_underline(); |
| 627 | void push_strikethrough(); |
| 628 | void push_language(const String &p_language); |
| 629 | void push_paragraph(HorizontalAlignment p_alignment, Control::TextDirection p_direction = Control::TEXT_DIRECTION_INHERITED, const String &p_language = "" , TextServer::StructuredTextParser p_st_parser = TextServer::STRUCTURED_TEXT_DEFAULT, BitField<TextServer::JustificationFlag> p_jst_flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_SKIP_LAST_LINE | TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE, const PackedFloat32Array &p_tab_stops = PackedFloat32Array()); |
| 630 | void push_indent(int p_level); |
| 631 | void push_list(int p_level, ListType p_list, bool p_capitalize, const String &p_bullet = String::utf8("•" )); |
| 632 | void push_meta(const Variant &p_meta); |
| 633 | void push_hint(const String &p_string); |
| 634 | void push_table(int p_columns, InlineAlignment p_alignment = INLINE_ALIGNMENT_TOP, int p_align_to_row = -1); |
| 635 | void push_fade(int p_start_index, int p_length); |
| 636 | void push_shake(int p_strength, float p_rate, bool p_connected); |
| 637 | void push_wave(float p_frequency, float p_amplitude, bool p_connected); |
| 638 | void push_tornado(float p_frequency, float p_radius, bool p_connected); |
| 639 | void push_rainbow(float p_saturation, float p_value, float p_frequency); |
| 640 | void push_pulse(const Color &p_color, float p_frequency, float p_ease); |
| 641 | void push_bgcolor(const Color &p_color); |
| 642 | void push_fgcolor(const Color &p_color); |
| 643 | void push_customfx(Ref<RichTextEffect> p_custom_effect, Dictionary p_environment); |
| 644 | void push_context(); |
| 645 | void set_table_column_expand(int p_column, bool p_expand, int p_ratio = 1); |
| 646 | void set_cell_row_background_color(const Color &p_odd_row_bg, const Color &p_even_row_bg); |
| 647 | void set_cell_border_color(const Color &p_color); |
| 648 | void set_cell_size_override(const Size2 &p_min_size, const Size2 &p_max_size); |
| 649 | void set_cell_padding(const Rect2 &p_padding); |
| 650 | int get_current_table_column() const; |
| 651 | void push_cell(); |
| 652 | void pop(); |
| 653 | void pop_context(); |
| 654 | void pop_all(); |
| 655 | |
| 656 | void clear(); |
| 657 | |
| 658 | void set_offset(int p_pixel); |
| 659 | |
| 660 | void set_meta_underline(bool p_underline); |
| 661 | bool is_meta_underlined() const; |
| 662 | |
| 663 | void set_hint_underline(bool p_underline); |
| 664 | bool is_hint_underlined() const; |
| 665 | |
| 666 | void set_scroll_active(bool p_active); |
| 667 | bool is_scroll_active() const; |
| 668 | |
| 669 | void set_scroll_follow(bool p_follow); |
| 670 | bool is_scroll_following() const; |
| 671 | |
| 672 | void set_tab_size(int p_spaces); |
| 673 | int get_tab_size() const; |
| 674 | |
| 675 | void (bool p_enabled); |
| 676 | bool () const; |
| 677 | |
| 678 | void set_shortcut_keys_enabled(bool p_enabled); |
| 679 | bool is_shortcut_keys_enabled() const; |
| 680 | |
| 681 | void set_fit_content(bool p_enabled); |
| 682 | bool is_fit_content_enabled() const; |
| 683 | |
| 684 | bool search(const String &p_string, bool p_from_selection = false, bool p_search_previous = false); |
| 685 | |
| 686 | void scroll_to_paragraph(int p_paragraph); |
| 687 | int get_paragraph_count() const; |
| 688 | int get_visible_paragraph_count() const; |
| 689 | |
| 690 | float get_line_offset(int p_line); |
| 691 | float get_paragraph_offset(int p_paragraph); |
| 692 | |
| 693 | void scroll_to_line(int p_line); |
| 694 | int get_line_count() const; |
| 695 | int get_visible_line_count() const; |
| 696 | |
| 697 | int get_content_height() const; |
| 698 | int get_content_width() const; |
| 699 | |
| 700 | void scroll_to_selection(); |
| 701 | |
| 702 | VScrollBar *get_v_scroll_bar() { return vscroll; } |
| 703 | |
| 704 | virtual CursorShape get_cursor_shape(const Point2 &p_pos) const override; |
| 705 | virtual Variant get_drag_data(const Point2 &p_point) override; |
| 706 | |
| 707 | void set_selection_enabled(bool p_enabled); |
| 708 | bool is_selection_enabled() const; |
| 709 | int get_selection_from() const; |
| 710 | int get_selection_to() const; |
| 711 | String get_selected_text() const; |
| 712 | void select_all(); |
| 713 | void selection_copy(); |
| 714 | |
| 715 | void set_deselect_on_focus_loss_enabled(const bool p_enabled); |
| 716 | bool is_deselect_on_focus_loss_enabled() const; |
| 717 | |
| 718 | void set_drag_and_drop_selection_enabled(const bool p_enabled); |
| 719 | bool is_drag_and_drop_selection_enabled() const; |
| 720 | |
| 721 | void deselect(); |
| 722 | |
| 723 | int get_pending_paragraphs() const; |
| 724 | bool is_ready() const; |
| 725 | bool is_updating() const; |
| 726 | |
| 727 | void set_threaded(bool p_threaded); |
| 728 | bool is_threaded() const; |
| 729 | |
| 730 | void set_progress_bar_delay(int p_delay_ms); |
| 731 | int get_progress_bar_delay() const; |
| 732 | |
| 733 | // Context menu. |
| 734 | PopupMenu *() const; |
| 735 | bool () const; |
| 736 | void (int p_option); |
| 737 | |
| 738 | void parse_bbcode(const String &p_bbcode); |
| 739 | void append_text(const String &p_bbcode); |
| 740 | |
| 741 | void set_use_bbcode(bool p_enable); |
| 742 | bool is_using_bbcode() const; |
| 743 | |
| 744 | void set_text(const String &p_bbcode); |
| 745 | String get_text() const; |
| 746 | |
| 747 | void set_text_direction(TextDirection p_text_direction); |
| 748 | TextDirection get_text_direction() const; |
| 749 | |
| 750 | void set_language(const String &p_language); |
| 751 | String get_language() const; |
| 752 | |
| 753 | void set_autowrap_mode(TextServer::AutowrapMode p_mode); |
| 754 | TextServer::AutowrapMode get_autowrap_mode() const; |
| 755 | |
| 756 | void set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser); |
| 757 | TextServer::StructuredTextParser get_structured_text_bidi_override() const; |
| 758 | |
| 759 | void set_structured_text_bidi_override_options(Array p_args); |
| 760 | Array get_structured_text_bidi_override_options() const; |
| 761 | |
| 762 | void set_visible_characters(int p_visible); |
| 763 | int get_visible_characters() const; |
| 764 | int get_character_line(int p_char); |
| 765 | int get_character_paragraph(int p_char); |
| 766 | int get_total_character_count() const; |
| 767 | int get_total_glyph_count() const; |
| 768 | |
| 769 | void set_visible_ratio(float p_ratio); |
| 770 | float get_visible_ratio() const; |
| 771 | |
| 772 | TextServer::VisibleCharactersBehavior get_visible_characters_behavior() const; |
| 773 | void set_visible_characters_behavior(TextServer::VisibleCharactersBehavior p_behavior); |
| 774 | |
| 775 | void set_effects(Array p_effects); |
| 776 | Array get_effects(); |
| 777 | |
| 778 | void install_effect(const Variant effect); |
| 779 | |
| 780 | virtual Size2 get_minimum_size() const override; |
| 781 | |
| 782 | RichTextLabel(const String &p_text = String()); |
| 783 | ~RichTextLabel(); |
| 784 | }; |
| 785 | |
| 786 | VARIANT_ENUM_CAST(RichTextLabel::ListType); |
| 787 | VARIANT_ENUM_CAST(RichTextLabel::MenuItems); |
| 788 | |
| 789 | #endif // RICH_TEXT_LABEL_H |
| 790 | |