Browse Source

label-with-widgets: Only invalidate children when necessary

merge-requests/1327/merge
Kévin Commaille 3 years ago
parent
commit
3f8a7e8bd0
No known key found for this signature in database
GPG Key ID: 29A48C1F03620416
  1. 72
      src/components/label_with_widgets.rs

72
src/components/label_with_widgets.rs

@ -1,4 +1,4 @@
use gtk::{glib, glib::clone, pango, prelude::*, subclass::prelude::*}; use gtk::{glib, pango, prelude::*, subclass::prelude::*};
pub const DEFAULT_PLACEHOLDER: &str = "<widget>"; pub const DEFAULT_PLACEHOLDER: &str = "<widget>";
const OBJECT_REPLACEMENT_CHARACTER: &str = "\u{FFFC}"; const OBJECT_REPLACEMENT_CHARACTER: &str = "\u{FFFC}";
@ -84,12 +84,6 @@ mod imp {
label.set_xalign(0.0); label.set_xalign(0.0);
label.set_valign(gtk::Align::Start); label.set_valign(gtk::Align::Start);
label.add_css_class("line-height"); label.add_css_class("line-height");
label.connect_notify_local(
Some("label"),
clone!(@weak obj => move |_, _| {
obj.invalidate_child_widgets();
}),
);
} }
fn dispose(&self) { fn dispose(&self) {
@ -217,11 +211,24 @@ impl LabelWithWidgets {
fn invalidate_child_widgets(&self) { fn invalidate_child_widgets(&self) {
self.imp().widgets_sizes.borrow_mut().clear(); self.imp().widgets_sizes.borrow_mut().clear();
self.allocate_shapes();
self.queue_resize(); self.queue_resize();
} }
fn allocate_shapes(&self) { fn allocate_shapes(&self) {
let imp = self.imp(); let imp = self.imp();
if imp.text.borrow().as_ref().map_or(true, |s| s.is_empty()) {
// No need to compute shapes if the label is empty.
return;
}
if imp.widgets.borrow().is_empty() {
// There should be no attributes if there are no widgets.
imp.label.set_attributes(None);
return;
}
let mut widgets_sizes = imp.widgets_sizes.borrow_mut(); let mut widgets_sizes = imp.widgets_sizes.borrow_mut();
let mut child_size_changed = false; let mut child_size_changed = false;
@ -340,34 +347,41 @@ impl LabelWithWidgets {
fn update_label(&self) { fn update_label(&self) {
let imp = self.imp(); let imp = self.imp();
if self.ellipsize() { let old_label = imp.label.text();
// Workaround: if both wrap and ellipsize are set, and there are let old_ellipsize = imp.label.ellipsize() == pango::EllipsizeMode::End;
// widgets inserted, GtkLabel reports an erroneous minimum width. let new_ellipsize = self.ellipsize();
imp.label.set_wrap(false);
imp.label.set_ellipsize(pango::EllipsizeMode::End); let new_label = if let Some(label) = imp.text.borrow().as_ref() {
let placeholder = imp.placeholder.borrow();
if let Some(label) = imp.text.borrow().as_ref() { let placeholder = placeholder.as_deref().unwrap_or(DEFAULT_PLACEHOLDER);
let placeholder = imp.placeholder.borrow(); let label = label.replace(placeholder, OBJECT_REPLACEMENT_CHARACTER);
let placeholder = placeholder.as_deref().unwrap_or(DEFAULT_PLACEHOLDER);
let label = label.replace(placeholder, OBJECT_REPLACEMENT_CHARACTER); if new_ellipsize {
let label = if let Some(pos) = label.find('\n') { if let Some(pos) = label.find('\n') {
format!("{}…", &label[0..pos]) format!("{}…", &label[0..pos])
} else { } else {
label label
}; }
imp.label.set_label(&label); } else {
label
} }
} else { } else {
imp.label.set_wrap(true); String::new()
imp.label.set_ellipsize(pango::EllipsizeMode::None); };
if let Some(label) = imp.text.borrow().as_ref() { if old_ellipsize != new_ellipsize || old_label != new_label {
let placeholder = imp.placeholder.borrow(); if new_ellipsize {
let placeholder = placeholder.as_deref().unwrap_or(DEFAULT_PLACEHOLDER); // Workaround: if both wrap and ellipsize are set, and there are
let label = label.replace(placeholder, OBJECT_REPLACEMENT_CHARACTER); // widgets inserted, GtkLabel reports an erroneous minimum width.
imp.label.set_label(&label); imp.label.set_wrap(false);
imp.label.set_ellipsize(pango::EllipsizeMode::End);
} else {
imp.label.set_wrap(true);
imp.label.set_ellipsize(pango::EllipsizeMode::None);
} }
imp.label.set_label(&new_label);
self.invalidate_child_widgets();
} }
self.invalidate_child_widgets();
} }
} }

Loading…
Cancel
Save