diff options
Diffstat (limited to 'scene/gui')
-rw-r--r-- | scene/gui/graph_node.cpp | 66 | ||||
-rw-r--r-- | scene/gui/line_edit.cpp | 69 | ||||
-rw-r--r-- | scene/gui/line_edit.h | 3 | ||||
-rw-r--r-- | scene/gui/range.cpp | 2 | ||||
-rw-r--r-- | scene/gui/rich_text_label.cpp | 31 | ||||
-rw-r--r-- | scene/gui/rich_text_label.h | 2 | ||||
-rw-r--r-- | scene/gui/text_edit.cpp | 23 | ||||
-rw-r--r-- | scene/gui/tree.cpp | 2 |
8 files changed, 117 insertions, 81 deletions
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index 5df4c066e4..83c789f3d5 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -366,38 +366,46 @@ void GraphNode::_notification(int p_what) { close_rect = Rect2(); } - for (const KeyValue<int, Slot> &E : slot_info) { - if (E.key < 0 || E.key >= cache_y.size()) { - continue; - } - if (!slot_info.has(E.key)) { - continue; - } - const Slot &s = slot_info[E.key]; - // Left port. - if (s.enable_left) { - Ref<Texture2D> p = port; - if (s.custom_slot_left.is_valid()) { - p = s.custom_slot_left; + if (get_child_count() > 0) { + for (const KeyValue<int, Slot> &E : slot_info) { + if (E.key < 0 || E.key >= cache_y.size()) { + continue; } - p->draw(get_canvas_item(), icofs + Point2(edgeofs, cache_y[E.key]), s.color_left); - } - // Right port. - if (s.enable_right) { - Ref<Texture2D> p = port; - if (s.custom_slot_right.is_valid()) { - p = s.custom_slot_right; + if (!slot_info.has(E.key)) { + continue; + } + const Slot &s = slot_info[E.key]; + // Left port. + if (s.enable_left) { + Ref<Texture2D> p = port; + if (s.custom_slot_left.is_valid()) { + p = s.custom_slot_left; + } + p->draw(get_canvas_item(), icofs + Point2(edgeofs, cache_y[E.key]), s.color_left); + } + // Right port. + if (s.enable_right) { + Ref<Texture2D> p = port; + if (s.custom_slot_right.is_valid()) { + p = s.custom_slot_right; + } + p->draw(get_canvas_item(), icofs + Point2(get_size().x - edgeofs, cache_y[E.key]), s.color_right); } - p->draw(get_canvas_item(), icofs + Point2(get_size().x - edgeofs, cache_y[E.key]), s.color_right); - } - // Draw slot stylebox. - if (s.draw_stylebox) { - Control *c = Object::cast_to<Control>(get_child(E.key)); - Rect2 c_rect = c->get_rect(); - c_rect.position.x = sb->get_margin(SIDE_LEFT); - c_rect.size.width = w; - draw_style_box(sb_slot, c_rect); + // Draw slot stylebox. + if (s.draw_stylebox) { + Control *c = Object::cast_to<Control>(get_child(E.key)); + if (!c || !c->is_visible_in_tree()) { + continue; + } + if (c->is_set_as_top_level()) { + continue; + } + Rect2 c_rect = c->get_rect(); + c_rect.position.x = sb->get_margin(SIDE_LEFT); + c_rect.size.width = w; + draw_style_box(sb_slot, c_rect); + } } } diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 8a77c39487..bd39ee3bb3 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -768,18 +768,18 @@ void LineEdit::_notification(int p_what) { case NOTIFICATION_WM_WINDOW_FOCUS_IN: { window_has_focus = true; - draw_caret = true; + _validate_caret_can_draw(); queue_redraw(); } break; case NOTIFICATION_WM_WINDOW_FOCUS_OUT: { window_has_focus = false; - draw_caret = false; + _validate_caret_can_draw(); queue_redraw(); } break; case NOTIFICATION_INTERNAL_PROCESS: { - if (caret_blinking) { + if (caret_blink_enabled && caret_can_draw) { caret_blink_timer += get_process_delta_time(); if (caret_blink_timer >= caret_blink_interval) { @@ -790,10 +790,6 @@ void LineEdit::_notification(int p_what) { } break; case NOTIFICATION_DRAW: { - if ((!has_focus() && !(menu && menu->has_focus()) && !caret_force_displayed) || !window_has_focus) { - draw_caret = false; - } - int width, height; bool rtl = is_layout_rtl(); @@ -806,7 +802,6 @@ void LineEdit::_notification(int p_what) { Ref<StyleBox> style = theme_cache.normal; if (!is_editable()) { style = theme_cache.read_only; - draw_caret = false; } Ref<Font> font = theme_cache.font; @@ -953,7 +948,7 @@ void LineEdit::_notification(int p_what) { // Draw carets. ofs.x = x_ofs + scroll_offset; - if (draw_caret || drag_caret_force_displayed) { + if ((caret_can_draw && draw_caret) || drag_caret_force_displayed) { // Prevent carets from disappearing at theme scales below 1.0 (if the caret width is 1). const int caret_width = theme_cache.caret_width * MAX(1, theme_cache.base_scale); @@ -1063,16 +1058,7 @@ void LineEdit::_notification(int p_what) { } break; case NOTIFICATION_FOCUS_ENTER: { - if (!caret_force_displayed) { - if (caret_blink_enabled) { - if (!caret_blinking) { - caret_blinking = true; - caret_blink_timer = 0.0; - } - } else { - draw_caret = true; - } - } + _validate_caret_can_draw(); if (select_all_on_focus) { if (Input::get_singleton()->is_mouse_button_pressed(MouseButton::LEFT)) { @@ -1093,9 +1079,7 @@ void LineEdit::_notification(int p_what) { } break; case NOTIFICATION_FOCUS_EXIT: { - if (caret_blink_enabled && !caret_force_displayed) { - caret_blinking = false; - } + _validate_caret_can_draw(); if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_IME)) { DisplayServer::get_singleton()->window_set_ime_position(Point2(), get_viewport()->get_window_id()); @@ -1401,21 +1385,18 @@ bool LineEdit::is_caret_blink_enabled() const { } void LineEdit::set_caret_blink_enabled(const bool p_enabled) { + if (caret_blink_enabled == p_enabled) { + return; + } + caret_blink_enabled = p_enabled; set_process_internal(p_enabled); - if (has_focus() || caret_force_displayed) { - if (p_enabled) { - if (!caret_blinking) { - caret_blinking = true; - caret_blink_timer = 0.0; - } - } else { - caret_blinking = false; - } + draw_caret = !caret_blink_enabled; + if (caret_blink_enabled) { + caret_blink_timer = 0.0; } - - draw_caret = true; + queue_redraw(); notify_property_list_changed(); } @@ -1425,8 +1406,13 @@ bool LineEdit::is_caret_force_displayed() const { } void LineEdit::set_caret_force_displayed(const bool p_enabled) { + if (caret_force_displayed == p_enabled) { + return; + } + caret_force_displayed = p_enabled; - set_caret_blink_enabled(caret_blink_enabled); + _validate_caret_can_draw(); + queue_redraw(); } @@ -1442,7 +1428,7 @@ void LineEdit::set_caret_blink_interval(const float p_interval) { void LineEdit::_reset_caret_blink_timer() { if (caret_blink_enabled) { draw_caret = true; - if (has_focus()) { + if (caret_can_draw) { caret_blink_timer = 0.0; queue_redraw(); } @@ -1451,11 +1437,19 @@ void LineEdit::_reset_caret_blink_timer() { void LineEdit::_toggle_draw_caret() { draw_caret = !draw_caret; - if (is_visible_in_tree() && ((has_focus() && window_has_focus) || caret_force_displayed)) { + if (is_visible_in_tree() && caret_can_draw) { queue_redraw(); } } +void LineEdit::_validate_caret_can_draw() { + if (caret_blink_enabled) { + draw_caret = true; + caret_blink_timer = 0.0; + } + caret_can_draw = editable && (window_has_focus || (menu && menu->has_focus())) && (has_focus() || caret_force_displayed); +} + void LineEdit::delete_char() { if ((text.length() <= 0) || (caret_column == 0)) { return; @@ -1846,6 +1840,7 @@ void LineEdit::set_editable(bool p_editable) { } editable = p_editable; + _validate_caret_can_draw(); update_minimum_size(); queue_redraw(); @@ -2523,6 +2518,8 @@ void LineEdit::_ensure_menu() { menu->add_child(menu_ctl, false, INTERNAL_MODE_FRONT); menu->connect("id_pressed", callable_mp(this, &LineEdit::menu_option)); + menu->connect(SNAME("focus_entered"), callable_mp(this, &LineEdit::_validate_caret_can_draw)); + menu->connect(SNAME("focus_exited"), callable_mp(this, &LineEdit::_validate_caret_can_draw)); menu_dir->connect("id_pressed", callable_mp(this, &LineEdit::menu_option)); menu_ctl->connect("id_pressed", callable_mp(this, &LineEdit::menu_option)); } diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index e0a079b623..79db9dce21 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -172,7 +172,7 @@ private: bool draw_caret = true; float caret_blink_interval = 0.65; double caret_blink_timer = 0.0; - bool caret_blinking = false; + bool caret_can_draw = false; bool pending_select_all_on_focus = false; bool select_all_on_focus = false; @@ -225,6 +225,7 @@ private: void _reset_caret_blink_timer(); void _toggle_draw_caret(); + void _validate_caret_can_draw(); void clear_internal(); diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp index e0e4ead55f..00c81c8616 100644 --- a/scene/gui/range.cpp +++ b/scene/gui/range.cpp @@ -85,7 +85,7 @@ void Range::set_value(double p_val) { void Range::set_value_no_signal(double p_val) { if (shared->step > 0) { - p_val = Math::round(p_val / shared->step) * shared->step; + p_val = Math::round((p_val - shared->min) / shared->step) * shared->step + shared->min; } if (_rounded_values) { diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index df41863e74..60d107cce6 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -4528,6 +4528,30 @@ void RichTextLabel::append_text(const String &p_bbcode) { } } +void RichTextLabel::scroll_to_selection() { + if (selection.active && selection.from_frame && selection.from_line >= 0 && selection.from_line < (int)selection.from_frame->lines.size()) { + // Selected frame paragraph offset. + float line_offset = selection.from_frame->lines[selection.from_line].offset.y; + + // Add wrapped line offset. + for (int i = 0; i < selection.from_frame->lines[selection.from_line].text_buf->get_line_count(); i++) { + Vector2i range = selection.from_frame->lines[selection.from_line].text_buf->get_line_range(i); + if (range.x <= selection.from_char && range.y >= selection.from_char) { + break; + } + line_offset += selection.from_frame->lines[selection.from_line].text_buf->get_line_size(i).y + theme_cache.line_separation; + } + + // Add nested frame (e.g. table cell) offset. + ItemFrame *it = selection.from_frame; + while (it->parent_frame != nullptr) { + line_offset += it->parent_frame->lines[it->line].offset.y; + it = it->parent_frame; + } + vscroll->set_value(line_offset); + } +} + void RichTextLabel::scroll_to_paragraph(int p_paragraph) { _validate_line_caches(); @@ -4772,7 +4796,7 @@ bool RichTextLabel::search(const String &p_string, bool p_from_selection, bool p char_idx = p_search_previous ? selection.from_char - 1 : selection.to_char; if (!(p_search_previous && char_idx < 0) && _search_line(selection.from_frame, selection.from_line, p_string, char_idx, p_search_previous)) { - scroll_to_line(selection.from_frame->line + selection.from_line); + scroll_to_selection(); queue_redraw(); return true; } @@ -4797,7 +4821,7 @@ bool RichTextLabel::search(const String &p_string, bool p_from_selection, bool p // Search for next element if (_search_table(parent_table, parent_element, p_string, p_search_previous)) { - scroll_to_line(selection.from_frame->line + selection.from_line); + scroll_to_selection(); queue_redraw(); return true; } @@ -4821,7 +4845,7 @@ bool RichTextLabel::search(const String &p_string, bool p_from_selection, bool p } if (_search_line(main, current_line, p_string, char_idx, p_search_previous)) { - scroll_to_line(current_line); + scroll_to_selection(); queue_redraw(); return true; } @@ -5309,6 +5333,7 @@ void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("scroll_to_line", "line"), &RichTextLabel::scroll_to_line); ClassDB::bind_method(D_METHOD("scroll_to_paragraph", "paragraph"), &RichTextLabel::scroll_to_paragraph); + ClassDB::bind_method(D_METHOD("scroll_to_selection"), &RichTextLabel::scroll_to_selection); ClassDB::bind_method(D_METHOD("set_tab_size", "spaces"), &RichTextLabel::set_tab_size); ClassDB::bind_method(D_METHOD("get_tab_size"), &RichTextLabel::get_tab_size); diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index d30baaa8d3..b00cc3d055 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -657,6 +657,8 @@ public: int get_content_height() const; int get_content_width() const; + void scroll_to_selection(); + VScrollBar *get_v_scroll_bar() { return vscroll; } virtual CursorShape get_cursor_shape(const Point2 &p_pos) const override; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index cce9fa4f34..a96d85dffa 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1108,8 +1108,9 @@ void TextEdit::_notification(int p_what) { int start = TS->shaped_text_get_range(rid).x; if (!clipped && !search_text.is_empty()) { // Search highhlight int search_text_col = _get_column_pos_of_word(search_text, str, search_flags, 0); + int search_text_len = search_text.length(); while (search_text_col != -1) { - Vector<Vector2> sel = TS->shaped_text_get_selection(rid, search_text_col + start, search_text_col + search_text.length() + start); + Vector<Vector2> sel = TS->shaped_text_get_selection(rid, search_text_col + start, search_text_col + search_text_len + start); for (int j = 0; j < sel.size(); j++) { Rect2 rect = Rect2(sel[j].x + char_margin + ofs_x, ofs_y, sel[j].y - sel[j].x, row_height); if (rect.position.x + rect.size.x <= xmargin_beg || rect.position.x > xmargin_end) { @@ -1125,14 +1126,15 @@ void TextEdit::_notification(int p_what) { draw_rect(rect, search_result_border_color, false); } - search_text_col = _get_column_pos_of_word(search_text, str, search_flags, search_text_col + 1); + search_text_col = _get_column_pos_of_word(search_text, str, search_flags, search_text_col + search_text_len); } } if (!clipped && highlight_all_occurrences && !only_whitespaces_highlighted && !highlighted_text.is_empty()) { // Highlight int highlighted_text_col = _get_column_pos_of_word(highlighted_text, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, 0); + int highlighted_text_len = highlighted_text.length(); while (highlighted_text_col != -1) { - Vector<Vector2> sel = TS->shaped_text_get_selection(rid, highlighted_text_col + start, highlighted_text_col + highlighted_text.length() + start); + Vector<Vector2> sel = TS->shaped_text_get_selection(rid, highlighted_text_col + start, highlighted_text_col + highlighted_text_len + start); for (int j = 0; j < sel.size(); j++) { Rect2 rect = Rect2(sel[j].x + char_margin + ofs_x, ofs_y, sel[j].y - sel[j].x, row_height); if (rect.position.x + rect.size.x <= xmargin_beg || rect.position.x > xmargin_end) { @@ -1147,15 +1149,16 @@ void TextEdit::_notification(int p_what) { draw_rect(rect, word_highlighted_color); } - highlighted_text_col = _get_column_pos_of_word(highlighted_text, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, highlighted_text_col + 1); + highlighted_text_col = _get_column_pos_of_word(highlighted_text, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, highlighted_text_col + highlighted_text_len); } } if (!clipped && lookup_symbol_word.length() != 0) { // Highlight word if (is_ascii_char(lookup_symbol_word[0]) || lookup_symbol_word[0] == '_' || lookup_symbol_word[0] == '.') { - int highlighted_word_col = _get_column_pos_of_word(lookup_symbol_word, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, 0); - while (highlighted_word_col != -1) { - Vector<Vector2> sel = TS->shaped_text_get_selection(rid, highlighted_word_col + start, highlighted_word_col + lookup_symbol_word.length() + start); + int lookup_symbol_word_col = _get_column_pos_of_word(lookup_symbol_word, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, 0); + int lookup_symbol_word_len = lookup_symbol_word.length(); + while (lookup_symbol_word_col != -1) { + Vector<Vector2> sel = TS->shaped_text_get_selection(rid, lookup_symbol_word_col + start, lookup_symbol_word_col + lookup_symbol_word_len + start); for (int j = 0; j < sel.size(); j++) { Rect2 rect = Rect2(sel[j].x + char_margin + ofs_x, ofs_y + (line_spacing / 2), sel[j].y - sel[j].x, row_height); if (rect.position.x + rect.size.x <= xmargin_beg || rect.position.x > xmargin_end) { @@ -1172,7 +1175,7 @@ void TextEdit::_notification(int p_what) { draw_rect(rect, color); } - highlighted_word_col = _get_column_pos_of_word(lookup_symbol_word, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, highlighted_word_col + 1); + lookup_symbol_word_col = _get_column_pos_of_word(lookup_symbol_word, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, lookup_symbol_word_col + lookup_symbol_word_len); } } } @@ -7038,8 +7041,8 @@ void TextEdit::_update_selection_mode_word() { if ((col <= carets[caret_idx].selection.selected_word_origin && line == get_selection_line(caret_idx)) || line < get_selection_line(caret_idx)) { carets.write[caret_idx].selection.selecting_column = carets[caret_idx].selection.selected_word_end; select(line, beg, get_selection_line(caret_idx), carets[caret_idx].selection.selected_word_end, caret_idx); - set_caret_line(get_selection_from_line(caret_idx), false, true, 0, caret_idx); - set_caret_column(get_selection_from_column(caret_idx), true, caret_idx); + set_caret_line(line, false, true, 0, caret_idx); + set_caret_column(beg, true, caret_idx); } else { carets.write[caret_idx].selection.selecting_column = carets[caret_idx].selection.selected_word_beg; select(get_selection_line(caret_idx), carets[caret_idx].selection.selected_word_beg, line, end, caret_idx); diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 93c910a7f0..c0990211aa 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -1018,7 +1018,7 @@ void TreeItem::set_as_cursor(int p_column) { if (tree->select_mode != Tree::SELECT_MULTI) { return; } - if (tree->selected_col == p_column) { + if (tree->selected_item == this && tree->selected_col == p_column) { return; } tree->selected_item = this; |