Commit 5d8ce756 authored by Eisha Chen-yen-su's avatar Eisha Chen-yen-su

Invite: Give the `GtkTextView` the appearance of a `GtkEntry`

See #78
parent e603c33a
extern crate gdk;
extern crate gtk;
use self::gtk::prelude::*;
......@@ -19,10 +20,31 @@ impl App {
let entry = self.ui.builder
.get_object::<gtk::Entry>("to_chat_entry")
.expect("Can't find to_chat_entry in ui file.");
let to_chat_textview_box = self.ui.builder
.get_object::<gtk::Box>("to_chat_textview_box")
.expect("Can't find to_chat_textview_box in ui file.");
let to_chat_textview = self.ui.builder
.get_object::<gtk::TextView>("to_chat_textview")
.expect("Can't find to_chat_textview in ui file.");
let dialog = self.ui.builder
.get_object::<gtk::Dialog>("direct_chat_dialog")
.expect("Can't find direct_chat_dialog in ui file.");
if let Some(buffer) = to_chat_textview.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));
......@@ -44,6 +66,35 @@ impl App {
glib::signal::Inhibit(false)
}));
to_chat_textview.connect_focus_in_event(clone!(op, to_chat_textview_box => move |_, _| {
if let Some(style) = to_chat_textview_box.get_style_context() {
style.add_class("message-input-focused");
}
op.lock().unwrap().remove_invite_user_dialog_placeholder();
Inhibit(false)
}));
to_chat_textview.connect_focus_out_event(clone!(op, to_chat_textview_box => move |_, _| {
if let Some(style) = to_chat_textview_box.get_style_context() {
style.remove_class("message-input-focused");
}
op.lock().unwrap().set_invite_user_dialog_placeholder();
Inhibit(false)
}));
if let Some(buffer) = to_chat_textview.get_buffer() {
buffer.connect_delete_range(clone!( op => move |_, _, _| {
gtk::idle_add(clone!(op => move || {
op.lock().unwrap().detect_removed_invite();
Continue(false)
}));
}));
}
dialog.connect_delete_event(clone!(op => move |_, _| {
op.lock().unwrap().close_direct_chat_dialog();
glib::signal::Inhibit(true)
......
extern crate gdk;
extern crate gtk;
use self::gtk::prelude::*;
......@@ -44,9 +45,9 @@ impl App {
let invite = self.ui.builder
.get_object::<gtk::Button>("invite_button")
.expect("Can't find invite_button in ui file.");
let to_chat_textview = self.ui.builder
.get_object::<gtk::TextView>("to_chat_textview")
.expect("Can't find to_chat_textview in ui file.");
let invite_textview_box = self.ui.builder
.get_object::<gtk::Box>("invite_textview_box")
.expect("Can't find invite_textview_box in ui file.");
let invite_textview = self.ui.builder
.get_object::<gtk::TextView>("invite_textview")
.expect("Can't find invite_textview in ui file.");
......@@ -57,34 +58,21 @@ impl App {
.get_object::<gtk::Dialog>("invite_user_dialog")
.expect("Can't find invite_user_dialog in ui file.");
// 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));
to_chat_textview.connect_key_release_event(clone!(op => move |entry, _| {
{
let mut id = source_id.lock().unwrap();
if let Some(sid) = id.take() {
glib::source::source_remove(sid);
}
}
let sid = gtk::timeout_add(500, clone!(op, entry, source_id => move || {
if let Some(buffer) = entry.get_buffer() {
let start = buffer.get_start_iter();
let end = buffer.get_end_iter();
let text = buffer.get_text(&start, &end, false);
op.lock().unwrap().search_invite_user(text);
}
if let Some(buffer) = invite_textview.get_buffer() {
let placeholder_tag = gtk::TextTag::new(Some("placeholder"));
*(source_id.lock().unwrap()) = None;
gtk::Continue(false)
placeholder_tag.set_property_foreground_rgba(Some(&gdk::RGBA {
red: 1.0,
green: 1.0,
blue: 1.0,
alpha: 0.5,
}));
*(source_id.lock().unwrap()) = Some(sid);
glib::signal::Inhibit(false)
}));
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));
......@@ -122,6 +110,10 @@ impl App {
if let Some(sid) = id.take() {
glib::source::source_remove(sid);
}
invite_textview.connect_focus_in_event(clone!(op, invite_textview_box => move |_, _| {
if let Some(style) = invite_textview_box.get_style_context() {
style.add_class("message-input-focused");
}
let sid = gtk::timeout_add(500, clone!(op, entry, source_id => move || {
......@@ -129,19 +121,22 @@ impl App {
*(source_id.lock().unwrap()) = None;
gtk::Continue(false)
}));
op.lock().unwrap().remove_invite_user_dialog_placeholder();
*(source_id.lock().unwrap()) = Some(sid);
glib::signal::Inhibit(false)
Inhibit(false)
}));
if let Some(buffer) = to_chat_textview.get_buffer() {
buffer.connect_delete_range(clone!( op => move |_, _, _| {
gtk::idle_add(clone!(op => move || {
op.lock().unwrap().detect_removed_invite();
Continue(false)
}));
}));
}
invite_textview.connect_focus_out_event(clone!(op, invite_textview_box => move |_, _| {
if let Some(style) = invite_textview_box.get_style_context() {
style.remove_class("message-input-focused");
}
op.lock().unwrap().set_invite_user_dialog_placeholder();
Inhibit(false)
}));
if let Some(buffer) = invite_textview.get_buffer() {
buffer.connect_delete_range(clone!( op => move |_, _, _| {
......
......@@ -10,6 +10,8 @@ use appop::member::SearchType;
use app::InternalCommand;
use backend::BKCommand;
use globals;
use widgets;
use types::Member;
......@@ -141,6 +143,9 @@ impl AppOp {
}
}
}
self.set_invite_user_dialog_placeholder();
dialog.present();
scroll.hide();
}
......@@ -227,4 +232,58 @@ impl AppOp {
self.invitation_roomid = Some(r.id.clone());
dialog.present();
}
pub fn set_invite_user_dialog_placeholder(&mut self) {
let textviewid = match self.search_type {
SearchType::Invite => "invite_textview",
SearchType::DirectChat => "to_chat_textview",
};
let to_invite_textview = self.ui.builder
.get_object::<gtk::TextView>(textviewid)
.expect("Can't find to_invite_textview in ui file.");
if let Some(buffer) = to_invite_textview.get_buffer() {
let start = buffer.get_start_iter();
let end = buffer.get_end_iter();
if let Some(text) = buffer.get_text(&start, &end, true) {
if text.is_empty() && self.invite_list.is_empty() {
buffer.set_text(globals::PLACEHOLDER_TEXT);
let start = buffer.get_start_iter();
let end = buffer.get_end_iter();
buffer.apply_tag_by_name("placeholder", &start, &end);
}
}
}
}
pub fn remove_invite_user_dialog_placeholder(&mut self) {
let textviewid = match self.search_type {
SearchType::Invite => "invite_textview",
SearchType::DirectChat => "to_chat_textview",
};
let to_invite_textview = self.ui.builder
.get_object::<gtk::TextView>(textviewid)
.expect("Can't find to_invite_textview in ui file.");
if let Some(buffer) = to_invite_textview.get_buffer() {
let mut start = buffer.get_start_iter();
let mut end = buffer.get_end_iter();
if let Some(text) = buffer.get_text(&start, &end, true) {
if text == globals::PLACEHOLDER_TEXT && self.invite_list.is_empty() {
buffer.set_text("");
let start = buffer.get_start_iter();
let end = buffer.get_end_iter();
buffer.remove_tag_by_name("placeholder", &start, &end);
}
}
}
}
}
......@@ -6,6 +6,7 @@ pub static PILL_ICON_SIZE: i32 = 18;
pub static MINUTES_TO_SPLIT_MSGS: i64 = 30;
pub static DEFAULT_HOMESERVER: &'static str = "https://matrix.org";
pub static DEFAULT_IDENTITYSERVER: &'static str = "https://vector.im";
pub static PLACEHOLDER_TEXT: &'static str = "Matrix username, email or phone number";
pub static MAX_IMAGE_SIZE: (i32, i32) = (600, 400);
pub static MAX_STICKER_SIZE: (i32, i32) = (200, 130);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment