feat(segmented_button): add FileNav style with related widget improvements
This commit is contained in:
parent
8412dd5939
commit
c10695600b
3 changed files with 100 additions and 57 deletions
|
|
@ -18,6 +18,8 @@ pub enum SegmentedButton {
|
|||
Control,
|
||||
/// Navigation bar style
|
||||
NavBar,
|
||||
/// File browser
|
||||
FileNav,
|
||||
/// Or implement any custom theme of your liking.
|
||||
Custom(Box<dyn Fn(&Theme) -> Appearance>),
|
||||
}
|
||||
|
|
@ -69,7 +71,7 @@ impl StyleSheet for Theme {
|
|||
}
|
||||
}
|
||||
|
||||
SegmentedButton::NavBar => Appearance {
|
||||
SegmentedButton::NavBar | SegmentedButton::FileNav => Appearance {
|
||||
active_width: 0.0,
|
||||
..horizontal::tab_bar(cosmic, container)
|
||||
},
|
||||
|
|
@ -124,7 +126,7 @@ impl StyleSheet for Theme {
|
|||
}
|
||||
}
|
||||
|
||||
SegmentedButton::NavBar => Appearance {
|
||||
SegmentedButton::NavBar | SegmentedButton::FileNav => Appearance {
|
||||
active_width: 0.0,
|
||||
..vertical::tab_bar(cosmic, container)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ where
|
|||
/ num as f32;
|
||||
}
|
||||
|
||||
let segmetned_control = matches!(self.style, crate::theme::SegmentedButton::Control);
|
||||
let is_control = matches!(self.style, crate::theme::SegmentedButton::Control);
|
||||
|
||||
Box::new(
|
||||
self.model
|
||||
|
|
@ -93,7 +93,7 @@ where
|
|||
let button_bounds = ItemBounds::Button(key, layout_bounds);
|
||||
let mut divider = None;
|
||||
|
||||
if self.dividers && segmetned_control && nth + 1 < num {
|
||||
if self.dividers && is_control && nth + 1 < num {
|
||||
divider = Some(ItemBounds::Divider(
|
||||
Rectangle {
|
||||
width: 1.0,
|
||||
|
|
@ -143,7 +143,7 @@ where
|
|||
let max_size = limits.height(Length::Fixed(max_height)).resolve(
|
||||
Length::Fill,
|
||||
max_height,
|
||||
Size::new(f32::MAX, max_height),
|
||||
Size::new(limits.max().width, max_height),
|
||||
);
|
||||
|
||||
let mut visible_width = 0.0;
|
||||
|
|
@ -152,7 +152,7 @@ where
|
|||
for (button_size, _actual_size) in &state.internal_layout {
|
||||
visible_width += button_size.width;
|
||||
|
||||
if max_size.width >= visible_width {
|
||||
if max_size.width - spacing >= visible_width {
|
||||
state.buttons_visible += 1;
|
||||
} else {
|
||||
visible_width = max_size.width - max_height;
|
||||
|
|
|
|||
|
|
@ -619,20 +619,19 @@ where
|
|||
|
||||
for key in self.model.order.iter().copied() {
|
||||
if let Some(text) = self.model.text.get(key) {
|
||||
let (font, button_state) = if self.button_is_focused(state, key) {
|
||||
(self.font_active, 0)
|
||||
let font = if self.button_is_focused(state, key) {
|
||||
self.font_active
|
||||
} else if state.show_context.is_some() || self.button_is_hovered(state, key) {
|
||||
(self.font_hovered, 1)
|
||||
self.font_hovered
|
||||
} else if self.model.is_active(key) {
|
||||
(self.font_active, 2)
|
||||
self.font_active
|
||||
} else {
|
||||
(self.font_inactive, 3)
|
||||
self.font_inactive
|
||||
};
|
||||
|
||||
let mut hasher = DefaultHasher::new();
|
||||
text.hash(&mut hasher);
|
||||
font.hash(&mut hasher);
|
||||
button_state.hash(&mut hasher);
|
||||
let text_hash = hasher.finish();
|
||||
|
||||
if let Some(prev_hash) = state.text_hashes.insert(key, text_hash) {
|
||||
|
|
@ -1293,6 +1292,15 @@ where
|
|||
);
|
||||
}
|
||||
|
||||
let rad_0 = THEME.lock().unwrap().cosmic().corner_radii.radius_0;
|
||||
|
||||
let divider_background = Background::Color(
|
||||
crate::theme::active()
|
||||
.cosmic()
|
||||
.primary_component_divider()
|
||||
.into(),
|
||||
);
|
||||
|
||||
// Draw each of the items in the widget.
|
||||
let mut nth = 0;
|
||||
self.variant_bounds(state, bounds).for_each(move |item| {
|
||||
|
|
@ -1337,7 +1345,7 @@ where
|
|||
let key_is_active = self.model.is_active(key);
|
||||
let key_is_focused = state.focused_visible && self.button_is_focused(state, key);
|
||||
let key_is_hovered = self.button_is_hovered(state, key);
|
||||
let status_appearance = if self.button_is_pressed(state, key) && key_is_hovered {
|
||||
let status_appearance = if self.button_is_pressed(state, key) {
|
||||
appearance.pressed
|
||||
} else if key_is_hovered || menu_open() {
|
||||
appearance.hover
|
||||
|
|
@ -1355,11 +1363,87 @@ where
|
|||
status_appearance.middle
|
||||
};
|
||||
|
||||
// Draw the active hint on tabs
|
||||
if appearance.active_width > 0.0 {
|
||||
let active_width = if key_is_active {
|
||||
appearance.active_width
|
||||
} else {
|
||||
1.0
|
||||
};
|
||||
|
||||
renderer.fill_quad(
|
||||
renderer::Quad {
|
||||
bounds: if Self::VERTICAL {
|
||||
Rectangle {
|
||||
x: bounds.x + bounds.width - active_width,
|
||||
width: active_width,
|
||||
..bounds
|
||||
}
|
||||
} else {
|
||||
Rectangle {
|
||||
y: bounds.y + bounds.height - active_width,
|
||||
height: active_width,
|
||||
..bounds
|
||||
}
|
||||
},
|
||||
border: Border {
|
||||
radius: rad_0.into(),
|
||||
..Default::default()
|
||||
},
|
||||
shadow: Shadow::default(),
|
||||
},
|
||||
appearance.active.text_color,
|
||||
);
|
||||
}
|
||||
|
||||
let original_bounds = bounds;
|
||||
bounds.x += f32::from(self.button_padding[0]);
|
||||
bounds.width -= f32::from(self.button_padding[0]) - f32::from(self.button_padding[2]);
|
||||
let mut indent_padding = 0.0;
|
||||
|
||||
// Adjust bounds by indent
|
||||
if let Some(indent) = self.model.indent(key) {
|
||||
if indent > 0 {
|
||||
let adjustment = f32::from(indent) * f32::from(self.indent_spacing);
|
||||
bounds.x += adjustment;
|
||||
bounds.width -= adjustment;
|
||||
|
||||
// Draw indent line
|
||||
if let crate::theme::SegmentedButton::FileNav = self.style {
|
||||
if indent > 1 {
|
||||
indent_padding = 7.0;
|
||||
renderer.fill_quad(
|
||||
renderer::Quad {
|
||||
bounds: Rectangle {
|
||||
x: bounds.x - self.indent_spacing as f32 + indent_padding,
|
||||
width: 1.0,
|
||||
..bounds
|
||||
},
|
||||
border: Border {
|
||||
radius: rad_0.into(),
|
||||
..Default::default()
|
||||
},
|
||||
shadow: Shadow::default(),
|
||||
},
|
||||
divider_background,
|
||||
);
|
||||
indent_padding += 4.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Render the background of the button.
|
||||
if key_is_focused || status_appearance.background.is_some() {
|
||||
renderer.fill_quad(
|
||||
renderer::Quad {
|
||||
bounds,
|
||||
bounds: Rectangle {
|
||||
x: bounds.x - f32::from(self.button_padding[0]) + indent_padding,
|
||||
width: bounds.width + f32::from(self.button_padding[0])
|
||||
- f32::from(self.button_padding[2])
|
||||
- indent_padding,
|
||||
..bounds
|
||||
},
|
||||
border: if key_is_focused {
|
||||
Border {
|
||||
width: 1.0,
|
||||
|
|
@ -1377,49 +1461,6 @@ where
|
|||
);
|
||||
}
|
||||
|
||||
// Draw the active hint on tabs
|
||||
if appearance.active_width > 0.0 {
|
||||
let rad_0 = THEME.lock().unwrap().cosmic().corner_radii.radius_0;
|
||||
let active_width = if key_is_active {
|
||||
appearance.active_width
|
||||
} else {
|
||||
1.0
|
||||
};
|
||||
let mut bounds = bounds;
|
||||
|
||||
if Self::VERTICAL {
|
||||
bounds.x += bounds.height - active_width;
|
||||
bounds.width = active_width;
|
||||
} else {
|
||||
bounds.y += bounds.height - active_width;
|
||||
bounds.height = active_width;
|
||||
}
|
||||
|
||||
renderer.fill_quad(
|
||||
renderer::Quad {
|
||||
bounds,
|
||||
border: Border {
|
||||
radius: rad_0.into(),
|
||||
..Default::default()
|
||||
},
|
||||
shadow: Shadow::default(),
|
||||
},
|
||||
appearance.active.text_color,
|
||||
);
|
||||
}
|
||||
|
||||
let original_bounds = bounds;
|
||||
|
||||
bounds.x += f32::from(self.button_padding[0]);
|
||||
bounds.width -= f32::from(self.button_padding[0]) - f32::from(self.button_padding[2]);
|
||||
|
||||
// Adjust bounds by indent
|
||||
if let Some(indent) = self.model.indent(key) {
|
||||
let adjustment = f32::from(indent) * f32::from(self.indent_spacing);
|
||||
bounds.x += adjustment;
|
||||
bounds.width -= adjustment;
|
||||
}
|
||||
|
||||
// Align contents of the button to the requested `button_alignment`.
|
||||
{
|
||||
let actual_width = state.internal_layout[nth].1.width;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue