diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index e024d3de..e4030150 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -82,6 +82,7 @@ SOURCES src/ui/add_conversation/list_row.vala src/ui/add_conversation/select_jid_fragment.vala src/ui/avatar_generator.vala + src/ui/chat_input/edit_history.vala src/ui/chat_input/occupants_tab_completer.vala src/ui/chat_input/smiley_converter.vala src/ui/chat_input/view.vala diff --git a/main/src/ui/chat_input/edit_history.vala b/main/src/ui/chat_input/edit_history.vala new file mode 100644 index 00000000..78a0f41e --- /dev/null +++ b/main/src/ui/chat_input/edit_history.vala @@ -0,0 +1,77 @@ +using Gdk; +using Gee; +using Gtk; + +using Dino.Entities; + +namespace Dino.Ui.ChatInput { + +class EditHistory { + + private StreamInteractor stream_interactor; + private Conversation? conversation; + private TextView text_input; + + private HashMap> histories = new HashMap>(Conversation.hash_func, Conversation.equals_func); + private HashMap indices = new HashMap(Conversation.hash_func, Conversation.equals_func); + + public EditHistory(TextView text_input, GLib.Application application) { + this.stream_interactor = stream_interactor; + this.text_input = text_input; + + text_input.key_press_event.connect(on_text_input_key_press); + } + + public void initialize_for_conversation(Conversation conversation) { + this.conversation = conversation; + if (!histories.has_key(conversation)) { + reset_history(); + } + } + + public bool on_text_input_key_press(EventKey event) { + if ((event.state & ModifierType.CONTROL_MASK) > 0) { + if (event.keyval == Key.z) { + undo(); + } else if (event.keyval == Key.Z) { + redo(); + } + } else if (event.keyval in new uint[]{ Key.space, Key.Tab, Key.ISO_Left_Tab }) { + if (indices[conversation] < histories[conversation].size - 1) { + histories[conversation] = histories[conversation].slice(0, indices[conversation] + 1); + } + save_state(); + } + return false; + } + + private void undo() { + if (histories[conversation][indices[conversation]] != text_input.buffer.text) { + save_state(); + } + if (indices[conversation] > 0) { + indices[conversation] = indices[conversation] - 1; + text_input.buffer.text = histories[conversation][indices[conversation]]; + } + } + + private void redo() { + if (indices[conversation] < histories[conversation].size - 1) { + indices[conversation] = indices[conversation] + 1; + text_input.buffer.text = histories[conversation][indices[conversation]]; + } + } + + private void save_state() { + histories[conversation].add(text_input.buffer.text); + indices[conversation] = indices[conversation] + 1; + } + + public void reset_history() { + histories[conversation] = new ArrayList(); + histories[conversation].add(""); + indices[conversation] = 0; + } +} + +} diff --git a/main/src/ui/chat_input/view.vala b/main/src/ui/chat_input/view.vala index 0887de25..d8a31a22 100644 --- a/main/src/ui/chat_input/view.vala +++ b/main/src/ui/chat_input/view.vala @@ -19,11 +19,13 @@ public class View : Box { private int vscrollbar_min_height; private OccupantsTabCompletor occupants_tab_completor; private SmileyConverter smiley_converter; + private EditHistory edit_history; public View(StreamInteractor stream_interactor) { this.stream_interactor = stream_interactor; occupants_tab_completor = new OccupantsTabCompletor(stream_interactor, text_input); smiley_converter = new SmileyConverter(stream_interactor, text_input); + edit_history = new EditHistory(text_input, GLib.Application.get_default()); scrolled.get_vscrollbar().get_preferred_height(out vscrollbar_min_height, null); scrolled.vadjustment.notify["upper"].connect_after(on_upper_notify); @@ -33,6 +35,7 @@ public class View : Box { public void initialize_for_conversation(Conversation conversation) { occupants_tab_completor.initialize_for_conversation(conversation); + edit_history.initialize_for_conversation(conversation); if (this.conversation != null) entry_cache[this.conversation] = text_input.buffer.text; this.conversation = conversation; @@ -81,6 +84,7 @@ public class View : Box { text_input.buffer.insert_at_cursor("\n", 1); } else if (text_input.buffer.text != ""){ send_text(); + edit_history.reset_history(); } return true; } @@ -103,4 +107,4 @@ public class View : Box { } } -} \ No newline at end of file +}