Skip to content

Commit

Permalink
Add text overflow listener to label (#218)
Browse files Browse the repository at this point in the history
  • Loading branch information
presiyan-ivanov authored Dec 8, 2023
1 parent 9dba156 commit 4a3a666
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 21 deletions.
76 changes: 55 additions & 21 deletions examples/responsive/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,67 @@
use floem::{
peniko::Color,
reactive::create_signal,
responsive::{range, ScreenSize},
style::TextOverflow,
unit::UnitExt,
view::View,
views::{label, stack, Decorators},
views::{h_stack, label, stack, text, Decorators},
};

fn app_view() -> impl View {
let (is_text_overflown, set_is_text_overflown) = create_signal(false);

stack({
(label(|| "Resize the window to see the magic").style(|s| {
s.border(1.0)
.border_radius(10.0)
.padding(10.0)
.margin_horiz(10.0)
.responsive(ScreenSize::XS, |s| s.background(Color::CYAN))
.responsive(ScreenSize::SM, |s| s.background(Color::PURPLE))
.responsive(ScreenSize::MD, |s| s.background(Color::ORANGE))
.responsive(ScreenSize::LG, |s| s.background(Color::GREEN))
.responsive(ScreenSize::XL, |s| s.background(Color::PINK))
.responsive(ScreenSize::XXL, |s| s.background(Color::RED))
.responsive(range(ScreenSize::XS..ScreenSize::LG), |s| {
s.width(90.0.pct()).max_width(500.0)
})
.responsive(
// equivalent to: range(ScreenSize::LG..)
ScreenSize::LG | ScreenSize::XL | ScreenSize::XXL,
|s| s.width(300.0),
)
}),)
(
label(|| "Resize the window to see the magic").style(|s| {
s.border(1.0)
.border_radius(10.0)
.padding(10.0)
.margin_horiz(10.0)
.responsive(ScreenSize::XS, |s| s.background(Color::CYAN))
.responsive(ScreenSize::SM, |s| s.background(Color::PURPLE))
.responsive(ScreenSize::MD, |s| s.background(Color::ORANGE))
.responsive(ScreenSize::LG, |s| s.background(Color::GREEN))
.responsive(ScreenSize::XL, |s| s.background(Color::PINK))
.responsive(ScreenSize::XXL, |s| s.background(Color::RED))
.responsive(range(ScreenSize::XS..ScreenSize::LG), |s| {
s.width(90.0.pct()).max_width(500.0)
})
.responsive(
// equivalent to: range(ScreenSize::LG..)
ScreenSize::LG | ScreenSize::XL | ScreenSize::XXL,
|s| s.width(300.0),
)
}),
text(
"Long text that will overflow on smaller screens since the available width is less",
)
.on_text_overflow(move |is_overflown| {
set_is_text_overflown.update(|overflown| *overflown = is_overflown);
})
.style(move |s| {
s.background(Color::DIM_GRAY)
.padding(10.0)
.color(Color::WHITE_SMOKE)
.margin_top(30.)
.width_pct(70.0)
.font_size(20.0)
.max_width(800.)
.text_overflow(TextOverflow::Ellipsis)
}),
h_stack((
text("The text fits in the available width?:"),
label(move || if is_text_overflown.get() { "No" } else { "Yes" }.to_string())
.style(move |s| {
s.color(if is_text_overflown.get() {
Color::RED
} else {
Color::GREEN
})
.font_bold()
}),
)),
)
})
.style(|s| {
s.size(100.pct(), 100.pct())
Expand Down
25 changes: 25 additions & 0 deletions src/views/label.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ prop_extracter! {
}
}

struct TextOverflowListener {
last_is_overflown: Option<bool>,
on_change_fn: Box<dyn Fn(bool) + 'static>,
}

pub struct Label {
data: ViewData,
label: String,
Expand All @@ -32,6 +37,7 @@ pub struct Label {
available_text: Option<String>,
available_width: Option<f32>,
available_text_layout: Option<TextLayout>,
text_overflow_listener: Option<TextOverflowListener>,
font: FontProps,
style: Extracter,
}
Expand All @@ -46,6 +52,7 @@ impl Label {
available_text: None,
available_width: None,
available_text_layout: None,
text_overflow_listener: None,
font: FontProps::default(),
style: Default::default(),
}
Expand All @@ -70,6 +77,14 @@ pub fn label<S: Display + 'static>(label: impl Fn() -> S + 'static) -> Label {
}

impl Label {
pub fn on_text_overflow(mut self, is_text_overflown_fn: impl Fn(bool) + 'static) -> Self {
self.text_overflow_listener = Some(TextOverflowListener {
on_change_fn: Box::new(is_text_overflown_fn),
last_is_overflown: None,
});
self
}

fn get_attrs_list(&self) -> AttrsList {
let mut attrs = Attrs::new().color(self.style.color().unwrap_or(Color::BLACK));
if let Some(font_size) = self.font.size() {
Expand Down Expand Up @@ -245,6 +260,16 @@ impl View for Label {
self.available_text_layout = None;
}
}

if let Some(listener) = self.text_overflow_listener.as_mut() {
let was_overflown = listener.last_is_overflown;
let now_overflown = width > available_width;

if was_overflown != Some(now_overflown) {
(listener.on_change_fn)(now_overflown);
listener.last_is_overflown = Some(now_overflown);
}
}
None
}

Expand Down

0 comments on commit 4a3a666

Please sign in to comment.