[fractal/get-widgets-from-ui-struct: 6/6] Access direct_chat_dialog widget and children directly
- From: Alejandro Domínguez <aledomu src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [fractal/get-widgets-from-ui-struct: 6/6] Access direct_chat_dialog widget and children directly
- Date: Mon, 14 Dec 2020 23:01:24 +0000 (UTC)
commit a11a1f72eb8caab7ad5db751babaccedcc22e1c0
Author: Alejandro Domínguez <adomu net-c com>
Date: Thu Dec 10 19:57:23 2020 +0100
Access direct_chat_dialog widget and children directly
fractal-gtk/res/ui/direct_chat.ui | 1 -
fractal-gtk/src/meson.build | 1 -
fractal-gtk/src/ui/connect/direct.rs | 125 ---------------------
fractal-gtk/src/ui/connect/mod.rs | 3 +-
fractal-gtk/src/ui/invite.rs | 4 +-
fractal-gtk/src/ui/member.rs | 40 +++----
fractal-gtk/src/ui/mod.rs | 7 +-
fractal-gtk/src/ui/start_chat.rs | 203 ++++++++++++++++++++++++++++-------
8 files changed, 189 insertions(+), 195 deletions(-)
---
diff --git a/fractal-gtk/res/ui/direct_chat.ui b/fractal-gtk/res/ui/direct_chat.ui
index 65940eed..2726f8e1 100644
--- a/fractal-gtk/res/ui/direct_chat.ui
+++ b/fractal-gtk/res/ui/direct_chat.ui
@@ -13,7 +13,6 @@
<property name="type_hint">dialog</property>
<property name="deletable">False</property>
<property name="gravity">center</property>
- <property name="transient_for">main_window</property>
<child internal-child="vbox">
<object class="GtkBox">
<property name="can_focus">False</property>
diff --git a/fractal-gtk/src/meson.build b/fractal-gtk/src/meson.build
index 2ec9d8b3..5b36427b 100644
--- a/fractal-gtk/src/meson.build
+++ b/fractal-gtk/src/meson.build
@@ -86,7 +86,6 @@ app_sources = files(
'model/room.rs',
'ui/connect/autocomplete.rs',
'ui/connect/directory.rs',
- 'ui/connect/direct.rs',
'ui/connect/headerbar.rs',
'ui/connect/invite.rs',
'ui/connect/join_room.rs',
diff --git a/fractal-gtk/src/ui/connect/mod.rs b/fractal-gtk/src/ui/connect/mod.rs
index f7e64b55..f69a4130 100644
--- a/fractal-gtk/src/ui/connect/mod.rs
+++ b/fractal-gtk/src/ui/connect/mod.rs
@@ -1,5 +1,4 @@
mod autocomplete;
-mod direct;
mod directory;
mod headerbar;
mod invite;
@@ -30,7 +29,7 @@ impl UI {
.connect(&self.builder, &self.main_window, app_runtime.clone());
invite::connect_dialog(self, app_runtime.clone());
invite::connect_user(self, app_runtime.clone());
- direct::connect(self, app_runtime.clone());
+ self.direct_chat_dialog.connect(app_runtime.clone());
roomlist_search::connect(self, app_runtime);
swipeable_widgets::connect(self);
}
diff --git a/fractal-gtk/src/ui/invite.rs b/fractal-gtk/src/ui/invite.rs
index db391f9e..a8dd3362 100644
--- a/fractal-gtk/src/ui/invite.rs
+++ b/fractal-gtk/src/ui/invite.rs
@@ -43,9 +43,7 @@ impl UI {
}
}
- if let Some(btn) = self.builder.get_object::<gtk::Button>("direct_chat_button") {
- btn.set_sensitive(true)
- }
+ self.direct_chat_dialog.button.set_sensitive(true);
if let Some(btn) = self.builder.get_object::<gtk::Button>("invite_button") {
btn.set_sensitive(true)
diff --git a/fractal-gtk/src/ui/member.rs b/fractal-gtk/src/ui/member.rs
index 795fa2e6..1747727d 100644
--- a/fractal-gtk/src/ui/member.rs
+++ b/fractal-gtk/src/ui/member.rs
@@ -24,28 +24,30 @@ impl UI {
users: Vec<Member>,
search_type: SearchType,
) {
- let (entry_label, listbox_label, scroll_label) = match search_type {
- SearchType::Invite => ("invite_entry", "user_search_box", "user_search_scroll"),
+ let (entry, listbox, scroll) = match search_type {
+ SearchType::Invite => {
+ let entry = self
+ .builder
+ .get_object::<gtk::TextView>("invite_entry")
+ .expect("Can't find invite_entry in ui file.");
+ let listbox = self
+ .builder
+ .get_object::<gtk::ListBox>("user_search_box")
+ .expect("Can't find user_search_box in ui file.");
+ let scroll = self
+ .builder
+ .get_object::<gtk::ScrolledWindow>("user_search_scroll")
+ .expect("Can't find user_search_scroll in ui file.");
+
+ (entry, listbox, scroll)
+ }
SearchType::DirectChat => (
- "to_chat_entry",
- "direct_chat_search_box",
- "direct_chat_search_scroll",
+ self.direct_chat_dialog.to_chat_entry.clone(),
+ self.direct_chat_dialog.search_box.clone(),
+ self.direct_chat_dialog.search_scroll.clone(),
),
};
- let entry = self
- .builder
- .get_object::<gtk::TextView>(entry_label)
- .expect("Can't find invite_entry in ui file.");
- let listbox = self
- .builder
- .get_object::<gtk::ListBox>(listbox_label)
- .expect("Can't find user_search_box in ui file.");
- let scroll = self
- .builder
- .get_object::<gtk::Widget>(scroll_label)
- .expect("Can't find user_search_scroll in ui file.");
-
if let Some(buffer) = entry.get_buffer() {
let start = buffer.get_start_iter();
let end = buffer.get_end_iter();
@@ -73,7 +75,7 @@ fn search_finished(
rooms: &RoomList,
mut users: Vec<Member>,
listbox: gtk::ListBox,
- scroll: gtk::Widget,
+ scroll: gtk::ScrolledWindow,
term: Option<String>,
) {
for ch in listbox.get_children().iter() {
diff --git a/fractal-gtk/src/ui/mod.rs b/fractal-gtk/src/ui/mod.rs
index 3a8d9219..04d464e0 100644
--- a/fractal-gtk/src/ui/mod.rs
+++ b/fractal-gtk/src/ui/mod.rs
@@ -36,6 +36,7 @@ pub struct UI {
pub leaflet: libhandy::Leaflet,
pub deck: libhandy::Deck,
pub account_settings: account::AccountSettings,
+ pub direct_chat_dialog: start_chat::DirectChatDialog,
}
impl UI {
@@ -89,9 +90,6 @@ impl UI {
// Depends on main_window
// These are all dialogs transient for main_window
- builder
- .add_from_resource("/org/gnome/Fractal/ui/direct_chat.ui")
- .expect("Can't load ui file: direct_chat.ui");
builder
.add_from_resource("/org/gnome/Fractal/ui/invite.ui")
.expect("Can't load ui file: invite.ui");
@@ -125,6 +123,8 @@ impl UI {
.get_object::<libhandy::Deck>("main_deck")
.expect("Couldn't find main_deck in ui file");
+ let direct_chat_dialog = start_chat::DirectChatDialog::new(&main_window);
+
UI {
builder,
gtk_app,
@@ -140,6 +140,7 @@ impl UI {
leaflet,
deck,
account_settings,
+ direct_chat_dialog,
}
}
diff --git a/fractal-gtk/src/ui/start_chat.rs b/fractal-gtk/src/ui/start_chat.rs
index a0b79a38..6e13a440 100644
--- a/fractal-gtk/src/ui/start_chat.rs
+++ b/fractal-gtk/src/ui/start_chat.rs
@@ -1,60 +1,181 @@
use super::UI;
+use crate::app::AppRuntime;
+use glib::clone;
+use glib::source::Continue;
use gtk::prelude::*;
+use std::sync::{Arc, Mutex};
-impl UI {
- pub fn show_direct_chat_dialog(&self) {
- let dialog = self
- .builder
- .get_object::<gtk::Dialog>("direct_chat_dialog")
+pub struct DirectChatDialog {
+ pub root: gtk::Dialog,
+ pub cancel: gtk::Button,
+ pub button: gtk::Button,
+ pub to_chat_entry_box: gtk::Box,
+ pub to_chat_entry: gtk::TextView,
+ pub search_scroll: gtk::ScrolledWindow,
+ pub search_box: gtk::ListBox,
+}
+
+impl DirectChatDialog {
+ pub fn new(parent: &libhandy::ApplicationWindow) -> Self {
+ let builder = gtk::Builder::from_resource("/org/gnome/Fractal/ui/direct_chat.ui");
+ let root: gtk::Dialog = builder
+ .get_object("direct_chat_dialog")
.expect("Can't find direct_chat_dialog in ui file.");
- let scroll = self
- .builder
- .get_object::<gtk::Widget>("direct_chat_search_scroll")
- .expect("Can't find direct_chat_search_scroll in ui file.");
- if let Some(btn) = self.builder.get_object::<gtk::Button>("direct_chat_button") {
- btn.set_sensitive(false)
+ root.set_transient_for(Some(parent));
+
+ Self {
+ root,
+ cancel: builder
+ .get_object("cancel_direct_chat")
+ .expect("Can't find cancel_direct_chat in ui file."),
+ button: builder
+ .get_object("direct_chat_button")
+ .expect("Can't find direct_chat_button in ui file."),
+ to_chat_entry_box: builder
+ .get_object("to_chat_entry_box")
+ .expect("Can't find to_chat_entry_box in ui file."),
+ to_chat_entry: builder
+ .get_object("to_chat_entry")
+ .expect("Can't find to_chat_entry in ui file."),
+ search_scroll: builder
+ .get_object("direct_chat_search_scroll")
+ .expect("Can't find search_scroll in ui file."),
+ search_box: builder
+ .get_object("direct_chat_search_box")
+ .expect("Can't find direct_chat_search_box in ui file."),
}
- dialog.present();
- scroll.hide();
}
- pub fn close_direct_chat_dialog(&mut self) {
- let listbox = self
- .builder
- .get_object::<gtk::ListBox>("direct_chat_search_box")
- .expect("Can't find direct_chat_search_box in ui file.");
- let scroll = self
- .builder
- .get_object::<gtk::Widget>("direct_chat_search_scroll")
- .expect("Can't find direct_chat_search_scroll in ui file.");
- let to_chat_entry = self
- .builder
- .get_object::<gtk::TextView>("to_chat_entry")
- .expect("Can't find to_chat_entry in ui file.");
- let entry = self
- .builder
- .get_object::<gtk::TextView>("to_chat_entry")
- .expect("Can't find to_chat_entry in ui file.");
- let dialog = self
- .builder
- .get_object::<gtk::Dialog>("direct_chat_dialog")
- .expect("Can't find direct_chat_dialog in ui file.");
+ pub fn connect(&self, app_runtime: AppRuntime) {
+ if let Some(buffer) = self.to_chat_entry.get_buffer() {
+ let placeholder_tag = gtk::TextTag::new(Some("placeholder"));
+
+ placeholder_tag.set_property_foreground_rgba(Some(&gdk::RGBA {
+ red: 1.0,
+ green: 1.0,
+ blue: 1.0,
+ alpha: 0.5,
+ }));
+
+ if let Some(tag_table) = buffer.get_tag_table() {
+ tag_table.add(&placeholder_tag);
+ }
+ }
+
+ // this is used to cancel the timeout and not search for every key input. We'll wait 500ms
+ // without key release event to launch the search
+ let source_id: Arc<Mutex<Option<glib::source::SourceId>>> = Arc::new(Mutex::new(None));
+ self.to_chat_entry.connect_key_release_event(clone!(@strong app_runtime => move |entry, _| {
+ {
+ let mut id = source_id.lock().unwrap();
+ if let Some(sid) = id.take() {
+ glib::source::source_remove(sid);
+ }
+ }
+
+ let sid = glib::timeout_add_local(
+ 500,
+ clone!(
+ @strong entry,
+ @strong source_id,
+ @strong app_runtime
+ => move || {
+ if let Some(buffer) = entry.get_buffer() {
+ let start = buffer.get_start_iter();
+ let end = buffer.get_end_iter();
+
+ if let Some(text) =
+ buffer.get_text(&start, &end, false).map(|gstr| gstr.to_string())
+ {
+ app_runtime.update_state_with(|state| state.search_invite_user(text));
+ }
+ }
+
+ *(source_id.lock().unwrap()) = None;
+ Continue(false)
+ }),
+ );
+
+ *(source_id.lock().unwrap()) = Some(sid);
+ glib::signal::Inhibit(false)
+ }));
+
+ self.to_chat_entry.connect_focus_in_event(clone!(
+ @strong self.to_chat_entry_box as to_chat_entry_box,
+ @strong app_runtime
+ => move |_, _| {
+ to_chat_entry_box.get_style_context().add_class("message-input-focused");
+ app_runtime.update_state_with(|state| state.remove_invite_user_dialog_placeholder());
+
+ Inhibit(false)
+ }
+ ));
+
+ self.to_chat_entry.connect_focus_out_event(clone!(
+ @strong self.to_chat_entry_box as to_chat_entry_box,
+ @strong app_runtime
+ => move |_, _| {
+ to_chat_entry_box.get_style_context().remove_class("message-input-focused");
+
+ app_runtime.update_state_with(|state| state.set_invite_user_dialog_placeholder());
+
+ Inhibit(false)
+ }
+ ));
+
+ if let Some(buffer) = self.to_chat_entry.get_buffer() {
+ buffer.connect_delete_range(clone!(@strong app_runtime => move |_, _, _| {
+ glib::idle_add_local(clone!(@strong app_runtime => move || {
+ app_runtime.update_state_with(|state| state.detect_removed_invite());
+ Continue(false)
+ }));
+ }));
+ }
+
+ self.root
+ .connect_delete_event(clone!(@strong app_runtime => move |_, _| {
+ app_runtime.update_state_with(|state| state.ui.close_direct_chat_dialog());
+ glib::signal::Inhibit(true)
+ }));
+ self.cancel
+ .connect_clicked(clone!(@strong app_runtime => move |_| {
+ app_runtime.update_state_with(|state| state.ui.close_direct_chat_dialog());
+ }));
+ self.button.set_sensitive(false);
+ self.button.connect_clicked(move |_| {
+ app_runtime.update_state_with(|state| state.start_chat());
+ });
+ }
+
+ pub fn show(&self) {
+ self.button.set_sensitive(false);
+ self.root.present();
+ self.search_scroll.hide();
+ }
+}
+
+impl UI {
+ pub fn show_direct_chat_dialog(&self) {
+ self.direct_chat_dialog.show();
+ }
+
+ pub fn close_direct_chat_dialog(&mut self) {
self.invite_list = vec![];
- if let Some(buffer) = to_chat_entry.get_buffer() {
+ if let Some(buffer) = self.direct_chat_dialog.to_chat_entry.get_buffer() {
let mut start = buffer.get_start_iter();
let mut end = buffer.get_end_iter();
buffer.delete(&mut start, &mut end);
}
- for ch in listbox.get_children().iter() {
- listbox.remove(ch);
+ for ch in self.direct_chat_dialog.search_box.get_children().iter() {
+ self.direct_chat_dialog.search_box.remove(ch);
}
- scroll.hide();
- if let Some(buffer) = entry.get_buffer() {
+ self.direct_chat_dialog.search_scroll.hide();
+ if let Some(buffer) = self.direct_chat_dialog.to_chat_entry.get_buffer() {
buffer.set_text("");
}
- dialog.hide();
- dialog.resize(300, 200);
+ self.direct_chat_dialog.root.hide();
+ self.direct_chat_dialog.root.resize(300, 200);
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]