using Gee; using Gdk; using Gtk; using Dino.Entities; using Xmpp.Xep; namespace Dino.Ui.Util { public class MultilineEntryRow : Adw.PreferencesRow { public signal void apply(); public string text { owned get { return text_view.buffer.text; } set { if (text_view.buffer.text == value) return; updating_text = true; text_view.buffer.text = value; updating_text = false; apply_button.visible = false; } } public TextView text_view { get; private set; } private Button apply_button; private bool updating_text = false; public MultilineEntryRow(string title) { Object(title: title); var title_label = new Label(title) { xalign = 0, hexpand = true }; apply_button = new Button.from_icon_name("object-select-symbolic") { valign = Align.CENTER, tooltip_text = _("Apply"), visible = false }; apply_button.add_css_class("flat"); apply_button.clicked.connect(() => { apply_button.visible = false; apply(); }); var header = new Box(Orientation.HORIZONTAL, 6); header.append(title_label); header.append(apply_button); text_view = new TextView() { wrap_mode = WrapMode.WORD_CHAR, accepts_tab = false, hexpand = true, left_margin = 6, right_margin = 6, top_margin = 6, bottom_margin = 6 }; text_view.buffer.changed.connect(() => { if (updating_text) return; apply_button.visible = true; notify_property("text"); }); var text_frame = new Frame(null) { child = text_view, hexpand = true }; var box = new Box(Orientation.VERTICAL, 6) { hexpand = true, margin_start = 12, margin_end = 12, margin_top = 6, margin_bottom = 6 }; box.append(header); box.append(text_frame); child = box; } } public Gee.List rows_to_preference_window_split_at_text(GLib.ListStore row_view_models) { var preference_groups = new ArrayList(); Adw.PreferencesGroup? preference_group = null; for (int preference_group_i = 0; preference_group_i < row_view_models.get_n_items(); preference_group_i++) { var preferences_row = (ViewModel.PreferencesRow.Any) row_view_models.get_item(preference_group_i); // If it's a text, start a new PreferencesGroup with the text as title. Else, add an item to the current group. var preferences_row_text = preferences_row as ViewModel.PreferencesRow.Text; if (preferences_row_text != null) { if (preference_group != null) preference_groups.add(preference_group); preference_group = new Adw.PreferencesGroup() { title=preferences_row_text.text }; } else { if (preference_group == null) { preference_group = new Adw.PreferencesGroup(); } Widget? w = row_to_preference_row(preferences_row); if (w == null) continue; preference_group.add(w); } } return preference_groups; } public Adw.PreferencesGroup rows_to_preference_group(GLib.ListStore row_view_models, string title) { var preference_group = new Adw.PreferencesGroup() { title=title }; for (int preference_group_i = 0; preference_group_i < row_view_models.get_n_items(); preference_group_i++) { var preferences_row = (ViewModel.PreferencesRow.Any) row_view_models.get_item(preference_group_i); Widget? w = row_to_preference_row(preferences_row); if (w == null) continue; preference_group.add(w); } return preference_group; } private static bool null_string_to_empty(GLib.Binding binding, GLib.Value from_value, ref GLib.Value to_value) { var str = (string) from_value; to_value = str ?? ""; return true; } public Adw.PreferencesRow? row_to_preference_row(ViewModel.PreferencesRow.Any preferences_row) { Adw.PreferencesRow? view = null; var entry_view_model = preferences_row as ViewModel.PreferencesRow.Entry; if (entry_view_model != null) { view = new Adw.EntryRow() { show_apply_button=true }; if (preferences_row.media_uri != null) { var bytes = Xmpp.get_data_for_uri(preferences_row.media_uri); Picture picture = new Picture.for_paintable(Texture.from_bytes(bytes)); ((Adw.EntryRow) view).add_suffix(picture); } entry_view_model.bind_property("text", view, "text", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL, null_string_to_empty); ((Adw.EntryRow) view).apply.connect(() => { entry_view_model.changed(); }); } var multiline_entry_view_model = preferences_row as ViewModel.PreferencesRow.MultilineEntry; if (multiline_entry_view_model != null) { var multiline_entry_row = new MultilineEntryRow(preferences_row.title); multiline_entry_view_model.bind_property("text", multiline_entry_row, "text", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL, null_string_to_empty); multiline_entry_row.apply.connect(() => { multiline_entry_view_model.changed(); }); view = multiline_entry_row; } var password_view_model = preferences_row as ViewModel.PreferencesRow.PrivateText; if (password_view_model != null) { view = new Adw.PasswordEntryRow() { show_apply_button=true }; password_view_model.bind_property("text", view, "text", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL, null_string_to_empty); ((Adw.EntryRow) view).apply.connect(() => { password_view_model.changed(); }); } var row_text = preferences_row as ViewModel.PreferencesRow.Text; if (row_text != null) { view = new Adw.ActionRow() { subtitle_selectable = true }; row_text.bind_property("text", view, "subtitle", BindingFlags.SYNC_CREATE, null_string_to_empty); view.add_css_class("property"); } var toggle_view_model = preferences_row as ViewModel.PreferencesRow.Toggle; if (toggle_view_model != null) { view = new Adw.SwitchRow(); toggle_view_model.bind_property("subtitle", view, "subtitle", BindingFlags.SYNC_CREATE, null_string_to_empty); toggle_view_model.bind_property("state", view, "active", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL); } var combobox_view_model = preferences_row as ViewModel.PreferencesRow.ComboBox; if (combobox_view_model != null) { var string_list = new StringList(null); foreach (string text in combobox_view_model.items) { string_list.append(text); } view = new Adw.ComboRow(); combobox_view_model.bind_property("subtitle", view, "subtitle", BindingFlags.SYNC_CREATE, null_string_to_empty); ((Adw.ComboRow)view).model = string_list; combobox_view_model.bind_property("active-item", view, "selected", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL); } var button_view_model = preferences_row as ViewModel.PreferencesRow.Button; if (button_view_model != null) { view = new Adw.ActionRow(); button_view_model.bind_property("subtitle", view, "subtitle", BindingFlags.SYNC_CREATE, null_string_to_empty); var button = new Button.with_label(button_view_model.button_text) { valign = Align.CENTER }; ((Adw.ActionRow)view).add_suffix(button); button.clicked.connect(() => button_view_model.clicked()); } preferences_row.bind_property("title", view, "title", BindingFlags.SYNC_CREATE); preferences_row.bind_property("visible", view, "visible", BindingFlags.SYNC_CREATE); return view; } }