diff --git a/.vscode/launch.json b/.vscode/launch.json index a6a3713f..f7252e2f 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -112,24 +112,6 @@ "args": [], "cwd": "${workspaceFolder}" }, - { - "type": "lldb", - "request": "launch", - "name": "Debug executable 'cupertino-alert'", - "cargo": { - "args": [ - "build", - "--bin=cupertino-alert", - "--package=cupertino-alert" - ], - "filter": { - "name": "cupertino-alert", - "kind": "bin" - } - }, - "args": [], - "cwd": "${workspaceFolder}" - }, { "type": "lldb", "request": "launch", diff --git a/Cargo.toml b/Cargo.toml index 288e9957..639f5368 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,29 +37,31 @@ quad = [] spinner = [] context_menu = [] segmented_button = [] +slide_bar = [] default = [ "badge", "card", - #"number_input", - #"date_picker", + "number_input", + "date_picker", "color_picker", - #"floating_element", + "floating_element", "grid", - #"modal", - #"tab_bar", - #"tabs", - #"time_picker", - # "wrap", - #"selection_list", - # "split", + "modal", + "tab_bar", + "tabs", + "time_picker", + "slide_bar", + "wrap", + "selection_list", + "split", #"menu", - #"quad", - #"context_menu", - #"spinner", - #"cupertino", - #"segmented_button", - #"num-traits" + "quad", + "context_menu", + "spinner", + "cupertino", + "segmented_button", + "num-traits" ] [dependencies] @@ -90,30 +92,30 @@ members = [ "examples/badge", "examples/card", "examples/color_picker", - #"examples/cupertino/cupertino_button", - #"examples/cupertino/cupertino_spinner", - #"examples/cupertino/cupertino_switch", - #"examples/date_picker", - #"examples/floating_element", - #"examples/floating_element_anchors", + "examples/cupertino/cupertino_button", + "examples/cupertino/cupertino_spinner", + "examples/cupertino/cupertino_switch", + "examples/date_picker", + "examples/floating_element", + "examples/floating_element_anchors", "examples/grid", - #"examples/modal", - #"examples/modal_component", - #"examples/multiple_modals", - #"examples/tab_bar", - #"examples/tabs", - #"examples/time_picker", - #"examples/wrap", - #"examples/number_input", - #"examples/selection_list", - #"examples/split", - #"examples/split_scroller", + "examples/modal", + "examples/modal_component", + "examples/multiple_modals", + "examples/tab_bar", + "examples/tabs", + "examples/time_picker", + "examples/wrap", + "examples/number_input", + "examples/selection_list", + "examples/split", + "examples/split_scroller", #"examples/menu", - #"examples/spinner", - #"examples/context_menu", - #"examples/WidgetIDReturn", - #"examples/segmented_button", - #"examples/sliderbar", + "examples/spinner", + "examples/context_menu", + "examples/WidgetIDReturn", + "examples/segmented_button", + "examples/sliderbar", ] [workspace.dependencies.iced] diff --git a/README.md b/README.md index 12e14ec7..530e7fba 100644 --- a/README.md +++ b/README.md @@ -174,6 +174,12 @@ Enable this widget with the feature `menu`. You might also want to enable the feature `quad` for drawing separators. +### Slide Bar + +Please take a look into our examples on how to use slidebars. + +Enable this widget with the feature `slide_bar`. + ## Quickstart features diff --git a/examples/WidgetIDReturn/src/main.rs b/examples/WidgetIDReturn/src/main.rs index 0f825769..5c59f8f2 100644 --- a/examples/WidgetIDReturn/src/main.rs +++ b/examples/WidgetIDReturn/src/main.rs @@ -2,7 +2,7 @@ use iced::{ alignment, font, theme::Theme, widget::{container, text, Column, Container, Row, Text}, - window, Alignment, Application, Command, Element, Length, Settings, + window, Alignment, Application, Command, Element, Length, Settings, Size, }; #[derive(Debug)] @@ -25,9 +25,9 @@ pub enum Message { fn main() -> iced::Result { NumberInputDemo::run(Settings { - default_text_size: 12.0, + default_text_size: iced::Pixels(12.0), window: window::Settings { - size: (500, 400), + size: Size::new(500.0, 400.0), ..Default::default() }, ..Settings::default() diff --git a/examples/card/src/main.rs b/examples/card/src/main.rs index 59a4a3f8..bccd1e9f 100644 --- a/examples/card/src/main.rs +++ b/examples/card/src/main.rs @@ -14,6 +14,7 @@ fn main() -> iced::Result { enum Message { CloseCard, OpenCard, + #[allow(dead_code)] Loaded(Result<(), String>), FontLoaded(Result<(), font::Error>), } diff --git a/examples/color_picker/src/main.rs b/examples/color_picker/src/main.rs index dd872888..a6e3acac 100644 --- a/examples/color_picker/src/main.rs +++ b/examples/color_picker/src/main.rs @@ -16,6 +16,7 @@ enum Message { ChooseColor, SubmitColor(Color), CancelColor, + #[allow(dead_code)] Loaded(Result<(), String>), FontLoaded(Result<(), font::Error>), } @@ -116,7 +117,9 @@ impl Application for ColorPickerExample { .center_x() .center_y() .width(Length::Fill) - .height(Length::Fill).center_x().center_y() + .height(Length::Fill) + .center_x() + .center_y() .into() } } diff --git a/examples/cupertino/cupertino_alert/Cargo.toml b/examples/cupertino/cupertino_alert/Cargo.toml deleted file mode 100644 index 5498ec8b..00000000 --- a/examples/cupertino/cupertino_alert/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "cupertino-alert" -version = "0.1.0" -authors = ["Brett Byler "] -edition = "2021" -publish = false - -[dependencies] -iced.workspace = true -iced_aw = { path = "../../../", features = ["cupertino"] } - diff --git a/examples/cupertino/cupertino_alert/Makefile b/examples/cupertino/cupertino_alert/Makefile deleted file mode 100644 index 2573848c..00000000 --- a/examples/cupertino/cupertino_alert/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -SHELL := /bin/bash - -run: - cargo run --package cupertino-alert - -.ONESHELL: - diff --git a/examples/cupertino/cupertino_alert/README.md b/examples/cupertino/cupertino_alert/README.md deleted file mode 100644 index 34e4a147..00000000 --- a/examples/cupertino/cupertino_alert/README.md +++ /dev/null @@ -1,19 +0,0 @@ -Cupertino Alert Example -========================= - -An application that uses the `CupertinoAlert` widget to draw a -Cupertino-style alert dialog box. - -The __[`main`]__ file contains all the code of the example. - -You can run it with `cargo run`: - -```bash -cargo run --package cupertino-alert - -# Or -make run -``` - -[`main`]: src/main.rs - diff --git a/examples/cupertino/cupertino_alert/src/main.rs b/examples/cupertino/cupertino_alert/src/main.rs deleted file mode 100644 index dab42e23..00000000 --- a/examples/cupertino/cupertino_alert/src/main.rs +++ /dev/null @@ -1,148 +0,0 @@ -use iced::widget::{column, container, Text}; -use iced::{alignment, executor, font, Application, Command, Element, Length, Settings, Theme}; -use iced_aw::native::cupertino::cupertino_alert::{CupertinoAlert, CupertinoDialogAction}; -use iced_aw::native::cupertino::cupertino_button::CupertinoButton; -use iced_aw::native::cupertino::cupertino_colors::system_red; - -pub fn main() -> iced::Result { - Alert::run(Settings { - antialiasing: true, - ..Settings::default() - }) -} - -#[derive(Debug)] -enum Alert { - BackdropClicked, - CancelEvent, - ConfirmEvent, - DialogEscape, - Loading, - ShowModal, -} - -#[derive(Debug, Clone)] -enum Message { - BackdropClicked, - CancelEvent, - ConfirmEvent, - DialogEscape, - ShowModal, - Loaded(Result<(), String>), - FontLoaded(Result<(), font::Error>), -} - -#[rustfmt::skip] -mod constants { - pub static PRIMARY_TEXT: &str = "Allow \"Maps\" to access your location while using the app?"; - pub static SECONDARY_TEXT: &str = "Your current location will be displayed on the map and used for directions, nearby search results, and estimated travel times. "; - pub static ALLOW: &str = "Allow"; - pub static DONT_ALLOW: &str = "Don't Allow"; -} - -use constants::*; - -async fn load() -> Result<(), String> { - Ok(()) -} - -// `cargo fmt` becomes unreadable for this example, so switching off // -#[rustfmt::skip] -impl Application for Alert { - type Executor = executor::Default; - type Message = Message; - type Theme = Theme; - type Flags = (); - - fn new(_flags: ()) -> (Self, Command) { - (Alert::Loading, Command::batch(vec![ - font::load(iced_aw::graphics::SF_UI_ROUNDED_BYTES).map(Message::FontLoaded), - Command::perform(load(), Message::Loaded), - ])) - } - - fn title(&self) -> String { - String::from("CupertinoAlert - Iced") - } - - fn update(&mut self, message: Message) -> Command { - match message { - Message::BackdropClicked => *self = Alert::BackdropClicked, - Message::CancelEvent => *self = Alert::CancelEvent, - Message::ConfirmEvent => *self = Alert::ConfirmEvent, - Message::DialogEscape => *self = Alert::DialogEscape, - Message::ShowModal => *self = Alert::ShowModal, - _ => {} - } - - Command::none() - } - - fn view(&self) -> Element { - let modal_hidden = !matches!(self, Alert::ShowModal); - - match self { - Alert::CancelEvent => println!("Received click for the cancel button"), - Alert::ConfirmEvent => println!("Received click for the confirm button"), - _ => (), - }; - - let confirm_button: CupertinoButton = CupertinoButton::new() - .on_pressed(Some(Message::ConfirmEvent)) - .body(Text::new(DONT_ALLOW) - .size(24) - .width(Length::Fixed(100.0)) - .height(Length::Fixed(50.0)) - ); - - let cancel_button: CupertinoButton = CupertinoButton::new() - .on_pressed(Some(Message::CancelEvent)) - .color(Some(system_red(1.0))) - .body(Text::new(ALLOW) - .size(24) - .width(Length::Fixed(100.0)) - .height(Length::Fixed(50.0)) - ); - - let alert = CupertinoAlert::new() - .is_hidden(modal_hidden) - .title(PRIMARY_TEXT.to_string()) - .content(SECONDARY_TEXT.to_string()) - .actions(vec![ - CupertinoDialogAction::new() - .is_enabled(true) - .child(confirm_button.into()) - .on_pressed(Some(Message::ConfirmEvent)), - - CupertinoDialogAction::new() - .is_enabled(true) - .child(cancel_button.into()) - .on_pressed(Some(Message::CancelEvent)), - - ]) - .backdrop(Some(Message::BackdropClicked)) - .on_escape(Some(Message::DialogEscape)); - - container(column![ - CupertinoButton::new() - .body(Text::new("Click to show the CupertinoAlertDialog") - .size(24.0) - .width(Length::Shrink) - .height(Length::Fixed(75.0)) - .horizontal_alignment(alignment::Horizontal::Center) - ) - .on_pressed(Some(Message::ShowModal)), - - alert, - ].align_items(alignment::Horizontal::Center.into())) - .center_x() - .center_y() - .width(Length::Fill) - .height(Length::Fill) - .into() - } - - fn theme(&self) -> Self::Theme { - Theme::Light - } -} diff --git a/examples/cupertino/cupertino_button/src/main.rs b/examples/cupertino/cupertino_button/src/main.rs index b69f42e3..94a5a9c2 100644 --- a/examples/cupertino/cupertino_button/src/main.rs +++ b/examples/cupertino/cupertino_button/src/main.rs @@ -23,6 +23,7 @@ enum ButtonApp { enum Message { EnabledButtonClicked, EnabledFilledButtonClicked, + #[allow(dead_code)] Loaded(Result<(), String>), FontLoaded(Result<(), font::Error>), } diff --git a/examples/cupertino/cupertino_switch/src/main.rs b/examples/cupertino/cupertino_switch/src/main.rs index 4b901c5d..36a5337a 100644 --- a/examples/cupertino/cupertino_switch/src/main.rs +++ b/examples/cupertino/cupertino_switch/src/main.rs @@ -76,17 +76,17 @@ impl Application for Switch { container(column![ text(left_text) - .width(Length::Fill) + .width(Length::Shrink) .size(25) .horizontal_alignment(alignment::Horizontal::Center) .vertical_alignment(alignment::Vertical::Center), text(right_text) - .width(Length::Fill) + .width(Length::Shrink) .size(25) .horizontal_alignment(alignment::Horizontal::Center) .vertical_alignment(alignment::Vertical::Center), - ]).width(Length::Fill).center_y(), + ]).width(Length::Shrink).center_y(), toggle_2, ].spacing(100).align_items(alignment::Alignment::Center).width(Length::Shrink); diff --git a/examples/date_picker/src/main.rs b/examples/date_picker/src/main.rs index 8e49a420..c61ce8fe 100644 --- a/examples/date_picker/src/main.rs +++ b/examples/date_picker/src/main.rs @@ -15,6 +15,7 @@ enum Message { ChooseDate, SubmitDate(Date), CancelDate, + #[allow(dead_code)] Loaded(Result<(), String>), FontLoaded(Result<(), font::Error>), } diff --git a/examples/floating_element/src/main.rs b/examples/floating_element/src/main.rs index eb79e97b..6a763de0 100644 --- a/examples/floating_element/src/main.rs +++ b/examples/floating_element/src/main.rs @@ -18,6 +18,7 @@ fn main() -> iced::Result { #[derive(Debug, Clone)] enum Message { ButtonPressed, + #[allow(dead_code)] Loaded(Result<(), String>), FontLoaded(Result<(), font::Error>), } diff --git a/examples/modal/src/main.rs b/examples/modal/src/main.rs index bcf0fc05..5dc61814 100644 --- a/examples/modal/src/main.rs +++ b/examples/modal/src/main.rs @@ -17,6 +17,7 @@ enum Message { CloseModal, CancelButtonPressed, OkButtonPressed, + #[allow(dead_code)] Loaded(Result<(), String>), FontLoaded(Result<(), font::Error>), } diff --git a/examples/modal_component/src/main.rs b/examples/modal_component/src/main.rs index 0bd03e98..b1566e6e 100644 --- a/examples/modal_component/src/main.rs +++ b/examples/modal_component/src/main.rs @@ -14,6 +14,7 @@ fn main() -> iced::Result { enum Message { OpenModal, CloseModal, + #[allow(dead_code)] Loaded(Result<(), String>), FontLoaded(Result<(), font::Error>), } diff --git a/examples/selection_list/src/main.rs b/examples/selection_list/src/main.rs index cb4e11af..6717183c 100644 --- a/examples/selection_list/src/main.rs +++ b/examples/selection_list/src/main.rs @@ -1,5 +1,5 @@ use iced::{ - widget::{button, Column, Container, Space, Text}, + widget::{button, Column, Container, Text}, Alignment, Element, Font, Length, Sandbox, Settings, }; use iced_aw::{selection_list::SelectionList, SelectionListStyles}; @@ -83,8 +83,9 @@ impl Sandbox for Example { .width(Length::Shrink) .height(Length::Fixed(100.0)); - let mut content = Column::new() + let content = Column::new() .width(Length::Fill) + .height(Length::Fill) .align_items(Alignment::Center) .spacing(10) .push(selection_list) @@ -93,7 +94,7 @@ impl Sandbox for Example { .push(button("press to add at selection").on_press(Message::AddAtSelection)) .push(button("Manual select Index 2").on_press(Message::ManualSelection)); - content = content.push(Space::with_height(Length::Fixed(800.0))); + //content = content.push(Space::with_height(Length::Fixed(400.0))); Container::new(content) .width(Length::Fill) diff --git a/examples/tab_bar/src/main.rs b/examples/tab_bar/src/main.rs index 4fb4e348..e494e7bd 100644 --- a/examples/tab_bar/src/main.rs +++ b/examples/tab_bar/src/main.rs @@ -19,6 +19,7 @@ enum Message { TabLabelInputChanged(String), TabContentInputChanged(String), NewTab, + #[allow(dead_code)] Loaded(Result<(), String>), FontLoaded(Result<(), font::Error>), } diff --git a/examples/tabs/src/ferris.rs b/examples/tabs/src/ferris.rs index 34317ec5..704e15b1 100644 --- a/examples/tabs/src/ferris.rs +++ b/examples/tabs/src/ferris.rs @@ -59,6 +59,7 @@ impl Tab for FerrisTab { FerrisMessage::ImageWidthChanged, )), ) + .align_x(iced::alignment::Horizontal::Center) .into(); content.map(Message::Ferris) diff --git a/examples/tabs/src/main.rs b/examples/tabs/src/main.rs index ed8186e1..1c2b2cc3 100644 --- a/examples/tabs/src/main.rs +++ b/examples/tabs/src/main.rs @@ -71,6 +71,7 @@ enum Message { Ferris(FerrisMessage), Counter(CounterMessage), Settings(SettingsMessage), + #[allow(dead_code)] Loaded(Result<(), String>), FontLoaded(Result<(), font::Error>), } @@ -196,7 +197,8 @@ trait Tab { let column = Column::new() .spacing(20) .push(Text::new(self.title()).size(HEADER_SIZE)) - .push(self.content()); + .push(self.content()) + .align_items(iced::Alignment::Center); Container::new(column) .width(Length::Fill) diff --git a/examples/time_picker/src/main.rs b/examples/time_picker/src/main.rs index 9ba56f48..619934e8 100644 --- a/examples/time_picker/src/main.rs +++ b/examples/time_picker/src/main.rs @@ -15,6 +15,7 @@ enum Message { ChooseTime, SubmitTime(Time), CancelTime, + #[allow(dead_code)] Loaded(Result<(), String>), FontLoaded(Result<(), font::Error>), } diff --git a/examples/wrap/src/main.rs b/examples/wrap/src/main.rs index f47e0aa2..0520d8c2 100644 --- a/examples/wrap/src/main.rs +++ b/examples/wrap/src/main.rs @@ -71,6 +71,7 @@ enum Message { ChangeSpacing(f32), ChangeLineSpacing(f32), ChangeMinimalLength(f32), + #[allow(dead_code)] Loaded(Result<(), String>), FontLoaded(Result<(), font::Error>), } diff --git a/src/core/overlay.rs b/src/core/overlay.rs index 0d0e22c7..d60bac4c 100644 --- a/src/core/overlay.rs +++ b/src/core/overlay.rs @@ -10,28 +10,28 @@ pub trait Position { } impl Position for layout::Node { - fn center_and_bounce(self, position: Point, _bounds: Size) -> Self { + fn center_and_bounce(self, position: Point, bounds: Size) -> Self { let size = self.size(); - let mut new_self = self.move_to(Point::new( + let new_self = self.move_to(Point::new( (position.x - size.width / 2.0).max(0.0), (position.y - size.height / 2.0).max(0.0), )); - let bounds = new_self.bounds(); + let new_self_bounds = new_self.bounds(); - new_self = new_self.move_to(Point::new( - if bounds.x + bounds.width > bounds.width { - (bounds.x - (bounds.width - (bounds.width - bounds.x))).max(0.0) + new_self.move_to(Point::new( + if new_self_bounds.x + new_self_bounds.width > bounds.width { + (new_self_bounds.x - (new_self_bounds.width - (bounds.width - new_self_bounds.x))) + .max(0.0) } else { - bounds.x + new_self_bounds.x }, - if bounds.y + bounds.height > bounds.height { - (bounds.y - (bounds.height - (bounds.height - bounds.y))).max(0.0) + if new_self_bounds.y + new_self_bounds.height > bounds.height { + (new_self_bounds.y - (new_self_bounds.height - (bounds.height - new_self_bounds.y))) + .max(0.0) } else { - bounds.y + new_self_bounds.y }, - )); - - new_self + )) } } diff --git a/src/lib.rs b/src/lib.rs index 59d7a491..05a7ba7e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -151,6 +151,8 @@ mod platform { #[cfg(feature = "spinner")] pub use {crate::native::spinner, crate::style::SpinnerStyle, spinner::Spinner}; + #[doc(no_inline)] + #[cfg(feature = "slide_bar")] pub use crate::native::SlideBar; #[doc(no_inline)] diff --git a/src/native/context_menu.rs b/src/native/context_menu.rs index 93127a74..293c2d72 100644 --- a/src/native/context_menu.rs +++ b/src/native/context_menu.rs @@ -87,12 +87,9 @@ where Renderer: 'a + core::Renderer, Renderer::Theme: StyleSheet, { - fn width(&self) -> Length { - self.underlay.as_widget().width() - } - fn height(&self) -> Length { - self.underlay.as_widget().height() + fn size(&self) -> core::Size { + self.underlay.as_widget().size() } fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { diff --git a/src/native/cupertino/cupertino_alert.rs b/src/native/cupertino/cupertino_alert.rs deleted file mode 100644 index 334e102d..00000000 --- a/src/native/cupertino/cupertino_alert.rs +++ /dev/null @@ -1,637 +0,0 @@ -#![allow(clippy::todo)] - -use crate::graphics::SF_UI_ROUNDED; -use crate::native::cupertino::cupertino_colors::secondary_system_fill; - -use iced_widget::{ - core::{ - self, - alignment::Horizontal, - event, keyboard, - layout::{Limits, Node}, - mouse::{self, Cursor}, - renderer::{self, Quad}, - touch, - widget::Tree, - Background, Clipboard, Color, Element, Event, Font, Layout, Length, Point, Rectangle, - Shell, Size, Widget, - }, - style::application, - text, Text, -}; -use std::ops::Range; - -/** - * `CupertinoDialogAction` - * - * See - * - * - * - * for constants, and - * - * - * - * for the Flutter example / expected usage. - * - */ -#[allow(missing_debug_implementations)] -pub struct CupertinoDialogAction<'a, Message, Renderer> -where - Message: Clone, - Renderer: core::Renderer + core::text::Renderer + 'a, - Renderer::Theme: application::StyleSheet + text::StyleSheet, -{ - on_pressed: Option, - - /// The content to show in the dialog box (typically a button) - child: Element<'a, Message, Renderer>, - - /// Use `is_enabled` to provide logic for making modal action buttons enabled/disabled. - /// Defaults to `true` - is_enabled: bool, -} - -impl<'a, Message, Renderer> Default for CupertinoDialogAction<'a, Message, Renderer> -where - Message: Clone, - Renderer: core::Renderer + core::text::Renderer + 'a, - Renderer::Theme: application::StyleSheet + text::StyleSheet, -{ - fn default() -> Self { - Self { - is_enabled: true, - on_pressed: None, - child: Text::new("Example").into(), - } - } -} - -impl<'a, Message, Renderer> CupertinoDialogAction<'a, Message, Renderer> -where - Message: Clone, - Renderer: core::Renderer + core::text::Renderer + 'a, - Renderer::Theme: application::StyleSheet + text::StyleSheet, -{ - /// Creates a new [`CupertinoDialogAction`] widget. - #[must_use] - pub fn new() -> Self { - Self::default() - } - - /// Sets the `child` for the [`CupertinoDialogAction`]. - #[must_use] - pub fn child(mut self, child: Element<'a, Message, Renderer>) -> Self { - self.child = child; - self - } - - /// Sets `is_enabled` for the [`CupertinoDialogAction`]. - #[must_use] - pub fn is_enabled(mut self, is_enabled: bool) -> Self { - self.is_enabled = is_enabled; - self - } - - /// Sets `on_pressed` for the [`CupertinoDialogAction`]. - #[must_use] - pub fn on_pressed(mut self, on_pressed: Option) -> Self { - self.on_pressed = on_pressed; - self - } -} - -/** - * `CupertinoAlert` - * - * See both - * - * 1. - * 2. - * - * as sources for API and behavior. The Iced AW modal (`src/native/modal.rs`) is also a source for - * the design of this struct. - * - * The example under `examples/cupertino/cupertino_alert/` shows how to work with the - * `CupertinoAlert`. - * - * Design and Default Behaviour - * ---------------------------- - * 1. By default: clicking the "Cancel" or "Confirm" buttons causes the modal to close - * 2. By default: pressing the escape key causes the modal to close - * 3. By default: clicking anywhere in the backdrop causes the modal to close - * 4. The modal assumes the actions are of length 2, with the "Confirm" action coming first, and - * the "Cancel" action coming second. - * - */ -#[allow(missing_debug_implementations)] -pub struct CupertinoAlert<'a, Message, Renderer> -where - Message: Clone, - Renderer: core::Renderer + core::text::Renderer + 'a, - Renderer::Theme: application::StyleSheet + text::StyleSheet, -{ - width: Length, - height: Length, - is_hidden: bool, - title: String, - content: String, - - /// Dialog actions (confirm, cancel, etc.) - actions: Vec>, - - /// The optional message that will be sent when the user clicks on the backdrop. - backdrop: Option, - - /// The optional message that will be sent when the ESC key is pressed. - on_escape: Option, -} - -impl<'a, Message, Renderer> Default for CupertinoAlert<'a, Message, Renderer> -where - Message: Clone + 'a, - Renderer: core::Renderer + core::text::Renderer + 'a, - Renderer::Theme: application::StyleSheet + text::StyleSheet, -{ - fn default() -> Self { - Self { - width: Length::Fixed(400.0), - height: Length::Fixed(200.0), - is_hidden: true, - title: "Title".to_owned(), - content: "Content".to_owned(), - actions: vec![], - backdrop: None, - on_escape: None, - } - } -} - -impl<'a, Message, Renderer> CupertinoAlert<'a, Message, Renderer> -where - Message: Clone + 'a, - Renderer: core::Renderer + core::text::Renderer + 'a, - Renderer::Theme: application::StyleSheet + text::StyleSheet, -{ - /// Creates a new [`CupertinoAlert`] widget. - #[must_use] - pub fn new() -> Self { - Self::default() - } - - /// Sets the `width` of the [`CupertinoAlert`]. - #[must_use] - pub fn width(mut self, width: Length) -> Self { - self.width = width; - self - } - - /// Sets the `actions` of the [`CupertinoAlert`]. - #[must_use] - pub fn actions(mut self, actions: Vec>) -> Self { - self.actions = actions; - self - } - - /// Sets the `backdrop` of the [`CupertinoAlert`]. - #[must_use] - pub fn backdrop(mut self, backdrop: Option) -> Self { - self.backdrop = backdrop; - self - } - - /// Sets the `content` of the [`CupertinoAlert`]. - #[must_use] - pub fn content(mut self, content: String) -> Self { - self.content = content; - self - } - - /// Sets the `height` of the [`CupertinoAlert`]. - #[must_use] - pub fn height(mut self, height: Length) -> Self { - self.height = height; - self - } - - /// Sets `is_hidden` for the [`CupertinoAlert`]. - #[must_use] - pub fn is_hidden(mut self, is_hidden: bool) -> Self { - self.is_hidden = is_hidden; - self - } - - /// Sets `on_escape` for the [`CupertinoAlert`]. - #[must_use] - pub fn on_escape(mut self, on_escape: Option) -> Self { - self.on_escape = on_escape; - self - } - - /// Sets the `title` of the [`CupertinoAlert`]. - #[must_use] - pub fn title(mut self, title: String) -> Self { - self.title = title; - self - } - - fn text_with_font(element: E) -> Element<'a, Message, Renderer> - where - E: Into>, - { - let as_text_element = element.into().font(SF_UI_ROUNDED); - - Element::from(as_text_element) - } -} - -impl<'a, Message, Renderer> Widget for CupertinoAlert<'a, Message, Renderer> -where - Message: Clone + 'a, - Renderer: core::Renderer + core::text::Renderer + 'a, - Renderer::Theme: application::StyleSheet + text::StyleSheet, -{ - fn width(&self) -> Length { - if self.is_hidden { - Length::Fixed(0.0) - } else { - self.width - } - } - - fn height(&self) -> Length { - if self.is_hidden { - Length::Fixed(0.0) - } else { - self.height - } - } - - fn layout(&self, _tree: &mut Tree, _renderer: &Renderer, limits: &Limits) -> Node { - Node::new( - limits - .width(if self.is_hidden { - Length::Fixed(0.0) - } else { - self.width - }) - .height(if self.is_hidden { - Length::Fixed(0.0) - } else { - self.height - }) - .resolve(Size::new(f32::INFINITY, f32::INFINITY)), - ) - } - - fn children(&self) -> Vec { - self.actions - .iter() - .map(|action| Tree::new(&action.child)) - .collect() - } - - fn draw( - &self, - state: &Tree, - renderer: &mut Renderer, - theme: &Renderer::Theme, - style: &renderer::Style, - layout: Layout<'_>, - cursor: Cursor, - viewport: &Rectangle, - ) { - // Technically, only 2 actions are supported at the moment... // - assert!((1..3).contains(&self.actions.len())); - - if !self.is_hidden { - let bounds: Rectangle = layout.bounds(); - let center: Point = bounds.center(); - - // The origin (`Point::ORIGIN`) leaves a slight gap in x and y. Move the point back - // (up-left) in x and y, and scale the size to cover the remaining space. - let rectangle: Rectangle = Rectangle::new( - Point { - x: Point::ORIGIN.x - 100.0, - y: Point::ORIGIN.y - 100.0, - }, - Size { - width: viewport.width + 100.0, - height: viewport.height + 100.0, - }, - ); - - let draw_element = |r: &mut Renderer| { - // Overlay // - r.fill_quad( - Quad { - bounds: rectangle, - border_radius: [0.0, 0.0, 0.0, 0.0].into(), - border_width: 0.0, - border_color: Color::TRANSPARENT, - }, - Background::Color(secondary_system_fill()), - ); - - // Dialog Box // - let Length::Fixed(width) = self.width else { - todo!() - }; - let Length::Fixed(height) = self.height else { - todo!() - }; - - // The `center` puts the top-left corner of the rectangle in the origin, so shift the - // rectangle up and to the left. The `height` calculation may seem strange, but - // it's to center the box on the page - let dialog_box: Rectangle = Rectangle::new( - Point { - x: center.x - width / 2.0, - y: center.y - 0.75 * height, - }, - Size { width, height }, - ); - - r.fill_quad( - Quad { - bounds: dialog_box, - border_radius: [15.0, 15.0, 15.0, 15.0].into(), - border_width: 0.0, - border_color: Color::WHITE, - }, - Background::Color(Color::WHITE), - ); - - // Bottom Section // - // TODO: Cover the case in which there is only one action (for whatever reason; - // maybe just a cancel button?) - // This is where things get interesting. Draw lines using very thin rectangles! // - let bottom_bar: Rectangle = Rectangle::new( - Point { - x: center.x - width / 2.0, - y: center.y, - }, - Size { width, height: 2.0 }, - ); - - // Horizontal Bar // - r.fill_quad( - Quad { - bounds: bottom_bar, - border_radius: [0.0, 0.0, 0.0, 0.0].into(), - border_width: 0.0, - border_color: secondary_system_fill(), - }, - Background::Color(secondary_system_fill()), - ); - - // Vertical Bar // - let vertical_bar: Rectangle = Rectangle::new( - Point { - x: center.x, - y: center.y, - }, - Size { - width: 2.0, - height: height / 4.0, - }, - ); - - r.fill_quad( - Quad { - bounds: vertical_bar, - border_radius: [0.0, 0.0, 0.0, 0.0].into(), - border_width: 0.0, - border_color: secondary_system_fill(), - }, - Background::Color(secondary_system_fill()), - ); - - if self.actions.len() == 2 { - let child_1 = self.actions[0].child.as_widget(); - let child_2 = self.actions[1].child.as_widget(); - - let Length::Fixed(child_1_width) = child_1.width() else { - todo!() - }; - let Length::Fixed(child_1_height) = child_1.height() else { - todo!() - }; - let Length::Fixed(child_2_width) = child_2.width() else { - todo!() - }; - let Length::Fixed(child_2_height) = child_2.height() else { - todo!() - }; - - let mut bottom_left: Node = Node::new(Size { - width: child_1_width, - height: child_1_height, - }); - - let mut bottom_right: Node = Node::new(Size { - width: child_2_width, - height: child_2_height, - }); - - bottom_left.move_to(Point { - x: center.x - width / 3.0, - y: center.y + 10.0, - }); - - bottom_right.move_to(Point { - x: center.x + width / 6.0, - y: center.y + 10.0, - }); - - child_1.draw( - &state.children[0], - r, - theme, - style, - Layout::new(&bottom_left), - cursor, - viewport, - ); - - child_2.draw( - &state.children[1], - r, - theme, - style, - Layout::new(&bottom_right), - cursor, - viewport, - ); - } - - let mut title_node: Node = Node::new(Size { - width, - height: 75.0, - }); - let mut content_node: Node = Node::new(Size { - width, - height: 150.0, - }); - - title_node.move_to(Point { - x: center.x - width / 2.0, - y: center.y - height / 1.5, - }); - - content_node.move_to(Point { - x: center.x - width / 2.0, - y: center.y - height / 3.0, - }); - - /*let title: Element<'a, Message, Renderer> = - CupertinoAlert::<'a, Message, Renderer>::text_with_font( - Text::new(self.title.clone()).horizontal_alignment(Horizontal::Center), - ); - - title.as_widget().draw( - state, - r, - theme, - style, - Layout::new(&title_node), - cursor, - viewport, - ); - - let content: Element<'a, Message, Renderer> = - CupertinoAlert::<'a, Message, Renderer>::text_with_font( - Text::new(self.content.clone()).horizontal_alignment(Horizontal::Center), - ); - - content.as_widget().draw( - state, - r, - theme, - style, - Layout::new(&content_node), - cursor, - viewport, - );*/ - }; - - renderer.with_layer(rectangle, draw_element); - } - } - - fn on_event( - &mut self, - _state: &mut Tree, - event: Event, - layout: Layout<'_>, - cursor: Cursor, - _renderer: &Renderer, - _clipboard: &mut dyn Clipboard, - shell: &mut Shell<'_, Message>, - _viewport: &Rectangle, - ) -> event::Status { - let cur_pos = cursor.position().unwrap_or_default(); - match event { - Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) - | Event::Touch(touch::Event::FingerPressed { .. }) => { - let bounds: Rectangle = layout.bounds(); - - // If either of the bounds width/height are 0, exit early; this means the modal - // is changing from hidden to visible - if bounds.width == 0.0 || bounds.height == 0.0 { - return event::Status::Ignored; - } - - // TODO: Handle the case when there is only 1 button, for whatever reason... // - if self.actions.len() == 2 { - // For some reason, the button callbacks aren't being triggered... // - - // Check for left button click // - // The hit boxes here are, by design, more generous // - // For the Y hit box, the range is very narrow, hence more tuning for the - // range - if self.actions[0].on_pressed.is_some() { - let hit_x: Range = - (bounds.x + 2.0 * bounds.width * 0.3)..(bounds.x + bounds.width * 0.9); - let hit_y: Range = (bounds.y + bounds.height / 2.0 + 10.0) - ..(bounds.y + bounds.height / 2.0 + 30.0); - - if hit_x.contains(&cur_pos.x) && hit_y.contains(&cur_pos.y) { - shell.publish( - self.actions[0] - .on_pressed - .clone() - .expect("Unable to retrieve the left button click message"), - ); - } - } - - // Check for right button click // - if self.actions[1].on_pressed.is_some() { - let hit_x: Range = - (bounds.x + bounds.width / 6.0)..(bounds.x + bounds.width / 2.0); - let hit_y: Range = (bounds.y + bounds.height / 2.0 + 10.0) - ..(bounds.y + bounds.height / 2.0 + 30.0); - - if hit_x.contains(&cur_pos.x) && hit_y.contains(&cur_pos.y) { - shell.publish( - self.actions[1] - .on_pressed - .clone() - .expect("Unable to retrieve the right button click message"), - ); - } - } - } - - // Check for clicking on the overlay // - let hit_x: Range = bounds.x..(bounds.x + bounds.width); - let hit_y: Range = - (bounds.y - bounds.height / 4.0)..(bounds.y + bounds.height * 0.85); - - if !hit_x.contains(&cur_pos.x) || !hit_y.contains(&cur_pos.y) { - if self.backdrop.is_some() { - shell.publish( - self.backdrop - .clone() - .expect("Unable to retrieve the backdrop message"), - ); - } - - // Default behaviour: hide the modal after clicking on the backdrop // - self.is_hidden = true; - } - } - - Event::Keyboard(keyboard::Event::KeyPressed { key_code, .. }) => { - if key_code == keyboard::KeyCode::Escape && self.on_escape.is_some() { - self.is_hidden = true; - - shell.publish( - self.on_escape - .clone() - .expect("Unable to retrieve the escape message"), - ); - return event::Status::Captured; - } - } - - _ => return event::Status::Ignored, - } - - event::Status::Ignored - } -} - -#[allow(clippy::type_repetition_in_bounds)] -impl<'a, Message, Renderer: 'a> From> - for Element<'a, Message, Renderer> -where - Message: Clone + 'a, - Renderer: core::Renderer + core::text::Renderer + 'a, - Renderer::Theme: application::StyleSheet + text::StyleSheet, -{ - fn from(alert: CupertinoAlert<'a, Message, Renderer>) -> Self { - Self::new(alert) - } -} diff --git a/src/native/cupertino/cupertino_button.rs b/src/native/cupertino/cupertino_button.rs index d9a8c39e..a9edb82d 100644 --- a/src/native/cupertino/cupertino_button.rs +++ b/src/native/cupertino/cupertino_button.rs @@ -120,11 +120,8 @@ where Renderer: core::Renderer + core::text::Renderer, Renderer::Theme: application::StyleSheet, { - fn width(&self) -> Length { - self.body.as_widget().width() - } - fn height(&self) -> Length { - self.body.as_widget().height() + fn size(&self) -> Size { + self.body.as_widget().size() } fn children(&self) -> Vec { diff --git a/src/native/cupertino/cupertino_spinner.rs b/src/native/cupertino/cupertino_spinner.rs index 408e1788..b2f2175f 100644 --- a/src/native/cupertino/cupertino_spinner.rs +++ b/src/native/cupertino/cupertino_spinner.rs @@ -91,20 +91,16 @@ impl CupertinoSpinner { } impl Widget> for CupertinoSpinner { - fn width(&self) -> Length { - self.width - } - fn height(&self) -> Length { - self.height + fn size(&self) -> Size { + Size::new(self.width, self.height) } fn layout(&self, _tree: &mut Tree, _renderer: &Renderer, limits: &Limits) -> Node { - Node::new( - limits - .width(self.width) - .height(self.height) - .resolve(Size::new(f32::INFINITY, f32::INFINITY)), - ) + Node::new(limits.width(self.width).height(self.height).resolve( + self.width, + self.height, + Size::new(f32::INFINITY, f32::INFINITY), + )) } fn draw( diff --git a/src/native/cupertino/cupertino_switch.rs b/src/native/cupertino/cupertino_switch.rs index 94b2043a..d2666543 100644 --- a/src/native/cupertino/cupertino_switch.rs +++ b/src/native/cupertino/cupertino_switch.rs @@ -159,20 +159,16 @@ impl Widget> for CupertinoSwitch Length { - self.width - } - fn height(&self) -> Length { - self.height + fn size(&self) -> Size { + Size::new(self.width, self.height) } fn layout(&self, _tree: &mut Tree, _renderer: &Renderer, limits: &Limits) -> Node { - Node::new( - limits - .width(self.width) - .height(self.height) - .resolve(Size::new(f32::INFINITY, f32::INFINITY)), - ) + Node::new(limits.width(self.width).height(self.height).resolve( + self.width, + self.height, + Size::new(100.0, 32.0), + )) } fn draw( diff --git a/src/native/date_picker.rs b/src/native/date_picker.rs index ef53775e..c82be666 100644 --- a/src/native/date_picker.rs +++ b/src/native/date_picker.rs @@ -173,12 +173,8 @@ where tree.diff_children(&[&self.underlay, &self.overlay_state]); } - fn width(&self) -> Length { - self.underlay.as_widget().width() - } - - fn height(&self) -> Length { - self.underlay.as_widget().width() + fn size(&self) -> core::Size { + self.underlay.as_widget().size() } fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { diff --git a/src/native/floating_element.rs b/src/native/floating_element.rs index 128b9dce..4e520c85 100644 --- a/src/native/floating_element.rs +++ b/src/native/floating_element.rs @@ -118,12 +118,8 @@ where tree.diff_children(&[&self.underlay, &self.element]); } - fn width(&self) -> Length { - self.underlay.as_widget().width() - } - - fn height(&self) -> Length { - self.underlay.as_widget().height() + fn size(&self) -> core::Size { + self.underlay.as_widget().size() } fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { diff --git a/src/native/mod.rs b/src/native/mod.rs index a89feae7..1117eb4d 100644 --- a/src/native/mod.rs +++ b/src/native/mod.rs @@ -137,6 +137,7 @@ pub mod segmented_button; pub type SegmentedButton<'a, Message, Renderer> = segmented_button::SegmentedButton<'a, Message, Renderer>; +#[cfg(feature = "slide_bar")] pub mod slide_bar; - +#[cfg(feature = "slide_bar")] pub use slide_bar::SlideBar; diff --git a/src/native/modal.rs b/src/native/modal.rs index cb71194f..c87a11aa 100644 --- a/src/native/modal.rs +++ b/src/native/modal.rs @@ -147,12 +147,8 @@ where } } - fn width(&self) -> Length { - self.underlay.as_widget().width() - } - - fn height(&self) -> Length { - self.underlay.as_widget().height() + fn size(&self) -> core::Size { + self.underlay.as_widget().size() } fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { diff --git a/src/native/number_input.rs b/src/native/number_input.rs index a408a689..253401eb 100644 --- a/src/native/number_input.rs +++ b/src/native/number_input.rs @@ -287,20 +287,17 @@ where ); } - fn width(&self) -> Length { - self.width - } - - fn height(&self) -> Length { - Length::Shrink + fn size(&self) -> Size { + Size::new(self.width, Length::Shrink) } fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { let padding = Padding::from(self.padding); + let num_size = self.size(); let limits = limits - .width(self.width()) + .width(num_size.width) .height(Length::Shrink) - .pad(padding); + .shrink(padding); let content = self .content .layout(&mut tree.children[0], renderer, &limits, None); @@ -348,9 +345,9 @@ where content.size().width - 1.0, content.size().height.max(modifier.size().height), ); - modifier.align(Alignment::End, Alignment::Center, intrinsic); + modifier = modifier.align(Alignment::End, Alignment::Center, intrinsic); - let size = limits.resolve(intrinsic); + let size = limits.resolve(num_size.width, Length::Shrink, intrinsic); Node::with_children(size, vec![content, modifier]) } diff --git a/src/native/overlay/context_menu.rs b/src/native/overlay/context_menu.rs index dbfbe630..515d2975 100644 --- a/src/native/overlay/context_menu.rs +++ b/src/native/overlay/context_menu.rs @@ -94,7 +94,7 @@ where position.y = f32::max(0.0, position.y - content.size().height); } - content.move_to(position); + content.move_to_mut(position); Node::with_children(max_size, vec![content]) } diff --git a/src/native/overlay/date_picker.rs b/src/native/overlay/date_picker.rs index f6cc996f..6613c7ee 100644 --- a/src/native/overlay/date_picker.rs +++ b/src/native/overlay/date_picker.rs @@ -376,7 +376,7 @@ where _translation: Vector, ) -> Node { let limits = Limits::new(Size::ZERO, bounds) - .pad(Padding::from(PADDING)) + .shrink(Padding::from(PADDING)) .width(Length::Fill) .height(Length::Fill) .max_width(300.0) @@ -490,10 +490,8 @@ where }; let mut col = element.as_widget().layout(col_tree, renderer, &limits); - col.move_to(Point::new( - col.bounds().x + PADDING, - col.bounds().y + PADDING, - )); + let col_bounds = col.bounds(); + col = col.move_to(Point::new(col_bounds.x + PADDING, col_bounds.y + PADDING)); // Buttons let cancel_limits = @@ -510,28 +508,26 @@ where self.submit_button .layout(&mut self.tree.children[1], renderer, &submit_limits); - cancel_button.move_to(Point { - x: cancel_button.bounds().x + PADDING, - y: cancel_button.bounds().y + col.bounds().height + PADDING + SPACING, + let cancel_bounds = cancel_button.bounds(); + cancel_button = cancel_button.move_to(Point { + x: cancel_bounds.x + PADDING, + y: cancel_bounds.y + col.bounds().height + PADDING + SPACING, }); - submit_button.move_to(Point { - x: submit_button.bounds().x + col.bounds().width - submit_button.bounds().width - + PADDING, - y: submit_button.bounds().y + col.bounds().height + PADDING + SPACING, + let submit_bounds = submit_button.bounds(); + submit_button = submit_button.move_to(Point { + x: submit_bounds.x + col.bounds().width - submit_bounds.width + PADDING, + y: submit_bounds.y + col.bounds().height + PADDING + SPACING, }); - let mut node = Node::with_children( + Node::with_children( Size::new( col.bounds().width + (2.0 * PADDING), col.bounds().height + cancel_button.bounds().height + (2.0 * PADDING) + SPACING, ), vec![col, cancel_button, submit_button], - ); - - node.center_and_bounce(position, bounds); - - node + ) + .center_and_bounce(position, bounds) } fn on_event( @@ -953,11 +949,7 @@ where tree.diff_children(&[&self.cancel_button, &self.submit_button]); } - fn width(&self) -> Length { - unimplemented!("This should never be reached!") - } - - fn height(&self) -> Length { + fn size(&self) -> Size { unimplemented!("This should never be reached!") } diff --git a/src/native/overlay/floating_element.rs b/src/native/overlay/floating_element.rs index 14a35869..69bf0c10 100644 --- a/src/native/overlay/floating_element.rs +++ b/src/native/overlay/floating_element.rs @@ -67,7 +67,7 @@ where let limits = layout::Limits::new(Size::ZERO, self.underlay_bounds.size()) .width(Length::Fill) .height(Length::Fill); - let mut node = self + let node = self .element .as_widget() .layout(self.state, renderer, &limits); @@ -108,8 +108,7 @@ where ), }; - node.move_to(position); - node + node.move_to(position) } fn on_event( diff --git a/src/native/overlay/modal.rs b/src/native/overlay/modal.rs index 15d6d021..c60ed039 100644 --- a/src/native/overlay/modal.rs +++ b/src/native/overlay/modal.rs @@ -83,7 +83,7 @@ where .layout(self.state, renderer, &limits); let max_size = limits.max(); - content.align( + content = content.align( Alignment::from(self.horizontal_alignment), Alignment::from(self.vertical_alignment), max_size, diff --git a/src/native/overlay/time_picker.rs b/src/native/overlay/time_picker.rs index 9e3e7016..3ca4e33e 100644 --- a/src/native/overlay/time_picker.rs +++ b/src/native/overlay/time_picker.rs @@ -513,7 +513,7 @@ where _translation: Vector, ) -> Node { let limits = Limits::new(Size::ZERO, bounds) - .pad(Padding::from(PADDING)) + .shrink(Padding::from(PADDING)) .width(Length::Fill) .height(Length::Fill) .max_width(300.0) @@ -540,14 +540,16 @@ where .height(Length::Fill) .layout(self.tree, renderer, &limits); - clock.move_to(Point::new( - clock.bounds().x + PADDING, - clock.bounds().y + PADDING, + let clock_bounds = clock.bounds(); + clock = clock.move_to(Point::new( + clock_bounds.x + PADDING, + clock_bounds.y + PADDING, )); - digital_clock.move_to(Point::new( - digital_clock.bounds().x + PADDING, - digital_clock.bounds().y + PADDING + SPACING + clock.bounds().height, + let digital_bounds = digital_clock.bounds(); + digital_clock = digital_clock.move_to(Point::new( + digital_bounds.x + PADDING, + digital_bounds.y + PADDING + SPACING + clock.bounds().height, )); // Buttons @@ -565,26 +567,27 @@ where self.submit_button .layout(&mut self.tree.children[1], renderer, &submit_limits); - cancel_button.move_to(Point { - x: cancel_button.bounds().x + PADDING, - y: cancel_button.bounds().y + let cancel_bounds = cancel_button.bounds(); + cancel_button = cancel_button.move_to(Point { + x: cancel_bounds.x + PADDING, + y: cancel_bounds.y + clock.bounds().height + PADDING + digital_clock.bounds().height + 2.0 * SPACING, }); - submit_button.move_to(Point { - x: submit_button.bounds().x + clock.bounds().width - submit_button.bounds().width - + PADDING, - y: submit_button.bounds().y + let submit_bounds = submit_button.bounds(); + submit_button = submit_button.move_to(Point { + x: submit_bounds.x + clock.bounds().width - submit_bounds.width + PADDING, + y: submit_bounds.y + clock.bounds().height + PADDING + digital_clock.bounds().height + 2.0 * SPACING, }); - let mut node = Node::with_children( + let node = Node::with_children( Size::new( clock.bounds().width + (2.0 * PADDING), clock.bounds().height @@ -596,9 +599,7 @@ where vec![clock, digital_clock, cancel_button, submit_button], ); - node.center_and_bounce(position, bounds); - - node + node.center_and_bounce(position, bounds) } fn on_event( @@ -1740,11 +1741,7 @@ where tree.diff_children(&[&self.cancel_button, &self.submit_button]); } - fn width(&self) -> Length { - unimplemented!("This should never be reached!") - } - - fn height(&self) -> Length { + fn size(&self) -> Size { unimplemented!("This should never be reached!") } diff --git a/src/native/quad.rs b/src/native/quad.rs index a09eb0e1..b4975e3e 100644 --- a/src/native/quad.rs +++ b/src/native/quad.rs @@ -7,7 +7,7 @@ use iced_widget::core::{ mouse::Cursor, renderer, widget::Tree, - Color, Element, Layout, Length, Rectangle, Widget, + Color, Element, Layout, Length, Rectangle, Size, Widget, }; use crate::native::InnerBounds; @@ -51,12 +51,8 @@ impl Widget for Quad where Renderer: renderer::Renderer, { - fn width(&self) -> Length { - self.width - } - - fn height(&self) -> Length { - self.height + fn size(&self) -> Size { + Size::new(self.width, self.height) } fn layout(&self, _tree: &mut Tree, _renderer: &Renderer, limits: &Limits) -> Node { diff --git a/src/native/segmented_button.rs b/src/native/segmented_button.rs index e716a47c..9233a1e2 100644 --- a/src/native/segmented_button.rs +++ b/src/native/segmented_button.rs @@ -133,12 +133,8 @@ where tree.diff_children(std::slice::from_ref(&self.content)); } - fn width(&self) -> Length { - self.width - } - - fn height(&self) -> Length { - self.height + fn size(&self) -> iced_widget::core::Size { + iced_widget::core::Size::new(self.width, self.height) } fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { @@ -147,18 +143,18 @@ where .loose() .width(self.width) .height(self.height) - .pad(padding); + .shrink(padding); let mut content = self.content .as_widget() .layout(&mut tree.children[0], renderer, &limits.loose()); - let size = limits.resolve(content.size()); + let size = limits.resolve(self.width, self.height, content.size()); - content.move_to(Point::new(padding.left, padding.top)); - content.align(self.horizontal_alignment, self.vertical_alignment, size); + content.move_to_mut(Point::new(padding.left, padding.top)); + content.align_mut(self.horizontal_alignment, self.vertical_alignment, size); - Node::with_children(size.pad(padding), vec![content]) + Node::with_children(size.expand(padding), vec![content]) } fn on_event( diff --git a/src/native/selection_list.rs b/src/native/selection_list.rs index 0230ce50..ab3183ca 100644 --- a/src/native/selection_list.rs +++ b/src/native/selection_list.rs @@ -171,12 +171,8 @@ where .collect(); } - fn width(&self) -> Length { - self.width - } - - fn height(&self) -> Length { - Length::Shrink + fn size(&self) -> Size { + Size::new(self.width, Length::Shrink) } fn tag(&self) -> tree::Tag { @@ -224,7 +220,7 @@ where let content = self .container .layout(&mut tree.children[0], renderer, &limits); - let size = limits.resolve(content.size()); + let size = limits.resolve(self.width, self.height, content.size()); Node::with_children(size, vec![content]) } diff --git a/src/native/selection_list/list.rs b/src/native/selection_list/list.rs index fd70c671..5894a401 100644 --- a/src/native/selection_list/list.rs +++ b/src/native/selection_list/list.rs @@ -109,12 +109,8 @@ where list_state.options = self.options.iter().map(ToString::to_string).collect(); } - fn width(&self) -> Length { - Length::Fill - } - - fn height(&self) -> Length { - Length::Shrink + fn size(&self) -> Size { + Size::new(Length::Fill, Length::Shrink) } fn layout( @@ -128,7 +124,7 @@ where #[allow(clippy::cast_precision_loss)] let intrinsic = Size::new( - limits.fill().width, + limits.max().width, (self.text_size + self.padding * 2.0) * self.options.len() as f32, ); diff --git a/src/native/slide_bar.rs b/src/native/slide_bar.rs index 9f14950a..a5c4bb50 100644 --- a/src/native/slide_bar.rs +++ b/src/native/slide_bar.rs @@ -153,7 +153,11 @@ where .width(self.width) .height(self.height.unwrap_or(Length::Fixed(DEFAULT_HEIGHT))); - let size = limits.resolve(self.width, self.height.unwrap_or(Length::Fixed(DEFAULT_HEIGHT)), Size::ZERO); + let size = limits.resolve( + self.width, + self.height.unwrap_or(Length::Fixed(DEFAULT_HEIGHT)), + Size::ZERO, + ); Node::new(size) } diff --git a/src/native/spinner.rs b/src/native/spinner.rs index 18cbccb8..5be9eb70 100644 --- a/src/native/spinner.rs +++ b/src/native/spinner.rs @@ -119,21 +119,16 @@ where Renderer: core::Renderer, Renderer::Theme: StyleSheet, { - fn width(&self) -> Length { - self.width - } - - fn height(&self) -> Length { - self.height + fn size(&self) -> Size { + Size::new(self.width, self.height) } fn layout(&self, _tree: &mut Tree, _renderer: &Renderer, limits: &Limits) -> Node { - Node::new( - limits - .width(self.width) - .height(self.height) - .resolve(Size::new(f32::INFINITY, f32::INFINITY)), - ) + Node::new(limits.width(self.width).height(self.height).resolve( + self.width, + self.height, + Size::new(f32::INFINITY, f32::INFINITY), + )) } fn draw( diff --git a/src/native/split.rs b/src/native/split.rs index 31f82aac..a2ccf7a8 100644 --- a/src/native/split.rs +++ b/src/native/split.rs @@ -192,12 +192,8 @@ where tree.diff_children(&[&self.first, &self.second]); } - fn width(&self) -> Length { - self.width - } - - fn height(&self) -> Length { - self.height + fn size(&self) -> Size { + Size::new(self.width, self.height) } fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { @@ -562,29 +558,29 @@ where 0.0, space.bounds().height - f32::from(divider_position), )) - .pad(padding); + .shrink(padding); let mut first = split .first .as_widget() .layout(&mut tree.children[0], renderer, &first_limits); - first.move_to(Point::new( + first.move_to_mut(Point::new( space.bounds().x + split.padding, space.bounds().y + split.padding, )); let mut divider = Node::new(Size::new(space.bounds().width, split.spacing)); - divider.move_to(Point::new(space.bounds().x, f32::from(divider_position))); + divider.move_to_mut(Point::new(space.bounds().x, f32::from(divider_position))); let second_limits = limits .clone() .shrink(Size::new(0.0, f32::from(divider_position) + split.spacing)) - .pad(padding); + .shrink(padding); let mut second = split .second .as_widget() .layout(&mut tree.children[1], renderer, &second_limits); - second.move_to(Point::new( + second.move_to_mut(Point::new( space.bounds().x + split.padding, space.bounds().y + f32::from(divider_position) + split.spacing + split.padding, )); @@ -641,29 +637,29 @@ where space.bounds().width - f32::from(divider_position), 0.0, )) - .pad(padding); + .shrink(padding); let mut first = split .first .as_widget() .layout(&mut tree.children[0], renderer, &first_limits); - first.move_to(Point::new( + first.move_to_mut(Point::new( space.bounds().x + split.padding, space.bounds().y + split.padding, )); let mut divider = Node::new(Size::new(split.spacing, space.bounds().height)); - divider.move_to(Point::new(f32::from(divider_position), space.bounds().y)); + divider.move_to_mut(Point::new(f32::from(divider_position), space.bounds().y)); let second_limits = limits .clone() .shrink(Size::new(f32::from(divider_position) + split.spacing, 0.0)) - .pad(padding); + .shrink(padding); let mut second = split .second .as_widget() .layout(&mut tree.children[1], renderer, &second_limits); - second.move_to(Point::new( + second.move_to_mut(Point::new( space.bounds().x + f32::from(divider_position) + split.spacing + split.padding, space.bounds().y + split.padding, )); diff --git a/src/native/tab_bar.rs b/src/native/tab_bar.rs index c638c0e8..9db2efdd 100644 --- a/src/native/tab_bar.rs +++ b/src/native/tab_bar.rs @@ -343,12 +343,8 @@ where Renderer::Theme: StyleSheet + text::StyleSheet, TabId: Eq + Clone, { - fn width(&self) -> Length { - self.width - } - - fn height(&self) -> Length { - self.height + fn size(&self) -> Size { + Size::new(self.width, self.height) } fn layout( diff --git a/src/native/tabs.rs b/src/native/tabs.rs index 1d6c1655..215345db 100644 --- a/src/native/tabs.rs +++ b/src/native/tabs.rs @@ -314,12 +314,8 @@ where tree.children[1].diff_children(&self.tabs); } - fn width(&self) -> Length { - self.width - } - - fn height(&self) -> Length { - self.height + fn size(&self) -> Size { + Size::new(self.width, self.height) } fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { @@ -344,18 +340,22 @@ where .layout(tree, renderer, &tab_content_limits) }; - tab_bar_node.move_to(Point::new( - tab_bar_node.bounds().x, - tab_bar_node.bounds().y + let tab_bar_bounds = tab_bar_node.bounds(); + tab_bar_node = tab_bar_node.move_to(Point::new( + tab_bar_bounds.x, + tab_bar_bounds.y + match self.tab_bar_position { TabBarPosition::Top => 0.0, - TabBarPosition::Bottom => tab_content_node.bounds().height, + TabBarPosition::Bottom => { + tab_content_node.bounds().height - tab_bar_bounds.height + } }, )); - tab_content_node.move_to(Point::new( - tab_content_node.bounds().x, - tab_content_node.bounds().y + let tab_content_bounds = tab_content_node.bounds(); + tab_content_node = tab_content_node.move_to(Point::new( + tab_content_bounds.x, + tab_content_bounds.y + match self.tab_bar_position { TabBarPosition::Top => tab_bar_node.bounds().height, TabBarPosition::Bottom => 0.0, diff --git a/src/native/time_picker.rs b/src/native/time_picker.rs index 4a098965..23c1cb41 100644 --- a/src/native/time_picker.rs +++ b/src/native/time_picker.rs @@ -187,12 +187,8 @@ where tree.diff_children(&[&self.underlay, &self.overlay_state]); } - fn width(&self) -> Length { - self.underlay.as_widget().width() - } - - fn height(&self) -> Length { - self.underlay.as_widget().height() + fn size(&self) -> iced_widget::core::Size { + self.underlay.as_widget().size() } fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { diff --git a/src/native/wrap.rs b/src/native/wrap.rs index 52a7060f..d491091d 100644 --- a/src/native/wrap.rs +++ b/src/native/wrap.rs @@ -168,12 +168,8 @@ where tree.diff_children(&self.elements); } - fn width(&self) -> Length { - self.width - } - - fn height(&self) -> Length { - self.height + fn size(&self) -> Size { + Size::new(self.width, self.height) } fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { @@ -354,7 +350,7 @@ where #[allow(clippy::cast_precision_loss)] // TODO: possible precision loss let line_minimal_length = self.line_minimal_length; let limits = limits - .pad(padding) + .shrink(padding) .width(self.width) .height(self.height) .max_width(self.max_width) @@ -394,10 +390,10 @@ where start = end; end += 1; current_line_height = line_minimal_length; - node.move_to(Point::new(padding.left, deep_curse)); + node.move_to_mut(Point::new(padding.left, deep_curse)); curse = offset_init + padding.left; } else { - node.move_to(Point::new(curse, deep_curse)); + node.move_to_mut(Point::new(curse, deep_curse)); curse = offset; end += 1; } @@ -414,16 +410,16 @@ where nodes[range].iter_mut().for_each(|node| { let size = node.size(); let space = Size::new(size.width, max_length); - node.align(Alignment::Start, self.alignment, space); + node.align_mut(Alignment::Start, self.alignment, space); }); } let (width, height) = ( max_main - padding.left, deep_curse - padding.left + current_line_height, ); - let size = limits.resolve(Size::new(width, height)); + let size = limits.resolve(self.width, self.height, Size::new(width, height)); - Node::with_children(size.pad(padding), nodes) + Node::with_children(size.expand(padding), nodes) } } @@ -441,7 +437,7 @@ where #[allow(clippy::cast_precision_loss)] // TODO: possible precision loss let line_minimal_length = self.line_minimal_length; let limits = limits - .pad(padding) + .shrink(padding) .width(self.width) .height(self.height) .max_width(self.max_width) @@ -481,10 +477,10 @@ where start = end; end += 1; current_line_width = line_minimal_length; - node.move_to(Point::new(wide_curse, padding.left)); + node = node.move_to(Point::new(wide_curse, padding.left)); curse = offset_init + padding.left; } else { - node.move_to(Point::new(wide_curse, curse)); + node = node.move_to(Point::new(wide_curse, curse)); end += 1; curse = offset; } @@ -502,7 +498,7 @@ where nodes[range].iter_mut().for_each(|node| { let size = node.size(); let space = Size::new(max_length, size.height); - node.align(self.alignment, Alignment::Start, space); + node.align_mut(self.alignment, Alignment::Start, space); }); } @@ -510,9 +506,9 @@ where wide_curse - padding.left + current_line_width, max_main - padding.left, ); - let size = limits.resolve(Size::new(width, height)); + let size = limits.resolve(self.width, self.height, Size::new(width, height)); - Node::with_children(size.pad(padding), nodes) + Node::with_children(size.expand(padding), nodes) } }