Browse Source

Reorganized connection dialog for much improved ease of use.

-Removed dest path field
-Added a "Source" signal
-Added an "Advanced" button to hide complexity
-Fix bug on Tree to make sure "ensure visible" works on hidden trees
-Fix bug on TextEdit to ensure signals created with script not open sill focus the right line
Juan Linietsky 6 years ago
parent
commit
9f4b5a91c0

+ 94 - 33
editor/connections_dialog.cpp

@@ -37,6 +37,25 @@
 #include "scene/gui/label.h"
 #include "scene/gui/label.h"
 #include "scene/gui/popup_menu.h"
 #include "scene/gui/popup_menu.h"
 
 
+static Node *_find_first_script(Node *p_root, Node *p_node) {
+	if (p_node != p_root && p_node->get_owner() != p_root) {
+		return NULL;
+	}
+	if (!p_node->get_script().is_null()) {
+		return p_node;
+	}
+
+	for (int i = 0; i < p_node->get_child_count(); i++) {
+
+		Node *ret = _find_first_script(p_root, p_node->get_child(i));
+		if (ret) {
+			return ret;
+		}
+	}
+
+	return NULL;
+}
+
 class ConnectDialogBinds : public Object {
 class ConnectDialogBinds : public Object {
 
 
 	GDCLASS(ConnectDialogBinds, Object);
 	GDCLASS(ConnectDialogBinds, Object);
@@ -122,17 +141,8 @@ void ConnectDialog::_tree_node_selected() {
 
 
 	Node *current = tree->get_selected();
 	Node *current = tree->get_selected();
 
 
-	if (!current) {
-		make_callback->hide();
-		return;
-	}
-
-	if (current->get_script().is_null())
-		make_callback->hide();
-	else
-		make_callback->show();
-
-	dst_path->set_text(source->get_path_to(current));
+	dst_path = source->get_path_to(current);
+	get_ok()->set_disabled(false);
 }
 }
 
 
 /*
 /*
@@ -195,6 +205,7 @@ void ConnectDialog::_notification(int p_what) {
 
 
 void ConnectDialog::_bind_methods() {
 void ConnectDialog::_bind_methods() {
 
 
+	ClassDB::bind_method("_advanced_pressed", &ConnectDialog::_advanced_pressed);
 	ClassDB::bind_method("_cancel", &ConnectDialog::_cancel_pressed);
 	ClassDB::bind_method("_cancel", &ConnectDialog::_cancel_pressed);
 	ClassDB::bind_method("_tree_node_selected", &ConnectDialog::_tree_node_selected);
 	ClassDB::bind_method("_tree_node_selected", &ConnectDialog::_tree_node_selected);
 	ClassDB::bind_method("_add_bind", &ConnectDialog::_add_bind);
 	ClassDB::bind_method("_add_bind", &ConnectDialog::_add_bind);
@@ -215,7 +226,7 @@ StringName ConnectDialog::get_signal_name() const {
 
 
 NodePath ConnectDialog::get_dst_path() const {
 NodePath ConnectDialog::get_dst_path() const {
 
 
-	return dst_path->get_text();
+	return dst_path;
 }
 }
 
 
 void ConnectDialog::set_dst_node(Node *p_node) {
 void ConnectDialog::set_dst_node(Node *p_node) {
@@ -272,8 +283,13 @@ void ConnectDialog::init(Connection c, bool bEdit) {
 	tree->set_selected(NULL);
 	tree->set_selected(NULL);
 	tree->set_marked(source, true);
 	tree->set_marked(source, true);
 
 
-	set_dst_node(static_cast<Node *>(c.target));
-	set_dst_method(c.method);
+	if (c.target) {
+		get_ok()->set_disabled(false);
+		set_dst_node(static_cast<Node *>(c.target));
+		set_dst_method(c.method);
+	} else {
+		get_ok()->set_disabled(true);
+	}
 
 
 	bool bDeferred = (c.flags & CONNECT_DEFERRED) == CONNECT_DEFERRED;
 	bool bDeferred = (c.flags & CONNECT_DEFERRED) == CONNECT_DEFERRED;
 	bool bOneshot = (c.flags & CONNECT_ONESHOT) == CONNECT_ONESHOT;
 	bool bOneshot = (c.flags & CONNECT_ONESHOT) == CONNECT_ONESHOT;
@@ -288,6 +304,36 @@ void ConnectDialog::init(Connection c, bool bEdit) {
 	bEditMode = bEdit;
 	bEditMode = bEdit;
 }
 }
 
 
+void ConnectDialog::popup_dialog(const String &p_for_signal, bool p_advanced) {
+
+	advanced->set_pressed(p_advanced);
+	from_signal->set_text(p_for_signal);
+	error_label->add_color_override("font_color", get_color("error_color", "Editor"));
+
+	if (p_advanced) {
+
+		popup_centered(Size2(900, 500) * EDSCALE);
+		connect_to_label->set_text("Connect to Node:");
+		tree->set_connect_to_script_mode(false);
+		error_label->hide();
+	} else {
+		popup_centered(Size2(700, 500) * EDSCALE);
+		connect_to_label->set_text("Connect to Script:");
+		tree->set_connect_to_script_mode(true);
+
+		if (!_find_first_script(get_tree()->get_edited_scene_root(), get_tree()->get_edited_scene_root())) {
+			error_label->show();
+		} else {
+			error_label->hide();
+		}
+	}
+}
+
+void ConnectDialog::_advanced_pressed() {
+	vbc_right->set_visible(advanced->is_pressed());
+	popup_dialog(from_signal->get_text(), advanced->is_pressed());
+}
+
 ConnectDialog::ConnectDialog() {
 ConnectDialog::ConnectDialog() {
 
 
 	VBoxContainer *vbc = memnew(VBoxContainer);
 	VBoxContainer *vbc = memnew(VBoxContainer);
@@ -301,15 +347,27 @@ ConnectDialog::ConnectDialog() {
 	main_hb->add_child(vbc_left);
 	main_hb->add_child(vbc_left);
 	vbc_left->set_h_size_flags(SIZE_EXPAND_FILL);
 	vbc_left->set_h_size_flags(SIZE_EXPAND_FILL);
 
 
+	from_signal = memnew(LineEdit);
+	from_signal->set_editable(false);
+	vbc_left->add_margin_child(TTR("From Signal:"), from_signal);
+
 	tree = memnew(SceneTreeEditor(false));
 	tree = memnew(SceneTreeEditor(false));
 	tree->get_scene_tree()->connect("item_activated", this, "_ok");
 	tree->get_scene_tree()->connect("item_activated", this, "_ok");
 	tree->connect("node_selected", this, "_tree_node_selected");
 	tree->connect("node_selected", this, "_tree_node_selected");
+	tree->set_connect_to_script_mode(true);
 
 
-	vbc_left->add_margin_child(TTR("Connect To Node:"), tree, true);
+	Node *mc = vbc_left->add_margin_child(TTR("Connect To Script:"), tree, true);
+	connect_to_label = Object::cast_to<Label>(vbc_left->get_child(mc->get_index() - 1));
 
 
-	VBoxContainer *vbc_right = memnew(VBoxContainer);
+	error_label = memnew(Label);
+	error_label->set_text(TTR("Scene does not contain any script."));
+	vbc_left->add_child(error_label);
+	error_label->hide();
+
+	vbc_right = memnew(VBoxContainer);
 	main_hb->add_child(vbc_right);
 	main_hb->add_child(vbc_right);
 	vbc_right->set_h_size_flags(SIZE_EXPAND_FILL);
 	vbc_right->set_h_size_flags(SIZE_EXPAND_FILL);
+	vbc_right->hide();
 
 
 	HBoxContainer *add_bind_hb = memnew(HBoxContainer);
 	HBoxContainer *add_bind_hb = memnew(HBoxContainer);
 
 
@@ -347,16 +405,18 @@ ConnectDialog::ConnectDialog() {
 
 
 	vbc_right->add_margin_child(TTR("Extra Call Arguments:"), bind_editor, true);
 	vbc_right->add_margin_child(TTR("Extra Call Arguments:"), bind_editor, true);
 
 
-	dst_path = memnew(LineEdit);
-	vbc->add_margin_child(TTR("Path to Node:"), dst_path);
-
 	HBoxContainer *dstm_hb = memnew(HBoxContainer);
 	HBoxContainer *dstm_hb = memnew(HBoxContainer);
-	vbc->add_margin_child("Method In Node:", dstm_hb);
+	vbc_left->add_margin_child("Method to Create:", dstm_hb);
 
 
 	dst_method = memnew(LineEdit);
 	dst_method = memnew(LineEdit);
 	dst_method->set_h_size_flags(SIZE_EXPAND_FILL);
 	dst_method->set_h_size_flags(SIZE_EXPAND_FILL);
 	dstm_hb->add_child(dst_method);
 	dstm_hb->add_child(dst_method);
 
 
+	advanced = memnew(CheckBox);
+	dstm_hb->add_child(advanced);
+	advanced->set_text(TTR("Advanced.."));
+	advanced->connect("pressed", this, "_advanced_pressed");
+
 	/*
 	/*
 	dst_method_list = memnew( MenuButton );
 	dst_method_list = memnew( MenuButton );
 	dst_method_list->set_text("List...");
 	dst_method_list->set_text("List...");
@@ -368,19 +428,13 @@ ConnectDialog::ConnectDialog() {
 	dst_method_list->set_end( Point2( 15,39  ) );
 	dst_method_list->set_end( Point2( 15,39  ) );
 	*/
 	*/
 
 
-	make_callback = memnew(CheckButton);
-	make_callback->set_toggle_mode(true);
-	make_callback->set_pressed(EDITOR_DEF("text_editor/tools/create_signal_callbacks", true));
-	make_callback->set_text(TTR("Make Function"));
-	dstm_hb->add_child(make_callback);
-
 	deferred = memnew(CheckButton);
 	deferred = memnew(CheckButton);
 	deferred->set_text(TTR("Deferred"));
 	deferred->set_text(TTR("Deferred"));
-	dstm_hb->add_child(deferred);
+	vbc_right->add_child(deferred);
 
 
 	oneshot = memnew(CheckButton);
 	oneshot = memnew(CheckButton);
 	oneshot->set_text(TTR("Oneshot"));
 	oneshot->set_text(TTR("Oneshot"));
-	dstm_hb->add_child(oneshot);
+	vbc_right->add_child(oneshot);
 
 
 	set_as_toplevel(true);
 	set_as_toplevel(true);
 
 
@@ -429,7 +483,8 @@ void ConnectionsDock::_make_or_edit_connection() {
 	bool oshot = connect_dialog->get_oneshot();
 	bool oshot = connect_dialog->get_oneshot();
 	cToMake.flags = CONNECT_PERSIST | (defer ? CONNECT_DEFERRED : 0) | (oshot ? CONNECT_ONESHOT : 0);
 	cToMake.flags = CONNECT_PERSIST | (defer ? CONNECT_DEFERRED : 0) | (oshot ? CONNECT_ONESHOT : 0);
 
 
-	bool add_script_function = connect_dialog->get_make_callback();
+	//conditions to add function, must have a script and must have a method
+	bool add_script_function = !target->get_script().is_null() && !ClassDB::has_method(target->get_class(), cToMake.method);
 	PoolStringArray script_function_args;
 	PoolStringArray script_function_args;
 	if (add_script_function) {
 	if (add_script_function) {
 		// pick up args here before "it" is deleted by update_tree
 		// pick up args here before "it" is deleted by update_tree
@@ -568,6 +623,7 @@ bool ConnectionsDock::_is_item_signal(TreeItem &item) {
 /*
 /*
 Open connection dialog with TreeItem data to CREATE a brand-new connection.
 Open connection dialog with TreeItem data to CREATE a brand-new connection.
 */
 */
+
 void ConnectionsDock::_open_connection_dialog(TreeItem &item) {
 void ConnectionsDock::_open_connection_dialog(TreeItem &item) {
 
 
 	String signal = item.get_metadata(0).operator Dictionary()["name"];
 	String signal = item.get_metadata(0).operator Dictionary()["name"];
@@ -590,6 +646,10 @@ void ConnectionsDock::_open_connection_dialog(TreeItem &item) {
 	}
 	}
 
 
 	Node *dst_node = selectedNode->get_owner() ? selectedNode->get_owner() : selectedNode;
 	Node *dst_node = selectedNode->get_owner() ? selectedNode->get_owner() : selectedNode;
+	if (!dst_node || dst_node->get_script().is_null()) {
+		dst_node = _find_first_script(get_tree()->get_edited_scene_root(), get_tree()->get_edited_scene_root());
+	}
+
 	StringName dst_method = "_on_" + midname + "_" + signal;
 	StringName dst_method = "_on_" + midname + "_" + signal;
 
 
 	Connection c;
 	Connection c;
@@ -598,9 +658,10 @@ void ConnectionsDock::_open_connection_dialog(TreeItem &item) {
 	c.target = dst_node;
 	c.target = dst_node;
 	c.method = dst_method;
 	c.method = dst_method;
 
 
+	//connect_dialog->set_title(TTR("Connect Signal: ") + signalname);
+	connect_dialog->popup_dialog(signalname, false);
 	connect_dialog->init(c);
 	connect_dialog->init(c);
-	connect_dialog->set_title(TTR("Connect Signal: ") + signalname);
-	connect_dialog->popup_centered_ratio();
+	connect_dialog->set_title(TTR("Connect a Signal to a Method"));
 }
 }
 
 
 /*
 /*
@@ -612,9 +673,9 @@ void ConnectionsDock::_open_connection_dialog(Connection cToEdit) {
 	Node *dst = static_cast<Node *>(cToEdit.target);
 	Node *dst = static_cast<Node *>(cToEdit.target);
 
 
 	if (src && dst) {
 	if (src && dst) {
-		connect_dialog->init(cToEdit, true);
-		connect_dialog->set_title(TTR("Edit Connection: ") + cToEdit.signal);
+		connect_dialog->set_title(TTR("Edit Connection:") + cToEdit.signal);
 		connect_dialog->popup_centered_ratio();
 		connect_dialog->popup_centered_ratio();
+		connect_dialog->init(cToEdit, true);
 	}
 	}
 }
 }
 
 

+ 9 - 3
editor/connections_dialog.h

@@ -53,12 +53,15 @@ class ConnectDialog : public ConfirmationDialog {
 
 
 	GDCLASS(ConnectDialog, ConfirmationDialog);
 	GDCLASS(ConnectDialog, ConfirmationDialog);
 
 
+	Label *connect_to_label;
+	LineEdit *from_signal;
 	Node *source;
 	Node *source;
 	StringName signal;
 	StringName signal;
-	LineEdit *dst_path;
 	LineEdit *dst_method;
 	LineEdit *dst_method;
 	ConnectDialogBinds *cdbinds;
 	ConnectDialogBinds *cdbinds;
 	bool bEditMode;
 	bool bEditMode;
+	NodePath dst_path;
+	VBoxContainer *vbc_right;
 
 
 	SceneTreeEditor *tree;
 	SceneTreeEditor *tree;
 	ConfirmationDialog *error;
 	ConfirmationDialog *error;
@@ -66,13 +69,16 @@ class ConnectDialog : public ConfirmationDialog {
 	OptionButton *type_list;
 	OptionButton *type_list;
 	CheckButton *deferred;
 	CheckButton *deferred;
 	CheckButton *oneshot;
 	CheckButton *oneshot;
-	CheckButton *make_callback;
+	CheckBox *advanced;
+
+	Label *error_label;
 
 
 	void ok_pressed();
 	void ok_pressed();
 	void _cancel_pressed();
 	void _cancel_pressed();
 	void _tree_node_selected();
 	void _tree_node_selected();
 	void _add_bind();
 	void _add_bind();
 	void _remove_bind();
 	void _remove_bind();
+	void _advanced_pressed();
 
 
 protected:
 protected:
 	void _notification(int p_what);
 	void _notification(int p_what);
@@ -87,13 +93,13 @@ public:
 	void set_dst_method(const StringName &p_method);
 	void set_dst_method(const StringName &p_method);
 	Vector<Variant> get_binds() const;
 	Vector<Variant> get_binds() const;
 
 
-	bool get_make_callback() { return make_callback->is_visible() && make_callback->is_pressed(); }
 	bool get_deferred() const;
 	bool get_deferred() const;
 	bool get_oneshot() const;
 	bool get_oneshot() const;
 	bool is_editing() const;
 	bool is_editing() const;
 
 
 	void init(Connection c, bool bEdit = false);
 	void init(Connection c, bool bEdit = false);
 
 
+	void popup_dialog(const String &p_for_signal, bool p_advanced);
 	ConnectDialog();
 	ConnectDialog();
 	~ConnectDialog();
 	~ConnectDialog();
 };
 };

+ 32 - 2
editor/scene_tree_editor.cpp

@@ -48,6 +48,9 @@ Node *SceneTreeEditor::get_scene_node() {
 
 
 void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_id) {
 void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_id) {
 
 
+	if (connect_to_script_mode) {
+		return; //dont do anything in this mode
+	}
 	TreeItem *item = Object::cast_to<TreeItem>(p_item);
 	TreeItem *item = Object::cast_to<TreeItem>(p_item);
 	ERR_FAIL_COND(!item);
 	ERR_FAIL_COND(!item);
 
 
@@ -190,7 +193,25 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
 	item->set_icon(0, icon);
 	item->set_icon(0, icon);
 	item->set_metadata(0, p_node->get_path());
 	item->set_metadata(0, p_node->get_path());
 
 
-	if (part_of_subscene) {
+	if (connect_to_script_mode) {
+		Color accent = get_color("accent_color", "Editor");
+
+		if (!p_node->get_script().is_null()) {
+			//has script
+			item->add_button(0, get_icon("Script", "EditorIcons"), BUTTON_SCRIPT);
+		} else {
+			//has no script
+			item->set_custom_color(0, get_color("disabled_font_color", "Editor"));
+			item->set_selectable(0, false);
+			accent.a *= 0.7;
+		}
+
+		if (marked.has(p_node)) {
+			item->set_text(0, String(p_node->get_name()) + " " + TTR("(Connecting From)"));
+
+			item->set_custom_color(0, accent);
+		}
+	} else if (part_of_subscene) {
 
 
 		//item->set_selectable(0,marked_selectable);
 		//item->set_selectable(0,marked_selectable);
 		if (valid_types.size() == 0) {
 		if (valid_types.size() == 0) {
@@ -199,7 +220,9 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
 
 
 	} else if (marked.has(p_node)) {
 	} else if (marked.has(p_node)) {
 
 
-		item->set_selectable(0, marked_selectable);
+		if (!connect_to_script_mode) {
+			item->set_selectable(0, marked_selectable);
+		}
 		item->set_custom_color(0, get_color("error_color", "Editor"));
 		item->set_custom_color(0, get_color("error_color", "Editor"));
 	} else if (!marked_selectable && !marked_children_selectable) {
 	} else if (!marked_selectable && !marked_children_selectable) {
 
 
@@ -620,6 +643,7 @@ void SceneTreeEditor::set_selected(Node *p_node, bool p_emit_selected) {
 		item->set_as_cursor(0);
 		item->set_as_cursor(0);
 		selected = p_node;
 		selected = p_node;
 		tree->ensure_cursor_is_visible();
 		tree->ensure_cursor_is_visible();
+
 	} else {
 	} else {
 		if (!p_node)
 		if (!p_node)
 			selected = NULL;
 			selected = NULL;
@@ -974,6 +998,11 @@ void SceneTreeEditor::_warning_changed(Node *p_for_node) {
 	update_timer->start();
 	update_timer->start();
 }
 }
 
 
+void SceneTreeEditor::set_connect_to_script_mode(bool p_enable) {
+	connect_to_script_mode = p_enable;
+	update_tree();
+}
+
 void SceneTreeEditor::_bind_methods() {
 void SceneTreeEditor::_bind_methods() {
 
 
 	ClassDB::bind_method("_tree_changed", &SceneTreeEditor::_tree_changed);
 	ClassDB::bind_method("_tree_changed", &SceneTreeEditor::_tree_changed);
@@ -1016,6 +1045,7 @@ void SceneTreeEditor::_bind_methods() {
 
 
 SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_open_instance) {
 SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_open_instance) {
 
 
+	connect_to_script_mode = false;
 	undo_redo = NULL;
 	undo_redo = NULL;
 	tree_dirty = true;
 	tree_dirty = true;
 	selected = NULL;
 	selected = NULL;

+ 4 - 0
editor/scene_tree_editor.h

@@ -67,6 +67,8 @@ class SceneTreeEditor : public Control {
 	AcceptDialog *error;
 	AcceptDialog *error;
 	AcceptDialog *warning;
 	AcceptDialog *warning;
 
 
+	bool connect_to_script_mode;
+
 	int blocked;
 	int blocked;
 
 
 	void _compute_hash(Node *p_node, uint64_t &hash);
 	void _compute_hash(Node *p_node, uint64_t &hash);
@@ -151,6 +153,8 @@ public:
 
 
 	void update_tree() { _update_tree(); }
 	void update_tree() { _update_tree(); }
 
 
+	void set_connect_to_script_mode(bool p_enable);
+
 	Tree *get_scene_tree() { return tree; }
 	Tree *get_scene_tree() { return tree; }
 
 
 	SceneTreeEditor(bool p_label = true, bool p_can_rename = false, bool p_can_open_instance = false);
 	SceneTreeEditor(bool p_label = true, bool p_can_rename = false, bool p_can_open_instance = false);

+ 7 - 0
scene/gui/text_edit.cpp

@@ -590,6 +590,12 @@ void TextEdit::_notification(int p_what) {
 			}
 			}
 		} break;
 		} break;
 		case NOTIFICATION_DRAW: {
 		case NOTIFICATION_DRAW: {
+
+			if (first_draw) {
+				//size may not be the final one, so attempts to ensure cursor was visible may have failed
+				adjust_viewport_to_cursor();
+				first_draw = false;
+			}
 			Size2 size = get_size();
 			Size2 size = get_size();
 			if ((!has_focus() && !menu->has_focus()) || !window_has_focus) {
 			if ((!has_focus() && !menu->has_focus()) || !window_has_focus) {
 				draw_caret = false;
 				draw_caret = false;
@@ -6356,6 +6362,7 @@ TextEdit::TextEdit() {
 	menu->add_item(RTR("Undo"), MENU_UNDO, KEY_MASK_CMD | KEY_Z);
 	menu->add_item(RTR("Undo"), MENU_UNDO, KEY_MASK_CMD | KEY_Z);
 	menu->add_item(RTR("Redo"), MENU_REDO, KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_Z);
 	menu->add_item(RTR("Redo"), MENU_REDO, KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_Z);
 	menu->connect("id_pressed", this, "menu_option");
 	menu->connect("id_pressed", this, "menu_option");
+	first_draw = true;
 }
 }
 
 
 TextEdit::~TextEdit() {
 TextEdit::~TextEdit() {

+ 1 - 0
scene/gui/text_edit.h

@@ -275,6 +275,7 @@ private:
 	int wrap_at;
 	int wrap_at;
 	int wrap_right_offset;
 	int wrap_right_offset;
 
 
+	bool first_draw;
 	bool setting_row;
 	bool setting_row;
 	bool draw_tabs;
 	bool draw_tabs;
 	bool override_selected_font_color;
 	bool override_selected_font_color;

+ 5 - 2
scene/gui/tree.cpp

@@ -3388,10 +3388,13 @@ void Tree::ensure_cursor_is_visible() {
 	int h = compute_item_height(selected) + cache.vseparation;
 	int h = compute_item_height(selected) + cache.vseparation;
 	int screenh = get_size().height - h_scroll->get_combined_minimum_size().height;
 	int screenh = get_size().height - h_scroll->get_combined_minimum_size().height;
 
 
-	if (ofs + h > v_scroll->get_value() + screenh)
+	if (h > screenh) { //screen size is too small, maybe it was not resized yet.
+		v_scroll->set_value(ofs);
+	} else if (ofs + h > v_scroll->get_value() + screenh) {
 		v_scroll->call_deferred("set_value", ofs - screenh + h);
 		v_scroll->call_deferred("set_value", ofs - screenh + h);
-	else if (ofs < v_scroll->get_value())
+	} else if (ofs < v_scroll->get_value()) {
 		v_scroll->set_value(ofs);
 		v_scroll->set_value(ofs);
+	}
 }
 }
 
 
 int Tree::get_pressed_button() const {
 int Tree::get_pressed_button() const {