diff options
Diffstat (limited to 'scene/gui')
-rw-r--r-- | scene/gui/control.cpp | 2 | ||||
-rw-r--r-- | scene/gui/file_dialog.cpp | 4 | ||||
-rw-r--r-- | scene/gui/graph_edit.cpp | 31 | ||||
-rw-r--r-- | scene/gui/graph_node.cpp | 132 | ||||
-rw-r--r-- | scene/gui/rich_text_label.cpp | 23 | ||||
-rw-r--r-- | scene/gui/tab_container.cpp | 3 | ||||
-rw-r--r-- | scene/gui/tree.cpp | 6 |
7 files changed, 157 insertions, 44 deletions
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index d209b17fa1..c13bce5e0c 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -96,6 +96,7 @@ void Control::_edit_set_state(const Dictionary &p_state) { void Control::_edit_set_position(const Point2 &p_position) { #ifdef TOOLS_ENABLED + ERR_FAIL_COND_MSG(!Engine::get_singleton()->is_editor_hint(), "This function can only be used from editor plugins."); set_position(p_position, CanvasItemEditor::get_singleton()->is_anchors_mode_enabled() && Object::cast_to<Control>(data.parent)); #else // Unlikely to happen. TODO: enclose all _edit_ functions into TOOLS_ENABLED @@ -117,6 +118,7 @@ Size2 Control::_edit_get_scale() const { void Control::_edit_set_rect(const Rect2 &p_edit_rect) { #ifdef TOOLS_ENABLED + ERR_FAIL_COND_MSG(!Engine::get_singleton()->is_editor_hint(), "This function can only be used from editor plugins."); set_position((get_position() + get_transform().basis_xform(p_edit_rect.position)).snapped(Vector2(1, 1)), CanvasItemEditor::get_singleton()->is_anchors_mode_enabled()); set_size(p_edit_rect.size.snapped(Vector2(1, 1)), CanvasItemEditor::get_singleton()->is_anchors_mode_enabled()); #else diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 7453324505..7fb5113130 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -731,9 +731,9 @@ FileDialog::Access FileDialog::get_access() const { } void FileDialog::_make_dir_confirm() { - Error err = dir_access->make_dir(makedirname->get_text()); + Error err = dir_access->make_dir(makedirname->get_text().strip_edges()); if (err == OK) { - dir_access->change_dir(makedirname->get_text()); + dir_access->change_dir(makedirname->get_text().strip_edges()); invalidate(); update_filters(); update_dir(); diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 331f0380c5..71d31434d4 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -180,7 +180,12 @@ void GraphEditMinimap::_gui_input(const Ref<InputEvent> &p_ev) { accept_event(); } else if (mm.is_valid() && is_pressing) { if (is_resizing) { - ge->set_minimap_size(ge->get_minimap_size() - mm->get_relative()); + // Prevent setting minimap wider than GraphEdit + Vector2 new_minimap_size; + new_minimap_size.x = MIN(get_size().x - mm->get_relative().x, ge->get_size().x - 2.0 * minimap_padding.x); + new_minimap_size.y = MIN(get_size().y - mm->get_relative().y, ge->get_size().y - 2.0 * minimap_padding.y); + ge->set_minimap_size(new_minimap_size); + update(); } else { Vector2 click_position = _convert_to_graph_position(mm->get_position() - minimap_padding) - graph_padding; @@ -1312,25 +1317,17 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) { minimap->update(); } - if (b->get_button_index() == BUTTON_WHEEL_UP && b->is_pressed()) { - //too difficult to get right - //set_zoom(zoom*ZOOM_SCALE); - } - - if (b->get_button_index() == BUTTON_WHEEL_DOWN && b->is_pressed()) { - //too difficult to get right - //set_zoom(zoom/ZOOM_SCALE); - } - if (b->get_button_index() == BUTTON_WHEEL_UP && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + if (b->get_button_index() == BUTTON_WHEEL_UP && Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { + set_zoom(zoom * ZOOM_SCALE); + } else if (b->get_button_index() == BUTTON_WHEEL_DOWN && Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { + set_zoom(zoom / ZOOM_SCALE); + } else if (b->get_button_index() == BUTTON_WHEEL_UP && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * b->get_factor() / 8); - } - if (b->get_button_index() == BUTTON_WHEEL_DOWN && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { + } else if (b->get_button_index() == BUTTON_WHEEL_DOWN && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) { v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * b->get_factor() / 8); - } - if (b->get_button_index() == BUTTON_WHEEL_RIGHT || (b->get_button_index() == BUTTON_WHEEL_DOWN && Input::get_singleton()->is_key_pressed(KEY_SHIFT))) { + } else if (b->get_button_index() == BUTTON_WHEEL_RIGHT || (b->get_button_index() == BUTTON_WHEEL_DOWN && Input::get_singleton()->is_key_pressed(KEY_SHIFT))) { h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * b->get_factor() / 8); - } - if (b->get_button_index() == BUTTON_WHEEL_LEFT || (b->get_button_index() == BUTTON_WHEEL_UP && Input::get_singleton()->is_key_pressed(KEY_SHIFT))) { + } else if (b->get_button_index() == BUTTON_WHEEL_LEFT || (b->get_button_index() == BUTTON_WHEEL_UP && Input::get_singleton()->is_key_pressed(KEY_SHIFT))) { h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() * b->get_factor() / 8); } } diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index b615cdb266..c80fc516e8 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -32,6 +32,12 @@ #include "core/string/translation.h" +struct _MinSizeCache { + int min_size; + bool will_stretch; + int final_size; +}; + bool GraphNode::_set(const StringName &p_name, const Variant &p_value) { String str = p_name; if (str.begins_with("opentype_features/")) { @@ -171,15 +177,23 @@ void GraphNode::_get_property_list(List<PropertyInfo> *p_list) const { } void GraphNode::_resort() { - int sep = get_theme_constant("separation"); + /** First pass, determine minimum size AND amount of stretchable elements */ + + Size2i new_size = get_size(); Ref<StyleBox> sb = get_theme_stylebox("frame"); - bool first = true; - Size2 minsize; + int sep = get_theme_constant("separation"); + + bool first = true; + int children_count = 0; + int stretch_min = 0; + int stretch_avail = 0; + float stretch_ratio_total = 0; + Map<Control *, _MinSizeCache> min_size_cache; for (int i = 0; i < get_child_count(); i++) { Control *c = Object::cast_to<Control>(get_child(i)); - if (!c) { + if (!c || !c->is_visible_in_tree()) { continue; } if (c->is_set_as_top_level()) { @@ -187,38 +201,120 @@ void GraphNode::_resort() { } Size2i size = c->get_combined_minimum_size(); + _MinSizeCache msc; - minsize.y += size.y; - minsize.x = MAX(minsize.x, size.x); + stretch_min += size.height; + msc.min_size = size.height; + msc.will_stretch = c->get_v_size_flags() & SIZE_EXPAND; - if (first) { - first = false; - } else { - minsize.y += sep; + if (msc.will_stretch) { + stretch_avail += msc.min_size; + stretch_ratio_total += c->get_stretch_ratio(); } + msc.final_size = msc.min_size; + min_size_cache[c] = msc; + children_count++; } - int vofs = 0; - int w = get_size().x - sb->get_minimum_size().x; + if (children_count == 0) { + return; + } + + int stretch_max = new_size.height - (children_count - 1) * sep; + int stretch_diff = stretch_max - stretch_min; + if (stretch_diff < 0) { + //avoid negative stretch space + stretch_diff = 0; + } + + stretch_avail += stretch_diff - sb->get_margin(SIDE_BOTTOM) - sb->get_margin(SIDE_TOP); //available stretch space. + /** Second, pass sucessively to discard elements that can't be stretched, this will run while stretchable + elements exist */ + + while (stretch_ratio_total > 0) { // first of all, don't even be here if no stretchable objects exist + bool refit_successful = true; //assume refit-test will go well + + for (int i = 0; i < get_child_count(); i++) { + Control *c = Object::cast_to<Control>(get_child(i)); + if (!c || !c->is_visible_in_tree()) { + continue; + } + if (c->is_set_as_top_level()) { + continue; + } + ERR_FAIL_COND(!min_size_cache.has(c)); + _MinSizeCache &msc = min_size_cache[c]; + + if (msc.will_stretch) { //wants to stretch + //let's see if it can really stretch + + int final_pixel_size = stretch_avail * c->get_stretch_ratio() / stretch_ratio_total; + if (final_pixel_size < msc.min_size) { + //if available stretching area is too small for widget, + //then remove it from stretching area + msc.will_stretch = false; + stretch_ratio_total -= c->get_stretch_ratio(); + refit_successful = false; + stretch_avail -= msc.min_size; + msc.final_size = msc.min_size; + break; + } else { + msc.final_size = final_pixel_size; + } + } + } + + if (refit_successful) { //uf refit went well, break + break; + } + } + + /** Final pass, draw and stretch elements **/ + + int ofs = sb->get_margin(SIDE_TOP); + + first = true; + int idx = 0; cache_y.clear(); + int w = new_size.width - sb->get_minimum_size().x; + for (int i = 0; i < get_child_count(); i++) { Control *c = Object::cast_to<Control>(get_child(i)); - if (!c) { + if (!c || !c->is_visible_in_tree()) { continue; } if (c->is_set_as_top_level()) { continue; } - Size2i size = c->get_combined_minimum_size(); + _MinSizeCache &msc = min_size_cache[c]; + + if (first) { + first = false; + } else { + ofs += sep; + } - Rect2 r(sb->get_margin(SIDE_LEFT), sb->get_margin(SIDE_TOP) + vofs, w, size.y); + int from = ofs; + int to = ofs + msc.final_size; - fit_child_in_rect(c, r); - cache_y.push_back(vofs + size.y * 0.5); + if (msc.will_stretch && idx == children_count - 1) { + //adjust so the last one always fits perfect + //compensating for numerical imprecision - vofs += size.y + sep; + to = new_size.height - sb->get_margin(SIDE_BOTTOM); + } + + int size = to - from; + + Rect2 rect(sb->get_margin(SIDE_LEFT), from, w, size); + + fit_child_in_rect(c, rect); + cache_y.push_back(from - sb->get_margin(SIDE_TOP) + size * 0.5); + + ofs = to; + idx++; } update(); diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index ed319f9fd0..bce30e7cd3 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -147,7 +147,7 @@ RichTextLabel::Item *RichTextLabel::_get_item_at_pos(RichTextLabel::Item *p_item case ITEM_TEXT: { ItemText *t = (ItemText *)it; offset += t->text.length(); - if (offset >= p_position) { + if (offset > p_position) { return it; } } break; @@ -588,7 +588,8 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> offset.x += table->columns[column].width + hseparation + frame->padding.size.x; row_height = MAX(yofs, row_height); - if (column == col_count - 1) { + // Add row height after last column of the row or last cell of the table. + if (column == col_count - 1 || E->next() == nullptr) { offset.x = 0; row_height += vseparation; table->total_height += row_height; @@ -1117,7 +1118,8 @@ void RichTextLabel::_find_click(ItemFrame *p_frame, const Point2i &p_click, Item Point2 ofs = text_rect.get_position() + Vector2(0, main->lines[from_line].offset.y - vofs); while (ofs.y < size.height && from_line < main->lines.size()) { - ofs.y += _find_click_in_line(p_frame, from_line, ofs, text_rect.size.x, p_click, r_click_frame, r_click_line, r_click_item, r_click_char); + _find_click_in_line(p_frame, from_line, ofs, text_rect.size.x, p_click, r_click_frame, r_click_line, r_click_item, r_click_char); + ofs.y += main->lines[from_line].text_buf->get_size().y; if (((r_click_item != nullptr) && ((*r_click_item) != nullptr)) || ((r_click_frame != nullptr) && ((*r_click_frame) != nullptr))) { if (r_outside != nullptr) { *r_outside = false; @@ -1244,8 +1246,19 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V if (r_click_item != nullptr) { Item *it = p_frame->lines[p_line].from; Item *it_to = (p_line + 1 < p_frame->lines.size()) ? p_frame->lines[p_line + 1].from : nullptr; - it = _get_item_at_pos(it, it_to, char_pos); - *r_click_item = it; + if (char_pos == p_frame->lines[p_line].char_count) { + // Selection after the end of line, select last item. + if (it_to != nullptr) { + *r_click_item = _get_prev_item(it_to); + } else { + for (Item *i = it; i && i != it_to; i = _get_next_item(i)) { + *r_click_item = i; + } + } + } else { + // Selection in the line. + *r_click_item = _get_item_at_pos(it, it_to, char_pos); + } } if (r_click_frame != nullptr) { diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index e3e3f549de..3bf163f670 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -645,7 +645,7 @@ int TabContainer::_get_tab_width(int p_index) const { // Get the width of the text displayed on the tab. Ref<Font> font = get_theme_font("font"); int font_size = get_theme_font_size("font_size"); - String text = control->has_meta("_tab_name") ? String(tr(String(control->get_meta("_tab_name")))) : String(control->get_name()); + String text = control->has_meta("_tab_name") ? String(tr(String(control->get_meta("_tab_name")))) : String(tr(control->get_name())); int width = font->get_string_size(text, font_size).width; // Add space for a tab icon. @@ -1023,6 +1023,7 @@ void TabContainer::set_tab_title(int p_tab, const String &p_title) { Control *child = _get_tab(p_tab); ERR_FAIL_COND(!child); child->set_meta("_tab_name", p_title); + _refresh_texts(); update(); } diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 6ac4d7fd2f..6f51a61329 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -3506,9 +3506,13 @@ int Tree::get_column_width(int p_column) const { return columns[p_column].min_width; } + int expand_area = get_size().width; + Ref<StyleBox> bg = cache.bg; - int expand_area = get_size().width - (bg->get_margin(SIDE_LEFT) + bg->get_margin(SIDE_RIGHT)); + if (bg.is_valid()) { + expand_area -= bg->get_margin(SIDE_LEFT) + bg->get_margin(SIDE_RIGHT); + } if (v_scroll->is_visible_in_tree()) { expand_area -= v_scroll->get_combined_minimum_size().width; |