Browse Source

Fixed completion and hint panel positioning in TextExit [3.2]

Filip 4 years ago
parent
commit
f1d00522f5
1 changed files with 53 additions and 42 deletions
  1. 53 42
      scene/gui/text_edit.cpp

+ 53 - 42
scene/gui/text_edit.cpp

@@ -885,6 +885,7 @@ void TextEdit::_notification(int p_what) {
 			}
 			}
 
 
 			Point2 cursor_pos;
 			Point2 cursor_pos;
+			bool is_cursor_visible = false;
 			int cursor_insert_offset_y = 0;
 			int cursor_insert_offset_y = 0;
 
 
 			// Get the highlighted words.
 			// Get the highlighted words.
@@ -1492,6 +1493,7 @@ void TextEdit::_notification(int p_what) {
 
 
 					if (cursor.column == (last_wrap_column + j) && cursor.line == line && cursor_wrap_index == line_wrap_index && (char_ofs + char_margin) >= xmargin_beg) {
 					if (cursor.column == (last_wrap_column + j) && cursor.line == line && cursor_wrap_index == line_wrap_index && (char_ofs + char_margin) >= xmargin_beg) {
 
 
+						is_cursor_visible = true;
 						cursor_pos = Point2i(char_ofs + char_margin + ofs_x, ofs_y);
 						cursor_pos = Point2i(char_ofs + char_margin + ofs_x, ofs_y);
 						cursor_pos.y += (get_row_height() - cache.font->get_height()) / 2;
 						cursor_pos.y += (get_row_height() - cache.font->get_height()) / 2;
 
 
@@ -1552,75 +1554,84 @@ void TextEdit::_notification(int p_what) {
 			}
 			}
 
 
 			bool completion_below = false;
 			bool completion_below = false;
-			if (completion_active && completion_options.size() > 0) {
-				// Code completion box.
-				Ref<StyleBox> csb = get_stylebox("completion");
-				int maxlines = get_constant("completion_lines");
-				int cmax_width = get_constant("completion_max_width") * cache.font->get_char_size('x').x;
-				int scrollw = get_constant("completion_scroll_width");
-				Color scrollc = get_color("completion_scroll_color");
+			if (completion_active && is_cursor_visible && completion_options.size() > 0) {
+				// Completion panel
 
 
+				const Ref<StyleBox> csb = get_stylebox("completion");
+				const int maxlines = get_constant("completion_lines");
+				const int cmax_width = get_constant("completion_max_width") * cache.font->get_char_size('x').x;
+				const Color scrollc = get_color("completion_scroll_color");
+
+				const int row_height = get_row_height();
 				const int completion_options_size = completion_options.size();
 				const int completion_options_size = completion_options.size();
-				int lines = MIN(completion_options_size, maxlines);
-				int w = 0;
-				int h = lines * get_row_height();
-				int nofs = cache.font->get_string_size(completion_base).width;
+				const int row_count = MIN(completion_options_size, maxlines);
+				const int completion_rows_height = row_count * row_height;
+				const int completion_base_width = cache.font->get_string_size(completion_base).width;
+
+				int scroll_rectangle_width = get_constant("completion_scroll_width");
+				int width = 0;
 
 
+				// Compute max width of the panel based on the longest completion option
 				if (completion_options_size < 50) {
 				if (completion_options_size < 50) {
 					for (int i = 0; i < completion_options_size; i++) {
 					for (int i = 0; i < completion_options_size; i++) {
-						int w2 = MIN(cache.font->get_string_size(completion_options[i].display).x, cmax_width);
-						if (w2 > w)
-							w = w2;
+						int line_width = MIN(cache.font->get_string_size(completion_options[i].display).x, cmax_width);
+						if (line_width > width) {
+							width = line_width;
+						}
 					}
 					}
 				} else {
 				} else {
-					w = cmax_width;
+					width = cmax_width;
 				}
 				}
 
 
 				// Add space for completion icons.
 				// Add space for completion icons.
 				const int icon_hsep = get_constant("hseparation", "ItemList");
 				const int icon_hsep = get_constant("hseparation", "ItemList");
-				Size2 icon_area_size(get_row_height(), get_row_height());
-				w += icon_area_size.width + icon_hsep;
+				const Size2 icon_area_size(row_height, row_height);
+				const int icon_area_width = icon_area_size.width + icon_hsep;
+				width += icon_area_size.width + icon_hsep;
 
 
-				int line_from = CLAMP(completion_index - lines / 2, 0, completion_options_size - lines);
+				const int line_from = CLAMP(completion_index - row_count / 2, 0, completion_options_size - row_count);
 
 
-				for (int i = 0; i < lines; i++) {
+				for (int i = 0; i < row_count; i++) {
 					int l = line_from + i;
 					int l = line_from + i;
 					ERR_CONTINUE(l < 0 || l >= completion_options_size);
 					ERR_CONTINUE(l < 0 || l >= completion_options_size);
 					if (completion_options[l].default_value.get_type() == Variant::COLOR) {
 					if (completion_options[l].default_value.get_type() == Variant::COLOR) {
-						w += icon_area_size.width;
+						width += icon_area_size.width;
 						break;
 						break;
 					}
 					}
 				}
 				}
 
 
-				int th = h + csb->get_minimum_size().y;
+				// Position completion panel
+				completion_rect.size.width = width + 2;
+				completion_rect.size.height = completion_rows_height;
 
 
-				if (cursor_pos.y + get_row_height() + th > get_size().height) {
-					completion_rect.position.y = cursor_pos.y - th - (cache.line_spacing / 2.0f) - cursor_insert_offset_y;
-				} else {
-					completion_rect.position.y = cursor_pos.y + cache.font->get_height() + (cache.line_spacing / 2.0f) + csb->get_offset().y - cursor_insert_offset_y;
-					completion_below = true;
+				if (completion_options_size <= maxlines) {
+					scroll_rectangle_width = 0;
 				}
 				}
 
 
-				if (cursor_pos.x - nofs + w + scrollw > get_size().width) {
-					completion_rect.position.x = get_size().width - w - scrollw;
+				const Point2 csb_offset = csb->get_offset();
+				const int total_height = completion_rect.size.height + csb->get_minimum_size().y;
+				const int ajdusted_cursor_y = cursor_pos.y - cursor_insert_offset_y - (get_row_height() - cache.font->get_height()) / 2;
+
+				completion_rect.position.x = cursor_pos.x - completion_base_width - icon_area_width - csb_offset.x;
+
+				if (ajdusted_cursor_y + row_height + total_height > get_size().height) {
+					// Completion panel above the cursor line
+					completion_rect.position.y = ajdusted_cursor_y - total_height;
 				} else {
 				} else {
-					completion_rect.position.x = cursor_pos.x - nofs;
+					// Completion panel below the cursor line
+					completion_rect.position.y = ajdusted_cursor_y + row_height;
+					completion_below = true;
 				}
 				}
 
 
-				completion_rect.size.width = w + 2;
-				completion_rect.size.height = h;
-				if (completion_options_size <= maxlines)
-					scrollw = 0;
-
-				draw_style_box(csb, Rect2(completion_rect.position - csb->get_offset(), completion_rect.size + csb->get_minimum_size() + Size2(scrollw, 0)));
+				draw_style_box(csb, Rect2(completion_rect.position - csb_offset, completion_rect.size + csb->get_minimum_size() + Size2(scroll_rectangle_width, 0)));
 
 
 				if (cache.completion_background_color.a > 0.01) {
 				if (cache.completion_background_color.a > 0.01) {
-					VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(completion_rect.position, completion_rect.size + Size2(scrollw, 0)), cache.completion_background_color);
+					VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(completion_rect.position, completion_rect.size + Size2(scroll_rectangle_width, 0)), cache.completion_background_color);
 				}
 				}
 				VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(completion_rect.position.x, completion_rect.position.y + (completion_index - line_from) * get_row_height()), Size2(completion_rect.size.width, get_row_height())), cache.completion_selected_color);
 				VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(completion_rect.position.x, completion_rect.position.y + (completion_index - line_from) * get_row_height()), Size2(completion_rect.size.width, get_row_height())), cache.completion_selected_color);
-				draw_rect(Rect2(completion_rect.position + Vector2(icon_area_size.x + icon_hsep, 0), Size2(MIN(nofs, completion_rect.size.width - (icon_area_size.x + icon_hsep)), completion_rect.size.height)), cache.completion_existing_color);
+				draw_rect(Rect2(completion_rect.position + Vector2(icon_area_size.x + icon_hsep, 0), Size2(MIN(completion_base_width, completion_rect.size.width - (icon_area_size.x + icon_hsep)), completion_rect.size.height)), cache.completion_existing_color);
 
 
-				for (int i = 0; i < lines; i++) {
+				for (int i = 0; i < row_count; i++) {
 
 
 					int l = line_from + i;
 					int l = line_from + i;
 					ERR_CONTINUE(l < 0 || l >= completion_options_size);
 					ERR_CONTINUE(l < 0 || l >= completion_options_size);
@@ -1653,11 +1664,11 @@ void TextEdit::_notification(int p_what) {
 					draw_string(cache.font, title_pos, completion_options[l].display, text_color, completion_rect.size.width - (icon_area_size.x + icon_hsep));
 					draw_string(cache.font, title_pos, completion_options[l].display, text_color, completion_rect.size.width - (icon_area_size.x + icon_hsep));
 				}
 				}
 
 
-				if (scrollw) {
+				if (scroll_rectangle_width) {
 					// Draw a small scroll rectangle to show a position in the options.
 					// Draw a small scroll rectangle to show a position in the options.
 					float r = (float)maxlines / completion_options_size;
 					float r = (float)maxlines / completion_options_size;
 					float o = (float)line_from / completion_options_size;
 					float o = (float)line_from / completion_options_size;
-					draw_rect(Rect2(completion_rect.position.x + completion_rect.size.width, completion_rect.position.y + o * completion_rect.size.y, scrollw, completion_rect.size.y * r), scrollc);
+					draw_rect(Rect2(completion_rect.position.x + completion_rect.size.width, completion_rect.position.y + o * completion_rect.size.y, scroll_rectangle_width, completion_rect.size.y * r), scrollc);
 				}
 				}
 
 
 				completion_line_ofs = line_from;
 				completion_line_ofs = line_from;
@@ -1665,7 +1676,7 @@ void TextEdit::_notification(int p_what) {
 
 
 			// Check to see if the hint should be drawn.
 			// Check to see if the hint should be drawn.
 			bool show_hint = false;
 			bool show_hint = false;
-			if (completion_hint != "") {
+			if (is_cursor_visible && completion_hint != "") {
 				if (completion_active) {
 				if (completion_active) {
 					if (completion_below && !callhint_below) {
 					if (completion_below && !callhint_below) {
 						show_hint = true;
 						show_hint = true;
@@ -1706,7 +1717,7 @@ void TextEdit::_notification(int p_what) {
 					completion_hint_offset = cursor_pos.x - offset;
 					completion_hint_offset = cursor_pos.x - offset;
 				}
 				}
 
 
-				Point2 hint_ofs = Vector2(completion_hint_offset, cursor_pos.y) + callhint_offset;
+				Point2 hint_ofs = Vector2(completion_hint_offset, cursor_pos.y - cursor_insert_offset_y - (get_row_height() - cache.font->get_height()) / 2) + callhint_offset;
 
 
 				if (callhint_below) {
 				if (callhint_below) {
 					hint_ofs.y += get_row_height() + sb->get_offset().y;
 					hint_ofs.y += get_row_height() + sb->get_offset().y;