mention: highlight own username in mentions using pango attributes
This commit is contained in:
parent
38d2d01546
commit
f92387cddd
1 changed files with 96 additions and 0 deletions
|
@ -219,10 +219,38 @@ impl<'a> MessageBox<'a> {
|
|||
fn build_room_msg_body(&self, body: &str) -> gtk::Box {
|
||||
let bx = gtk::Box::new(gtk::Orientation::Horizontal, 0);
|
||||
let msg = gtk::Label::new("");
|
||||
let uname = self.op.username.clone().unwrap_or_default();
|
||||
|
||||
msg.set_markup(&markup_text(body));
|
||||
self.set_label_styles(&msg);
|
||||
|
||||
if String::from(body).contains(&uname) {
|
||||
|
||||
let name = uname.clone();
|
||||
msg.connect_property_cursor_position_notify(move |w| {
|
||||
if let Some(text) = w.get_text() {
|
||||
if let Some(attr) = highlight_username(w.clone(), &name, text) {
|
||||
w.set_attributes(&attr);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let name = uname.clone();
|
||||
msg.connect_property_selection_bound_notify(move |w| {
|
||||
if let Some(text) = w.get_text() {
|
||||
if let Some(attr) = highlight_username(w.clone(), &name, text) {
|
||||
w.set_attributes(&attr);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(text) = msg.get_text() {
|
||||
if let Some(attr) = highlight_username(msg.clone(), &uname, text) {
|
||||
msg.set_attributes(&attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bx.add(&msg);
|
||||
bx
|
||||
}
|
||||
|
@ -336,3 +364,71 @@ impl<'a> MessageBox<'a> {
|
|||
bx
|
||||
}
|
||||
}
|
||||
|
||||
fn highlight_username(label: gtk::Label, alias: &String, input: String) -> Option<pango::AttrList> {
|
||||
fn contains((start, end): (i32, i32), item: i32) -> bool {
|
||||
match start <= end {
|
||||
true => start <= item && end > item,
|
||||
false => start <= item || end > item,
|
||||
}
|
||||
}
|
||||
|
||||
let input = input.to_lowercase();
|
||||
let bounds = label.get_selection_bounds();
|
||||
let context = gtk::Widget::get_style_context (&label.clone().upcast::<gtk::Widget>())?;
|
||||
let fg = gtk::StyleContext::lookup_color (&context, "theme_selected_bg_color")?;
|
||||
let red = fg.red * 65535. + 0.5;
|
||||
let green = fg.green * 65535. + 0.5;
|
||||
let blue = fg.blue * 65535. + 0.5;
|
||||
let color = pango::Attribute::new_foreground(red as u16, green as u16, blue as u16)?;
|
||||
|
||||
let attr = pango::AttrList::new();
|
||||
let mut input = input.clone();
|
||||
let alias = &alias.to_lowercase();
|
||||
let mut removed_char = 0;
|
||||
while input.contains(alias) {
|
||||
let pos = {
|
||||
let start = input.find(alias)? as i32;
|
||||
(start, start + alias.len() as i32)
|
||||
};
|
||||
let mut color = color.clone();
|
||||
let mark_start = removed_char as i32 + pos.0;
|
||||
let mark_end = removed_char as i32 + pos.1;
|
||||
let mut final_pos = Some((mark_start, mark_end));
|
||||
/* exclude selected text */
|
||||
if let Some((bounds_start, bounds_end)) = bounds {
|
||||
/* If the selection is within the alias */
|
||||
if contains((mark_start, mark_end), bounds_start) &&
|
||||
contains((mark_start, mark_end), bounds_end) {
|
||||
final_pos = Some((mark_start, bounds_start));
|
||||
/* Add blue color after a selection */
|
||||
let mut color = color.clone();
|
||||
color.set_start_index(bounds_end as u32);
|
||||
color.set_end_index(mark_end as u32);
|
||||
attr.insert(color);
|
||||
} else {
|
||||
/* The alias starts inside a selection */
|
||||
if contains(bounds?, mark_start) {
|
||||
final_pos = Some((bounds_end, final_pos?.1));
|
||||
}
|
||||
/* The alias ends inside a selection */
|
||||
if contains(bounds?, mark_end - 1) {
|
||||
final_pos = Some((final_pos?.0, bounds_start));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((start, end)) = final_pos {
|
||||
color.set_start_index(start as u32);
|
||||
color.set_end_index(end as u32);
|
||||
attr.insert(color);
|
||||
}
|
||||
{
|
||||
let end = pos.1 as usize;
|
||||
input.drain(0..end);
|
||||
}
|
||||
removed_char = removed_char + pos.1 as u32;
|
||||
}
|
||||
|
||||
Some(attr)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue