1 /*************************************************************************/ 2 /* rich_text_label.h */ 3 /*************************************************************************/ 4 /* This file is part of: */ 5 /* GODOT ENGINE */ 6 /* https://godotengine.org */ 7 /*************************************************************************/ 8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ 9 /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ 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 #ifndef RICH_TEXT_LABEL_H 31 #define RICH_TEXT_LABEL_H 32 33 #include "scene/gui/scroll_bar.h" 34 35 class RichTextLabel : public Control { 36 37 OBJ_TYPE(RichTextLabel, Control); 38 39 public: 40 enum Align { 41 42 ALIGN_LEFT, 43 ALIGN_CENTER, 44 ALIGN_RIGHT, 45 ALIGN_FILL 46 }; 47 48 enum ListType { 49 50 LIST_NUMBERS, 51 LIST_LETTERS, 52 LIST_DOTS 53 }; 54 55 enum ItemType { 56 57 ITEM_FRAME, 58 ITEM_TEXT, 59 ITEM_IMAGE, 60 ITEM_NEWLINE, 61 ITEM_FONT, 62 ITEM_COLOR, 63 ITEM_UNDERLINE, 64 ITEM_ALIGN, 65 ITEM_INDENT, 66 ITEM_LIST, 67 ITEM_TABLE, 68 ITEM_META 69 }; 70 71 protected: 72 static void _bind_methods(); 73 74 private: 75 struct Item; 76 77 struct Line { 78 79 Item *from; 80 Vector<int> offset_caches; 81 Vector<int> height_caches; 82 Vector<int> space_caches; 83 int height_cache; 84 int height_accum_cache; 85 int char_count; 86 int minimum_width; 87 LineLine88 Line() { 89 from = NULL; 90 char_count = 0; 91 } 92 }; 93 94 struct Item { 95 96 int index; 97 Item *parent; 98 ItemType type; 99 List<Item *> subitems; 100 List<Item *>::Element *E; 101 int line; 102 _clear_childrenItem103 void _clear_children() { 104 while (subitems.size()) { 105 memdelete(subitems.front()->get()); 106 subitems.pop_front(); 107 } 108 } 109 ItemItem110 Item() { 111 parent = NULL; 112 E = NULL; 113 line = 0; 114 } ~ItemItem115 virtual ~Item() { _clear_children(); } 116 }; 117 118 struct ItemFrame : public Item { 119 120 int parent_line; 121 bool cell; 122 Vector<Line> lines; 123 int first_invalid_line; 124 ItemFrame *parent_frame; 125 ItemFrameItemFrame126 ItemFrame() { 127 type = ITEM_FRAME; 128 parent_frame = NULL; 129 cell = false; 130 parent_line = 0; 131 } 132 }; 133 134 struct ItemText : public Item { 135 136 String text; ItemTextItemText137 ItemText() { type = ITEM_TEXT; } 138 }; 139 140 struct ItemImage : public Item { 141 142 Ref<Texture> image; ItemImageItemImage143 ItemImage() { type = ITEM_IMAGE; } 144 }; 145 146 struct ItemFont : public Item { 147 148 Ref<Font> font; ItemFontItemFont149 ItemFont() { type = ITEM_FONT; } 150 }; 151 152 struct ItemColor : public Item { 153 154 Color color; ItemColorItemColor155 ItemColor() { type = ITEM_COLOR; } 156 }; 157 158 struct ItemUnderline : public Item { 159 ItemUnderlineItemUnderline160 ItemUnderline() { type = ITEM_UNDERLINE; } 161 }; 162 163 struct ItemMeta : public Item { 164 165 Variant meta; ItemMetaItemMeta166 ItemMeta() { type = ITEM_META; } 167 }; 168 169 struct ItemAlign : public Item { 170 171 Align align; ItemAlignItemAlign172 ItemAlign() { type = ITEM_ALIGN; } 173 }; 174 175 struct ItemIndent : public Item { 176 177 int level; ItemIndentItemIndent178 ItemIndent() { type = ITEM_INDENT; } 179 }; 180 181 struct ItemList : public Item { 182 183 ListType list_type; ItemListItemList184 ItemList() { type = ITEM_LIST; } 185 }; 186 187 struct ItemNewline : public Item { 188 189 int line; ItemNewlineItemNewline190 ItemNewline() { type = ITEM_NEWLINE; } 191 }; 192 193 struct ItemTable : public Item { 194 195 struct Column { 196 bool expand; 197 int expand_ratio; 198 int min_width; 199 int width; 200 }; 201 202 Vector<Column> columns; 203 int total_width; ItemTableItemTable204 ItemTable() { type = ITEM_TABLE; } 205 }; 206 207 ItemFrame *main; 208 Item *current; 209 ItemFrame *current_frame; 210 211 VScrollBar *vscroll; 212 213 bool scroll_visible; 214 bool scroll_follow; 215 bool scroll_following; 216 bool scroll_active; 217 int scroll_w; 218 bool updating_scroll; 219 int current_idx; 220 221 int tab_size; 222 bool underline_meta; 223 224 Align default_align; 225 226 void _invalidate_current_line(ItemFrame *p_frame); 227 void _validate_line_caches(ItemFrame *p_frame); 228 229 void _add_item(Item *p_item, bool p_enter = false, bool p_ensure_newline = false); 230 void _remove_item(Item *p_item, const int p_line, const int p_subitem_line); 231 232 struct ProcessState { 233 234 int line_width; 235 }; 236 237 enum ProcessMode { 238 239 PROCESS_CACHE, 240 PROCESS_DRAW, 241 PROCESS_POINTER 242 }; 243 244 struct Selection { 245 246 Item *click; 247 int click_char; 248 249 Item *from; 250 int from_char; 251 Item *to; 252 int to_char; 253 254 bool active; 255 bool enabled; 256 }; 257 258 Selection selection; 259 260 int visible_characters; 261 float percent_visible; 262 263 void _process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &y, int p_width, int p_line, ProcessMode p_mode, const Ref<Font> &p_base_font, const Color &p_base_color, const Point2i &p_click_pos = Point2i(), Item **r_click_item = NULL, int *r_click_char = NULL, bool *r_outside = NULL, int p_char_count = 0); 264 void _find_click(ItemFrame *p_frame, const Point2i &p_click, Item **r_click_item = NULL, int *r_click_char = NULL, bool *r_outside = NULL); 265 266 Ref<Font> _find_font(Item *p_item); 267 int _find_margin(Item *p_item, const Ref<Font> &p_base_font); 268 Align _find_align(Item *p_item); 269 Color _find_color(Item *p_item, const Color &p_default_color); 270 bool _find_underline(Item *p_item); 271 bool _find_meta(Item *p_item, Variant *r_meta); 272 273 void _update_scroll(); 274 void _scroll_changed(double); 275 276 void _input_event(InputEvent p_event); 277 Item *_get_next_item(Item *p_item, bool p_free = false); 278 279 bool use_bbcode; 280 String bbcode; 281 282 void _update_all_lines(); 283 284 protected: 285 void _notification(int p_what); 286 287 public: 288 String get_text(); 289 void add_text(const String &p_text); 290 void add_image(const Ref<Texture> &p_image); 291 void add_newline(); 292 bool remove_line(const int p_line); 293 void push_font(const Ref<Font> &p_font); 294 void push_color(const Color &p_color); 295 void push_underline(); 296 void push_align(Align p_align); 297 void push_indent(int p_level); 298 void push_list(ListType p_list); 299 void push_meta(const Variant &p_data); 300 void push_table(int p_columns); 301 void set_table_column_expand(int p_column, bool p_expand, int p_ratio = 1); 302 int get_current_table_column() const; 303 void push_cell(); 304 void pop(); 305 306 void clear(); 307 308 void set_offset(int p_pixel); 309 310 void set_meta_underline(bool p_underline); 311 bool is_meta_underlined() const; 312 313 void set_scroll_active(bool p_active); 314 bool is_scroll_active() const; 315 316 void set_scroll_follow(bool p_follow); 317 bool is_scroll_following() const; 318 319 void set_tab_size(int p_spaces); 320 int get_tab_size() const; 321 322 bool search(const String &p_string, bool p_from_selection = false); 323 324 void scroll_to_line(int p_line); 325 int get_line_count() const; 326 get_v_scroll()327 VScrollBar *get_v_scroll() { return vscroll; } 328 329 virtual CursorShape get_cursor_shape(const Point2 &p_pos) const; 330 331 void set_selection_enabled(bool p_enabled); 332 bool is_selection_enabled() const; 333 void selection_copy(); 334 335 Error parse_bbcode(const String &p_bbcode); 336 Error append_bbcode(const String &p_bbcode); 337 338 void set_use_bbcode(bool p_enable); 339 bool is_using_bbcode() const; 340 341 void set_bbcode(const String &p_bbcode); 342 String get_bbcode() const; 343 344 void set_text(const String &p_string); 345 346 void set_visible_characters(int p_visible); 347 int get_visible_characters() const; 348 int get_total_character_count() const; 349 350 void set_percent_visible(float p_percent); 351 float get_percent_visible() const; 352 353 RichTextLabel(); 354 ~RichTextLabel(); 355 }; 356 357 VARIANT_ENUM_CAST(RichTextLabel::Align); 358 VARIANT_ENUM_CAST(RichTextLabel::ListType); 359 VARIANT_ENUM_CAST(RichTextLabel::ItemType); 360 361 #endif // RICH_TEXT_LABEL_H 362