Skip to content

Commit

Permalink
Merge pull request #78744 from KoBeWi/easy_peasy_routine_refactor_stuff
Browse files Browse the repository at this point in the history
Standardize dialog input validation as a new class
  • Loading branch information
akien-mga committed Aug 8, 2023
2 parents 14256a2 + 7f41403 commit 60d6e14
Show file tree
Hide file tree
Showing 13 changed files with 382 additions and 341 deletions.
40 changes: 12 additions & 28 deletions editor/directory_create_dialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@
#include "core/io/dir_access.h"
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
#include "editor/gui/editor_validation_panel.h"
#include "scene/gui/box_container.h"
#include "scene/gui/label.h"
#include "scene/gui/line_edit.h"
#include "scene/gui/panel_container.h"

static String sanitize_input(const String &p_path) {
String path = p_path.strip_edges();
Expand Down Expand Up @@ -73,24 +73,17 @@ String DirectoryCreateDialog::_validate_path(const String &p_path) const {
return String();
}

void DirectoryCreateDialog::_on_dir_path_changed(const String &p_text) {
const String path = sanitize_input(p_text);
void DirectoryCreateDialog::_on_dir_path_changed() {
const String path = sanitize_input(dir_path->get_text());
const String error = _validate_path(path);

if (error.is_empty()) {
status_label->add_theme_color_override("font_color", get_theme_color(SNAME("success_color"), SNAME("Editor")));

if (path.contains("/")) {
status_label->set_text(TTR("Using slashes in folder names will create subfolders recursively."));
} else {
status_label->set_text(TTR("Folder name is valid."));
validation_panel->set_message(EditorValidationPanel::MSG_ID_DEFAULT, TTR("Using slashes in folder names will create subfolders recursively."), EditorValidationPanel::MSG_OK);
}
} else {
status_label->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor")));
status_label->set_text(error);
validation_panel->set_message(EditorValidationPanel::MSG_ID_DEFAULT, error, EditorValidationPanel::MSG_ERROR);
}

get_ok_button()->set_disabled(!error.is_empty());
}

void DirectoryCreateDialog::ok_pressed() {
Expand Down Expand Up @@ -127,21 +120,13 @@ void DirectoryCreateDialog::config(const String &p_base_dir) {
label->set_text(vformat(TTR("Create new folder in %s:"), base_dir));
dir_path->set_text("new folder");
dir_path->select_all();
_on_dir_path_changed(dir_path->get_text());
validation_panel->update();
}

void DirectoryCreateDialog::_bind_methods() {
ADD_SIGNAL(MethodInfo("dir_created"));
}

void DirectoryCreateDialog::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED: {
status_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree")));
} break;
}
}

DirectoryCreateDialog::DirectoryCreateDialog() {
set_title(TTR("Create Folder"));
set_min_size(Size2i(480, 0) * EDSCALE);
Expand All @@ -154,19 +139,18 @@ DirectoryCreateDialog::DirectoryCreateDialog() {
vb->add_child(label);

dir_path = memnew(LineEdit);
dir_path->connect("text_changed", callable_mp(this, &DirectoryCreateDialog::_on_dir_path_changed));
vb->add_child(dir_path);
register_text_enter(dir_path);

Control *spacing = memnew(Control);
spacing->set_custom_minimum_size(Size2(0, 10 * EDSCALE));
vb->add_child(spacing);

status_panel = memnew(PanelContainer);
status_panel->set_v_size_flags(Control::SIZE_EXPAND_FILL);
vb->add_child(status_panel);
validation_panel = memnew(EditorValidationPanel);
vb->add_child(validation_panel);
validation_panel->add_line(EditorValidationPanel::MSG_ID_DEFAULT, TTR("Folder name is valid."));
validation_panel->set_update_callback(callable_mp(this, &DirectoryCreateDialog::_on_dir_path_changed));
validation_panel->set_accept_button(get_ok_button());

status_label = memnew(Label);
status_label->set_v_size_flags(Control::SIZE_EXPAND_FILL);
status_panel->add_child(status_label);
dir_path->connect("text_changed", callable_mp(validation_panel, &EditorValidationPanel::update).unbind(1));
}
10 changes: 3 additions & 7 deletions editor/directory_create_dialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@

#include "scene/gui/dialogs.h"

class EditorValidationPanel;
class Label;
class LineEdit;
class PanelContainer;

class DirectoryCreateDialog : public ConfirmationDialog {
GDCLASS(DirectoryCreateDialog, ConfirmationDialog);
Expand All @@ -44,17 +44,13 @@ class DirectoryCreateDialog : public ConfirmationDialog {

Label *label = nullptr;
LineEdit *dir_path = nullptr;

PanelContainer *status_panel = nullptr;
Label *status_label = nullptr;
EditorValidationPanel *validation_panel = nullptr;

String _validate_path(const String &p_path) const;

void _on_dir_path_changed(const String &p_text);
void _on_dir_path_changed();

protected:
static void _bind_methods();
void _notification(int p_what);

virtual void ok_pressed() override;
virtual void _post_popup() override;
Expand Down
56 changes: 19 additions & 37 deletions editor/editor_inspector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/gui/editor_validation_panel.h"
#include "editor/inspector_dock.h"
#include "editor/plugins/script_editor_plugin.h"
#include "multi_node_edit.h"
Expand Down Expand Up @@ -3927,12 +3928,6 @@ void EditorInspector::_notification(int p_what) {
}
} break;

case NOTIFICATION_THEME_CHANGED: {
if (add_meta_error_panel) {
add_meta_error_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree")));
}
} break;

case NOTIFICATION_PREDELETE: {
edit(nullptr); //just in case
} break;
Expand Down Expand Up @@ -4083,27 +4078,17 @@ void EditorInspector::_add_meta_confirm() {
undo_redo->commit_action();
}

void EditorInspector::_check_meta_name(const String &p_name) {
String error;

if (p_name == "") {
error = TTR("Metadata name can't be empty.");
} else if (!p_name.is_valid_identifier()) {
error = TTR("Metadata name must be a valid identifier.");
} else if (object->has_meta(p_name)) {
error = vformat(TTR("Metadata with name \"%s\" already exists."), p_name);
} else if (p_name[0] == '_') {
error = TTR("Names starting with _ are reserved for editor-only metadata.");
}
void EditorInspector::_check_meta_name() {
const String meta_name = add_meta_name->get_text();

if (error != "") {
add_meta_error->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor")));
add_meta_error->set_text(error);
add_meta_dialog->get_ok_button()->set_disabled(true);
} else {
add_meta_error->add_theme_color_override("font_color", get_theme_color(SNAME("success_color"), SNAME("Editor")));
add_meta_error->set_text(TTR("Metadata name is valid."));
add_meta_dialog->get_ok_button()->set_disabled(false);
if (meta_name.is_empty()) {
validation_panel->set_message(EditorValidationPanel::MSG_ID_DEFAULT, TTR("Metadata name can't be empty."), EditorValidationPanel::MSG_ERROR);
} else if (!meta_name.is_valid_identifier()) {
validation_panel->set_message(EditorValidationPanel::MSG_ID_DEFAULT, TTR("Metadata name must be a valid identifier."), EditorValidationPanel::MSG_ERROR);
} else if (object->has_meta(meta_name)) {
validation_panel->set_message(EditorValidationPanel::MSG_ID_DEFAULT, vformat(TTR("Metadata with name \"%s\" already exists."), meta_name), EditorValidationPanel::MSG_ERROR);
} else if (meta_name[0] == '_') {
validation_panel->set_message(EditorValidationPanel::MSG_ID_DEFAULT, TTR("Names starting with _ are reserved for editor-only metadata."), EditorValidationPanel::MSG_ERROR);
}
}

Expand Down Expand Up @@ -4143,16 +4128,13 @@ void EditorInspector::_show_add_meta_dialog() {
add_meta_dialog->register_text_enter(add_meta_name);
add_meta_dialog->connect("confirmed", callable_mp(this, &EditorInspector::_add_meta_confirm));

add_meta_error_panel = memnew(PanelContainer);
vbc->add_child(add_meta_error_panel);
if (is_inside_tree()) {
add_meta_error_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree")));
}

add_meta_error = memnew(Label);
add_meta_error_panel->add_child(add_meta_error);
validation_panel = memnew(EditorValidationPanel);
vbc->add_child(validation_panel);
validation_panel->add_line(EditorValidationPanel::MSG_ID_DEFAULT, TTR("Metadata name is valid."));
validation_panel->set_update_callback(callable_mp(this, &EditorInspector::_check_meta_name));
validation_panel->set_accept_button(add_meta_dialog->get_ok_button());

add_meta_name->connect("text_changed", callable_mp(this, &EditorInspector::_check_meta_name));
add_meta_name->connect("text_changed", callable_mp(validation_panel, &EditorValidationPanel::update).unbind(1));
}

Node *node = Object::cast_to<Node>(object);
Expand All @@ -4164,9 +4146,9 @@ void EditorInspector::_show_add_meta_dialog() {
}

add_meta_dialog->popup_centered();
add_meta_name->set_text("");
_check_meta_name("");
add_meta_name->grab_focus();
add_meta_name->set_text("");
validation_panel->update();
}

void EditorInspector::_bind_methods() {
Expand Down
6 changes: 3 additions & 3 deletions editor/editor_inspector.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class AcceptDialog;
class Button;
class ConfirmationDialog;
class EditorInspector;
class EditorValidationPanel;
class LineEdit;
class OptionButton;
class PanelContainer;
Expand Down Expand Up @@ -543,12 +544,11 @@ class EditorInspector : public ScrollContainer {
ConfirmationDialog *add_meta_dialog = nullptr;
LineEdit *add_meta_name = nullptr;
OptionButton *add_meta_type = nullptr;
PanelContainer *add_meta_error_panel = nullptr;
Label *add_meta_error = nullptr;
EditorValidationPanel *validation_panel = nullptr;

void _add_meta_confirm();
void _show_add_meta_dialog();
void _check_meta_name(const String &p_name);
void _check_meta_name();

protected:
static void _bind_methods();
Expand Down
1 change: 1 addition & 0 deletions editor/editor_themes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1280,6 +1280,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
}

theme->set_stylebox("panel", "Tree", style_tree_bg);
theme->set_stylebox("panel", "EditorValidationPanel", style_tree_bg);

// Tree
theme->set_icon("checked", "Tree", theme->get_icon(SNAME("GuiChecked"), SNAME("EditorIcons")));
Expand Down
134 changes: 134 additions & 0 deletions editor/gui/editor_validation_panel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/**************************************************************************/
/* editor_validation_panel.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#include "editor_validation_panel.h"

#include "editor/editor_scale.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
#include "scene/gui/label.h"

void EditorValidationPanel::_update() {
for (const KeyValue<int, String> &E : valid_messages) {
set_message(E.key, E.value, MSG_OK);
}

valid = true;
update_callback.callv(Array());

if (accept_button) {
accept_button->set_disabled(!valid);
}
pending_update = false;
}

void EditorValidationPanel::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED: {
theme_cache.valid_color = get_theme_color(SNAME("success_color"), SNAME("Editor"));
theme_cache.warning_color = get_theme_color(SNAME("warning_color"), SNAME("Editor"));
theme_cache.error_color = get_theme_color(SNAME("error_color"), SNAME("Editor"));
} break;
}
}

void EditorValidationPanel::add_line(int p_id, const String &p_valid_message) {
ERR_FAIL_COND(valid_messages.has(p_id));

Label *label = memnew(Label);
message_container->add_child(label);
label->set_custom_minimum_size(Size2(200 * EDSCALE, 0));
label->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);

valid_messages[p_id] = p_valid_message;
labels[p_id] = label;
}

void EditorValidationPanel::set_accept_button(Button *p_button) {
accept_button = p_button;
}

void EditorValidationPanel::set_update_callback(const Callable &p_callback) {
update_callback = p_callback;
}

void EditorValidationPanel::update() {
ERR_FAIL_COND(update_callback.is_null());

if (pending_update) {
return;
}
pending_update = true;
callable_mp(this, &EditorValidationPanel::_update).call_deferred();
}

void EditorValidationPanel::set_message(int p_id, const String &p_text, MessageType p_type, bool p_auto_prefix) {
ERR_FAIL_COND(!valid_messages.has(p_id));

Label *label = labels[p_id];
if (p_text.is_empty()) {
label->hide();
return;
}
label->show();

if (p_auto_prefix) {
label->set_text(String(U"") + p_text);
} else {
label->set_text(p_text);
}

switch (p_type) {
case MSG_OK:
label->add_theme_color_override(SNAME("font_color"), theme_cache.valid_color);
break;
case MSG_WARNING:
label->add_theme_color_override(SNAME("font_color"), theme_cache.warning_color);
break;
case MSG_ERROR:
label->add_theme_color_override(SNAME("font_color"), theme_cache.error_color);
valid = false;
break;
case MSG_INFO:
label->remove_theme_color_override(SNAME("font_color"));
break;
}
}

bool EditorValidationPanel::is_valid() const {
return valid;
}

EditorValidationPanel::EditorValidationPanel() {
set_v_size_flags(SIZE_EXPAND_FILL);

message_container = memnew(VBoxContainer);
add_child(message_container);
}
Loading

0 comments on commit 60d6e14

Please sign in to comment.