diff options
Diffstat (limited to 'scene/gui')
-rw-r--r-- | scene/gui/box_container.h | 8 | ||||
-rw-r--r-- | scene/gui/check_box.cpp | 4 | ||||
-rw-r--r-- | scene/gui/color_picker.cpp | 9 | ||||
-rw-r--r-- | scene/gui/color_picker.h | 1 | ||||
-rw-r--r-- | scene/gui/file_dialog.cpp | 121 | ||||
-rw-r--r-- | scene/gui/file_dialog.h | 13 | ||||
-rw-r--r-- | scene/gui/item_list.cpp | 27 | ||||
-rw-r--r-- | scene/gui/item_list.h | 2 | ||||
-rw-r--r-- | scene/gui/line_edit.cpp | 4 | ||||
-rw-r--r-- | scene/gui/popup_menu.cpp | 6 | ||||
-rw-r--r-- | scene/gui/rich_text_label.cpp | 11 | ||||
-rw-r--r-- | scene/gui/scroll_bar.h | 8 | ||||
-rw-r--r-- | scene/gui/scroll_container.cpp | 2 | ||||
-rw-r--r-- | scene/gui/slider.h | 8 | ||||
-rw-r--r-- | scene/gui/split_container.h | 8 | ||||
-rw-r--r-- | scene/gui/text_edit.cpp | 190 | ||||
-rw-r--r-- | scene/gui/text_edit.h | 7 | ||||
-rw-r--r-- | scene/gui/tree.cpp | 25 | ||||
-rw-r--r-- | scene/gui/tree.h | 2 | ||||
-rw-r--r-- | scene/gui/video_player.cpp | 1 |
20 files changed, 339 insertions, 118 deletions
diff --git a/scene/gui/box_container.h b/scene/gui/box_container.h index 4d00a2011f..ebbbbed1f9 100644 --- a/scene/gui/box_container.h +++ b/scene/gui/box_container.h @@ -70,8 +70,8 @@ class HBoxContainer : public BoxContainer { GDCLASS(HBoxContainer, BoxContainer); public: - HBoxContainer() - : BoxContainer(false) {} + HBoxContainer() : + BoxContainer(false) {} }; class MarginContainer; @@ -82,8 +82,8 @@ class VBoxContainer : public BoxContainer { public: MarginContainer *add_margin_child(const String &p_label, Control *p_control, bool p_expand = false); - VBoxContainer() - : BoxContainer(true) {} + VBoxContainer() : + BoxContainer(true) {} }; VARIANT_ENUM_CAST(BoxContainer::AlignMode); diff --git a/scene/gui/check_box.cpp b/scene/gui/check_box.cpp index e2b10a948f..00f6153062 100644 --- a/scene/gui/check_box.cpp +++ b/scene/gui/check_box.cpp @@ -56,8 +56,8 @@ bool CheckBox::is_radio() { return get_button_group().is_valid(); } -CheckBox::CheckBox(const String &p_text) - : Button(p_text) { +CheckBox::CheckBox(const String &p_text) : + Button(p_text) { set_toggle_mode(true); set_text_align(ALIGN_LEFT); } diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index dbd7c1bbc0..cb6283507e 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -486,8 +486,8 @@ void ColorPicker::_bind_methods() { ADD_SIGNAL(MethodInfo("color_changed", PropertyInfo(Variant::COLOR, "color"))); } -ColorPicker::ColorPicker() - : BoxContainer(true) { +ColorPicker::ColorPicker() : + BoxContainer(true) { updating = true; edit_alpha = true; @@ -664,11 +664,16 @@ ColorPicker *ColorPickerButton::get_picker() { return picker; } +PopupPanel *ColorPickerButton::get_popup() { + return popup; +} + void ColorPickerButton::_bind_methods() { ClassDB::bind_method(D_METHOD("set_pick_color", "color"), &ColorPickerButton::set_pick_color); ClassDB::bind_method(D_METHOD("get_pick_color"), &ColorPickerButton::get_pick_color); ClassDB::bind_method(D_METHOD("get_picker"), &ColorPickerButton::get_picker); + ClassDB::bind_method(D_METHOD("get_popup"), &ColorPickerButton::get_popup); ClassDB::bind_method(D_METHOD("set_edit_alpha", "show"), &ColorPickerButton::set_edit_alpha); ClassDB::bind_method(D_METHOD("is_editing_alpha"), &ColorPickerButton::is_editing_alpha); ClassDB::bind_method(D_METHOD("_color_changed"), &ColorPickerButton::_color_changed); diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index 7de67a707c..c02cdc8608 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -130,6 +130,7 @@ public: bool is_editing_alpha() const; ColorPicker *get_picker(); + PopupPanel *get_popup(); ColorPickerButton(); }; diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 6aba535572..6af869c503 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -47,12 +47,7 @@ void FileDialog::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { refresh->set_icon(get_icon("reload")); - } - - if (p_what == NOTIFICATION_DRAW) { - - //RID ci = get_canvas_item(); - //get_stylebox("panel","PopupMenu")->draw(ci,Rect2(Point2(),get_size())); + dir_up->set_icon(get_icon("parent_folder")); } if (p_what == NOTIFICATION_POPUP_HIDE) { @@ -85,6 +80,10 @@ void FileDialog::_unhandled_input(const Ref<InputEvent> &p_event) { invalidate(); } break; + case KEY_BACKSPACE: { + + _dir_entered(".."); + } break; default: { handled = false; } } @@ -118,6 +117,9 @@ void FileDialog::update_dir() { if (drives->is_visible()) { drives->select(dir_access->get_current_drive()); } + + // Deselect any item, to make "Select Current Folder" button text by default. + deselect_items(); } void FileDialog::_dir_entered(String p_dir) { @@ -152,6 +154,10 @@ void FileDialog::_post_popup() { tree->grab_focus(); set_process_unhandled_input(true); + + // For open dir mode, deselect all items on file dialog open. + if (mode == MODE_OPEN_DIR) + deselect_items(); } void FileDialog::_action_pressed() { @@ -189,7 +195,7 @@ void FileDialog::_action_pressed() { TreeItem *item = tree->get_selected(); if (item) { Dictionary d = item->get_metadata(0); - if (d["dir"]) { + if (d["dir"] && d["name"] != "..") { path = path.plus_file(d["name"]); } } @@ -272,6 +278,57 @@ void FileDialog::_cancel_pressed() { hide(); } +bool FileDialog::_is_open_should_be_disabled() { + + if (mode == MODE_OPEN_ANY || mode == MODE_SAVE_FILE) + return false; + + TreeItem *ti = tree->get_selected(); + // We have something that we can't select? + if (!ti) + return true; + + Dictionary d = ti->get_metadata(0); + + // Opening a file, but selected a folder? Forbidden. + if (((mode == MODE_OPEN_FILE || mode == MODE_OPEN_FILES) && d["dir"]) || // Flipped case, also forbidden. + (mode == MODE_OPEN_DIR && !d["dir"])) + return true; + + return false; +} + +void FileDialog::_go_up() { + + dir_access->change_dir(".."); + update_file_list(); + update_dir(); +} + +void FileDialog::deselect_items() { + + // Clear currently selected items in file manager. + tree->deselect_all(); + + // And change get_ok title. + if (!tree->is_anything_selected()) { + get_ok()->set_disabled(_is_open_should_be_disabled()); + + switch (mode) { + + case MODE_OPEN_FILE: + case MODE_OPEN_FILES: + get_ok()->set_text(TTR("Open")); + get_ok()->set_disabled(false); + break; + + case MODE_OPEN_DIR: + get_ok()->set_text(TTR("Select Current Folder")); + get_ok()->set_disabled(false); + break; + } + } +} void FileDialog::_tree_selected() { TreeItem *ti = tree->get_selected(); @@ -282,7 +339,11 @@ void FileDialog::_tree_selected() { if (!d["dir"]) { file->set_text(d["name"]); + } else if (mode == MODE_OPEN_DIR) { + get_ok()->set_text(TTR("Select this Folder")); } + + get_ok()->set_disabled(_is_open_should_be_disabled()); } void FileDialog::_tree_dc_selected() { @@ -323,7 +384,7 @@ void FileDialog::update_file_list() { while ((item = dir_access->get_next(&isdir)) != "") { - if (item == ".") + if (item == "." || item == "..") continue; ishidden = dir_access->current_is_hidden(); @@ -336,11 +397,6 @@ void FileDialog::update_file_list() { } } - if (dirs.find("..") == NULL) { - //may happen if lacking permissions - dirs.push_back(".."); - } - dirs.sort_custom<NaturalNoCaseComparator>(); files.sort_custom<NaturalNoCaseComparator>(); @@ -547,6 +603,14 @@ void FileDialog::set_current_path(const String &p_path) { } } +void FileDialog::set_mode_overrides_title(bool p_override) { + mode_overrides_title = p_override; +} + +bool FileDialog::is_mode_overriding_title() const { + return mode_overrides_title; +} + void FileDialog::set_mode(Mode p_mode) { mode = p_mode; @@ -554,27 +618,32 @@ void FileDialog::set_mode(Mode p_mode) { case MODE_OPEN_FILE: get_ok()->set_text(RTR("Open")); - set_title(RTR("Open a File")); + if (mode_overrides_title) + set_title(RTR("Open a File")); makedir->hide(); break; case MODE_OPEN_FILES: get_ok()->set_text(RTR("Open")); - set_title(RTR("Open File(s)")); + if (mode_overrides_title) + set_title(RTR("Open File(s)")); makedir->hide(); break; case MODE_OPEN_DIR: - get_ok()->set_text(RTR("Open")); - set_title(RTR("Open a Directory")); + get_ok()->set_text(RTR("Select Current Folder")); + if (mode_overrides_title) + set_title(RTR("Open a Directory")); makedir->show(); break; case MODE_OPEN_ANY: get_ok()->set_text(RTR("Open")); - set_title(RTR("Open a File or Directory")); + if (mode_overrides_title) + set_title(RTR("Open a File or Directory")); makedir->show(); break; case MODE_SAVE_FILE: get_ok()->set_text(RTR("Save")); - set_title(RTR("Save a File")); + if (mode_overrides_title) + set_title(RTR("Save a File")); makedir->show(); break; } @@ -704,6 +773,8 @@ void FileDialog::_bind_methods() { ClassDB::bind_method(D_METHOD("set_current_dir", "dir"), &FileDialog::set_current_dir); ClassDB::bind_method(D_METHOD("set_current_file", "file"), &FileDialog::set_current_file); ClassDB::bind_method(D_METHOD("set_current_path", "path"), &FileDialog::set_current_path); + ClassDB::bind_method(D_METHOD("set_mode_overrides_title", "override"), &FileDialog::set_mode_overrides_title); + ClassDB::bind_method(D_METHOD("is_mode_overriding_title"), &FileDialog::is_mode_overriding_title); ClassDB::bind_method(D_METHOD("set_mode", "mode"), &FileDialog::set_mode); ClassDB::bind_method(D_METHOD("get_mode"), &FileDialog::get_mode); ClassDB::bind_method(D_METHOD("get_vbox"), &FileDialog::get_vbox); @@ -716,6 +787,8 @@ void FileDialog::_bind_methods() { ClassDB::bind_method(D_METHOD("_make_dir_confirm"), &FileDialog::_make_dir_confirm); ClassDB::bind_method(D_METHOD("_update_file_list"), &FileDialog::update_file_list); ClassDB::bind_method(D_METHOD("_update_dir"), &FileDialog::update_dir); + ClassDB::bind_method(D_METHOD("_go_up"), &FileDialog::_go_up); + ClassDB::bind_method(D_METHOD("deselect_items"), &FileDialog::deselect_items); ClassDB::bind_method(D_METHOD("invalidate"), &FileDialog::invalidate); @@ -733,6 +806,7 @@ void FileDialog::_bind_methods() { BIND_ENUM_CONSTANT(ACCESS_USERDATA); BIND_ENUM_CONSTANT(ACCESS_FILESYSTEM); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "mode_overrides_title"), "set_mode_overrides_title", "is_mode_overriding_title"); ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Open one,Open many,Open folder,Open any,Save"), "set_mode", "get_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User data,File system"), "set_access", "get_access"); ADD_PROPERTY(PropertyInfo(Variant::POOL_STRING_ARRAY, "filters"), "set_filters", "get_filters"); @@ -756,6 +830,8 @@ FileDialog::FileDialog() { show_hidden_files = default_show_hidden_files; + mode_overrides_title = true; + VBoxContainer *vbc = memnew(VBoxContainer); add_child(vbc); @@ -763,6 +839,12 @@ FileDialog::FileDialog() { set_title(RTR("Save a File")); HBoxContainer *hbc = memnew(HBoxContainer); + + dir_up = memnew(ToolButton); + dir_up->set_tooltip(TTR("Go to parent folder")); + hbc->add_child(dir_up); + dir_up->connect("pressed", this, "_go_up"); + hbc->add_child(memnew(Label(RTR("Path:")))); dir = memnew(LineEdit); hbc->add_child(dir); @@ -807,6 +889,7 @@ FileDialog::FileDialog() { //cancel->connect("pressed", this,"_cancel_pressed"); tree->connect("cell_selected", this, "_tree_selected", varray(), CONNECT_DEFERRED); tree->connect("item_activated", this, "_tree_db_selected", varray()); + tree->connect("nothing_selected", this, "deselect_items"); dir->connect("text_entered", this, "_dir_entered"); file->connect("text_entered", this, "_file_entered"); filter->connect("item_selected", this, "_filter_selected"); diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h index 34cecfe4d0..c8c1f23105 100644 --- a/scene/gui/file_dialog.h +++ b/scene/gui/file_dialog.h @@ -33,7 +33,6 @@ #include "box_container.h" #include "os/dir_access.h" #include "scene/gui/dialogs.h" -#include "scene/gui/dialogs.h" #include "scene/gui/line_edit.h" #include "scene/gui/option_button.h" #include "scene/gui/tool_button.h" @@ -87,10 +86,14 @@ private: DirAccess *dir_access; ConfirmationDialog *confirm_save; + ToolButton *dir_up; + ToolButton *refresh; Vector<String> filters; + bool mode_overrides_title; + static bool default_show_hidden_files; bool show_hidden_files; @@ -112,11 +115,14 @@ private: void _filter_selected(int); void _make_dir(); void _make_dir_confirm(); + void _go_up(); void _update_drives(); void _unhandled_input(const Ref<InputEvent> &p_event); + bool _is_open_should_be_disabled(); + virtual void _post_popup(); protected: @@ -139,6 +145,9 @@ public: void set_current_file(const String &p_file); void set_current_path(const String &p_path); + void set_mode_overrides_title(bool p_override); + bool is_mode_overriding_title() const; + void set_mode(Mode p_mode); Mode get_mode() const; @@ -155,6 +164,8 @@ public: void invalidate(); + void deselect_items(); + FileDialog(); ~FileDialog(); }; diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 51ab49e643..197e474fd6 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -257,6 +257,20 @@ void ItemList::unselect(int p_idx) { } update(); } + +void ItemList::unselect_all() { + + if (items.size() < 1) + return; + + for (int i = 0; i < items.size(); i++) { + + items[i].selected = false; + } + + update(); +} + bool ItemList::is_selected(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, items.size(), false); @@ -530,6 +544,9 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) { return; } + + // Since closest is null, more likely we clicked on empty space, so send signal to interested controls. Allows, for example, implement items deselecting. + emit_signal("nothing_selected"); } if (mb.is_valid() && mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed()) { @@ -1249,6 +1266,15 @@ Vector<int> ItemList::get_selected_items() { return selected; } +bool ItemList::is_anything_selected() { + for (int i = 0; i < items.size(); i++) { + if (items[i].selected) + return true; + } + + return false; +} + void ItemList::_set_items(const Array &p_items) { ERR_FAIL_COND(p_items.size() % 3); @@ -1409,6 +1435,7 @@ void ItemList::_bind_methods() { ADD_SIGNAL(MethodInfo("multi_selected", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::BOOL, "selected"))); ADD_SIGNAL(MethodInfo("item_activated", PropertyInfo(Variant::INT, "index"))); ADD_SIGNAL(MethodInfo("rmb_clicked", PropertyInfo(Variant::VECTOR2, "at_position"))); + ADD_SIGNAL(MethodInfo("nothing_selected")); GLOBAL_DEF("gui/timers/incremental_search_max_interval_msec", 2000); } diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h index ccdd705325..b1e1e5eeb0 100644 --- a/scene/gui/item_list.h +++ b/scene/gui/item_list.h @@ -156,8 +156,10 @@ public: void select(int p_idx, bool p_single = true); void unselect(int p_idx); + void unselect_all(); bool is_selected(int p_idx) const; Vector<int> get_selected_items(); + bool is_anything_selected(); void set_current(int p_current); int get_current() const; diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index f7bf1cd9ea..85ae6d6241 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -1046,6 +1046,10 @@ void LineEdit::set_cursor_position(int p_pos) { } else if (cursor_pos > window_pos) { /* Adjust window if cursor goes too much to the right */ int window_width = get_size().width - style->get_minimum_size().width; + if (has_icon("right_icon")) { + Ref<Texture> r_icon = Control::get_icon("right_icon"); + window_width -= r_icon->get_width(); + } if (window_width < 0) return; diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index f3711b86b6..4ee6f93c9a 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -202,10 +202,10 @@ void PopupMenu::_activate_submenu(int over) { void PopupMenu::_submenu_timeout() { - if (mouse_over == submenu_over) { + if (mouse_over == submenu_over) _activate_submenu(mouse_over); - submenu_over = -1; - } + + submenu_over = -1; } void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) { diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 124c268c8a..9cf4c105b4 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -793,6 +793,17 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) { selection.click = item; selection.click_char = line; + + // Erase previous selection. + if (selection.active) { + selection.from = NULL; + selection.from_char = NULL; + selection.to = NULL; + selection.to_char = NULL; + selection.active = false; + + update(); + } } } diff --git a/scene/gui/scroll_bar.h b/scene/gui/scroll_bar.h index 373483a8a0..753bd35de7 100644 --- a/scene/gui/scroll_bar.h +++ b/scene/gui/scroll_bar.h @@ -117,8 +117,8 @@ class HScrollBar : public ScrollBar { GDCLASS(HScrollBar, ScrollBar); public: - HScrollBar() - : ScrollBar(HORIZONTAL) { set_v_size_flags(0); } + HScrollBar() : + ScrollBar(HORIZONTAL) { set_v_size_flags(0); } }; class VScrollBar : public ScrollBar { @@ -126,8 +126,8 @@ class VScrollBar : public ScrollBar { GDCLASS(VScrollBar, ScrollBar); public: - VScrollBar() - : ScrollBar(VERTICAL) { set_h_size_flags(0); } + VScrollBar() : + ScrollBar(VERTICAL) { set_h_size_flags(0); } }; #endif diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index a71a1c5f92..ffe0db691f 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -354,6 +354,7 @@ void ScrollContainer::update_scrollbars() { if (!scroll_v || min.height <= size.height - hmin.height) { v_scroll->hide(); + v_scroll->set_max(0); scroll.y = 0; } else { @@ -366,6 +367,7 @@ void ScrollContainer::update_scrollbars() { if (!scroll_h || min.width <= size.width - vmin.width) { h_scroll->hide(); + h_scroll->set_max(0); scroll.x = 0; } else { diff --git a/scene/gui/slider.h b/scene/gui/slider.h index a2334a69fc..95ae429d63 100644 --- a/scene/gui/slider.h +++ b/scene/gui/slider.h @@ -77,8 +77,8 @@ class HSlider : public Slider { GDCLASS(HSlider, Slider); public: - HSlider() - : Slider(HORIZONTAL) { set_v_size_flags(0); } + HSlider() : + Slider(HORIZONTAL) { set_v_size_flags(0); } }; class VSlider : public Slider { @@ -86,8 +86,8 @@ class VSlider : public Slider { GDCLASS(VSlider, Slider); public: - VSlider() - : Slider(VERTICAL) { set_h_size_flags(0); } + VSlider() : + Slider(VERTICAL) { set_h_size_flags(0); } }; #endif // SLIDER_H diff --git a/scene/gui/split_container.h b/scene/gui/split_container.h index 8ec21b5eaa..c7a484c4c5 100644 --- a/scene/gui/split_container.h +++ b/scene/gui/split_container.h @@ -87,8 +87,8 @@ class HSplitContainer : public SplitContainer { GDCLASS(HSplitContainer, SplitContainer); public: - HSplitContainer() - : SplitContainer(false) { set_default_cursor_shape(CURSOR_HSPLIT); } + HSplitContainer() : + SplitContainer(false) { set_default_cursor_shape(CURSOR_HSPLIT); } }; class VSplitContainer : public SplitContainer { @@ -96,8 +96,8 @@ class VSplitContainer : public SplitContainer { GDCLASS(VSplitContainer, SplitContainer); public: - VSplitContainer() - : SplitContainer(true) { set_default_cursor_shape(CURSOR_VSPLIT); } + VSplitContainer() : + SplitContainer(true) { set_default_cursor_shape(CURSOR_VSPLIT); } }; #endif // SPLIT_CONTAINER_H diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index b5e809fd03..e5169089f2 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -251,13 +251,14 @@ void TextEdit::Text::clear() { insert(0, ""); } -int TextEdit::Text::get_max_width() const { +int TextEdit::Text::get_max_width(bool p_exclude_hidden) const { //quite some work.. but should be fast enough. int max = 0; - - for (int i = 0; i < text.size(); i++) - max = MAX(max, get_line_width(i)); + for (int i = 0; i < text.size(); i++) { + if (!p_exclude_hidden || !is_hidden(i)) + max = MAX(max, get_line_width(i)); + } return max; } @@ -303,13 +304,11 @@ void TextEdit::_update_scrollbars() { int total_rows = (is_hiding_enabled() ? get_total_unhidden_rows() : text.size()); if (scroll_past_end_of_file_enabled) { total_rows += visible_rows - 1; - } else { - total_rows -= 1; } int vscroll_pixels = v_scroll->get_combined_minimum_size().width; int visible_width = size.width - cache.style_normal->get_minimum_size().width; - int total_width = text.get_max_width() + vmin.x; + int total_width = text.get_max_width(true) + vmin.x; if (line_numbers) total_width += cache.line_number_w; @@ -362,6 +361,7 @@ void TextEdit::_update_scrollbars() { } } else { + cursor.line_ofs = 0; line_scroll_pos = 0; v_scroll->set_value(0); @@ -373,12 +373,16 @@ void TextEdit::_update_scrollbars() { h_scroll->show(); h_scroll->set_max(total_width); h_scroll->set_page(visible_width); + if (cursor.x_ofs > (total_width - visible_width)) + cursor.x_ofs = (total_width - visible_width); if (fabs(h_scroll->get_value() - (double)cursor.x_ofs) >= 1) { h_scroll->set_value(cursor.x_ofs); } } else { + cursor.x_ofs = 0; + h_scroll->set_value(0); h_scroll->hide(); } @@ -596,6 +600,12 @@ void TextEdit::_notification(int p_what) { int xmargin_end = cache.size.width - cache.style_normal->get_margin(MARGIN_RIGHT); //let's do it easy for now: cache.style_normal->draw(ci, Rect2(Point2(), cache.size)); + float readonly_alpha = 1.0; // used to set the input text color when in read-only mode + if (readonly) { + cache.style_readonly->draw(ci, Rect2(Point2(), cache.size)); + readonly_alpha = .5; + draw_caret = false; + } if (has_focus()) cache.style_focus->draw(ci, Rect2(Point2(), cache.size)); @@ -606,6 +616,8 @@ void TextEdit::_notification(int p_what) { int tab_w = cache.font->get_char_size(' ').width * indent_size; Color color = cache.font_color; + color.a *= readonly_alpha; + int in_region = -1; if (syntax_coloring) { @@ -825,10 +837,16 @@ void TextEdit::_notification(int p_what) { int char_margin = xmargin_beg - cursor.x_ofs; int char_ofs = 0; - int ofs_y = (i * get_row_height() + cache.line_spacing / 2); - if (smooth_scroll_enabled) { - ofs_y -= (v_scroll->get_value() - get_line_scroll_pos()) * get_row_height(); + + int ofs_readonly = 0; + int ofs_x = 0; + if (readonly) { + ofs_readonly = cache.style_readonly->get_offset().y / 2; + ofs_x = cache.style_readonly->get_offset().x / 2; } + int ofs_y = (i * get_row_height() + cache.line_spacing / 2) + ofs_readonly; + if (smooth_scroll_enabled) + ofs_y -= ((v_scroll->get_value() - get_line_scroll_pos()) * get_row_height()); bool prev_is_char = false; bool prev_is_number = false; @@ -854,27 +872,32 @@ void TextEdit::_notification(int p_what) { if (text.is_marked(line)) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg, ofs_y, xmargin_end - xmargin_beg, get_row_height()), cache.mark_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, xmargin_end - xmargin_beg, get_row_height()), cache.mark_color); } if (str.length() == 0) { // draw line background if empty as we won't loop at at all if (line == cursor.line && highlight_current_line) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(0, ofs_y, xmargin_end, get_row_height()), cache.current_line_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(ofs_x, ofs_y, xmargin_end, get_row_height()), cache.current_line_color); } // give visual indication of empty selected line if (selection.active && line >= selection.from_line && line <= selection.to_line) { int char_w = cache.font->get_char_size(' ').width; - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg, ofs_y, char_w, get_row_height()), cache.selection_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, char_w, get_row_height()), cache.selection_color); + } + } else { + // if it has text, then draw current line marker in the margin, as line number ect will draw over it, draw the rest of line marker later. + if (line == cursor.line && highlight_current_line) { + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(0, ofs_y, xmargin_beg, get_row_height()), cache.current_line_color); } } if (text.is_breakpoint(line) && !draw_breakpoint_gutter) { #ifdef TOOLS_ENABLED - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg, ofs_y + get_row_height() - EDSCALE, xmargin_end - xmargin_beg, EDSCALE), cache.breakpoint_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y + get_row_height() - EDSCALE, xmargin_end - xmargin_beg, EDSCALE), cache.breakpoint_color); #else - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg, ofs_y, xmargin_end - xmargin_beg, get_row_height()), cache.breakpoint_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, xmargin_end - xmargin_beg, get_row_height()), cache.breakpoint_color); #endif } @@ -897,11 +920,11 @@ void TextEdit::_notification(int p_what) { if (is_folded(line)) { int xofs = horizontal_gap - (cache.can_fold_icon->get_width()) / 2; int yofs = (get_row_height() - cache.folded_icon->get_height()) / 2; - cache.folded_icon->draw(ci, Point2(gutter_left + xofs, ofs_y + yofs), Color(0.8f, 0.8f, 0.8f, 0.8f)); + cache.folded_icon->draw(ci, Point2(gutter_left + xofs + ofs_x, ofs_y + yofs), cache.code_folding_color); } else if (can_fold(line)) { int xofs = -cache.can_fold_icon->get_width() / 2 - horizontal_gap + 3; int yofs = (get_row_height() - cache.can_fold_icon->get_height()) / 2; - cache.can_fold_icon->draw(ci, Point2(gutter_left + xofs, ofs_y + yofs), Color(0.8f, 0.8f, 0.8f, 0.8f)); + cache.can_fold_icon->draw(ci, Point2(gutter_left + xofs + ofs_x, ofs_y + yofs), cache.code_folding_color); } } @@ -911,7 +934,7 @@ void TextEdit::_notification(int p_what) { fc = line_num_padding + fc; } - cache.font->draw(ci, Point2(cache.style_normal->get_margin(MARGIN_LEFT) + cache.breakpoint_gutter_width, ofs_y + cache.font->get_ascent()), fc, cache.line_number_color); + cache.font->draw(ci, Point2(cache.style_normal->get_margin(MARGIN_LEFT) + cache.breakpoint_gutter_width + ofs_x, ofs_y + cache.font->get_ascent()), fc, cache.line_number_color); } //loop through charcters in one line for (int j = 0; j < str.length(); j++) { @@ -926,6 +949,7 @@ void TextEdit::_notification(int p_what) { if (syntax_coloring && deregion == 0) { color = cache.font_color; //reset + color.a *= readonly_alpha; //find keyword bool is_char = _is_text_char(str[j]); bool is_symbol = _is_symbol(str[j]); @@ -1107,34 +1131,30 @@ void TextEdit::_notification(int p_what) { bool in_selection = (selection.active && line >= selection.from_line && line <= selection.to_line && (line > selection.from_line || j >= selection.from_column) && (line < selection.to_line || j < selection.to_column)); if (line == cursor.line && highlight_current_line) { - // if its the first char draw behind line numbers - if (j == 0) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(0, ofs_y, (char_ofs + char_margin), get_row_height()), cache.current_line_color); - } // if its the last char draw to end of the line if (j == str.length() - 1) { VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(char_ofs + char_margin + char_w, ofs_y, xmargin_end - (char_ofs + char_margin + char_w), get_row_height()), cache.current_line_color); } // actual text if (!in_selection) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin, ofs_y), Size2i(char_w, get_row_height())), cache.current_line_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin + ofs_x, ofs_y), Size2i(char_w, get_row_height())), cache.current_line_color); } } if (in_selection) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin, ofs_y), Size2i(char_w, get_row_height())), cache.selection_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin + ofs_x, ofs_y), Size2i(char_w, get_row_height())), cache.selection_color); } if (in_search_result) { Color border_color = (line == search_result_line && j >= search_result_col && j < search_result_col + search_text.length()) ? cache.font_color : cache.search_result_border_color; - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin, ofs_y), Size2i(char_w, 1)), border_color); - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin, ofs_y + get_row_height() - 1), Size2i(char_w, 1)), border_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin + ofs_x, ofs_y), Size2i(char_w, 1)), border_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin + ofs_x, ofs_y + get_row_height() - 1), Size2i(char_w, 1)), border_color); if (j == search_text_col) - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin, ofs_y), Size2i(1, get_row_height())), border_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin + ofs_x, ofs_y), Size2i(1, get_row_height())), border_color); if (j == search_text_col + search_text.length() - 1) - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin + char_w - 1, ofs_y), Size2i(1, get_row_height())), border_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin + char_w + ofs_x - 1, ofs_y), Size2i(1, get_row_height())), border_color); } if (highlight_all_occurrences) { @@ -1153,7 +1173,7 @@ void TextEdit::_notification(int p_what) { } if (in_highlighted_word) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin, ofs_y), Size2i(char_w, get_row_height())), cache.word_highlighted_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin + ofs_x, ofs_y), Size2i(char_w, get_row_height())), cache.word_highlighted_color); } } } @@ -1164,7 +1184,7 @@ void TextEdit::_notification(int p_what) { if (brace_open_mismatch) color = cache.brace_mismatch_color; - cache.font->draw_char(ci, Point2i(char_ofs + char_margin, ofs_y + ascent), '_', str[j + 1], in_selection && override_selected_font_color ? cache.font_selected_color : color); + cache.font->draw_char(ci, Point2i(char_ofs + char_margin + ofs_x, ofs_y + ascent), '_', str[j + 1], in_selection && override_selected_font_color ? cache.font_selected_color : color); } if ( @@ -1173,13 +1193,13 @@ void TextEdit::_notification(int p_what) { if (brace_close_mismatch) color = cache.brace_mismatch_color; - cache.font->draw_char(ci, Point2i(char_ofs + char_margin, ofs_y + ascent), '_', str[j + 1], in_selection && override_selected_font_color ? cache.font_selected_color : color); + cache.font->draw_char(ci, Point2i(char_ofs + char_margin + ofs_x, ofs_y + ascent), '_', str[j + 1], in_selection && override_selected_font_color ? cache.font_selected_color : color); } } if (cursor.column == j && cursor.line == line) { - cursor_pos = Point2i(char_ofs + char_margin, ofs_y); + cursor_pos = Point2i(char_ofs + char_margin + ofs_x, ofs_y); if (insert_mode) { cursor_pos.y += (get_row_height() - 3); @@ -1206,7 +1226,7 @@ void TextEdit::_notification(int p_what) { VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(char_ofs + char_margin, ofs_y + get_row_height()), Size2(im_char_width, 1)), color); } - cache.font->draw_char(ci, Point2(char_ofs + char_margin, ofs_y + ascent), cchar, next, color); + cache.font->draw_char(ci, Point2(char_ofs + char_margin + ofs_x, ofs_y + ascent), cchar, next, color); char_ofs += im_char_width; ofs++; @@ -1229,18 +1249,19 @@ void TextEdit::_notification(int p_what) { color = cache.caret_background_color; } else if (!syntax_coloring && block_caret) { color = cache.font_color; + color.a *= readonly_alpha; } if (str[j] >= 32) { - int w = cache.font->draw_char(ci, Point2i(char_ofs + char_margin, ofs_y + ascent), str[j], str[j + 1], in_selection && override_selected_font_color ? cache.font_selected_color : color); + int w = cache.font->draw_char(ci, Point2i(char_ofs + char_margin + ofs_x, ofs_y + ascent), str[j], str[j + 1], in_selection && override_selected_font_color ? cache.font_selected_color : color); if (underlined) { - draw_rect(Rect2(char_ofs + char_margin, ofs_y + ascent + 2, w, 1), in_selection && override_selected_font_color ? cache.font_selected_color : color); + draw_rect(Rect2(char_ofs + char_margin + ofs_x, ofs_y + ascent + 2, w, 1), in_selection && override_selected_font_color ? cache.font_selected_color : color); } } else if (draw_tabs && str[j] == '\t') { int yofs = (get_row_height() - cache.tab_icon->get_height()) / 2; - cache.tab_icon->draw(ci, Point2(char_ofs + char_margin, ofs_y + yofs), in_selection && override_selected_font_color ? cache.font_selected_color : color); + cache.tab_icon->draw(ci, Point2(char_ofs + char_margin + ofs_x, ofs_y + yofs), in_selection && override_selected_font_color ? cache.font_selected_color : color); } char_ofs += char_w; @@ -1248,13 +1269,15 @@ void TextEdit::_notification(int p_what) { if (j == str.length() - 1 && is_folded(line)) { int yofs = (get_row_height() - cache.folded_eol_icon->get_height()) / 2; int xofs = cache.folded_eol_icon->get_width() / 2; - cache.folded_eol_icon->draw(ci, Point2(char_ofs + char_margin + xofs, ofs_y + yofs), Color(1, 1, 1, 1)); + Color eol_color = cache.code_folding_color; + eol_color.a = 1; + cache.folded_eol_icon->draw(ci, Point2(char_ofs + char_margin + xofs + ofs_x, ofs_y + yofs), eol_color); } } if (cursor.column == str.length() && cursor.line == line && (char_ofs + char_margin) >= xmargin_beg) { - cursor_pos = Point2i(char_ofs + char_margin, ofs_y); + cursor_pos = Point2i(char_ofs + char_margin + ofs_x, ofs_y); if (insert_mode) { cursor_pos.y += (get_row_height() - 3); @@ -1279,7 +1302,7 @@ void TextEdit::_notification(int p_what) { VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(char_ofs + char_margin, ofs_y + get_row_height()), Size2(im_char_width, 1)), color); } - cache.font->draw_char(ci, Point2(char_ofs + char_margin, ofs_y + ascent), cchar, next, color); + cache.font->draw_char(ci, Point2(char_ofs + char_margin + ofs_x, ofs_y + ascent), cchar, next, color); char_ofs += im_char_width; ofs++; @@ -1712,12 +1735,12 @@ void TextEdit::_get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) co rows -= cache.style_normal->get_margin(MARGIN_TOP); rows /= get_row_height(); int lsp = get_line_scroll_pos(true); - int row = cursor.line_ofs + (rows + (v_scroll->get_value() - lsp)); + int row = cursor.line_ofs + (rows + (round(v_scroll->get_value()) - lsp)); if (is_hiding_enabled()) { // row will be offset by the hidden rows int f_ofs = num_lines_from(CLAMP(cursor.line_ofs, 0, text.size() - 1), MIN(rows + 1, text.size() - cursor.line_ofs)) - 1; - row = cursor.line_ofs + (f_ofs + (v_scroll->get_value() - lsp)); + row = cursor.line_ofs + (f_ofs + (round(v_scroll->get_value()) - lsp)); row = CLAMP(row, 0, text.size() - num_lines_from(text.size() - 1, -1)); } @@ -3081,7 +3104,7 @@ void TextEdit::_scroll_down(real_t p_delta) { if (smooth_scroll_enabled) { int max_v_scroll = get_total_unhidden_rows(); if (!scroll_past_end_of_file_enabled) { - max_v_scroll -= get_visible_rows() + 1; + max_v_scroll -= get_visible_rows(); max_v_scroll = CLAMP(max_v_scroll, 0, get_total_unhidden_rows()); } @@ -3139,7 +3162,7 @@ void TextEdit::_scroll_lines_down() { // calculate the maximum vertical scroll position int max_v_scroll = get_total_unhidden_rows(); if (!scroll_past_end_of_file_enabled) { - max_v_scroll -= get_visible_rows() + 1; + max_v_scroll -= get_visible_rows(); max_v_scroll = CLAMP(max_v_scroll, 0, get_total_unhidden_rows()); } @@ -3475,11 +3498,13 @@ void TextEdit::adjust_viewport_to_cursor() { int num_rows = num_lines_from(CLAMP(cursor.line_ofs, 0, text.size() - 1), MIN(visible_rows, text.size() - 1 - cursor.line_ofs)); // make sure the cursor is on the screen + // above the caret if (cursor.line > (cursor.line_ofs + MAX(num_rows, visible_rows))) { cursor.line_ofs = cursor.line - num_lines_from(cursor.line, -visible_rows) + 1; } - if (cursor.line < cursor.line_ofs) { - cursor.line_ofs = cursor.line; + // below the caret + if (cursor.line_ofs == cursor.line) { + cursor.line_ofs = cursor.line - 2; } int line_ofs_max = text.size() - 1; if (!scroll_past_end_of_file_enabled) { @@ -3499,17 +3524,17 @@ void TextEdit::adjust_viewport_to_cursor() { if (cursor_x < cursor.x_ofs) cursor.x_ofs = cursor_x; + updating_scrolls = true; h_scroll->set_value(cursor.x_ofs); update_line_scroll_pos(); - v_scroll->set_value(get_line_scroll_pos()); + double new_v_scroll = get_line_scroll_pos(); + // keep offset if smooth scroll is enabled + if (smooth_scroll_enabled) { + new_v_scroll += fmod(v_scroll->get_value(), 1.0); + } + v_scroll->set_value(new_v_scroll); + updating_scrolls = false; update(); - /* - get_range()->set_max(text.size()); - - get_range()->set_page(get_visible_rows()); - - get_range()->set((int)cursor.line_ofs); -*/ } void TextEdit::center_viewport_to_cursor() { @@ -3540,10 +3565,16 @@ void TextEdit::center_viewport_to_cursor() { if (cursor_x < cursor.x_ofs) cursor.x_ofs = cursor_x; + updating_scrolls = true; h_scroll->set_value(cursor.x_ofs); update_line_scroll_pos(); - v_scroll->set_value(get_line_scroll_pos()); - + double new_v_scroll = get_line_scroll_pos(); + // keep offset if smooth scroll is enabled + if (smooth_scroll_enabled) { + new_v_scroll += fmod(v_scroll->get_value(), 1.0); + } + v_scroll->set_value(new_v_scroll); + updating_scrolls = false; update(); } @@ -3666,7 +3697,7 @@ void TextEdit::_scroll_moved(double p_to_val) { cursor.x_ofs = h_scroll->get_value(); if (v_scroll->is_visible_in_tree()) { double val = v_scroll->get_value(); - cursor.line_ofs = num_lines_from(0, (int)floor(val)) - 1; + cursor.line_ofs = num_lines_from(0, (int)floor(val)); line_scroll_pos = (int)floor(val); } update(); @@ -3907,6 +3938,7 @@ void TextEdit::clear() { void TextEdit::set_readonly(bool p_readonly) { readonly = p_readonly; + update(); } bool TextEdit::is_readonly() const { @@ -3944,6 +3976,7 @@ void TextEdit::_update_caches() { cache.style_normal = get_stylebox("normal"); cache.style_focus = get_stylebox("focus"); + cache.style_readonly = get_stylebox("read_only"); cache.completion_background_color = get_color("completion_background_color"); cache.completion_selected_color = get_color("completion_selected_color"); cache.completion_existing_color = get_color("completion_existing_color"); @@ -3963,6 +3996,7 @@ void TextEdit::_update_caches() { cache.current_line_color = get_color("current_line_color"); cache.line_length_guideline_color = get_color("line_length_guideline_color"); cache.breakpoint_color = get_color("breakpoint_color"); + cache.code_folding_color = get_color("code_folding_color"); cache.brace_mismatch_color = get_color("brace_mismatch_color"); cache.word_highlighted_color = get_color("word_highlighted_color"); cache.search_result_color = get_color("search_result_color"); @@ -4483,16 +4517,17 @@ int TextEdit::num_lines_from(int p_line_from, int unhidden_amount) const { return num_total; } -int TextEdit::get_whitespace_level(int p_line) const { +int TextEdit::get_indent_level(int p_line) const { ERR_FAIL_INDEX_V(p_line, text.size(), 0); // counts number of tabs and spaces before line starts + int tab_count = 0; int whitespace_count = 0; int line_length = text[p_line].size(); for (int i = 0; i < line_length - 1; i++) { if (text[p_line][i] == '\t') { - whitespace_count++; + tab_count++; } else if (text[p_line][i] == ' ') { whitespace_count++; } else if (text[p_line][i] == '#') { @@ -4501,7 +4536,7 @@ int TextEdit::get_whitespace_level(int p_line) const { break; } } - return whitespace_count; + return tab_count + whitespace_count / indent_size; } bool TextEdit::can_fold(int p_line) const { @@ -4518,12 +4553,12 @@ bool TextEdit::can_fold(int p_line) const { if (is_line_hidden(p_line)) return false; - int start_indent = get_whitespace_level(p_line); + int start_indent = get_indent_level(p_line); for (int i = p_line + 1; i < text.size(); i++) { if (text[i].size() == 0) continue; - int next_indent = get_whitespace_level(i); + int next_indent = get_indent_level(i); if (next_indent > start_indent) return true; else @@ -4552,22 +4587,20 @@ void TextEdit::fold_line(int p_line) { return; // hide lines below this one - int start_indent = get_whitespace_level(p_line); + int start_indent = get_indent_level(p_line); + int last_line = start_indent; for (int i = p_line + 1; i < text.size(); i++) { - int cur_indent = get_whitespace_level(i); - if (text[i].size() == 0 || cur_indent > start_indent) { - set_line_as_hidden(i, true); - } else { - // exclude trailing empty lines - for (int trail_i = i - 1; trail_i > p_line; trail_i--) { - if (text[trail_i].size() == 0) - set_line_as_hidden(trail_i, false); - else - break; + if (text[i].strip_edges().size() != 0) { + if (get_indent_level(i) > start_indent) { + last_line = i; + } else { + break; } - break; } } + for (int i = p_line + 1; i <= last_line; i++) { + set_line_as_hidden(i, true); + } // fix selection if (is_selection_active()) { @@ -4613,6 +4646,16 @@ void TextEdit::unfold_line(int p_line) { update(); } +void TextEdit::toggle_fold_line(int p_line) { + + ERR_FAIL_INDEX(p_line, text.size()); + + if (!is_folded(p_line)) + fold_line(p_line); + else + unfold_line(p_line); +} + int TextEdit::get_line_count() const { return text.size(); @@ -5428,6 +5471,7 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("unhide_all_lines"), &TextEdit::unhide_all_lines); ClassDB::bind_method(D_METHOD("fold_line", "line"), &TextEdit::fold_line); ClassDB::bind_method(D_METHOD("unfold_line", "line"), &TextEdit::unfold_line); + ClassDB::bind_method(D_METHOD("toggle_fold_line", "line"), &TextEdit::toggle_fold_line); ClassDB::bind_method(D_METHOD("can_fold", "line"), &TextEdit::can_fold); ClassDB::bind_method(D_METHOD("is_folded", "line"), &TextEdit::is_folded); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index bb9ca87d06..dd305d5822 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -78,6 +78,7 @@ class TextEdit : public Control { Ref<Texture> folded_eol_icon; Ref<StyleBox> style_normal; Ref<StyleBox> style_focus; + Ref<StyleBox> style_readonly; Ref<Font> font; Color completion_background_color; Color completion_selected_color; @@ -95,6 +96,7 @@ class TextEdit : public Control { Color selection_color; Color mark_color; Color breakpoint_color; + Color code_folding_color; Color current_line_color; Color line_length_guideline_color; Color brace_mismatch_color; @@ -158,7 +160,7 @@ class TextEdit : public Control { void set_font(const Ref<Font> &p_font); void set_color_regions(const Vector<ColorRegion> *p_regions) { color_regions = p_regions; } int get_line_width(int p_line) const; - int get_max_width() const; + int get_max_width(bool p_exclude_hidden = false) const; const Map<int, ColorRegionInfo> &get_color_region_info(int p_line); void set(int p_line, const String &p_text); void set_marked(int p_line, bool p_marked) { text[p_line].marked = p_marked; } @@ -430,11 +432,11 @@ public: void fold_all_lines(); void unhide_all_lines(); int num_lines_from(int p_line_from, int unhidden_amount) const; - int get_whitespace_level(int p_line) const; bool can_fold(int p_line) const; bool is_folded(int p_line) const; void fold_line(int p_line); void unfold_line(int p_line); + void toggle_fold_line(int p_line); String get_text(); String get_line(int line) const; @@ -443,6 +445,7 @@ public: void indent_selection_left(); void indent_selection_right(); + int get_indent_level(int p_line) const; inline void set_scroll_pass_end_of_file(bool p_enabled) { scroll_past_end_of_file_enabled = p_enabled; diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 9213296c55..ab12d123ba 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -2599,6 +2599,11 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { if (drag_touching) { set_physics_process(true); } + + if (b->get_button_index() == BUTTON_LEFT) { + if (get_item_at_position(b->get_position()) == NULL && !b->get_shift() && !b->get_control() && !b->get_command()) + emit_signal("nothing_selected"); + } } } break; @@ -3043,6 +3048,25 @@ void Tree::set_select_mode(SelectMode p_mode) { select_mode = p_mode; } +void Tree::deselect_all() { + + TreeItem *item = get_next_selected(get_root()); + while (item) { + item->deselect(selected_col); + item = get_next_selected(get_root()); + } + + selected_item = NULL; + selected_col = -1; + + update(); +} + +bool Tree::is_anything_selected() { + + return (selected_item != NULL); +} + void Tree::clear() { if (blocked > 0) { @@ -3750,6 +3774,7 @@ void Tree::_bind_methods() { ADD_SIGNAL(MethodInfo("custom_popup_edited", PropertyInfo(Variant::BOOL, "arrow_clicked"))); ADD_SIGNAL(MethodInfo("item_activated")); ADD_SIGNAL(MethodInfo("column_title_pressed", PropertyInfo(Variant::INT, "column"))); + ADD_SIGNAL(MethodInfo("nothing_selected")); BIND_ENUM_CONSTANT(SELECT_SINGLE); BIND_ENUM_CONSTANT(SELECT_ROW); diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 64d6016942..112de3165f 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -546,6 +546,8 @@ public: int get_selected_column() const; int get_pressed_button() const; void set_select_mode(SelectMode p_mode); + void deselect_all(); + bool is_anything_selected(); void set_columns(int p_columns); int get_columns() const; diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp index c7157d539d..8f567f9796 100644 --- a/scene/gui/video_player.cpp +++ b/scene/gui/video_player.cpp @@ -490,6 +490,7 @@ VideoPlayer::VideoPlayer() { expand = true; audio_track = 0; + bus_index = 0; buffering_ms = 500; server_mix_rate = 44100; |