Browse Source

Merge pull request #22353 from YeldhamDev/bbcode_strikethrough

Add proper strikethrough BBCode to RichTextLabel
Rémi Verschelde 7 years ago
parent
commit
49665a46d8
2 changed files with 56 additions and 15 deletions
  1. 48 15
      scene/gui/rich_text_label.cpp
  2. 8 0
      scene/gui/rich_text_label.h

+ 48 - 15
scene/gui/rich_text_label.cpp

@@ -320,14 +320,17 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
 				Color color;
 				Color font_color_shadow;
 				bool underline = false;
+				bool strikethrough = false;
 
 				if (p_mode == PROCESS_DRAW) {
 					color = _find_color(text, p_base_color);
 					font_color_shadow = _find_color(text, p_font_color_shadow);
-					underline = _find_underline(text);
-					if (_find_meta(text, &meta) && underline_meta) {
+					if (_find_underline(text) || (_find_meta(text, &meta) && underline_meta)) {
 
 						underline = true;
+					} else if (_find_strikethrough(text)) {
+
+						strikethrough = true;
 					}
 
 				} else if (p_mode == PROCESS_CACHE) {
@@ -469,6 +472,15 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
 							underline_width *= EDSCALE;
 #endif
 							VS::get_singleton()->canvas_item_add_line(ci, p_ofs + Point2(align_ofs + wofs, uy), p_ofs + Point2(align_ofs + wofs + w, uy), uc, underline_width);
+						} else if (strikethrough) {
+							Color uc = color;
+							uc.a *= 0.5;
+							int uy = y + lh / 2 - line_descent + 2;
+							float strikethrough_width = 1.0;
+#ifdef TOOLS_ENABLED
+							strikethrough_width *= EDSCALE;
+#endif
+							VS::get_singleton()->canvas_item_add_line(ci, p_ofs + Point2(align_ofs + wofs, uy), p_ofs + Point2(align_ofs + wofs + w, uy), uc, strikethrough_width);
 						}
 					}
 
@@ -1227,6 +1239,23 @@ bool RichTextLabel::_find_underline(Item *p_item) {
 	return false;
 }
 
+bool RichTextLabel::_find_strikethrough(Item *p_item) {
+
+	Item *item = p_item;
+
+	while (item) {
+
+		if (item->type == ITEM_STRIKETHROUGH) {
+
+			return true;
+		}
+
+		item = item->parent;
+	}
+
+	return false;
+}
+
 bool RichTextLabel::_find_meta(Item *p_item, Variant *r_meta) {
 
 	Item *item = p_item;
@@ -1458,6 +1487,7 @@ void RichTextLabel::push_font(const Ref<Font> &p_font) {
 	item->font = p_font;
 	_add_item(item, true);
 }
+
 void RichTextLabel::push_color(const Color &p_color) {
 
 	ERR_FAIL_COND(current->type == ITEM_TABLE);
@@ -1466,6 +1496,7 @@ void RichTextLabel::push_color(const Color &p_color) {
 	item->color = p_color;
 	_add_item(item, true);
 }
+
 void RichTextLabel::push_underline() {
 
 	ERR_FAIL_COND(current->type == ITEM_TABLE);
@@ -1474,6 +1505,14 @@ void RichTextLabel::push_underline() {
 	_add_item(item, true);
 }
 
+void RichTextLabel::push_strikethrough() {
+
+	ERR_FAIL_COND(current->type == ITEM_TABLE);
+	ItemStrikethrough *item = memnew(ItemStrikethrough);
+
+	_add_item(item, true);
+}
+
 void RichTextLabel::push_align(Align p_align) {
 
 	ERR_FAIL_COND(current->type == ITEM_TABLE);
@@ -1683,7 +1722,7 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
 		}
 
 		if (brk_pos == p_bbcode.length())
-			break; //nothing else o add
+			break; //nothing else to add
 
 		int brk_end = p_bbcode.find("]", brk_pos + 1);
 
@@ -1749,7 +1788,7 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
 			int columns = tag.substr(6, tag.length()).to_int();
 			if (columns < 1)
 				columns = 1;
-			//use monospace font
+
 			push_table(columns);
 			pos = brk_end + 1;
 			tag_stack.push_front("table");
@@ -1763,7 +1802,7 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
 			int ratio = tag.substr(5, tag.length()).to_int();
 			if (ratio < 1)
 				ratio = 1;
-			//use monospace font
+
 			set_table_column_expand(get_current_table_column(), true, ratio);
 			push_cell();
 			pos = brk_end + 1;
@@ -1776,43 +1815,37 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
 			tag_stack.push_front(tag);
 		} else if (tag == "s") {
 
-			//use strikethrough (not supported underline instead)
-			push_underline();
+			//use strikethrough
+			push_strikethrough();
 			pos = brk_end + 1;
 			tag_stack.push_front(tag);
 		} else if (tag == "center") {
 
-			//use underline
 			push_align(ALIGN_CENTER);
 			pos = brk_end + 1;
 			tag_stack.push_front(tag);
 		} else if (tag == "fill") {
 
-			//use underline
 			push_align(ALIGN_FILL);
 			pos = brk_end + 1;
 			tag_stack.push_front(tag);
 		} else if (tag == "right") {
 
-			//use underline
 			push_align(ALIGN_RIGHT);
 			pos = brk_end + 1;
 			tag_stack.push_front(tag);
 		} else if (tag == "ul") {
 
-			//use underline
 			push_list(LIST_DOTS);
 			pos = brk_end + 1;
 			tag_stack.push_front(tag);
 		} else if (tag == "ol") {
 
-			//use underline
 			push_list(LIST_NUMBERS);
 			pos = brk_end + 1;
 			tag_stack.push_front(tag);
 		} else if (tag == "indent") {
 
-			//use underline
 			indent_level++;
 			push_indent(indent_level);
 			pos = brk_end + 1;
@@ -1820,7 +1853,6 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
 
 		} else if (tag == "url") {
 
-			//use strikethrough (not supported underline instead)
 			int end = p_bbcode.find("[", brk_end);
 			if (end == -1)
 				end = p_bbcode.length();
@@ -1838,7 +1870,6 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
 			tag_stack.push_front("url");
 		} else if (tag == "img") {
 
-			//use strikethrough (not supported underline instead)
 			int end = p_bbcode.find("[", brk_end);
 			if (end == -1)
 				end = p_bbcode.length();
@@ -2145,6 +2176,7 @@ void RichTextLabel::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("push_list", "type"), &RichTextLabel::push_list);
 	ClassDB::bind_method(D_METHOD("push_meta", "data"), &RichTextLabel::push_meta);
 	ClassDB::bind_method(D_METHOD("push_underline"), &RichTextLabel::push_underline);
+	ClassDB::bind_method(D_METHOD("push_strikethrough"), &RichTextLabel::push_strikethrough);
 	ClassDB::bind_method(D_METHOD("push_table", "columns"), &RichTextLabel::push_table);
 	ClassDB::bind_method(D_METHOD("set_table_column_expand", "column", "expand", "ratio"), &RichTextLabel::set_table_column_expand);
 	ClassDB::bind_method(D_METHOD("push_cell"), &RichTextLabel::push_cell);
@@ -2233,6 +2265,7 @@ void RichTextLabel::_bind_methods() {
 	BIND_ENUM_CONSTANT(ITEM_FONT);
 	BIND_ENUM_CONSTANT(ITEM_COLOR);
 	BIND_ENUM_CONSTANT(ITEM_UNDERLINE);
+	BIND_ENUM_CONSTANT(ITEM_STRIKETHROUGH);
 	BIND_ENUM_CONSTANT(ITEM_ALIGN);
 	BIND_ENUM_CONSTANT(ITEM_INDENT);
 	BIND_ENUM_CONSTANT(ITEM_LIST);

+ 8 - 0
scene/gui/rich_text_label.h

@@ -62,6 +62,7 @@ public:
 		ITEM_FONT,
 		ITEM_COLOR,
 		ITEM_UNDERLINE,
+		ITEM_STRIKETHROUGH,
 		ITEM_ALIGN,
 		ITEM_INDENT,
 		ITEM_LIST,
@@ -164,6 +165,11 @@ private:
 		ItemUnderline() { type = ITEM_UNDERLINE; }
 	};
 
+	struct ItemStrikethrough : public Item {
+
+		ItemStrikethrough() { type = ITEM_STRIKETHROUGH; }
+	};
+
 	struct ItemMeta : public Item {
 
 		Variant meta;
@@ -277,6 +283,7 @@ private:
 	Align _find_align(Item *p_item);
 	Color _find_color(Item *p_item, const Color &p_default_color);
 	bool _find_underline(Item *p_item);
+	bool _find_strikethrough(Item *p_item);
 	bool _find_meta(Item *p_item, Variant *r_meta);
 
 	void _update_scroll();
@@ -307,6 +314,7 @@ public:
 	void push_font(const Ref<Font> &p_font);
 	void push_color(const Color &p_color);
 	void push_underline();
+	void push_strikethrough();
 	void push_align(Align p_align);
 	void push_indent(int p_level);
 	void push_list(ListType p_list);