From 7e7dcedaf31ee35499875491c9f569c575d28435 Mon Sep 17 00:00:00 2001 From: fiaxh Date: Mon, 14 Feb 2022 14:55:59 +0100 Subject: Port from GTK3 to GTK4 --- main/src/ui/chat_input/chat_input_controller.vala | 15 +++-- main/src/ui/chat_input/chat_text_view.vala | 55 ++++++++-------- main/src/ui/chat_input/edit_history.vala | 77 ---------------------- main/src/ui/chat_input/encryption_button.vala | 43 ++++++------ .../src/ui/chat_input/occupants_tab_completer.vala | 14 ++-- main/src/ui/chat_input/smiley_converter.vala | 8 ++- main/src/ui/chat_input/view.vala | 30 +++------ 7 files changed, 80 insertions(+), 162 deletions(-) delete mode 100644 main/src/ui/chat_input/edit_history.vala (limited to 'main/src/ui/chat_input') diff --git a/main/src/ui/chat_input/chat_input_controller.vala b/main/src/ui/chat_input/chat_input_controller.vala index d7a69c3d..41891519 100644 --- a/main/src/ui/chat_input/chat_input_controller.vala +++ b/main/src/ui/chat_input/chat_input_controller.vala @@ -34,9 +34,12 @@ public class ChatInputController : Object { reset_input_field_status(); - chat_input.chat_text_view.text_view.buffer.changed.connect(on_text_input_changed); - chat_input.chat_text_view.text_view.key_press_event.connect(on_text_input_key_press); + var text_input_key_events = new EventControllerKey(); + text_input_key_events.key_pressed.connect(on_text_input_key_press); + chat_input.chat_text_view.text_view.add_controller(text_input_key_events); + chat_input.chat_text_view.text_view.paste_clipboard.connect(() => clipboard_pasted()); + chat_input.chat_text_view.text_view.buffer.changed.connect(on_text_input_changed); chat_text_view_controller.send_text.connect(send_text); @@ -50,7 +53,7 @@ public class ChatInputController : Object { status_description_label.activate_link.connect((uri) => { if (uri == OPEN_CONVERSATION_DETAILS_URI){ ContactDetails.Dialog contact_details_dialog = new ContactDetails.Dialog(stream_interactor, conversation); - contact_details_dialog.set_transient_for((Gtk.Window) chat_input.get_toplevel()); + contact_details_dialog.set_transient_for((Gtk.Window) chat_input.get_root()); contact_details_dialog.present(); } return true; @@ -136,7 +139,7 @@ public class ChatInputController : Object { case "/ping": Xmpp.XmppStream? stream = stream_interactor.get_stream(conversation.account); try { - stream.get_module(Xmpp.Xep.Ping.Module.IDENTITY).send_ping.begin(stream, conversation.counterpart.with_resource(token[1]), null); + stream.get_module(Xmpp.Xep.Ping.Module.IDENTITY).send_ping.begin(stream, conversation.counterpart.with_resource(token[1])); } catch (Xmpp.InvalidJidError e) { warning("Could not ping invalid Jid: %s", e.message); } @@ -184,8 +187,8 @@ public class ChatInputController : Object { } } - private bool on_text_input_key_press(EventKey event) { - if (event.keyval == Gdk.Key.Up && chat_input.chat_text_view.text_view.buffer.text == "") { + private bool on_text_input_key_press(uint keyval, uint keycode, Gdk.ModifierType state) { + if (keyval == Gdk.Key.Up && chat_input.chat_text_view.text_view.buffer.text == "") { activate_last_message_correction(); return true; } else { diff --git a/main/src/ui/chat_input/chat_text_view.vala b/main/src/ui/chat_input/chat_text_view.vala index 2f8393d2..b1f719b6 100644 --- a/main/src/ui/chat_input/chat_text_view.vala +++ b/main/src/ui/chat_input/chat_text_view.vala @@ -30,61 +30,64 @@ public class ChatTextViewController : Object { } } -public class ChatTextView : ScrolledWindow { +public class ChatTextView : Box { public signal void send_text(); public signal void cancel_input(); - public TextView text_view = new TextView() { can_focus=true, hexpand=true, margin=8, wrap_mode=Gtk.WrapMode.WORD_CHAR, valign=Align.CENTER, visible=true }; + public ScrolledWindow scrolled_window = new ScrolledWindow() { propagate_natural_height=true, max_content_height=300 }; + public TextView text_view = new TextView() { hexpand=true, wrap_mode=Gtk.WrapMode.WORD_CHAR, valign=Align.CENTER, margin_top=7, margin_bottom=7 }; private int vscrollbar_min_height; private SmileyConverter smiley_converter; - public EditHistory edit_history; - private SpellChecker spell_checker; +// private SpellChecker spell_checker; construct { - max_content_height = 300; - propagate_natural_height = true; - this.add(text_view); + scrolled_window.set_child(text_view); + this.append(scrolled_window); smiley_converter = new SmileyConverter(text_view); - edit_history = new EditHistory(text_view); - spell_checker = new SpellChecker(text_view); - this.get_vscrollbar().get_preferred_height(out vscrollbar_min_height, null); - this.vadjustment.notify["upper"].connect_after(on_upper_notify); - text_view.key_press_event.connect(on_text_input_key_press); +// scrolled_window.get_vscrollbar().get_preferred_size(out vscrollbar_min_size, null); + scrolled_window.vadjustment.notify["upper"].connect(on_upper_notify); - Gtk.drag_dest_unset(text_view); + var text_input_key_events = new EventControllerKey(); + text_input_key_events.key_pressed.connect(on_text_input_key_press); + text_view.add_controller(text_input_key_events); + + text_view.realize.connect(() => { + var minimum_size = new Requisition(); + scrolled_window.get_preferred_size(out minimum_size, null); + vscrollbar_min_height = minimum_size.height; + }); +// Gtk.drag_dest_unset(text_view); } public void initialize_for_conversation(Conversation conversation) { - edit_history.initialize_for_conversation(conversation); - spell_checker.initialize_for_conversation(conversation); +// spell_checker.initialize_for_conversation(conversation); } - public override void get_preferred_height(out int min_height, out int nat_height) { - base.get_preferred_height(out min_height, out nat_height); - min_height = nat_height; - } +// public override void get_preferred_size(out Gtk.Requisition minimum_size, out Gtk.Requisition natural_size) { +// base.get_preferred_height(out min_height, out nat_height); +// min_height = nat_height; +// } private void on_upper_notify() { - this.vadjustment.value = this.vadjustment.upper - this.vadjustment.page_size; + scrolled_window.vadjustment.value = scrolled_window.vadjustment.upper - scrolled_window.vadjustment.page_size; // hack for vscrollbar not requiring space and making textview higher //TODO doesn't resize immediately - this.get_vscrollbar().visible = (this.vadjustment.upper > this.max_content_height - 2 * this.vscrollbar_min_height); + scrolled_window.get_vscrollbar().visible = (scrolled_window.vadjustment.upper > scrolled_window.max_content_height - 2 * this.vscrollbar_min_height); } - private bool on_text_input_key_press(EventKey event) { - if (event.keyval in new uint[]{Key.Return, Key.KP_Enter}) { - if ((event.state & ModifierType.SHIFT_MASK) > 0) { + private bool on_text_input_key_press(uint keyval, uint keycode, Gdk.ModifierType state) { + if (keyval in new uint[]{ Key.Return, Key.KP_Enter }) { + if ((state & ModifierType.SHIFT_MASK) > 0) { text_view.buffer.insert_at_cursor("\n", 1); } else if (text_view.buffer.text.strip() != "") { send_text(); - edit_history.reset_history(); } return true; } - if (event.keyval == Key.Escape) { + if (keyval == Key.Escape) { cancel_input(); } return false; diff --git a/main/src/ui/chat_input/edit_history.vala b/main/src/ui/chat_input/edit_history.vala deleted file mode 100644 index 70f6d400..00000000 --- a/main/src/ui/chat_input/edit_history.vala +++ /dev/null @@ -1,77 +0,0 @@ -using Gdk; -using Gee; -using Gtk; - -using Dino.Entities; - -namespace Dino.Ui { - -public class EditHistory { - - 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) { - this.text_input = text_input; - - text_input.key_press_event.connect(on_text_input_key_press); - text_input.cut_clipboard.connect_after(save_state); - text_input.paste_clipboard.connect_after(save_state); - text_input.move_cursor.connect_after(save_state); - text_input.button_release_event.connect_after(() => { save_state(); return false; }); - } - - 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) { - bool ctrl_pressed = (event.state & ModifierType.CONTROL_MASK) > 0; - if (ctrl_pressed && event.keyval == Key.z) { - undo(); - } else if (ctrl_pressed && (event.keyval in new uint[]{ Key.Z, Key.y } )) { - redo(); - } else if (event.keyval in new uint[]{ Key.space, Key.Tab, Key.ISO_Left_Tab }) { - save_state(); - } - return false; - } - - private void undo() { - 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() { - if (histories[conversation][indices[conversation]] == text_input.buffer.text) return; - if (indices[conversation] < histories[conversation].size - 1) { - histories[conversation] = histories[conversation].slice(0, indices[conversation] + 1); - } - 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/encryption_button.vala b/main/src/ui/chat_input/encryption_button.vala index 11466931..e5831802 100644 --- a/main/src/ui/chat_input/encryption_button.vala +++ b/main/src/ui/chat_input/encryption_button.vala @@ -5,27 +5,25 @@ using Dino.Entities; namespace Dino.Ui { -public class EncryptionButton : MenuButton { +public class EncryptionButton { public signal void encryption_changed(Plugins.EncryptionListEntry? encryption_entry); + private MenuButton menu_button; private Conversation? conversation; - private RadioButton? button_unencrypted; - private Map encryption_radios = new HashMap(); + private CheckButton? button_unencrypted; + private Map encryption_radios = new HashMap(); private string? current_icon; private StreamInteractor stream_interactor; - public EncryptionButton(StreamInteractor stream_interactor) { + public EncryptionButton(StreamInteractor stream_interactor, MenuButton menu_button) { this.stream_interactor = stream_interactor; - - use_popover = true; - image = new Image.from_icon_name("changes-allow-symbolic", IconSize.BUTTON); - get_style_context().add_class("flat"); + this.menu_button = menu_button; Builder builder = new Builder.from_resource("/im/dino/Dino/menu_encryption.ui"); - popover = builder.get_object("menu_encryption") as PopoverMenu; + menu_button.popover = builder.get_object("menu_encryption") as PopoverMenu; Box encryption_box = builder.get_object("encryption_box") as Box; - button_unencrypted = builder.get_object("button_unencrypted") as RadioButton; + button_unencrypted = builder.get_object("button_unencrypted") as CheckButton; button_unencrypted.toggled.connect(encryption_button_toggled); stream_interactor.get_module(MucManager.IDENTITY).room_info_updated.connect((account, muc_jid) => { @@ -36,17 +34,18 @@ public class EncryptionButton : MenuButton { Application app = GLib.Application.get_default() as Application; foreach (var e in app.plugin_registry.encryption_list_entries) { - RadioButton btn = new RadioButton.with_label(button_unencrypted.get_group(), e.name); + CheckButton btn = new CheckButton.with_label(e.name); + btn.set_group(button_unencrypted); encryption_radios[btn] = e; btn.toggled.connect(encryption_button_toggled); btn.visible = true; - encryption_box.pack_end(btn, false); + encryption_box.prepend(btn); } - clicked.connect(update_encryption_menu_state); + menu_button.activate.connect(update_encryption_menu_state); } private void encryption_button_toggled() { - foreach (RadioButton e in encryption_radios.keys) { + foreach (CheckButton e in encryption_radios.keys) { if (e.get_active()) { conversation.encryption = encryption_radios[e].encryption; encryption_changed(encryption_radios[e]); @@ -62,7 +61,7 @@ public class EncryptionButton : MenuButton { } private void update_encryption_menu_state() { - foreach (RadioButton e in encryption_radios.keys) { + foreach (CheckButton e in encryption_radios.keys) { if (conversation.encryption == encryption_radios[e].encryption) { e.set_active(true); encryption_changed(encryption_radios[e]); @@ -76,7 +75,7 @@ public class EncryptionButton : MenuButton { private void set_icon(string icon) { if (icon != current_icon) { - image = new Image.from_icon_name(icon, IconSize.BUTTON); + menu_button.set_icon_name(icon); current_icon = icon; } } @@ -87,23 +86,23 @@ public class EncryptionButton : MenuButton { private void update_visibility() { if (conversation.encryption != Encryption.NONE) { - visible = true; + menu_button.visible = true; return; } switch (conversation.type_) { case Conversation.Type.CHAT: - visible = true; + menu_button.visible = true; break; case Conversation.Type.GROUPCHAT_PM: - visible = false; + menu_button.visible = false; break; case Conversation.Type.GROUPCHAT: - visible = stream_interactor.get_module(MucManager.IDENTITY).is_private_room(conversation.account, conversation.counterpart); + menu_button.visible = stream_interactor.get_module(MucManager.IDENTITY).is_private_room(conversation.account, conversation.counterpart); break; } } - public new void set_conversation(Conversation conversation) { + public void set_conversation(Conversation conversation) { this.conversation = conversation; update_encryption_menu_state(); update_encryption_menu_icon(); @@ -111,4 +110,4 @@ public class EncryptionButton : MenuButton { } } -} +} \ No newline at end of file diff --git a/main/src/ui/chat_input/occupants_tab_completer.vala b/main/src/ui/chat_input/occupants_tab_completer.vala index 6d2a7434..e50fe831 100644 --- a/main/src/ui/chat_input/occupants_tab_completer.vala +++ b/main/src/ui/chat_input/occupants_tab_completer.vala @@ -27,16 +27,18 @@ public class OccupantsTabCompletor { this.stream_interactor = stream_interactor; this.text_input = text_input; - text_input.key_press_event.connect(on_text_input_key_press); + var text_input_key_events = new EventControllerKey(); + text_input_key_events.key_pressed.connect(on_text_input_key_press); + text_input.add_controller(text_input_key_events); } public void initialize_for_conversation(Conversation conversation) { this.conversation = conversation; } - public bool on_text_input_key_press(EventKey event) { + public bool on_text_input_key_press(uint keyval, uint keycode, Gdk.ModifierType state) { if (conversation.type_ == Conversation.Type.GROUPCHAT) { - if (event.keyval == Key.Tab || event.keyval == Key.ISO_Left_Tab) { + if (keyval == Key.Tab || keyval == Key.ISO_Left_Tab) { string text = text_input.buffer.text; int start_index = int.max(text.last_index_of(" "), text.last_index_of("\n")) + 1; string word = text.substring(start_index); @@ -51,11 +53,11 @@ public class OccupantsTabCompletor { index = -1; } } - if (event.keyval != Key.ISO_Group_Shift && active) { - text_input.buffer.text = next_completion(event.keyval == Key.ISO_Left_Tab); + if (keyval != Key.ISO_Group_Shift && active) { + text_input.buffer.text = next_completion(keyval == Key.ISO_Left_Tab); return true; } - } else if (event.keyval != Key.Shift_L && active) { + } else if (keyval != Key.Shift_L && active) { active = false; } } diff --git a/main/src/ui/chat_input/smiley_converter.vala b/main/src/ui/chat_input/smiley_converter.vala index 8f4dee9a..fe280d99 100644 --- a/main/src/ui/chat_input/smiley_converter.vala +++ b/main/src/ui/chat_input/smiley_converter.vala @@ -33,11 +33,13 @@ class SmileyConverter { public SmileyConverter(TextView text_input) { this.text_input = text_input; - text_input.key_press_event.connect(on_text_input_key_press); + var text_input_key_events = new EventControllerKey(); + text_input_key_events.key_pressed.connect(on_text_input_key_press); + text_input.add_controller(text_input_key_events); } - public bool on_text_input_key_press(EventKey event) { - if (event.keyval == Key.space || event.keyval == Key.Return) { + public bool on_text_input_key_press(uint keyval, uint keycode, Gdk.ModifierType state) { + if (keyval == Key.space || keyval == Key.Return) { check_convert(); } return false; diff --git a/main/src/ui/chat_input/view.vala b/main/src/ui/chat_input/view.vala index 5142eb10..6524a825 100644 --- a/main/src/ui/chat_input/view.vala +++ b/main/src/ui/chat_input/view.vala @@ -23,6 +23,8 @@ public class View : Box { [GtkChild] public unowned ChatTextView chat_text_view; [GtkChild] public unowned Box outer_box; [GtkChild] public unowned Button file_button; + [GtkChild] public unowned MenuButton emoji_button; + [GtkChild] public unowned MenuButton encryption_button; [GtkChild] public unowned Separator file_separator; [GtkChild] public unowned Label chat_input_status; @@ -31,29 +33,13 @@ public class View : Box { public View init(StreamInteractor stream_interactor) { this.stream_interactor = stream_interactor; - encryption_widget = new EncryptionButton(stream_interactor) { relief=ReliefStyle.NONE, margin_top=3, valign=Align.START, visible=true }; + encryption_widget = new EncryptionButton(stream_interactor, encryption_button); - file_button.get_style_context().add_class("dino-attach-button"); - - encryption_widget.get_style_context().add_class("dino-chatinput-button"); - - // Emoji button for emoji picker (recents don't work < 3.22.19, category icons don't work <3.23.2) - if (Gtk.get_major_version() >= 3 && Gtk.get_minor_version() >= 24) { - MenuButton emoji_button = new MenuButton() { relief=ReliefStyle.NONE, margin_top=3, valign=Align.START, visible=true }; - emoji_button.get_style_context().add_class("flat"); - emoji_button.get_style_context().add_class("dino-chatinput-button"); - emoji_button.image = new Image.from_icon_name("dino-emoticon-symbolic", IconSize.BUTTON) { visible=true }; - - EmojiChooser chooser = new EmojiChooser(); - chooser.emoji_picked.connect((emoji) => { - chat_text_view.text_view.buffer.insert_at_cursor(emoji, emoji.data.length); - }); - emoji_button.set_popover(chooser); - - outer_box.add(emoji_button); - } - - outer_box.add(encryption_widget); + EmojiChooser chooser = new EmojiChooser(); + chooser.emoji_picked.connect((emoji) => { + chat_text_view.text_view.buffer.insert_at_cursor(emoji, emoji.data.length); + }); + emoji_button.set_popover(chooser); Util.force_css(frame, "* { border-radius: 3px; }"); -- cgit v1.2.3-54-g00ecf