BREAKING CHANGE: Various type and function names have changed to reflect themselves better in documentation. Code has been reorganized into separate modules with a better placement in libcosmic. Most of the functions, types, and modules now have documentation and examples. These changes no longer require the `Model` type to define the data/component type that it stores. The component functionality is now optional, and it's also possible to associate many components to an item with one component per type. This has had a side effect of simplifying a lot of the type signatures in the implementation. Before, to insert an item into the model, you had to define a `SegmentedItem` and a `Component` on insert, and get back an ID for that item. Which makes it difficult to define an item that contains only an icon or has no components. And requires an extra insert function to activate the item on insert. Now, there is a flexible builder-style API for configuring newly-inserted items in the model. So the complexity for inserting and retrieving values from the model has decreased significantly
95 lines
3.1 KiB
Rust
95 lines
3.1 KiB
Rust
// Copyright 2022 System76 <info@system76.com>
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
//! Implementation details for the horizontal layout of a segmented button.
|
|
|
|
use super::model::{Model, Selectable};
|
|
use super::style::StyleSheet;
|
|
use super::widget::{SegmentedButton, SegmentedVariant};
|
|
|
|
use iced::{Length, Rectangle, Size};
|
|
use iced_native::layout;
|
|
|
|
/// Horizontal [`SegmentedButton`].
|
|
pub type HorizontalSegmentedButton<'a, SelectionMode, Message, Renderer> =
|
|
SegmentedButton<'a, Horizontal, SelectionMode, Message, Renderer>;
|
|
|
|
/// A type marker defining the horizontal variant of a [`SegmentedButton`].
|
|
pub struct Horizontal;
|
|
|
|
/// Horizontal implementation of the [`SegmentedButton`].
|
|
///
|
|
/// For details on the model, see the [`segmented_button`](super) module for more details.
|
|
#[must_use]
|
|
pub fn horizontal<SelectionMode: Default, Message, Renderer>(
|
|
model: &Model<SelectionMode>,
|
|
) -> SegmentedButton<Horizontal, SelectionMode, Message, Renderer>
|
|
where
|
|
Renderer: iced_native::Renderer
|
|
+ iced_native::text::Renderer
|
|
+ iced_native::image::Renderer
|
|
+ iced_native::svg::Renderer,
|
|
Renderer::Theme: StyleSheet,
|
|
Model<SelectionMode>: Selectable,
|
|
{
|
|
SegmentedButton::new(model)
|
|
}
|
|
|
|
impl<'a, SelectionMode, Message, Renderer> SegmentedVariant
|
|
for SegmentedButton<'a, Horizontal, SelectionMode, Message, Renderer>
|
|
where
|
|
Renderer: iced_native::Renderer
|
|
+ iced_native::text::Renderer
|
|
+ iced_native::image::Renderer
|
|
+ iced_native::svg::Renderer,
|
|
Renderer::Theme: StyleSheet,
|
|
Model<SelectionMode>: Selectable,
|
|
SelectionMode: Default,
|
|
{
|
|
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.horizontal(style)
|
|
}
|
|
|
|
#[allow(clippy::cast_precision_loss)]
|
|
fn variant_button_bounds(&self, mut bounds: Rectangle, nth: usize) -> Rectangle {
|
|
let num = self.model.items.len();
|
|
if num != 0 {
|
|
let spacing = f32::from(self.spacing);
|
|
bounds.width = (bounds.width - (num as f32 * spacing) + spacing) / num as f32;
|
|
|
|
if nth != 0 {
|
|
bounds.x += (nth as f32 * bounds.width) + (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 (mut width, height) = self.max_button_dimensions(renderer, text_size, limits.max());
|
|
|
|
let num = self.model.items.len();
|
|
let spacing = f32::from(self.spacing);
|
|
|
|
if num != 0 {
|
|
width = (num as f32 * width) + (num as f32 * spacing) - spacing;
|
|
}
|
|
|
|
let size = limits
|
|
.height(Length::Units(height as u16))
|
|
.resolve(Size::new(width, height));
|
|
|
|
layout::Node::new(size)
|
|
}
|
|
}
|