feat(segmented_button): add ellipsize support
This commit is contained in:
parent
7a56762422
commit
dc3ebaa38e
3 changed files with 69 additions and 5 deletions
|
|
@ -213,6 +213,18 @@ where
|
|||
state.buttons_offset = num - state.buttons_visible;
|
||||
}
|
||||
|
||||
// Resize paragraph bounds so that text ellipsis can take effect.
|
||||
if !matches!(self.width, Length::Shrink) || state.collapsed {
|
||||
let num = state.buttons_visible.max(1) as f32;
|
||||
let spacing = f32::from(self.spacing);
|
||||
let mut width_offset = 0.0;
|
||||
if state.collapsed {
|
||||
width_offset = f32::from(self.button_height) * 2.0;
|
||||
}
|
||||
let button_width = ((num).mul_add(-spacing, size.width - width_offset) + spacing) / num;
|
||||
self.resize_paragraphs(state, button_width);
|
||||
}
|
||||
|
||||
size
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,10 +117,15 @@ where
|
|||
height += item_height;
|
||||
}
|
||||
|
||||
limits.height(Length::Fixed(height)).resolve(
|
||||
let size = limits.height(Length::Fixed(height)).resolve(
|
||||
self.width,
|
||||
self.height,
|
||||
Size::new(width, height),
|
||||
)
|
||||
);
|
||||
|
||||
// Resize paragraph bounds so that text ellipsis can take effect.
|
||||
self.resize_paragraphs(state, size.width);
|
||||
|
||||
size
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,6 +156,8 @@ where
|
|||
pub(super) spacing: u16,
|
||||
/// LineHeight of the font.
|
||||
pub(super) line_height: LineHeight,
|
||||
/// Ellipsize strategy for button text.
|
||||
pub(super) ellipsize: Ellipsize,
|
||||
/// Style to draw the widget in.
|
||||
#[setters(into)]
|
||||
pub(super) style: Style,
|
||||
|
|
@ -223,6 +225,7 @@ where
|
|||
width: Length::Fill,
|
||||
spacing: 0,
|
||||
line_height: LineHeight::default(),
|
||||
ellipsize: Ellipsize::default(),
|
||||
style: Style::default(),
|
||||
context_menu: None,
|
||||
on_activate: None,
|
||||
|
|
@ -275,7 +278,7 @@ where
|
|||
shaping: Shaping::Advanced,
|
||||
wrapping: Wrapping::None,
|
||||
line_height: self.line_height,
|
||||
ellipsize: Ellipsize::default(),
|
||||
ellipsize: self.ellipsize,
|
||||
};
|
||||
paragraph.update(text);
|
||||
} else {
|
||||
|
|
@ -289,7 +292,7 @@ where
|
|||
shaping: Shaping::Advanced,
|
||||
wrapping: Wrapping::None,
|
||||
line_height: self.line_height,
|
||||
ellipsize: Ellipsize::default(),
|
||||
ellipsize: self.ellipsize,
|
||||
};
|
||||
state.paragraphs.insert(key, crate::Plain::new(text));
|
||||
}
|
||||
|
|
@ -621,7 +624,7 @@ where
|
|||
align_y: alignment::Vertical::Center,
|
||||
shaping: Shaping::Advanced,
|
||||
wrapping: Wrapping::default(),
|
||||
ellipsize: Ellipsize::default(),
|
||||
ellipsize: self.ellipsize,
|
||||
line_height: self.line_height,
|
||||
})
|
||||
});
|
||||
|
|
@ -657,6 +660,50 @@ where
|
|||
(width, f32::from(self.button_height))
|
||||
}
|
||||
|
||||
/// Resizes paragraph bounds based on the actual available button width so that
|
||||
/// text ellipsis can take effect. Call this after `variant_layout` has populated
|
||||
/// `state.internal_layout` with final button sizes.
|
||||
pub(super) fn resize_paragraphs(&self, state: &mut LocalState, available_width: f32) {
|
||||
if matches!(self.ellipsize, Ellipsize::None) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (nth, key) in self.model.order.iter().copied().enumerate() {
|
||||
if self.model.text(key).is_some_and(|text| !text.is_empty()) {
|
||||
let mut non_text_width =
|
||||
f32::from(self.button_padding[0]) + f32::from(self.button_padding[2]);
|
||||
|
||||
if let Some(icon) = self.model.icon(key) {
|
||||
non_text_width += f32::from(icon.size) + f32::from(self.button_spacing);
|
||||
} else if self.model.is_active(key) {
|
||||
if let crate::theme::SegmentedButton::Control = self.style {
|
||||
non_text_width += 16.0 + f32::from(self.button_spacing);
|
||||
}
|
||||
}
|
||||
|
||||
if self.model.is_closable(key) {
|
||||
non_text_width +=
|
||||
f32::from(self.close_icon.size) + f32::from(self.button_spacing);
|
||||
}
|
||||
|
||||
let text_width = (available_width - non_text_width).max(0.0);
|
||||
|
||||
if let Some(paragraph) = state.paragraphs.get_mut(key) {
|
||||
paragraph.resize(Size::new(text_width, f32::INFINITY));
|
||||
|
||||
// Update internal_layout actual content width so that
|
||||
// button_alignment centering uses the ellipsized size.
|
||||
let content_width = paragraph.min_bounds().width + non_text_width
|
||||
- f32::from(self.button_padding[0])
|
||||
- f32::from(self.button_padding[2]);
|
||||
if let Some(entry) = state.internal_layout.get_mut(nth) {
|
||||
entry.1.width = content_width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn max_button_dimensions(
|
||||
&self,
|
||||
state: &mut LocalState,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue