diff options
45 files changed, 380 insertions, 282 deletions
diff --git a/core/src/alignment.rs b/core/src/alignment.rs index 51b7fca9..cacf7ce3 100644 --- a/core/src/alignment.rs +++ b/core/src/alignment.rs @@ -1,5 +1,30 @@ //! Align and position widgets. +/// Returns a value representing center alignment. +pub const fn center() -> Alignment { + Alignment::Center +} + +/// Returns a value representing left alignment. +pub const fn left() -> Horizontal { + Horizontal::Left +} + +/// Returns a value representing right alignment. +pub const fn right() -> Horizontal { + Horizontal::Right +} + +/// Returns a value representing top alignment. +pub const fn top() -> Vertical { + Vertical::Top +} + +/// Returns a value representing bottom alignment. +pub const fn bottom() -> Vertical { + Vertical::Bottom +} + /// Alignment on the axis of a container. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Alignment { @@ -46,6 +71,16 @@ pub enum Horizontal { Right, } +impl From<Alignment> for Horizontal { + fn from(alignment: Alignment) -> Self { + match alignment { + Alignment::Start => Self::Left, + Alignment::Center => Self::Center, + Alignment::End => Self::Right, + } + } +} + /// The vertical [`Alignment`] of some resource. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Vertical { @@ -58,3 +93,13 @@ pub enum Vertical { /// Align bottom Bottom, } + +impl From<Alignment> for Vertical { + fn from(alignment: Alignment) -> Self { + match alignment { + Alignment::Start => Self::Top, + Alignment::Center => Self::Center, + Alignment::End => Self::Bottom, + } + } +} diff --git a/core/src/pixels.rs b/core/src/pixels.rs index 425c0028..f5550a10 100644 --- a/core/src/pixels.rs +++ b/core/src/pixels.rs @@ -6,7 +6,7 @@ /// (e.g. `impl Into<Pixels>`) and, since `Pixels` implements `From` both for /// `f32` and `u16`, you should be able to provide both integers and float /// literals as needed. -#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] +#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)] pub struct Pixels(pub f32); impl From<f32> for Pixels { @@ -27,6 +27,30 @@ impl From<Pixels> for f32 { } } +impl std::ops::Add for Pixels { + type Output = Pixels; + + fn add(self, rhs: Self) -> Self { + Pixels(self.0 + rhs.0) + } +} + +impl std::ops::Add<f32> for Pixels { + type Output = Pixels; + + fn add(self, rhs: f32) -> Self { + Pixels(self.0 + rhs) + } +} + +impl std::ops::Mul for Pixels { + type Output = Pixels; + + fn mul(self, rhs: Self) -> Self { + Pixels(self.0 * rhs.0) + } +} + impl std::ops::Mul<f32> for Pixels { type Output = Pixels; diff --git a/core/src/widget/text.rs b/core/src/widget/text.rs index 081407e5..6ae95c8b 100644 --- a/core/src/widget/text.rs +++ b/core/src/widget/text.rs @@ -86,21 +86,56 @@ where self } + /// Centers the [`Text`], both horizontally and vertically. + pub fn center(self) -> Self { + self.center_x().center_y() + } + + /// Centers the [`Text`] horizontally. + pub fn center_x(self) -> Self { + self.align_x(alignment::center()) + } + + /// Aligns the [`Text`] to the left, the default. + pub fn align_left(self) -> Self { + self.align_x(alignment::left()) + } + + /// Aligns the [`Text`] to the right. + pub fn align_right(self) -> Self { + self.align_x(alignment::right()) + } + + /// Centers the [`Text`] vertically. + pub fn center_y(self) -> Self { + self.align_y(alignment::center()) + } + + /// Aligns the [`Text`] to the top, the default. + pub fn align_top(self) -> Self { + self.align_y(alignment::top()) + } + + /// Aligns the [`Text`] to the bottom. + pub fn align_bottom(self) -> Self { + self.align_y(alignment::bottom()) + } + /// Sets the [`alignment::Horizontal`] of the [`Text`]. - pub fn horizontal_alignment( + pub fn align_x( mut self, - alignment: alignment::Horizontal, + alignment: impl Into<alignment::Horizontal>, ) -> Self { - self.horizontal_alignment = alignment; + self.horizontal_alignment = alignment.into(); self } /// Sets the [`alignment::Vertical`] of the [`Text`]. - pub fn vertical_alignment( + pub fn align_y( mut self, - alignment: alignment::Vertical, + alignment: impl Into<alignment::Vertical>, ) -> Self { - self.vertical_alignment = alignment; + self.vertical_alignment = alignment.into(); self } diff --git a/examples/bezier_tool/src/main.rs b/examples/bezier_tool/src/main.rs index eaf84b97..2e5490e2 100644 --- a/examples/bezier_tool/src/main.rs +++ b/examples/bezier_tool/src/main.rs @@ -1,5 +1,4 @@ //! This example showcases an interactive `Canvas` for drawing Bézier curves. -use iced::alignment; use iced::widget::{button, container, horizontal_space, hover}; use iced::{Element, Length, Theme}; @@ -49,7 +48,7 @@ impl Example { ) .padding(10) .width(Length::Fill) - .align_x(alignment::Horizontal::Right) + .align_right() }, )) .padding(20) diff --git a/examples/color_palette/src/main.rs b/examples/color_palette/src/main.rs index e4b19731..870e4ca7 100644 --- a/examples/color_palette/src/main.rs +++ b/examples/color_palette/src/main.rs @@ -1,4 +1,4 @@ -use iced::alignment::{self, Alignment}; +use iced::alignment; use iced::mouse; use iced::widget::canvas::{self, Canvas, Frame, Geometry, Path}; use iced::widget::{column, row, text, Slider}; @@ -320,7 +320,7 @@ impl<C: ColorSpace + Copy> ColorPicker<C> { text(color.to_string()).width(185).size(12), ] .spacing(10) - .align_items(Alignment::Center) + .center_y() .into() } } diff --git a/examples/combo_box/src/main.rs b/examples/combo_box/src/main.rs index ff759ab4..0b321472 100644 --- a/examples/combo_box/src/main.rs +++ b/examples/combo_box/src/main.rs @@ -1,7 +1,7 @@ use iced::widget::{ center, column, combo_box, scrollable, text, vertical_space, }; -use iced::{Alignment, Element, Length}; +use iced::{Element, Length}; pub fn main() -> iced::Result { iced::run("Combo Box - Iced", Example::update, Example::view) @@ -65,7 +65,7 @@ impl Example { vertical_space().height(150), ] .width(Length::Fill) - .align_items(Alignment::Center) + .center_x() .spacing(10); center(scrollable(content)).into() diff --git a/examples/component/src/main.rs b/examples/component/src/main.rs index 5625f12a..14d3d9ba 100644 --- a/examples/component/src/main.rs +++ b/examples/component/src/main.rs @@ -34,7 +34,6 @@ impl Component { } mod numeric_input { - use iced::alignment::{self, Alignment}; use iced::widget::{button, component, row, text, text_input, Component}; use iced::{Element, Length, Size}; @@ -108,8 +107,7 @@ mod numeric_input { text(label) .width(Length::Fill) .height(Length::Fill) - .horizontal_alignment(alignment::Horizontal::Center) - .vertical_alignment(alignment::Vertical::Center), + .center(), ) .width(40) .height(40) @@ -130,7 +128,7 @@ mod numeric_input { .padding(10), button("+", Event::IncrementPressed), ] - .align_items(Alignment::Center) + .center_y() .spacing(10) .into() } diff --git a/examples/counter/src/main.rs b/examples/counter/src/main.rs index 0dd7a976..848c4c6c 100644 --- a/examples/counter/src/main.rs +++ b/examples/counter/src/main.rs @@ -1,5 +1,4 @@ use iced::widget::{button, column, text, Column}; -use iced::Alignment; pub fn main() -> iced::Result { iced::run("A cool counter", Counter::update, Counter::view) @@ -35,6 +34,6 @@ impl Counter { button("Decrement").on_press(Message::Decrement) ] .padding(20) - .align_items(Alignment::Center) + .center_x() } } diff --git a/examples/custom_quad/src/main.rs b/examples/custom_quad/src/main.rs index b53a40d6..ce7eb4ac 100644 --- a/examples/custom_quad/src/main.rs +++ b/examples/custom_quad/src/main.rs @@ -82,7 +82,7 @@ mod quad { } use iced::widget::{center, column, slider, text}; -use iced::{Alignment, Color, Element, Shadow, Vector}; +use iced::{Color, Element, Shadow, Vector}; pub fn main() -> iced::Result { iced::run("Custom Quad - Iced", Example::update, Example::view) @@ -185,7 +185,7 @@ impl Example { .padding(20) .spacing(20) .max_width(500) - .align_items(Alignment::Center); + .center_x(); center(content).into() } diff --git a/examples/custom_shader/src/main.rs b/examples/custom_shader/src/main.rs index b04a8183..3e29e7be 100644 --- a/examples/custom_shader/src/main.rs +++ b/examples/custom_shader/src/main.rs @@ -6,7 +6,7 @@ use iced::time::Instant; use iced::widget::shader::wgpu; use iced::widget::{center, checkbox, column, row, shader, slider, text}; use iced::window; -use iced::{Alignment, Color, Element, Length, Subscription}; +use iced::{Color, Element, Length, Subscription}; fn main() -> iced::Result { iced::application( @@ -122,12 +122,12 @@ impl IcedCubes { let controls = column![top_controls, bottom_controls,] .spacing(10) .padding(20) - .align_items(Alignment::Center); + .center_x(); let shader = shader(&self.scene).width(Length::Fill).height(Length::Fill); - center(column![shader, controls].align_items(Alignment::Center)).into() + center(column![shader, controls].center_x()).into() } fn subscription(&self) -> Subscription<Message> { diff --git a/examples/custom_widget/src/main.rs b/examples/custom_widget/src/main.rs index 3cf10e22..9f5dcfd0 100644 --- a/examples/custom_widget/src/main.rs +++ b/examples/custom_widget/src/main.rs @@ -83,7 +83,7 @@ mod circle { use circle::circle; use iced::widget::{center, column, slider, text}; -use iced::{Alignment, Element}; +use iced::Element; pub fn main() -> iced::Result { iced::run("Custom Widget - Iced", Example::update, Example::view) @@ -120,7 +120,7 @@ impl Example { .padding(20) .spacing(20) .max_width(500) - .align_items(Alignment::Center); + .center_x(); center(content).into() } diff --git a/examples/download_progress/src/main.rs b/examples/download_progress/src/main.rs index d91e5eab..8064b4ae 100644 --- a/examples/download_progress/src/main.rs +++ b/examples/download_progress/src/main.rs @@ -1,7 +1,7 @@ mod download; use iced::widget::{button, center, column, progress_bar, text, Column}; -use iced::{Alignment, Element, Subscription}; +use iced::{Element, Subscription}; pub fn main() -> iced::Result { iced::application( @@ -69,7 +69,7 @@ impl Example { .padding(10), ) .spacing(20) - .align_items(Alignment::End); + .align_right(); center(downloads).padding(20).into() } @@ -160,7 +160,7 @@ impl Download { State::Finished => { column!["Download finished!", button("Start again")] .spacing(10) - .align_items(Alignment::Center) + .center_x() .into() } State::Downloading { .. } => { @@ -171,14 +171,14 @@ impl Download { button("Try again").on_press(Message::Download(self.id)), ] .spacing(10) - .align_items(Alignment::Center) + .center_x() .into(), }; Column::new() .spacing(10) .padding(10) - .align_items(Alignment::Center) + .center_x() .push(progress_bar) .push(control) .into() diff --git a/examples/editor/src/main.rs b/examples/editor/src/main.rs index ce3c478d..e24c4ab6 100644 --- a/examples/editor/src/main.rs +++ b/examples/editor/src/main.rs @@ -4,7 +4,7 @@ use iced::widget::{ button, column, container, horizontal_space, pick_list, row, text, text_editor, tooltip, }; -use iced::{Alignment, Element, Font, Length, Subscription, Task, Theme}; +use iced::{Element, Font, Length, Subscription, Task, Theme}; use std::ffi; use std::io; @@ -158,7 +158,7 @@ impl Editor { .padding([5, 10]) ] .spacing(10) - .align_items(Alignment::Center); + .center_y(); let status = row![ text(if let Some(path) = &self.file { diff --git a/examples/events/src/main.rs b/examples/events/src/main.rs index 2cd3c5d8..7c9e78a6 100644 --- a/examples/events/src/main.rs +++ b/examples/events/src/main.rs @@ -1,8 +1,7 @@ -use iced::alignment; use iced::event::{self, Event}; use iced::widget::{button, center, checkbox, text, Column}; use iced::window; -use iced::{Alignment, Element, Length, Subscription, Task}; +use iced::{Element, Length, Subscription, Task}; pub fn main() -> iced::Result { iced::application("Events - Iced", Events::update, Events::view) @@ -67,17 +66,13 @@ impl Events { let toggle = checkbox("Listen to runtime events", self.enabled) .on_toggle(Message::Toggled); - let exit = button( - text("Exit") - .width(Length::Fill) - .horizontal_alignment(alignment::Horizontal::Center), - ) - .width(100) - .padding(10) - .on_press(Message::Exit); + let exit = button(text("Exit").width(Length::Fill).center_x()) + .width(100) + .padding(10) + .on_press(Message::Exit); let content = Column::new() - .align_items(Alignment::Center) + .center_x() .spacing(20) .push(events) .push(toggle) diff --git a/examples/exit/src/main.rs b/examples/exit/src/main.rs index 1f108df2..03ddfb2c 100644 --- a/examples/exit/src/main.rs +++ b/examples/exit/src/main.rs @@ -1,6 +1,6 @@ use iced::widget::{button, center, column}; use iced::window; -use iced::{Alignment, Element, Task}; +use iced::{Element, Task}; pub fn main() -> iced::Result { iced::application("Exit - Iced", Exit::update, Exit::view).run() @@ -44,7 +44,7 @@ impl Exit { ] } .spacing(10) - .align_items(Alignment::Center); + .center_x(); center(content).padding(20).into() } diff --git a/examples/ferris/src/main.rs b/examples/ferris/src/main.rs index 88006898..5d468de1 100644 --- a/examples/ferris/src/main.rs +++ b/examples/ferris/src/main.rs @@ -4,7 +4,7 @@ use iced::widget::{ }; use iced::window; use iced::{ - Alignment, Color, ContentFit, Degrees, Element, Length, Radians, Rotation, + Color, ContentFit, Degrees, Element, Length, Radians, Rotation, Subscription, Theme, }; @@ -108,7 +108,7 @@ impl Image { "I am Ferris!" ] .spacing(20) - .align_items(Alignment::Center); + .center_x(); let fit = row![ pick_list( @@ -134,7 +134,7 @@ impl Image { .width(Length::Fill), ] .spacing(10) - .align_items(Alignment::End); + .align_bottom(); let properties = row![ with_value( @@ -159,12 +159,12 @@ impl Image { .size(12) ] .spacing(10) - .align_items(Alignment::Center), + .center_y(), format!("Rotation: {:.0}°", f32::from(self.rotation.degrees())) ) ] .spacing(10) - .align_items(Alignment::End); + .align_bottom(); container(column![fit, center(i_am_ferris), properties].spacing(10)) .padding(10) @@ -206,6 +206,6 @@ fn with_value<'a>( ) -> Element<'a, Message> { column![control.into(), text(value).size(12).line_height(1.0)] .spacing(2) - .align_items(Alignment::Center) + .center_x() .into() } diff --git a/examples/game_of_life/src/main.rs b/examples/game_of_life/src/main.rs index 421f862a..38eb692b 100644 --- a/examples/game_of_life/src/main.rs +++ b/examples/game_of_life/src/main.rs @@ -9,7 +9,7 @@ use iced::time; use iced::widget::{ button, checkbox, column, container, pick_list, row, slider, text, }; -use iced::{Alignment, Element, Length, Subscription, Task, Theme}; +use iced::{Element, Length, Subscription, Task, Theme}; use std::time::Duration; pub fn main() -> iced::Result { @@ -169,7 +169,7 @@ fn view_controls<'a>( slider(1.0..=1000.0, speed as f32, Message::SpeedChanged), text!("x{speed}").size(16), ] - .align_items(Alignment::Center) + .center_y() .spacing(10); row![ @@ -186,7 +186,7 @@ fn view_controls<'a>( ] .padding(10) .spacing(20) - .align_items(Alignment::Center) + .center_y() .into() } diff --git a/examples/gradient/src/main.rs b/examples/gradient/src/main.rs index e5b19443..018bab82 100644 --- a/examples/gradient/src/main.rs +++ b/examples/gradient/src/main.rs @@ -3,7 +3,7 @@ use iced::gradient; use iced::widget::{ checkbox, column, container, horizontal_space, row, slider, text, }; -use iced::{Alignment, Color, Element, Length, Radians, Theme}; +use iced::{Color, Element, Length, Radians, Theme}; pub fn main() -> iced::Result { tracing_subscriber::fmt::init(); @@ -77,7 +77,7 @@ impl Gradient { ] .spacing(8) .padding(8) - .align_items(Alignment::Center); + .center_y(); let transparency_toggle = iced::widget::Container::new( checkbox("Transparent window", transparent) @@ -129,6 +129,6 @@ fn color_picker(label: &str, color: Color) -> Element<'_, Color> { ] .spacing(8) .padding(8) - .align_items(Alignment::Center) + .center_y() .into() } diff --git a/examples/integration/src/controls.rs b/examples/integration/src/controls.rs index d0654996..b03aa6d4 100644 --- a/examples/integration/src/controls.rs +++ b/examples/integration/src/controls.rs @@ -1,6 +1,5 @@ use iced_wgpu::Renderer; use iced_widget::{column, container, row, slider, text, text_input}; -use iced_winit::core::alignment; use iced_winit::core::{Color, Element, Length, Theme}; use iced_winit::runtime::{Program, Task}; @@ -87,7 +86,7 @@ impl Program for Controls { ) .padding(10) .height(Length::Fill) - .align_y(alignment::Vertical::Bottom) + .align_bottom() .into() } } diff --git a/examples/layout/src/main.rs b/examples/layout/src/main.rs index 2e774415..2bc7fb30 100644 --- a/examples/layout/src/main.rs +++ b/examples/layout/src/main.rs @@ -5,8 +5,8 @@ use iced::widget::{ pick_list, row, scrollable, text, }; use iced::{ - color, Alignment, Element, Font, Length, Point, Rectangle, Renderer, - Subscription, Theme, + color, Element, Font, Length, Point, Rectangle, Renderer, Subscription, + Theme, }; pub fn main() -> iced::Result { @@ -74,7 +74,7 @@ impl Layout { pick_list(Theme::ALL, Some(&self.theme), Message::ThemeSelected), ] .spacing(20) - .align_items(Alignment::Center); + .center_y(); let example = center(if self.explain { self.example.view().explain(color!(0x0000ff)) @@ -234,7 +234,7 @@ fn application<'a>() -> Element<'a, Message> { square(40), ] .padding(10) - .align_items(Alignment::Center), + .center_y(), ) .style(|theme| { let palette = theme.extended_palette(); @@ -248,7 +248,7 @@ fn application<'a>() -> Element<'a, Message> { .spacing(40) .padding(10) .width(200) - .align_items(Alignment::Center), + .center_x(), ) .style(container::rounded_box) .center_y(Length::Fill); @@ -263,7 +263,7 @@ fn application<'a>() -> Element<'a, Message> { "The end" ] .spacing(40) - .align_items(Alignment::Center) + .center_x() .width(Length::Fill), ) .height(Length::Fill), diff --git a/examples/loading_spinners/src/main.rs b/examples/loading_spinners/src/main.rs index 503f2d7a..7fa7ac97 100644 --- a/examples/loading_spinners/src/main.rs +++ b/examples/loading_spinners/src/main.rs @@ -67,7 +67,7 @@ impl LoadingSpinners { Duration::from_secs_f32(self.cycle_duration) ) ] - .align_items(iced::Alignment::Center) + .center_y() .spacing(20.0), ) }) @@ -83,7 +83,7 @@ impl LoadingSpinners { .width(200.0), text!("{:.2}s", self.cycle_duration), ] - .align_items(iced::Alignment::Center) + .center_y() .spacing(20.0), ), ) diff --git a/examples/loupe/src/main.rs b/examples/loupe/src/main.rs index c4d3b449..8c9b4def 100644 --- a/examples/loupe/src/main.rs +++ b/examples/loupe/src/main.rs @@ -1,5 +1,5 @@ use iced::widget::{button, center, column, text}; -use iced::{Alignment, Element}; +use iced::Element; use loupe::loupe; @@ -39,7 +39,7 @@ impl Loupe { button("Decrement").on_press(Message::Decrement) ] .padding(20) - .align_items(Alignment::Center), + .center_x(), )) .into() } diff --git a/examples/modal/src/main.rs b/examples/modal/src/main.rs index 413485e7..6f0f7182 100644 --- a/examples/modal/src/main.rs +++ b/examples/modal/src/main.rs @@ -5,7 +5,7 @@ use iced::widget::{ self, button, center, column, container, horizontal_space, mouse_area, opaque, pick_list, row, stack, text, text_input, }; -use iced::{Alignment, Color, Element, Length, Subscription, Task}; +use iced::{Color, Element, Length, Subscription, Task}; use std::fmt; @@ -96,7 +96,6 @@ impl App { let content = container( column![ row![text("Top Left"), horizontal_space(), text("Top Right")] - .align_items(Alignment::Start) .height(Length::Fill), center(button(text("Show Modal")).on_press(Message::ShowModal)), row![ @@ -104,7 +103,7 @@ impl App { horizontal_space(), text("Bottom Right") ] - .align_items(Alignment::End) + .align_bottom() .height(Length::Fill), ] .height(Length::Fill), diff --git a/examples/multi_window/src/main.rs b/examples/multi_window/src/main.rs index 460ca3b5..b1276320 100644 --- a/examples/multi_window/src/main.rs +++ b/examples/multi_window/src/main.rs @@ -3,7 +3,7 @@ use iced::widget::{ text_input, }; use iced::window; -use iced::{Alignment, Element, Length, Subscription, Task, Theme, Vector}; +use iced::{Element, Length, Subscription, Task, Theme, Vector}; use std::collections::BTreeMap; @@ -189,7 +189,7 @@ impl Window { column![scale_input, title_input, new_window_button] .spacing(50) .width(Length::Fill) - .align_items(Alignment::Center), + .center_x(), ); container(content).center_x(200).into() diff --git a/examples/pane_grid/src/main.rs b/examples/pane_grid/src/main.rs index db9f7a05..1d1efeeb 100644 --- a/examples/pane_grid/src/main.rs +++ b/examples/pane_grid/src/main.rs @@ -1,4 +1,3 @@ -use iced::alignment::{self, Alignment}; use iced::keyboard; use iced::widget::pane_grid::{self, PaneGrid}; use iced::widget::{ @@ -255,15 +254,10 @@ fn view_content<'a>( size: Size, ) -> Element<'a, Message> { let button = |label, message| { - button( - text(label) - .width(Length::Fill) - .horizontal_alignment(alignment::Horizontal::Center) - .size(16), - ) - .width(Length::Fill) - .padding(8) - .on_press(message) + button(text(label).width(Length::Fill).center_x().size(16)) + .width(Length::Fill) + .padding(8) + .on_press(message) }; let controls = column![ @@ -287,7 +281,7 @@ fn view_content<'a>( let content = column![text!("{}x{}", size.width, size.height).size(24), controls,] .spacing(10) - .align_items(Alignment::Center); + .center_x(); container(scrollable(content)) .center_y(Length::Fill) diff --git a/examples/pick_list/src/main.rs b/examples/pick_list/src/main.rs index 2be6f5b0..038204f0 100644 --- a/examples/pick_list/src/main.rs +++ b/examples/pick_list/src/main.rs @@ -1,5 +1,5 @@ use iced::widget::{column, pick_list, scrollable, vertical_space}; -use iced::{Alignment, Element, Length}; +use iced::{Element, Length}; pub fn main() -> iced::Result { iced::run("Pick List - Iced", Example::update, Example::view) @@ -39,7 +39,7 @@ impl Example { vertical_space().height(600), ] .width(Length::Fill) - .align_items(Alignment::Center) + .center_x() .spacing(10); scrollable(content).into() diff --git a/examples/pokedex/src/main.rs b/examples/pokedex/src/main.rs index 7414ae54..8131bb7e 100644 --- a/examples/pokedex/src/main.rs +++ b/examples/pokedex/src/main.rs @@ -1,6 +1,6 @@ use iced::futures; use iced::widget::{self, center, column, image, row, text}; -use iced::{Alignment, Element, Length, Task}; +use iced::{Element, Length, Task}; pub fn main() -> iced::Result { iced::application(Pokedex::title, Pokedex::update, Pokedex::view) @@ -74,13 +74,13 @@ impl Pokedex { ] .max_width(500) .spacing(20) - .align_items(Alignment::End), + .align_right(), Pokedex::Errored => column![ text("Whoops! Something went wrong...").size(40), button("Try again").on_press(Message::Search) ] .spacing(20) - .align_items(Alignment::End), + .align_right(), }; center(content).into() @@ -106,14 +106,14 @@ impl Pokemon { text(&self.name).size(30).width(Length::Fill), text!("#{}", self.number).size(20).color([0.5, 0.5, 0.5]), ] - .align_items(Alignment::Center) + .center_y() .spacing(20), self.description.as_ref(), ] .spacing(20), ] .spacing(20) - .align_items(Alignment::Center) + .center_y() .into() } diff --git a/examples/qr_code/src/main.rs b/examples/qr_code/src/main.rs index b30ecf15..14db776e 100644 --- a/examples/qr_code/src/main.rs +++ b/examples/qr_code/src/main.rs @@ -1,5 +1,5 @@ use iced::widget::{center, column, pick_list, qr_code, row, text, text_input}; -use iced::{Alignment, Element, Theme}; +use iced::{Element, Theme}; pub fn main() -> iced::Result { iced::application( @@ -58,7 +58,7 @@ impl QRGenerator { pick_list(Theme::ALL, Some(&self.theme), Message::ThemeChanged,) ] .spacing(10) - .align_items(Alignment::Center); + .center_y(); let content = column![title, input, choose_theme] .push_maybe( @@ -68,7 +68,7 @@ impl QRGenerator { ) .width(700) .spacing(20) - .align_items(Alignment::Center); + .center_x(); center(content).padding(20).into() } diff --git a/examples/screenshot/src/main.rs b/examples/screenshot/src/main.rs index acde8367..3b583d13 100644 --- a/examples/screenshot/src/main.rs +++ b/examples/screenshot/src/main.rs @@ -1,11 +1,8 @@ -use iced::alignment; use iced::keyboard; use iced::widget::{button, column, container, image, row, text, text_input}; use iced::window; use iced::window::screenshot::{self, Screenshot}; -use iced::{ - Alignment, ContentFit, Element, Length, Rectangle, Subscription, Task, -}; +use iced::{ContentFit, Element, Length, Rectangle, Subscription, Task}; use ::image as img; use ::image::ColorType; @@ -127,32 +124,24 @@ impl Example { .style(container::rounded_box); let crop_origin_controls = row![ - text("X:") - .vertical_alignment(alignment::Vertical::Center) - .width(30), + text("X:").width(30), numeric_input("0", self.x_input_value).map(Message::XInputChanged), - text("Y:") - .vertical_alignment(alignment::Vertical::Center) - .width(30), + text("Y:").width(30), numeric_input("0", self.y_input_value).map(Message::YInputChanged) ] .spacing(10) - .align_items(Alignment::Center); + .center_y(); let crop_dimension_controls = row![ - text("W:") - .vertical_alignment(alignment::Vertical::Center) - .width(30), + text("W:").width(30), numeric_input("0", self.width_input_value) .map(Message::WidthInputChanged), - text("H:") - .vertical_alignment(alignment::Vertical::Center) - .width(30), + text("H:").width(30), numeric_input("0", self.height_input_value) .map(Message::HeightInputChanged) ] .spacing(10) - .align_items(Alignment::Center); + .center_y(); let crop_controls = column![crop_origin_controls, crop_dimension_controls] @@ -162,7 +151,7 @@ impl Example { .map(|error| text!("Crop error! \n{error}")), ) .spacing(10) - .align_items(Alignment::Center); + .center_x(); let controls = { let save_result = @@ -203,7 +192,7 @@ impl Example { .width(Length::Fill), ] .spacing(10) - .align_items(Alignment::Center), + .center_x(), ] .push_maybe(save_result.map(text)) .spacing(40) @@ -215,7 +204,7 @@ impl Example { .spacing(10) .width(Length::Fill) .height(Length::Fill) - .align_items(Alignment::Center); + .center_y(); container(content).padding(10).into() } @@ -276,8 +265,5 @@ fn numeric_input( } fn centered_text(content: &str) -> Element<'_, Message> { - text(content) - .width(Length::Fill) - .horizontal_alignment(alignment::Horizontal::Center) - .into() + text(content).width(Length::Fill).center_x().into() } diff --git a/examples/scrollable/src/main.rs b/examples/scrollable/src/main.rs index 067dcd70..bf8fdedf 100644 --- a/examples/scrollable/src/main.rs +++ b/examples/scrollable/src/main.rs @@ -2,7 +2,7 @@ use iced::widget::{ button, column, container, horizontal_space, progress_bar, radio, row, scrollable, slider, text, vertical_space, }; -use iced::{Alignment, Border, Color, Element, Length, Task, Theme}; +use iced::{Border, Color, Element, Length, Task, Theme}; use once_cell::sync::Lazy; @@ -24,7 +24,7 @@ struct ScrollableDemo { scrollbar_margin: u16, scroller_width: u16, current_scroll_offset: scrollable::RelativeOffset, - alignment: scrollable::Alignment, + anchor: scrollable::Anchor, } #[derive(Debug, Clone, Eq, PartialEq, Copy)] @@ -37,7 +37,7 @@ enum Direction { #[derive(Debug, Clone)] enum Message { SwitchDirection(Direction), - AlignmentChanged(scrollable::Alignment), + AlignmentChanged(scrollable::Anchor), ScrollbarWidthChanged(u16), ScrollbarMarginChanged(u16), ScrollerWidthChanged(u16), @@ -54,7 +54,7 @@ impl ScrollableDemo { scrollbar_margin: 0, scroller_width: 10, current_scroll_offset: scrollable::RelativeOffset::START, - alignment: scrollable::Alignment::Start, + anchor: scrollable::Anchor::Start, } } @@ -71,7 +71,7 @@ impl ScrollableDemo { } Message::AlignmentChanged(alignment) => { self.current_scroll_offset = scrollable::RelativeOffset::START; - self.alignment = alignment; + self.anchor = alignment; scrollable::snap_to( SCROLLABLE_ID.clone(), @@ -168,14 +168,14 @@ impl ScrollableDemo { text("Scrollable alignment:"), radio( "Start", - scrollable::Alignment::Start, - Some(self.alignment), + scrollable::Anchor::Start, + Some(self.anchor), Message::AlignmentChanged, ), radio( "End", - scrollable::Alignment::End, - Some(self.alignment), + scrollable::Anchor::End, + Some(self.anchor), Message::AlignmentChanged, ) ] @@ -212,7 +212,7 @@ impl ScrollableDemo { text("End!"), scroll_to_beginning_button(), ] - .align_items(Alignment::Center) + .center_x() .padding([40, 0, 40, 0]) .spacing(40), ) @@ -221,7 +221,7 @@ impl ScrollableDemo { .width(self.scrollbar_width) .margin(self.scrollbar_margin) .scroller_width(self.scroller_width) - .alignment(self.alignment), + .anchor(self.anchor), )) .width(Length::Fill) .height(Length::Fill) @@ -238,7 +238,7 @@ impl ScrollableDemo { scroll_to_beginning_button(), ] .height(450) - .align_items(Alignment::Center) + .center_y() .padding([0, 40, 0, 40]) .spacing(40), ) @@ -247,7 +247,7 @@ impl ScrollableDemo { .width(self.scrollbar_width) .margin(self.scrollbar_margin) .scroller_width(self.scroller_width) - .alignment(self.alignment), + .anchor(self.anchor), )) .width(Length::Fill) .height(Length::Fill) @@ -280,7 +280,7 @@ impl ScrollableDemo { text("Horizontal - End!"), scroll_to_beginning_button(), ] - .align_items(Alignment::Center) + .center_y() .padding([0, 40, 0, 40]) .spacing(40), ) @@ -289,7 +289,7 @@ impl ScrollableDemo { .width(self.scrollbar_width) .margin(self.scrollbar_margin) .scroller_width(self.scroller_width) - .alignment(self.alignment); + .anchor(self.anchor); scrollable::Direction::Both { horizontal: scrollbar, @@ -322,7 +322,7 @@ impl ScrollableDemo { let content: Element<Message> = column![scroll_controls, scrollable_content, progress_bars] - .align_items(Alignment::Center) + .center_x() .spacing(10) .into(); diff --git a/examples/sierpinski_triangle/src/main.rs b/examples/sierpinski_triangle/src/main.rs index 4c751937..159b5597 100644 --- a/examples/sierpinski_triangle/src/main.rs +++ b/examples/sierpinski_triangle/src/main.rs @@ -60,7 +60,7 @@ impl SierpinskiEmulator { .padding(10) .spacing(20), ] - .align_items(iced::Alignment::Center) + .center_x() .into() } } diff --git a/examples/slider/src/main.rs b/examples/slider/src/main.rs index fd312763..5443c645 100644 --- a/examples/slider/src/main.rs +++ b/examples/slider/src/main.rs @@ -1,5 +1,5 @@ use iced::widget::{column, container, iced, slider, text, vertical_slider}; -use iced::{Alignment, Element, Length}; +use iced::{Element, Length}; pub fn main() -> iced::Result { iced::run("Slider - Iced", Slider::update, Slider::view) @@ -46,7 +46,7 @@ impl Slider { column![v_slider, h_slider, text, iced(self.value as f32),] .width(Length::Fill) - .align_items(Alignment::Center) + .center_x() .spacing(20) .padding(20) .into() diff --git a/examples/stopwatch/src/main.rs b/examples/stopwatch/src/main.rs index bd56785a..ca7b8f91 100644 --- a/examples/stopwatch/src/main.rs +++ b/examples/stopwatch/src/main.rs @@ -1,8 +1,7 @@ -use iced::alignment; use iced::keyboard; use iced::time; use iced::widget::{button, center, column, row, text}; -use iced::{Alignment, Element, Subscription, Theme}; +use iced::{Element, Subscription, Theme}; use std::time::{Duration, Instant}; @@ -101,13 +100,8 @@ impl Stopwatch { ) .size(40); - let button = |label| { - button( - text(label).horizontal_alignment(alignment::Horizontal::Center), - ) - .padding(10) - .width(80) - }; + let button = + |label| button(text(label).center_x()).padding(10).width(80); let toggle_button = { let label = match self.state { @@ -124,9 +118,7 @@ impl Stopwatch { let controls = row![toggle_button, reset_button].spacing(20); - let content = column![duration, controls] - .align_items(Alignment::Center) - .spacing(20); + let content = column![duration, controls].center_x().spacing(20); center(content).into() } diff --git a/examples/styling/src/main.rs b/examples/styling/src/main.rs index 3124493b..8f979ea8 100644 --- a/examples/styling/src/main.rs +++ b/examples/styling/src/main.rs @@ -3,7 +3,7 @@ use iced::widget::{ row, scrollable, slider, text, text_input, toggler, vertical_rule, vertical_space, }; -use iced::{Alignment, Element, Length, Theme}; +use iced::{Element, Length, Theme}; pub fn main() -> iced::Result { iced::application("Styling - Iced", Styling::update, Styling::view) @@ -88,9 +88,7 @@ impl Styling { let content = column![ choose_theme, horizontal_rule(38), - row![text_input, button] - .spacing(10) - .align_items(Alignment::Center), + row![text_input, button].spacing(10).center_y(), slider, progress_bar, row![ @@ -100,7 +98,7 @@ impl Styling { ] .spacing(10) .height(100) - .align_items(Alignment::Center), + .center_y(), ] .spacing(20) .padding(20) diff --git a/examples/toast/src/main.rs b/examples/toast/src/main.rs index 232133b1..fd7f07c2 100644 --- a/examples/toast/src/main.rs +++ b/examples/toast/src/main.rs @@ -4,7 +4,7 @@ use iced::keyboard::key; use iced::widget::{ self, button, center, column, pick_list, row, slider, text, text_input, }; -use iced::{Alignment, Element, Length, Subscription, Task}; +use iced::{Element, Length, Subscription, Task}; use toast::{Status, Toast}; @@ -142,7 +142,7 @@ impl App { .spacing(5) .into() ), - column![add_toast].align_items(Alignment::End) + column![add_toast].center_x() ] .spacing(10) .max_width(200), @@ -245,7 +245,7 @@ mod toast { .on_press((on_close)(index)) .padding(3), ] - .align_items(Alignment::Center) + .center_y() ) .width(Length::Fill) .padding(5) diff --git a/examples/todos/src/main.rs b/examples/todos/src/main.rs index b34f71ce..af651ee2 100644 --- a/examples/todos/src/main.rs +++ b/examples/todos/src/main.rs @@ -1,4 +1,3 @@ -use iced::alignment::{self, Alignment}; use iced::keyboard; use iced::widget::{ self, button, center, checkbox, column, container, keyed_column, row, @@ -196,7 +195,7 @@ impl Todos { .width(Length::Fill) .size(100) .color([0.5, 0.5, 0.5]) - .horizontal_alignment(alignment::Horizontal::Center); + .center_x(); let input = text_input("What needs to be done?", input_value) .id(INPUT_ID.clone()) @@ -355,7 +354,7 @@ impl Task { .style(button::text), ] .spacing(20) - .align_items(Alignment::Center) + .center_y() .into() } TaskState::Editing => { @@ -369,16 +368,14 @@ impl Task { row![ text_input, button( - row![delete_icon(), "Delete"] - .spacing(10) - .align_items(Alignment::Center) + row![delete_icon(), "Delete"].spacing(10).center_y() ) .on_press(TaskMessage::Delete) .padding(10) .style(button::danger) ] .spacing(20) - .align_items(Alignment::Center) + .center_y() .into() } } @@ -415,7 +412,7 @@ fn view_controls(tasks: &[Task], current_filter: Filter) -> Element<Message> { .spacing(10) ] .spacing(20) - .align_items(Alignment::Center) + .center_y() .into() } @@ -440,12 +437,7 @@ impl Filter { } fn loading_message<'a>() -> Element<'a, Message> { - center( - text("Loading...") - .horizontal_alignment(alignment::Horizontal::Center) - .size(50), - ) - .into() + center(text("Loading...").center_x().size(50)).into() } fn empty_message(message: &str) -> Element<'_, Message> { @@ -453,7 +445,7 @@ fn empty_message(message: &str) -> Element<'_, Message> { text(message) .width(Length::Fill) .size(25) - .horizontal_alignment(alignment::Horizontal::Center) + .center_x() .color([0.7, 0.7, 0.7]), ) .height(200) @@ -464,10 +456,7 @@ fn empty_message(message: &str) -> Element<'_, Message> { const ICONS: Font = Font::with_name("Iced-Todos-Icons"); fn icon(unicode: char) -> Text<'static> { - text(unicode.to_string()) - .font(ICONS) - .width(20) - .horizontal_alignment(alignment::Horizontal::Center) + text(unicode.to_string()).font(ICONS).width(20).center_x() } fn edit_icon() -> Text<'static> { diff --git a/examples/tour/src/main.rs b/examples/tour/src/main.rs index 94ba78ee..941c5b33 100644 --- a/examples/tour/src/main.rs +++ b/examples/tour/src/main.rs @@ -1,4 +1,3 @@ -use iced::alignment::{self, Alignment}; use iced::widget::{ button, checkbox, column, container, horizontal_space, image, radio, row, scrollable, slider, text, text_input, toggler, vertical_space, @@ -235,11 +234,7 @@ impl Tour { 0 to 100:", ) .push(slider(0..=100, self.slider, Message::SliderChanged)) - .push( - text(self.slider.to_string()) - .width(Length::Fill) - .horizontal_alignment(alignment::Horizontal::Center), - ) + .push(text(self.slider.to_string()).width(Length::Fill).center_x()) } fn rows_and_columns(&self) -> Column<Message> { @@ -268,9 +263,7 @@ impl Tour { let spacing_section = column![ slider(0..=80, self.spacing, Message::SpacingChanged), - text!("{} px", self.spacing) - .width(Length::Fill) - .horizontal_alignment(alignment::Horizontal::Center), + text!("{} px", self.spacing).width(Length::Fill).center_x(), ] .spacing(10); @@ -381,11 +374,7 @@ impl Tour { .push("An image that tries to keep its aspect ratio.") .push(ferris(width, filter_method)) .push(slider(100..=500, width, Message::ImageWidthChanged)) - .push( - text!("Width: {width} px") - .width(Length::Fill) - .horizontal_alignment(alignment::Horizontal::Center), - ) + .push(text!("Width: {width} px").width(Length::Fill).center_x()) .push( checkbox( "Use nearest interpolation", @@ -393,7 +382,7 @@ impl Tour { ) .on_toggle(Message::ImageUseNearestToggled), ) - .align_items(Alignment::Center) + .center_x() } fn scrollable(&self) -> Column<Message> { @@ -411,16 +400,11 @@ impl Tour { text("You are halfway there!") .width(Length::Fill) .size(30) - .horizontal_alignment(alignment::Horizontal::Center), + .center_x(), ) .push(vertical_space().height(4096)) .push(ferris(300, image::FilterMethod::Linear)) - .push( - text("You made it!") - .width(Length::Fill) - .size(50) - .horizontal_alignment(alignment::Horizontal::Center), - ) + .push(text("You made it!").width(Length::Fill).size(50).center_x()) } fn text_input(&self) -> Column<Message> { @@ -465,7 +449,7 @@ impl Tour { value }) .width(Length::Fill) - .horizontal_alignment(alignment::Horizontal::Center), + .center_x(), ) } diff --git a/examples/vectorial_text/src/main.rs b/examples/vectorial_text/src/main.rs index 6dd3273a..f7af486a 100644 --- a/examples/vectorial_text/src/main.rs +++ b/examples/vectorial_text/src/main.rs @@ -1,4 +1,4 @@ -use iced::alignment::{self, Alignment}; +use iced::alignment; use iced::mouse; use iced::widget::{ canvas, checkbox, column, horizontal_space, row, slider, text, @@ -85,7 +85,7 @@ impl VectorialText { ] .spacing(20), ] - .align_items(Alignment::Center) + .center_x() .spacing(10) ] .spacing(10) diff --git a/examples/visible_bounds/src/main.rs b/examples/visible_bounds/src/main.rs index e46d1ff0..245600c5 100644 --- a/examples/visible_bounds/src/main.rs +++ b/examples/visible_bounds/src/main.rs @@ -5,8 +5,7 @@ use iced::widget::{ }; use iced::window; use iced::{ - Alignment, Color, Element, Font, Length, Point, Rectangle, Subscription, - Task, Theme, + Color, Element, Font, Length, Point, Rectangle, Subscription, Task, Theme, }; pub fn main() -> iced::Result { @@ -70,7 +69,7 @@ impl Example { .color_maybe(color), ] .height(40) - .align_items(Alignment::Center) + .center_y() }; let view_bounds = |label, bounds: Option<Rectangle>| { diff --git a/examples/websocket/src/main.rs b/examples/websocket/src/main.rs index d8246436..1bac61aa 100644 --- a/examples/websocket/src/main.rs +++ b/examples/websocket/src/main.rs @@ -1,6 +1,5 @@ mod echo; -use iced::alignment::{self, Alignment}; use iced::widget::{ self, button, center, column, row, scrollable, text, text_input, }; @@ -113,12 +112,8 @@ impl WebSocket { .on_input(Message::NewMessageChanged) .padding(10); - let mut button = button( - text("Send") - .height(40) - .vertical_alignment(alignment::Vertical::Center), - ) - .padding([0, 20]); + let mut button = + button(text("Send").height(40).center_y()).padding([0, 20]); if matches!(self.state, State::Connected(_)) { if let Some(message) = echo::Message::new(&self.new_message) { @@ -127,9 +122,7 @@ impl WebSocket { } } - row![input, button] - .spacing(10) - .align_items(Alignment::Center) + row![input, button].spacing(10).center_y() }; column![message_log, new_message_input] diff --git a/widget/src/column.rs b/widget/src/column.rs index 0b81c545..ef4ee99d 100644 --- a/widget/src/column.rs +++ b/widget/src/column.rs @@ -1,4 +1,5 @@ //! Distribute content vertically. +use crate::core::alignment::{self, Alignment}; use crate::core::event::{self, Event}; use crate::core::layout; use crate::core::mouse; @@ -6,8 +7,8 @@ use crate::core::overlay; use crate::core::renderer; use crate::core::widget::{Operation, Tree}; use crate::core::{ - Alignment, Clipboard, Element, Layout, Length, Padding, Pixels, Rectangle, - Shell, Size, Vector, Widget, + Clipboard, Element, Layout, Length, Padding, Pixels, Rectangle, Shell, + Size, Vector, Widget, }; /// A container that distributes its contents vertically. @@ -19,7 +20,7 @@ pub struct Column<'a, Message, Theme = crate::Theme, Renderer = crate::Renderer> width: Length, height: Length, max_width: f32, - align_items: Alignment, + align: Alignment, clip: bool, children: Vec<Element<'a, Message, Theme, Renderer>>, } @@ -63,7 +64,7 @@ where width: Length::Shrink, height: Length::Shrink, max_width: f32::INFINITY, - align_items: Alignment::Start, + align: Alignment::Start, clip: false, children, } @@ -103,9 +104,24 @@ where self } + /// Centers the contents of the [`Column`] horizontally. + pub fn center_x(self) -> Self { + self.align_x(Alignment::Center) + } + + /// Aligns the contents of the [`Column`] to the left. + pub fn align_left(self) -> Self { + self.align_x(alignment::left()) + } + + /// Aligns the contents of the [`Column`] to the right. + pub fn align_right(self) -> Self { + self.align_x(alignment::right()) + } + /// Sets the horizontal alignment of the contents of the [`Column`] . - pub fn align_items(mut self, align: Alignment) -> Self { - self.align_items = align; + pub fn align_x(mut self, align: impl Into<alignment::Horizontal>) -> Self { + self.align = Alignment::from(align.into()); self } @@ -210,7 +226,7 @@ where self.height, self.padding, self.spacing, - self.align_items, + self.align, &self.children, &mut tree.children, ) diff --git a/widget/src/container.rs b/widget/src/container.rs index 08d5cb17..adfe347c 100644 --- a/widget/src/container.rs +++ b/widget/src/container.rs @@ -94,27 +94,19 @@ where /// Sets the [`Container`] to fill the available space in the horizontal axis. /// - /// This can be useful to quickly position content when chained with - /// alignment functions—like [`center_x`]. - /// /// Calling this method is equivalent to calling [`width`] with a /// [`Length::Fill`]. /// - /// [`center_x`]: Self::center_x /// [`width`]: Self::width pub fn fill_x(self) -> Self { self.width(Length::Fill) } - /// Sets the [`Container`] to fill the available space in the vetical axis. - /// - /// This can be useful to quickly position content when chained with - /// alignment functions—like [`center_y`]. + /// Sets the [`Container`] to fill the available space in the vertical axis. /// /// Calling this method is equivalent to calling [`height`] with a /// [`Length::Fill`]. /// - /// [`center_y`]: Self::center_x /// [`height`]: Self::height pub fn fill_y(self) -> Self { self.height(Length::Fill) @@ -125,7 +117,6 @@ where /// Calling this method is equivalent to chaining [`fill_x`] and /// [`fill_y`]. /// - /// [`center`]: Self::center /// [`fill_x`]: Self::fill_x /// [`fill_y`]: Self::fill_y pub fn fill(self) -> Self { @@ -144,18 +135,6 @@ where self } - /// Sets the content alignment for the horizontal axis of the [`Container`]. - pub fn align_x(mut self, alignment: alignment::Horizontal) -> Self { - self.horizontal_alignment = alignment; - self - } - - /// Sets the content alignment for the vertical axis of the [`Container`]. - pub fn align_y(mut self, alignment: alignment::Vertical) -> Self { - self.vertical_alignment = alignment; - self - } - /// Sets the width of the [`Container`] and centers its contents horizontally. pub fn center_x(self, width: impl Into<Length>) -> Self { self.width(width).align_x(alignment::Horizontal::Center) @@ -179,6 +158,44 @@ where self.center_x(length).center_y(length) } + /// Aligns the contents of the [`Container`] to the left. + pub fn align_left(self) -> Self { + self.align_x(alignment::left()) + } + + /// Aligns the contents of the [`Container`] to the right. + pub fn align_right(self) -> Self { + self.align_x(alignment::right()) + } + + /// Aligns the contents of the [`Container`] to the top. + pub fn align_top(self) -> Self { + self.align_y(alignment::top()) + } + + /// Aligns the contents of the [`Container`] to the bottom. + pub fn align_bottom(self) -> Self { + self.align_y(alignment::bottom()) + } + + /// Sets the content alignment for the horizontal axis of the [`Container`]. + pub fn align_x( + mut self, + alignment: impl Into<alignment::Horizontal>, + ) -> Self { + self.horizontal_alignment = alignment.into(); + self + } + + /// Sets the content alignment for the vertical axis of the [`Container`]. + pub fn align_y( + mut self, + alignment: impl Into<alignment::Vertical>, + ) -> Self { + self.vertical_alignment = alignment.into(); + self + } + /// Sets whether the contents of the [`Container`] should be clipped on /// overflow. pub fn clip(mut self, clip: bool) -> Self { diff --git a/widget/src/helpers.rs b/widget/src/helpers.rs index d7631959..f27b7807 100644 --- a/widget/src/helpers.rs +++ b/widget/src/helpers.rs @@ -906,7 +906,7 @@ where + 'a, Theme: text::Catalog + crate::svg::Catalog + 'a, { - use crate::core::{Alignment, Font}; + use crate::core::Font; use crate::svg; use once_cell::sync::Lazy; @@ -921,7 +921,7 @@ where text("iced").size(text_size).font(Font::MONOSPACE) ] .spacing(text_size.0 / 3.0) - .align_items(Alignment::Center) + .center_y() .into() } diff --git a/widget/src/row.rs b/widget/src/row.rs index c8fcdb61..129feb7e 100644 --- a/widget/src/row.rs +++ b/widget/src/row.rs @@ -1,4 +1,5 @@ //! Distribute content horizontally. +use crate::core::alignment::{self, Alignment}; use crate::core::event::{self, Event}; use crate::core::layout::{self, Layout}; use crate::core::mouse; @@ -6,8 +7,8 @@ use crate::core::overlay; use crate::core::renderer; use crate::core::widget::{Operation, Tree}; use crate::core::{ - Alignment, Clipboard, Element, Length, Padding, Pixels, Rectangle, Shell, - Size, Vector, Widget, + Clipboard, Element, Length, Padding, Pixels, Rectangle, Shell, Size, + Vector, Widget, }; /// A container that distributes its contents horizontally. @@ -17,7 +18,7 @@ pub struct Row<'a, Message, Theme = crate::Theme, Renderer = crate::Renderer> { padding: Padding, width: Length, height: Length, - align_items: Alignment, + align: Alignment, clip: bool, children: Vec<Element<'a, Message, Theme, Renderer>>, } @@ -60,7 +61,7 @@ where padding: Padding::ZERO, width: Length::Shrink, height: Length::Shrink, - align_items: Alignment::Start, + align: Alignment::Start, clip: false, children, } @@ -94,9 +95,24 @@ where self } + /// Centers the contents of the [`Row`] vertically. + pub fn center_y(self) -> Self { + self.align_y(Alignment::Center) + } + + /// Aligns the contents of the [`Row`] to the top. + pub fn align_top(self) -> Self { + self.align_y(alignment::top()) + } + + /// Aligns the contents of the [`Row`] to the bottom. + pub fn align_bottom(self) -> Self { + self.align_y(alignment::bottom()) + } + /// Sets the vertical alignment of the contents of the [`Row`] . - pub fn align_items(mut self, align: Alignment) -> Self { - self.align_items = align; + pub fn align_y(mut self, align: impl Into<alignment::Vertical>) -> Self { + self.align = Alignment::from(align.into()); self } @@ -199,7 +215,7 @@ where self.height, self.padding, self.spacing, - self.align_items, + self.align, &self.children, &mut tree.children, ) diff --git a/widget/src/scrollable.rs b/widget/src/scrollable.rs index e6208528..cd669cad 100644 --- a/widget/src/scrollable.rs +++ b/widget/src/scrollable.rs @@ -109,8 +109,28 @@ where self } - /// Sets the alignment of the horizontal direction of the [`Scrollable`], if applicable. - pub fn align_x(mut self, alignment: Alignment) -> Self { + /// Anchors the vertical [`Scrollable`] direction to the top. + pub fn anchor_top(self) -> Self { + self.anchor_y(Anchor::Start) + } + + /// Anchors the vertical [`Scrollable`] direction to the bottom. + pub fn anchor_bottom(self) -> Self { + self.anchor_y(Anchor::End) + } + + /// Anchors the horizontal [`Scrollable`] direction to the left. + pub fn anchor_left(self) -> Self { + self.anchor_x(Anchor::Start) + } + + /// Anchors the horizontal [`Scrollable`] direction to the right. + pub fn anchor_right(self) -> Self { + self.anchor_x(Anchor::End) + } + + /// Sets the [`Anchor`] of the horizontal direction of the [`Scrollable`], if applicable. + pub fn anchor_x(mut self, alignment: Anchor) -> Self { match &mut self.direction { Direction::Horizontal(horizontal) | Direction::Both { horizontal, .. } => { @@ -122,8 +142,8 @@ where self } - /// Sets the alignment of the vertical direction of the [`Scrollable`], if applicable. - pub fn align_y(mut self, alignment: Alignment) -> Self { + /// Sets the [`Anchor`] of the vertical direction of the [`Scrollable`], if applicable. + pub fn anchor_y(mut self, alignment: Anchor) -> Self { match &mut self.direction { Direction::Vertical(vertical) | Direction::Both { vertical, .. } => { @@ -228,7 +248,7 @@ pub struct Scrollbar { width: f32, margin: f32, scroller_width: f32, - alignment: Alignment, + alignment: Anchor, embedded: bool, } @@ -238,7 +258,7 @@ impl Default for Scrollbar { width: 10.0, margin: 0.0, scroller_width: 10.0, - alignment: Alignment::Start, + alignment: Anchor::Start, embedded: false, } } @@ -250,26 +270,26 @@ impl Scrollbar { Self::default() } - /// Sets the scrollbar width of the [`Scrollable`] . + /// Sets the scrollbar width of the [`Scrollbar`] . pub fn width(mut self, width: impl Into<Pixels>) -> Self { self.width = width.into().0.max(0.0); self } - /// Sets the scrollbar margin of the [`Scrollable`] . + /// Sets the scrollbar margin of the [`Scrollbar`] . pub fn margin(mut self, margin: impl Into<Pixels>) -> Self { self.margin = margin.into().0; self } - /// Sets the scroller width of the [`Scrollable`] . + /// Sets the scroller width of the [`Scrollbar`] . pub fn scroller_width(mut self, scroller_width: impl Into<Pixels>) -> Self { self.scroller_width = scroller_width.into().0.max(0.0); self } - /// Sets the alignment of the [`Scrollable`] . - pub fn alignment(mut self, alignment: Alignment) -> Self { + /// Sets the [`Anchor`] of the [`Scrollbar`] . + pub fn anchor(mut self, alignment: Anchor) -> Self { self.alignment = alignment; self } @@ -284,13 +304,14 @@ impl Scrollbar { } } -/// Alignment of the scrollable's content relative to it's [`Viewport`] in one direction. +/// The anchor of the scroller of the [`Scrollable`] relative to its [`Viewport`] +/// on a given axis. #[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] -pub enum Alignment { - /// Content is aligned to the start of the [`Viewport`]. +pub enum Anchor { + /// Scroller is anchoer to the start of the [`Viewport`]. #[default] Start, - /// Content is aligned to the end of the [`Viewport`] + /// Content is aligned to the end of the [`Viewport`]. End, } @@ -1159,13 +1180,13 @@ impl Offset { self, viewport: f32, content: f32, - alignment: Alignment, + alignment: Anchor, ) -> f32 { let offset = self.absolute(viewport, content); match alignment { - Alignment::Start => offset, - Alignment::End => ((content - viewport).max(0.0) - offset).max(0.0), + Anchor::Start => offset, + Anchor::End => ((content - viewport).max(0.0) - offset).max(0.0), } } } @@ -1252,9 +1273,9 @@ impl State { .map(|p| p.alignment) .unwrap_or_default(); - let align = |alignment: Alignment, delta: f32| match alignment { - Alignment::Start => delta, - Alignment::End => -delta, + let align = |alignment: Anchor, delta: f32| match alignment { + Anchor::Start => delta, + Anchor::End => -delta, }; let delta = Vector::new( @@ -1592,14 +1613,14 @@ impl Scrollbars { pub(super) mod internals { use crate::core::{Point, Rectangle}; - use super::Alignment; + use super::Anchor; #[derive(Debug, Copy, Clone)] pub struct Scrollbar { pub total_bounds: Rectangle, pub bounds: Rectangle, pub scroller: Option<Scroller>, - pub alignment: Alignment, + pub alignment: Anchor, } impl Scrollbar { @@ -1621,8 +1642,8 @@ pub(super) mod internals { / (self.bounds.height - scroller.bounds.height); match self.alignment { - Alignment::Start => percentage, - Alignment::End => 1.0 - percentage, + Anchor::Start => percentage, + Anchor::End => 1.0 - percentage, } } else { 0.0 @@ -1642,8 +1663,8 @@ pub(super) mod internals { / (self.bounds.width - scroller.bounds.width); match self.alignment { - Alignment::Start => percentage, - Alignment::End => 1.0 - percentage, + Anchor::Start => percentage, + Anchor::End => 1.0 - percentage, } } else { 0.0 |