It's difficult to make iterative developments when there's two nearly-identical types that need to be kept synchronized to any change. Rust gives us traits so we should use them instead of duplicating code. This made it easier to make styling and layout improvements to both instances of the segmented button.
78 lines
2.5 KiB
Rust
78 lines
2.5 KiB
Rust
use super::state::State;
|
|
use super::style::StyleSheet;
|
|
use super::widget::{SegmentedButton, SegmentedVariant};
|
|
|
|
use iced::{Length, Rectangle, Size};
|
|
use iced_native::layout;
|
|
|
|
/// A type marker defining the vertical variant of a [`SegmentedButton`].
|
|
pub struct Vertical;
|
|
|
|
/// Vertical [`SegmentedButton`].
|
|
pub type VerticalSegmentedButton<'a, Message, Renderer> =
|
|
SegmentedButton<'a, Vertical, Message, Renderer>;
|
|
|
|
/// Vertical implementation of the [`SegmentedButton`].
|
|
#[must_use]
|
|
pub fn vertical_segmented_button<Message, Renderer, Data>(
|
|
state: &State<Data>,
|
|
) -> SegmentedButton<Vertical, Message, Renderer>
|
|
where
|
|
Renderer: iced_native::Renderer + iced_native::text::Renderer,
|
|
Renderer::Theme: StyleSheet,
|
|
{
|
|
SegmentedButton::new(&state.inner)
|
|
}
|
|
|
|
impl<'a, Message, Renderer> SegmentedVariant for SegmentedButton<'a, Vertical, Message, Renderer>
|
|
where
|
|
Renderer: iced_native::Renderer + iced_native::text::Renderer,
|
|
Renderer::Theme: StyleSheet,
|
|
{
|
|
type Renderer = Renderer;
|
|
|
|
fn variant_appearance(
|
|
theme: &<Self::Renderer as iced_native::Renderer>::Theme,
|
|
style: &<<Self::Renderer as iced_native::Renderer>::Theme as StyleSheet>::Style,
|
|
) -> super::Appearance {
|
|
theme.vertical(style)
|
|
}
|
|
|
|
#[allow(clippy::cast_precision_loss)]
|
|
fn variant_button_bounds(&self, mut bounds: Rectangle, nth: usize) -> Rectangle {
|
|
let num = self.state.buttons.len();
|
|
if num != 0 {
|
|
let spacing = f32::from(self.spacing);
|
|
bounds.height = (bounds.height - (num as f32 * spacing) + spacing) / num as f32;
|
|
|
|
if nth != 0 {
|
|
bounds.y += (nth as f32 * bounds.height) + (nth as f32 * spacing);
|
|
}
|
|
}
|
|
|
|
bounds
|
|
}
|
|
|
|
#[allow(clippy::cast_precision_loss)]
|
|
#[allow(clippy::cast_possible_truncation)]
|
|
#[allow(clippy::cast_sign_loss)]
|
|
fn variant_layout(&self, renderer: &Renderer, limits: &layout::Limits) -> layout::Node {
|
|
let limits = limits.width(self.width);
|
|
let text_size = renderer.default_size();
|
|
|
|
let (width, mut height) = self.max_button_dimensions(renderer, text_size, limits.max());
|
|
|
|
let num = self.state.buttons.len();
|
|
let spacing = f32::from(self.spacing);
|
|
|
|
if num != 0 {
|
|
height = (num as f32 * height) + (num as f32 * spacing) - spacing;
|
|
}
|
|
|
|
let size = limits
|
|
.height(Length::Units(height as u16))
|
|
.resolve(Size::new(width, height));
|
|
|
|
layout::Node::new(size)
|
|
}
|
|
}
|