Repository: godotengine/godot
File: editor/gui/editor_bottom_panel.cpp (C++)

Code before:
	tb->set_toggle_mode(true);
	tb->connect(SceneStringName(visibility_changed), callable_mp(this, &EditorBottomPanel::_on_button_visibility_changed).bind(tb, dock));
	legacy_buttons.push_back(tb);
	return tb;
}

void EditorBottomPanel::remove_item(Control *p_item) {
	EditorDock *dock = _get_dock_from_control(p_item);
	ERR_FAIL_NULL_MSG(dock, vformat("Cannot remove unknown dock \"%s\" from the bottom panel.", p_item->get_name()));

	int item_idx = bottom_docks.find(dock);
	ERR_FAIL_COND(item_idx == -1);

	bottom_docks.remove_at(item_idx);

	legacy_buttons[item_idx]->queue_free();
	legacy_buttons.remove_at(item_idx);

	EditorDockManager::get_singleton()->remove_dock(dock);
	dock->remove_child(p_item);
	dock->queue_free();
}

void EditorBottomPanel::_on_button_visibility_changed(Button *p_button, EditorDock *p_dock) {
	if (p_button->is_visible()) {
		p_dock->make_visible();
	} else {
		p_dock->close();
	}
}

EditorBottomPanel::EditorBottomPanel() {
	get_tab_bar()->connect("tab_changed", callable_mp(this, &EditorBottomPanel::_on_tab_changed));
	set_tabs_position(TabPosition::POSITION_BOTTOM);
	set_deselect_enabled(true);

	bottom_hbox = memnew(HBoxContainer);
	bottom_hbox->set_mouse_filter(MOUSE_FILTER_IGNORE);
	bottom_hbox->set_anchors_and_offsets_preset(Control::PRESET_RIGHT_WIDE);
	bottom_hbox->set_h_grow_direction(Control::GROW_DIRECTION_END);
	get_tab_bar()->add_child(bottom_hbox);

	icon_spacer = memnew(Control);
	icon_spacer->set_mouse_filter(MOUSE_FILTER_IGNORE);
	bottom_hbox->add_child(icon_spacer);

	bottom_hbox->add_child(memnew(VSeparator));

	editor_toaster = memnew(EditorToaster);
	bottom_hbox->add_child(editor_toaster);


Review comment (suggestion):
I think this is one of the cases that `open()` is preferred. This code is meant to replicate how the bottom panel used to work, which tied the button's visibility to whether the dock is available, and `EditorBottomPanel::make_visible()` to whether it is visible. Typically `button->show()` would be paired with `make_visible(dock)`. In the cases where this is not true (ie only the button was shown), this shows an intention to not grab focus, and I think this should respect that.

Code after:
	tb->set_toggle_mode(true);
	tb->connect(SceneStringName(visibility_changed), callable_mp(this, &EditorBottomPanel::_on_button_visibility_changed).bind(tb, dock));
	legacy_buttons.push_back(tb);
	return tb;
}

void EditorBottomPanel::remove_item(Control *p_item) {
	EditorDock *dock = _get_dock_from_control(p_item);
	ERR_FAIL_NULL_MSG(dock, vformat("Cannot remove unknown dock \"%s\" from the bottom panel.", p_item->get_name()));

	int item_idx = bottom_docks.find(dock);
	ERR_FAIL_COND(item_idx == -1);

	bottom_docks.remove_at(item_idx);

	legacy_buttons[item_idx]->queue_free();
	legacy_buttons.remove_at(item_idx);

	EditorDockManager::get_singleton()->remove_dock(dock);
	dock->remove_child(p_item);
	dock->queue_free();
}

void EditorBottomPanel::_on_button_visibility_changed(Button *p_button, EditorDock *p_dock) {
	if (p_button->is_visible()) {
		p_dock->open();
	} else {
		p_dock->close();
	}
}

EditorBottomPanel::EditorBottomPanel() {
	get_tab_bar()->connect("tab_changed", callable_mp(this, &EditorBottomPanel::_on_tab_changed));
	set_tabs_position(TabPosition::POSITION_BOTTOM);
	set_deselect_enabled(true);

	bottom_hbox = memnew(HBoxContainer);
	bottom_hbox->set_mouse_filter(MOUSE_FILTER_IGNORE);
	bottom_hbox->set_anchors_and_offsets_preset(Control::PRESET_RIGHT_WIDE);
	bottom_hbox->set_h_grow_direction(Control::GROW_DIRECTION_END);
	get_tab_bar()->add_child(bottom_hbox);

	icon_spacer = memnew(Control);
	icon_spacer->set_mouse_filter(MOUSE_FILTER_IGNORE);
	bottom_hbox->add_child(icon_spacer);

	bottom_hbox->add_child(memnew(VSeparator));

	editor_toaster = memnew(EditorToaster);
	bottom_hbox->add_child(editor_toaster);