summaryrefslogtreecommitdiff
path: root/scene/gui/line_edit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/gui/line_edit.cpp')
-rw-r--r--scene/gui/line_edit.cpp111
1 files changed, 78 insertions, 33 deletions
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index ed8eff436c..40e2dba6c2 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -161,13 +161,14 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
} break;
- case (KEY_Z): { // Simple One level undo
-
+ case (KEY_Z): { // undo / redo
if (editable) {
-
- undo();
+ if (k->get_shift()) {
+ redo();
+ } else {
+ undo();
+ }
}
-
} break;
case (KEY_U): { // Delete from start to cursor
@@ -175,7 +176,6 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
if (editable) {
selection_clear();
- undo_text = text;
text = text.substr(cursor_pos, text.length() - cursor_pos);
Ref<Font> font = get_font("font");
@@ -205,7 +205,6 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
if (editable) {
selection_clear();
- undo_text = text;
text = text.substr(0, cursor_pos);
_text_changed();
}
@@ -245,7 +244,6 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
break;
if (selection.enabled) {
- undo_text = text;
selection_delete();
break;
}
@@ -276,7 +274,6 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
set_cursor_position(cc);
} else {
- undo_text = text;
delete_char();
}
@@ -382,7 +379,6 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
}
if (selection.enabled) {
- undo_text = text;
selection_delete();
break;
}
@@ -417,7 +413,6 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
delete_text(cursor_pos, cc);
} else {
- undo_text = text;
set_cursor_position(cursor_pos + 1);
delete_char();
}
@@ -778,7 +773,6 @@ void LineEdit::copy_text() {
void LineEdit::cut_text() {
if (selection.enabled) {
- undo_text = text;
OS::get_singleton()->set_clipboard(text.substr(selection.begin, selection.end - selection.begin));
selection_delete();
}
@@ -798,23 +792,33 @@ void LineEdit::paste_text() {
}
void LineEdit::undo() {
-
- int old_cursor_pos = cursor_pos;
- text = undo_text;
-
- Ref<Font> font = get_font("font");
-
- cached_width = 0;
- for (int i = 0; i < text.length(); i++)
- cached_width += font->get_char_size(text[i]).width;
-
- if (old_cursor_pos > text.length()) {
- set_cursor_position(text.length());
- } else {
- set_cursor_position(old_cursor_pos);
+ if (undo_stack_pos == NULL) {
+ if (undo_stack.size() <= 1) {
+ return;
+ }
+ undo_stack_pos = undo_stack.back();
+ } else if (undo_stack_pos == undo_stack.front()) {
+ return;
}
+ undo_stack_pos = undo_stack_pos->prev();
+ TextOperation op = undo_stack_pos->get();
+ text = op.text;
+ set_cursor_position(op.cursor_pos);
+ _emit_text_change();
+}
- _text_changed();
+void LineEdit::redo() {
+ if (undo_stack_pos == NULL) {
+ return;
+ }
+ if (undo_stack_pos == undo_stack.back()) {
+ return;
+ }
+ undo_stack_pos = undo_stack_pos->next();
+ TextOperation op = undo_stack_pos->get();
+ text = op.text;
+ set_cursor_position(op.cursor_pos);
+ _emit_text_change();
}
void LineEdit::shift_selection_check_pre(bool p_shift) {
@@ -947,8 +951,6 @@ void LineEdit::delete_char() {
void LineEdit::delete_text(int p_from_column, int p_to_column) {
- undo_text = text;
-
if (text.size() > 0) {
Ref<Font> font = get_font("font");
if (font != NULL) {
@@ -1036,9 +1038,11 @@ void LineEdit::set_cursor_position(int p_pos) {
Ref<StyleBox> style = get_stylebox("normal");
Ref<Font> font = get_font("font");
- if (cursor_pos < window_pos) {
+ if (cursor_pos <= window_pos) {
/* Adjust window if cursor goes too much to the left */
- set_window_pos(cursor_pos);
+ if (window_pos > 0)
+ set_window_pos(window_pos - 1);
+
} 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;
@@ -1086,8 +1090,6 @@ void LineEdit::append_at_cursor(String p_text) {
if ((max_length <= 0) || (text.length() + p_text.length() <= max_length)) {
- undo_text = text;
-
Ref<Font> font = get_font("font");
if (font != NULL) {
for (int i = 0; i < p_text.length(); i++)
@@ -1105,6 +1107,7 @@ void LineEdit::append_at_cursor(String p_text) {
void LineEdit::clear_internal() {
+ _clear_undo_stack();
cached_width = 0;
cursor_pos = 0;
window_pos = 0;
@@ -1275,6 +1278,11 @@ void LineEdit::menu_option(int p_option) {
undo();
}
} break;
+ case MENU_REDO: {
+ if (editable) {
+ redo();
+ }
+ }
}
}
@@ -1312,10 +1320,43 @@ void LineEdit::_text_changed() {
if (expand_to_text_length)
minimum_size_changed();
+ _emit_text_change();
+ _clear_redo();
+}
+
+void LineEdit::_emit_text_change() {
emit_signal("text_changed", text);
_change_notify("text");
}
+void LineEdit::_clear_redo() {
+ _create_undo_state();
+ if (undo_stack_pos == NULL) {
+ return;
+ }
+
+ undo_stack_pos = undo_stack_pos->next();
+ while (undo_stack_pos) {
+ List<TextOperation>::Element *elem = undo_stack_pos;
+ undo_stack_pos = undo_stack_pos->next();
+ undo_stack.erase(elem);
+ }
+ _create_undo_state();
+}
+
+void LineEdit::_clear_undo_stack() {
+ undo_stack.clear();
+ undo_stack_pos = NULL;
+ _create_undo_state();
+}
+
+void LineEdit::_create_undo_state() {
+ TextOperation op;
+ op.text = text;
+ op.cursor_pos = cursor_pos;
+ undo_stack.push_back(op);
+}
+
void LineEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("_toggle_draw_caret"), &LineEdit::_toggle_draw_caret);
@@ -1369,6 +1410,7 @@ void LineEdit::_bind_methods() {
BIND_ENUM_CONSTANT(MENU_CLEAR);
BIND_ENUM_CONSTANT(MENU_SELECT_ALL);
BIND_ENUM_CONSTANT(MENU_UNDO);
+ BIND_ENUM_CONSTANT(MENU_REDO);
BIND_ENUM_CONSTANT(MENU_MAX);
ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text");
@@ -1388,6 +1430,8 @@ void LineEdit::_bind_methods() {
LineEdit::LineEdit() {
+ undo_stack_pos = NULL;
+ _create_undo_state();
align = ALIGN_LEFT;
cached_width = 0;
cursor_pos = 0;
@@ -1421,6 +1465,7 @@ LineEdit::LineEdit() {
menu->add_item(TTR("Clear"), MENU_CLEAR);
menu->add_separator();
menu->add_item(TTR("Undo"), MENU_UNDO, KEY_MASK_CMD | KEY_Z);
+ menu->add_item(TTR("Redo"), MENU_REDO, KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_Z);
menu->connect("id_pressed", this, "menu_option");
expand_to_text_length = false;
}