From d7100fd2597da82d97eaf196d50573ea64f3f8ff Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 16 Mar 2022 17:37:19 +0700 Subject: Export widget modules in `iced_pure` ... and fix collisions with the new `helpers` --- examples/pure/component/Cargo.toml | 1 + examples/pure/component/src/main.rs | 8 +- examples/pure/counter/src/main.rs | 3 +- examples/pure/game_of_life/src/main.rs | 6 +- examples/pure/pane_grid/src/main.rs | 2 +- examples/pure/pick_list/src/main.rs | 4 +- examples/pure/todos/src/main.rs | 5 +- examples/pure/tour/src/main.rs | 5 +- graphics/src/widget/pure/canvas.rs | 2 +- lazy/src/pure/responsive.rs | 2 +- pure/src/element.rs | 163 +++++++++++++++++++++++++++++++ pure/src/helpers.rs | 153 +++++++++++++++++++++++++++++ pure/src/lib.rs | 7 +- pure/src/overlay.rs | 2 +- pure/src/widget.rs | 169 ++------------------------------- pure/src/widget/button.rs | 7 +- pure/src/widget/checkbox.rs | 5 +- pure/src/widget/column.rs | 3 +- pure/src/widget/container.rs | 3 +- pure/src/widget/element.rs | 163 ------------------------------- pure/src/widget/pane_grid.rs | 3 +- pure/src/widget/progress_bar.rs | 3 +- pure/src/widget/radio.rs | 5 +- pure/src/widget/row.rs | 3 +- pure/src/widget/rule.rs | 3 +- pure/src/widget/scrollable.rs | 2 +- pure/src/widget/space.rs | 3 +- pure/src/widget/text.rs | 3 +- pure/src/widget/text_input.rs | 4 +- pure/src/widget/tree.rs | 2 +- src/pure.rs | 37 ++------ src/pure/widget.rs | 155 ++++++++++++++++++++++++++++++ 32 files changed, 541 insertions(+), 395 deletions(-) create mode 100644 pure/src/element.rs create mode 100644 pure/src/helpers.rs delete mode 100644 pure/src/widget/element.rs create mode 100644 src/pure/widget.rs diff --git a/examples/pure/component/Cargo.toml b/examples/pure/component/Cargo.toml index a15f134f..b6c7a513 100644 --- a/examples/pure/component/Cargo.toml +++ b/examples/pure/component/Cargo.toml @@ -9,3 +9,4 @@ publish = false iced = { path = "../../..", features = ["debug", "pure"] } iced_native = { path = "../../../native" } iced_lazy = { path = "../../../lazy", features = ["pure"] } +iced_pure = { path = "../../../pure" } diff --git a/examples/pure/component/src/main.rs b/examples/pure/component/src/main.rs index ab10317f..b38d6fca 100644 --- a/examples/pure/component/src/main.rs +++ b/examples/pure/component/src/main.rs @@ -1,4 +1,4 @@ -use iced::pure::widget::container; +use iced::pure::container; use iced::pure::{Element, Sandbox}; use iced::{Length, Settings}; @@ -47,12 +47,12 @@ impl Sandbox for Component { } mod numeric_input { - use iced::pure::widget::Element; - use iced::pure::widget::{row, text, text_input}; + use iced::pure::{button, row, text, text_input}; use iced_lazy::pure::{self, Component}; use iced_native::alignment::{self, Alignment}; use iced_native::text; use iced_native::Length; + use iced_pure::Element; pub struct NumericInput { value: Option, @@ -120,8 +120,6 @@ mod numeric_input { fn view(&self, _state: &Self::State) -> Element { let button = |label, on_press| { - use iced::pure::widget::button; - button( text(label) .width(Length::Fill) diff --git a/examples/pure/counter/src/main.rs b/examples/pure/counter/src/main.rs index 9b520347..726009df 100644 --- a/examples/pure/counter/src/main.rs +++ b/examples/pure/counter/src/main.rs @@ -1,5 +1,4 @@ -use iced::pure::widget::{button, column, text}; -use iced::pure::{Element, Sandbox}; +use iced::pure::{button, column, text, Element, Sandbox}; use iced::{Alignment, Settings}; pub fn main() -> iced::Result { diff --git a/examples/pure/game_of_life/src/main.rs b/examples/pure/game_of_life/src/main.rs index 75a0deef..f63ef41b 100644 --- a/examples/pure/game_of_life/src/main.rs +++ b/examples/pure/game_of_life/src/main.rs @@ -5,7 +5,7 @@ mod style; use grid::Grid; use iced::executor; -use iced::pure::widget::{ +use iced::pure::{ button, checkbox, column, container, pick_list, row, slider, text, }; use iced::pure::{Application, Element}; @@ -207,8 +207,8 @@ fn view_controls<'a>( mod grid { use crate::Preset; - use iced::pure::canvas::event::{self, Event}; - use iced::pure::canvas::{ + use iced::pure::widget::canvas::event::{self, Event}; + use iced::pure::widget::canvas::{ self, Cache, Canvas, Cursor, Frame, Geometry, Path, Text, }; use iced::pure::Element; diff --git a/examples/pure/pane_grid/src/main.rs b/examples/pure/pane_grid/src/main.rs index 6a733023..65516956 100644 --- a/examples/pure/pane_grid/src/main.rs +++ b/examples/pure/pane_grid/src/main.rs @@ -1,7 +1,7 @@ use iced::alignment::{self, Alignment}; use iced::executor; use iced::keyboard; -use iced::pure::pane_grid::{self, PaneGrid}; +use iced::pure::widget::pane_grid::{self, PaneGrid}; use iced::pure::{button, column, container, row, scrollable, text}; use iced::pure::{Application, Element}; use iced::{Color, Command, Length, Settings, Size, Subscription}; diff --git a/examples/pure/pick_list/src/main.rs b/examples/pure/pick_list/src/main.rs index f9d55dd0..b9947107 100644 --- a/examples/pure/pick_list/src/main.rs +++ b/examples/pure/pick_list/src/main.rs @@ -1,6 +1,4 @@ -use iced::pure::widget::{ - column, container, pick_list, scrollable, vertical_space, -}; +use iced::pure::{column, container, pick_list, scrollable, vertical_space}; use iced::pure::{Element, Sandbox}; use iced::{Alignment, Length, Settings}; diff --git a/examples/pure/todos/src/main.rs b/examples/pure/todos/src/main.rs index e993c598..6a6c6300 100644 --- a/examples/pure/todos/src/main.rs +++ b/examples/pure/todos/src/main.rs @@ -1,8 +1,9 @@ use iced::alignment::{self, Alignment}; -use iced::pure::widget::{ +use iced::pure::widget::Text; +use iced::pure::{ button, checkbox, column, container, row, scrollable, text, text_input, + Application, Element, }; -use iced::pure::{Application, Element, Text}; use iced::window; use iced::{Command, Font, Length, Settings}; use serde::{Deserialize, Serialize}; diff --git a/examples/pure/tour/src/main.rs b/examples/pure/tour/src/main.rs index 7a50bcdc..a44d99f3 100644 --- a/examples/pure/tour/src/main.rs +++ b/examples/pure/tour/src/main.rs @@ -1,9 +1,10 @@ use iced::alignment; -use iced::pure::widget::{ +use iced::pure::widget::{Button, Column, Container, Slider}; +use iced::pure::{ checkbox, column, container, horizontal_space, image, radio, row, scrollable, slider, text, text_input, toggler, vertical_space, }; -use iced::pure::{Button, Column, Container, Element, Sandbox, Slider}; +use iced::pure::{Element, Sandbox}; use iced::{Color, Length, Settings}; pub fn main() -> iced::Result { diff --git a/graphics/src/widget/pure/canvas.rs b/graphics/src/widget/pure/canvas.rs index 91214392..c48dea6c 100644 --- a/graphics/src/widget/pure/canvas.rs +++ b/graphics/src/widget/pure/canvas.rs @@ -16,7 +16,7 @@ use iced_native::mouse; use iced_native::renderer; use iced_native::{Clipboard, Length, Point, Rectangle, Shell, Size, Vector}; use iced_pure::widget::tree::{self, Tree}; -use iced_pure::widget::{Element, Widget}; +use iced_pure::{Element, Widget}; /// A widget capable of drawing 2D graphics. /// diff --git a/lazy/src/pure/responsive.rs b/lazy/src/pure/responsive.rs index 291f1aaf..2b62a047 100644 --- a/lazy/src/pure/responsive.rs +++ b/lazy/src/pure/responsive.rs @@ -3,8 +3,8 @@ use iced_native::layout::{self, Layout}; use iced_native::mouse; use iced_native::renderer; use iced_native::{Clipboard, Length, Point, Rectangle, Shell, Size}; +use iced_pure::horizontal_space; use iced_pure::overlay; -use iced_pure::widget::horizontal_space; use iced_pure::widget::tree::{self, Tree}; use iced_pure::{Element, Widget}; diff --git a/pure/src/element.rs b/pure/src/element.rs new file mode 100644 index 00000000..3d5697fe --- /dev/null +++ b/pure/src/element.rs @@ -0,0 +1,163 @@ +use crate::widget::tree::{self, Tree}; +use crate::widget::Widget; + +use iced_native::event::{self, Event}; +use iced_native::layout::{self, Layout}; +use iced_native::mouse; +use iced_native::renderer; +use iced_native::{Clipboard, Length, Point, Rectangle, Shell}; + +pub struct Element<'a, Message, Renderer> { + widget: Box + 'a>, +} + +impl<'a, Message, Renderer> Element<'a, Message, Renderer> { + pub fn new(widget: impl Widget + 'a) -> Self { + Self { + widget: Box::new(widget), + } + } + + pub fn as_widget(&self) -> &dyn Widget { + self.widget.as_ref() + } + + pub fn as_widget_mut(&mut self) -> &mut dyn Widget { + self.widget.as_mut() + } + + pub fn map( + self, + f: impl Fn(Message) -> B + 'a, + ) -> Element<'a, B, Renderer> + where + Message: 'a, + Renderer: iced_native::Renderer + 'a, + B: 'a, + { + Element::new(Map::new(self.widget, f)) + } +} + +struct Map<'a, A, B, Renderer> { + widget: Box + 'a>, + mapper: Box B + 'a>, +} + +impl<'a, A, B, Renderer> Map<'a, A, B, Renderer> { + pub fn new( + widget: Box + 'a>, + mapper: F, + ) -> Map<'a, A, B, Renderer> + where + F: 'a + Fn(A) -> B, + { + Map { + widget, + mapper: Box::new(mapper), + } + } +} + +impl<'a, A, B, Renderer> Widget for Map<'a, A, B, Renderer> +where + Renderer: iced_native::Renderer + 'a, + A: 'a, + B: 'a, +{ + fn tag(&self) -> tree::Tag { + self.widget.tag() + } + + fn state(&self) -> tree::State { + self.widget.state() + } + + fn children(&self) -> Vec { + self.widget.children() + } + + fn diff(&self, tree: &mut Tree) { + self.widget.diff(tree) + } + + fn width(&self) -> Length { + self.widget.width() + } + + fn height(&self) -> Length { + self.widget.height() + } + + fn layout( + &self, + renderer: &Renderer, + limits: &layout::Limits, + ) -> layout::Node { + self.widget.layout(renderer, limits) + } + + fn on_event( + &mut self, + tree: &mut Tree, + event: Event, + layout: Layout<'_>, + cursor_position: Point, + renderer: &Renderer, + clipboard: &mut dyn Clipboard, + shell: &mut Shell<'_, B>, + ) -> event::Status { + let mut local_messages = Vec::new(); + let mut local_shell = Shell::new(&mut local_messages); + + let status = self.widget.on_event( + tree, + event, + layout, + cursor_position, + renderer, + clipboard, + &mut local_shell, + ); + + shell.merge(local_shell, &self.mapper); + + status + } + + fn draw( + &self, + tree: &Tree, + renderer: &mut Renderer, + style: &renderer::Style, + layout: Layout<'_>, + cursor_position: Point, + viewport: &Rectangle, + ) { + self.widget.draw( + tree, + renderer, + style, + layout, + cursor_position, + viewport, + ) + } + + fn mouse_interaction( + &self, + tree: &Tree, + layout: Layout<'_>, + cursor_position: Point, + viewport: &Rectangle, + renderer: &Renderer, + ) -> mouse::Interaction { + self.widget.mouse_interaction( + tree, + layout, + cursor_position, + viewport, + renderer, + ) + } +} diff --git a/pure/src/helpers.rs b/pure/src/helpers.rs new file mode 100644 index 00000000..24f6dbaa --- /dev/null +++ b/pure/src/helpers.rs @@ -0,0 +1,153 @@ +use crate::widget; +use crate::Element; + +use iced_native::Length; +use std::borrow::Cow; +use std::ops::RangeInclusive; + +pub fn container<'a, Message, Renderer>( + content: impl Into>, +) -> widget::Container<'a, Message, Renderer> +where + Renderer: iced_native::Renderer, +{ + widget::Container::new(content) +} + +pub fn column<'a, Message, Renderer>() -> widget::Column<'a, Message, Renderer> +{ + widget::Column::new() +} + +pub fn row<'a, Message, Renderer>() -> widget::Row<'a, Message, Renderer> { + widget::Row::new() +} + +pub fn scrollable<'a, Message, Renderer>( + content: impl Into>, +) -> widget::Scrollable<'a, Message, Renderer> +where + Renderer: iced_native::Renderer, +{ + widget::Scrollable::new(content) +} + +pub fn button<'a, Message, Renderer>( + content: impl Into>, +) -> widget::Button<'a, Message, Renderer> { + widget::Button::new(content) +} + +pub fn text(text: impl Into) -> widget::Text +where + Renderer: iced_native::text::Renderer, +{ + widget::Text::new(text) +} + +pub fn checkbox<'a, Message, Renderer>( + label: impl Into, + is_checked: bool, + f: impl Fn(bool) -> Message + 'a, +) -> widget::Checkbox<'a, Message, Renderer> +where + Renderer: iced_native::text::Renderer, +{ + widget::Checkbox::new(is_checked, label, f) +} + +pub fn radio<'a, Message, Renderer, V>( + label: impl Into, + value: V, + selected: Option, + on_click: impl FnOnce(V) -> Message, +) -> widget::Radio<'a, Message, Renderer> +where + Message: Clone, + Renderer: iced_native::text::Renderer, + V: Copy + Eq, +{ + widget::Radio::new(value, label, selected, on_click) +} + +pub fn toggler<'a, Message, Renderer>( + label: impl Into>, + is_checked: bool, + f: impl Fn(bool) -> Message + 'a, +) -> widget::Toggler<'a, Message, Renderer> +where + Renderer: iced_native::text::Renderer, +{ + widget::Toggler::new(is_checked, label, f) +} + +pub fn text_input<'a, Message, Renderer>( + placeholder: &str, + value: &str, + on_change: impl Fn(String) -> Message + 'a, +) -> widget::TextInput<'a, Message, Renderer> +where + Message: Clone, + Renderer: iced_native::text::Renderer, +{ + widget::TextInput::new(placeholder, value, on_change) +} + +pub fn slider<'a, Message, T>( + range: std::ops::RangeInclusive, + value: T, + on_change: impl Fn(T) -> Message + 'a, +) -> widget::Slider<'a, T, Message> +where + Message: Clone, + T: Copy + From + std::cmp::PartialOrd, +{ + widget::Slider::new(range, value, on_change) +} + +pub fn pick_list<'a, Message, Renderer, T>( + options: impl Into>, + selected: Option, + on_selected: impl Fn(T) -> Message + 'a, +) -> widget::PickList<'a, T, Message, Renderer> +where + T: ToString + Eq + 'static, + [T]: ToOwned>, + Renderer: iced_native::text::Renderer, +{ + widget::PickList::new(options, selected, on_selected) +} + +pub fn image(handle: impl Into) -> widget::Image { + widget::Image::new(handle.into()) +} + +pub fn horizontal_space(width: Length) -> widget::Space { + widget::Space::with_width(width) +} + +pub fn vertical_space(height: Length) -> widget::Space { + widget::Space::with_height(height) +} + +/// Creates a horizontal [`Rule`] with the given height. +pub fn horizontal_rule<'a>(height: u16) -> widget::Rule<'a> { + widget::Rule::horizontal(height) +} + +/// Creates a vertical [`Rule`] with the given width. +pub fn vertical_rule<'a>(width: u16) -> widget::Rule<'a> { + widget::Rule::horizontal(width) +} + +/// Creates a new [`ProgressBar`]. +/// +/// It expects: +/// * an inclusive range of possible values +/// * the current value of the [`ProgressBar`] +pub fn progress_bar<'a>( + range: RangeInclusive, + value: f32, +) -> widget::ProgressBar<'a> { + widget::ProgressBar::new(range, value) +} diff --git a/pure/src/lib.rs b/pure/src/lib.rs index 1b51d55b..ec2f29f8 100644 --- a/pure/src/lib.rs +++ b/pure/src/lib.rs @@ -1,9 +1,14 @@ +pub mod helpers; pub mod overlay; pub mod widget; pub(crate) mod flex; -pub use widget::*; +mod element; + +pub use element::Element; +pub use helpers::*; +pub use widget::Widget; use iced_native::event::{self, Event}; use iced_native::layout::{self, Layout}; diff --git a/pure/src/overlay.rs b/pure/src/overlay.rs index 72415634..c87dfce8 100644 --- a/pure/src/overlay.rs +++ b/pure/src/overlay.rs @@ -1,4 +1,4 @@ -use crate::Tree; +use crate::widget::Tree; use iced_native::Layout; diff --git a/pure/src/widget.rs b/pure/src/widget.rs index 564f0583..be73c5fa 100644 --- a/pure/src/widget.rs +++ b/pure/src/widget.rs @@ -1,29 +1,27 @@ +pub mod button; +pub mod checkbox; +pub mod container; pub mod image; pub mod pane_grid; +pub mod pick_list; pub mod progress_bar; +pub mod radio; pub mod rule; +pub mod scrollable; +pub mod slider; +pub mod text_input; +pub mod toggler; pub mod tree; -mod button; -mod checkbox; mod column; -mod container; -mod element; -mod pick_list; -mod radio; mod row; -mod scrollable; -mod slider; mod space; mod text; -mod text_input; -mod toggler; pub use button::Button; pub use checkbox::Checkbox; pub use column::Column; pub use container::Container; -pub use element::Element; pub use image::Image; pub use pane_grid::PaneGrid; pub use pick_list::PickList; @@ -46,9 +44,6 @@ use iced_native::overlay; use iced_native::renderer; use iced_native::{Clipboard, Length, Point, Rectangle, Shell}; -use std::borrow::Cow; -use std::ops::RangeInclusive; - pub trait Widget { fn width(&self) -> Length; @@ -117,149 +112,3 @@ pub trait Widget { None } } - -pub fn container<'a, Message, Renderer>( - content: impl Into>, -) -> Container<'a, Message, Renderer> -where - Renderer: iced_native::Renderer, -{ - Container::new(content) -} - -pub fn column<'a, Message, Renderer>() -> Column<'a, Message, Renderer> { - Column::new() -} - -pub fn row<'a, Message, Renderer>() -> Row<'a, Message, Renderer> { - Row::new() -} - -pub fn scrollable<'a, Message, Renderer>( - content: impl Into>, -) -> Scrollable<'a, Message, Renderer> -where - Renderer: iced_native::Renderer, -{ - Scrollable::new(content) -} - -pub fn button<'a, Message, Renderer>( - content: impl Into>, -) -> Button<'a, Message, Renderer> { - Button::new(content) -} - -pub fn text(text: impl Into) -> Text -where - Renderer: iced_native::text::Renderer, -{ - Text::new(text) -} - -pub fn checkbox<'a, Message, Renderer>( - label: impl Into, - is_checked: bool, - f: impl Fn(bool) -> Message + 'a, -) -> Checkbox<'a, Message, Renderer> -where - Renderer: iced_native::text::Renderer, -{ - Checkbox::new(is_checked, label, f) -} - -pub fn radio<'a, Message, Renderer, V>( - label: impl Into, - value: V, - selected: Option, - on_click: impl FnOnce(V) -> Message, -) -> Radio<'a, Message, Renderer> -where - Message: Clone, - Renderer: iced_native::text::Renderer, - V: Copy + Eq, -{ - Radio::new(value, label, selected, on_click) -} - -pub fn toggler<'a, Message, Renderer>( - label: impl Into>, - is_checked: bool, - f: impl Fn(bool) -> Message + 'a, -) -> Toggler<'a, Message, Renderer> -where - Renderer: iced_native::text::Renderer, -{ - Toggler::new(is_checked, label, f) -} - -pub fn text_input<'a, Message, Renderer>( - placeholder: &str, - value: &str, - on_change: impl Fn(String) -> Message + 'a, -) -> TextInput<'a, Message, Renderer> -where - Message: Clone, - Renderer: iced_native::text::Renderer, -{ - TextInput::new(placeholder, value, on_change) -} - -pub fn slider<'a, Message, T>( - range: std::ops::RangeInclusive, - value: T, - on_change: impl Fn(T) -> Message + 'a, -) -> Slider<'a, T, Message> -where - Message: Clone, - T: Copy + From + std::cmp::PartialOrd, -{ - Slider::new(range, value, on_change) -} - -pub fn pick_list<'a, Message, Renderer, T>( - options: impl Into>, - selected: Option, - on_selected: impl Fn(T) -> Message + 'a, -) -> PickList<'a, T, Message, Renderer> -where - T: ToString + Eq + 'static, - [T]: ToOwned>, - Renderer: iced_native::text::Renderer, -{ - PickList::new(options, selected, on_selected) -} - -pub fn image(handle: impl Into) -> Image { - Image::new(handle.into()) -} - -pub fn horizontal_space(width: Length) -> Space { - Space::with_width(width) -} - -pub fn vertical_space(height: Length) -> Space { - Space::with_height(height) -} - -/// Creates a horizontal [`Rule`] with the given height. -pub fn horizontal_rule<'a>(height: u16) -> Rule<'a> { - Rule::horizontal(height) -} - -/// Creates a vertical [`Rule`] with the given width. -pub fn vertical_rule<'a>(width: u16) -> Rule<'a> { - Rule::horizontal(width) -} - -/// Creates a new [`ProgressBar`]. -/// -/// It expects: -/// * an inclusive range of possible values -/// * the current value of the [`ProgressBar`] -pub fn progress_bar<'a>( - range: RangeInclusive, - value: f32, -) -> ProgressBar<'a> { - ProgressBar::new(range, value) -} diff --git a/pure/src/widget/button.rs b/pure/src/widget/button.rs index 4380b608..f99d3018 100644 --- a/pure/src/widget/button.rs +++ b/pure/src/widget/button.rs @@ -1,6 +1,6 @@ use crate::overlay; use crate::widget::tree::{self, Tree}; -use crate::widget::{Element, Widget}; +use crate::{Element, Widget}; use iced_native::event::{self, Event}; use iced_native::layout; @@ -10,9 +10,10 @@ use iced_native::widget::button; use iced_native::{ Clipboard, Layout, Length, Padding, Point, Rectangle, Shell, }; -use iced_style::button::StyleSheet; -pub use button::State; +pub use iced_style::button::{Style, StyleSheet}; + +use button::State; pub struct Button<'a, Message, Renderer> { content: Element<'a, Message, Renderer>, diff --git a/pure/src/widget/checkbox.rs b/pure/src/widget/checkbox.rs index 3448e616..971980e3 100644 --- a/pure/src/widget/checkbox.rs +++ b/pure/src/widget/checkbox.rs @@ -1,4 +1,5 @@ -use crate::{Element, Tree, Widget}; +use crate::widget::Tree; +use crate::{Element, Widget}; use iced_native::event::{self, Event}; use iced_native::layout::{self, Layout}; @@ -7,7 +8,7 @@ use iced_native::renderer; use iced_native::text; use iced_native::{Clipboard, Length, Point, Rectangle, Shell}; -pub use iced_native::widget::Checkbox; +pub use iced_native::widget::checkbox::{Checkbox, Style, StyleSheet}; impl<'a, Message, Renderer> Widget for Checkbox<'a, Message, Renderer> diff --git a/pure/src/widget/column.rs b/pure/src/widget/column.rs index 37ff96c5..6b447270 100644 --- a/pure/src/widget/column.rs +++ b/pure/src/widget/column.rs @@ -1,6 +1,7 @@ use crate::flex; use crate::overlay; -use crate::widget::{Element, Tree, Widget}; +use crate::widget::Tree; +use crate::{Element, Widget}; use iced_native::event::{self, Event}; use iced_native::layout::{self, Layout}; diff --git a/pure/src/widget/container.rs b/pure/src/widget/container.rs index ebf69cab..91db1f3f 100644 --- a/pure/src/widget/container.rs +++ b/pure/src/widget/container.rs @@ -1,5 +1,6 @@ //! Decorate content and apply alignment. -use crate::{Element, Tree, Widget}; +use crate::widget::Tree; +use crate::{Element, Widget}; use iced_native::alignment; use iced_native::event::{self, Event}; diff --git a/pure/src/widget/element.rs b/pure/src/widget/element.rs deleted file mode 100644 index 3d5697fe..00000000 --- a/pure/src/widget/element.rs +++ /dev/null @@ -1,163 +0,0 @@ -use crate::widget::tree::{self, Tree}; -use crate::widget::Widget; - -use iced_native::event::{self, Event}; -use iced_native::layout::{self, Layout}; -use iced_native::mouse; -use iced_native::renderer; -use iced_native::{Clipboard, Length, Point, Rectangle, Shell}; - -pub struct Element<'a, Message, Renderer> { - widget: Box + 'a>, -} - -impl<'a, Message, Renderer> Element<'a, Message, Renderer> { - pub fn new(widget: impl Widget + 'a) -> Self { - Self { - widget: Box::new(widget), - } - } - - pub fn as_widget(&self) -> &dyn Widget { - self.widget.as_ref() - } - - pub fn as_widget_mut(&mut self) -> &mut dyn Widget { - self.widget.as_mut() - } - - pub fn map( - self, - f: impl Fn(Message) -> B + 'a, - ) -> Element<'a, B, Renderer> - where - Message: 'a, - Renderer: iced_native::Renderer + 'a, - B: 'a, - { - Element::new(Map::new(self.widget, f)) - } -} - -struct Map<'a, A, B, Renderer> { - widget: Box + 'a>, - mapper: Box B + 'a>, -} - -impl<'a, A, B, Renderer> Map<'a, A, B, Renderer> { - pub fn new( - widget: Box + 'a>, - mapper: F, - ) -> Map<'a, A, B, Renderer> - where - F: 'a + Fn(A) -> B, - { - Map { - widget, - mapper: Box::new(mapper), - } - } -} - -impl<'a, A, B, Renderer> Widget for Map<'a, A, B, Renderer> -where - Renderer: iced_native::Renderer + 'a, - A: 'a, - B: 'a, -{ - fn tag(&self) -> tree::Tag { - self.widget.tag() - } - - fn state(&self) -> tree::State { - self.widget.state() - } - - fn children(&self) -> Vec { - self.widget.children() - } - - fn diff(&self, tree: &mut Tree) { - self.widget.diff(tree) - } - - fn width(&self) -> Length { - self.widget.width() - } - - fn height(&self) -> Length { - self.widget.height() - } - - fn layout( - &self, - renderer: &Renderer, - limits: &layout::Limits, - ) -> layout::Node { - self.widget.layout(renderer, limits) - } - - fn on_event( - &mut self, - tree: &mut Tree, - event: Event, - layout: Layout<'_>, - cursor_position: Point, - renderer: &Renderer, - clipboard: &mut dyn Clipboard, - shell: &mut Shell<'_, B>, - ) -> event::Status { - let mut local_messages = Vec::new(); - let mut local_shell = Shell::new(&mut local_messages); - - let status = self.widget.on_event( - tree, - event, - layout, - cursor_position, - renderer, - clipboard, - &mut local_shell, - ); - - shell.merge(local_shell, &self.mapper); - - status - } - - fn draw( - &self, - tree: &Tree, - renderer: &mut Renderer, - style: &renderer::Style, - layout: Layout<'_>, - cursor_position: Point, - viewport: &Rectangle, - ) { - self.widget.draw( - tree, - renderer, - style, - layout, - cursor_position, - viewport, - ) - } - - fn mouse_interaction( - &self, - tree: &Tree, - layout: Layout<'_>, - cursor_position: Point, - viewport: &Rectangle, - renderer: &Renderer, - ) -> mouse::Interaction { - self.widget.mouse_interaction( - tree, - layout, - cursor_position, - viewport, - renderer, - ) - } -} diff --git a/pure/src/widget/pane_grid.rs b/pure/src/widget/pane_grid.rs index 717c9ceb..34a56bcc 100644 --- a/pure/src/widget/pane_grid.rs +++ b/pure/src/widget/pane_grid.rs @@ -54,7 +54,8 @@ pub use iced_style::pane_grid::{Line, StyleSheet}; /// ## Example /// /// ``` -/// # use iced_pure::widget::{pane_grid, text}; +/// # use iced_pure::widget::pane_grid; +/// # use iced_pure::text; /// # /// # type PaneGrid<'a, Message> = /// # iced_pure::widget::PaneGrid<'a, Message, iced_native::renderer::Null>; diff --git a/pure/src/widget/progress_bar.rs b/pure/src/widget/progress_bar.rs index 9b996f02..3f4ffd55 100644 --- a/pure/src/widget/progress_bar.rs +++ b/pure/src/widget/progress_bar.rs @@ -1,4 +1,5 @@ -use crate::{Element, Tree, Widget}; +use crate::widget::Tree; +use crate::{Element, Widget}; use iced_native::event::{self, Event}; use iced_native::layout::{self, Layout}; diff --git a/pure/src/widget/radio.rs b/pure/src/widget/radio.rs index ce3ede84..c20f8f3e 100644 --- a/pure/src/widget/radio.rs +++ b/pure/src/widget/radio.rs @@ -1,4 +1,5 @@ -use crate::{Element, Tree, Widget}; +use crate::widget::Tree; +use crate::{Element, Widget}; use iced_native::event::{self, Event}; use iced_native::layout::{self, Layout}; @@ -7,7 +8,7 @@ use iced_native::renderer; use iced_native::text; use iced_native::{Clipboard, Length, Point, Rectangle, Shell}; -pub use iced_native::widget::Radio; +pub use iced_native::widget::radio::{Radio, Style, StyleSheet}; impl<'a, Message, Renderer> Widget for Radio<'a, Message, Renderer> diff --git a/pure/src/widget/row.rs b/pure/src/widget/row.rs index fa0efa68..d7f90540 100644 --- a/pure/src/widget/row.rs +++ b/pure/src/widget/row.rs @@ -1,6 +1,7 @@ use crate::flex; use crate::overlay; -use crate::widget::{Element, Tree, Widget}; +use crate::widget::Tree; +use crate::{Element, Widget}; use iced_native::event::{self, Event}; use iced_native::layout::{self, Layout}; diff --git a/pure/src/widget/rule.rs b/pure/src/widget/rule.rs index 375bed9e..40b1fc90 100644 --- a/pure/src/widget/rule.rs +++ b/pure/src/widget/rule.rs @@ -1,4 +1,5 @@ -use crate::{Element, Tree, Widget}; +use crate::widget::Tree; +use crate::{Element, Widget}; use iced_native::event::{self, Event}; use iced_native::layout::{self, Layout}; diff --git a/pure/src/widget/scrollable.rs b/pure/src/widget/scrollable.rs index 1548fa9d..f9a51200 100644 --- a/pure/src/widget/scrollable.rs +++ b/pure/src/widget/scrollable.rs @@ -9,7 +9,7 @@ use iced_native::renderer; use iced_native::widget::scrollable; use iced_native::{Clipboard, Length, Point, Rectangle, Shell, Vector}; -pub use iced_style::scrollable::StyleSheet; +pub use iced_style::scrollable::{Scrollbar, Scroller, StyleSheet}; /// A widget that can vertically display an infinite amount of content with a /// scrollbar. diff --git a/pure/src/widget/space.rs b/pure/src/widget/space.rs index c04d962a..b408153b 100644 --- a/pure/src/widget/space.rs +++ b/pure/src/widget/space.rs @@ -1,4 +1,5 @@ -use crate::{Element, Tree, Widget}; +use crate::widget::Tree; +use crate::{Element, Widget}; use iced_native::event::{self, Event}; use iced_native::layout::{self, Layout}; diff --git a/pure/src/widget/text.rs b/pure/src/widget/text.rs index bfcbaa4b..edc35cd1 100644 --- a/pure/src/widget/text.rs +++ b/pure/src/widget/text.rs @@ -1,4 +1,5 @@ -use crate::{Element, Tree, Widget}; +use crate::widget::Tree; +use crate::{Element, Widget}; use iced_native::layout::{self, Layout}; use iced_native::renderer; diff --git a/pure/src/widget/text_input.rs b/pure/src/widget/text_input.rs index dec11164..d6041d7f 100644 --- a/pure/src/widget/text_input.rs +++ b/pure/src/widget/text_input.rs @@ -1,5 +1,5 @@ use crate::widget::tree::{self, Tree}; -use crate::widget::{Element, Widget}; +use crate::{Element, Widget}; use iced_native::event::{self, Event}; use iced_native::layout::{self, Layout}; @@ -9,7 +9,7 @@ use iced_native::text; use iced_native::widget::text_input; use iced_native::{Clipboard, Length, Padding, Point, Rectangle, Shell}; -pub use iced_style::text_input::StyleSheet; +pub use iced_style::text_input::{Style, StyleSheet}; /// A field that can be filled with text. /// diff --git a/pure/src/widget/tree.rs b/pure/src/widget/tree.rs index 3fcf0922..bd7c259c 100644 --- a/pure/src/widget/tree.rs +++ b/pure/src/widget/tree.rs @@ -1,4 +1,4 @@ -use crate::widget::Element; +use crate::Element; use std::any::{self, Any}; diff --git a/src/pure.rs b/src/pure.rs index f3f73bba..948183f1 100644 --- a/src/pure.rs +++ b/src/pure.rs @@ -17,33 +17,7 @@ //! [the original widgets]: crate::widget //! [`button::State`]: crate::widget::button::State //! [impure `Application`]: crate::Application -pub use iced_pure::{ - Button as _, Column as _, Element as _, Image as _, Row as _, Text as _, *, -}; - -/// A generic, pure [`Widget`]. -pub type Element<'a, Message> = - iced_pure::Element<'a, Message, crate::Renderer>; - -/// A pure container widget. -pub type Container<'a, Message> = - iced_pure::Container<'a, Message, crate::Renderer>; - -/// A pure column widget. -pub type Column<'a, Message> = iced_pure::Column<'a, Message, crate::Renderer>; - -/// A pure row widget. -pub type Row<'a, Message> = iced_pure::Row<'a, Message, crate::Renderer>; - -/// A pure button widget. -pub type Button<'a, Message> = iced_pure::Button<'a, Message, crate::Renderer>; - -/// A pure text widget. -pub type Text = iced_pure::Text; - -#[cfg(feature = "image")] -/// A pure image widget. -pub type Image = iced_pure::Image; +pub mod widget; mod application; mod sandbox; @@ -51,8 +25,9 @@ mod sandbox; pub use application::Application; pub use sandbox::Sandbox; -#[cfg(feature = "canvas")] -pub use iced_graphics::widget::pure::canvas; +pub use iced_pure::helpers::*; +pub use iced_pure::{Pure, State}; -#[cfg(feature = "canvas")] -pub use canvas::Canvas; +/// A generic, pure [`Widget`]. +pub type Element<'a, Message> = + iced_pure::Element<'a, Message, crate::Renderer>; diff --git a/src/pure/widget.rs b/src/pure/widget.rs new file mode 100644 index 00000000..e9a533ea --- /dev/null +++ b/src/pure/widget.rs @@ -0,0 +1,155 @@ +//! Pure versions of the widgets. + +/// A container that distributes its contents vertically. +pub type Column<'a, Message> = + iced_pure::widget::Column<'a, Message, crate::Renderer>; + +/// A container that distributes its contents horizontally. +pub type Row<'a, Message> = + iced_pure::widget::Row<'a, Message, crate::Renderer>; + +/// A paragraph of text. +pub type Text = iced_pure::widget::Text; + +pub mod button { + //! Allow your users to perform actions by pressing a button. + pub use iced_pure::widget::button::{Style, StyleSheet}; + + /// A widget that produces a message when clicked. + pub type Button<'a, Message> = + iced_pure::widget::Button<'a, Message, crate::Renderer>; +} + +pub mod checkbox { + //! Show toggle controls using checkboxes. + pub use iced_pure::widget::checkbox::{Style, StyleSheet}; + + /// A box that can be checked. + pub type Checkbox<'a, Message> = + iced_native::widget::Checkbox<'a, Message, crate::Renderer>; +} + +pub mod container { + //! Decorate content and apply alignment. + pub use iced_pure::widget::container::{Style, StyleSheet}; + + /// An element decorating some content. + pub type Container<'a, Message> = + iced_pure::widget::Container<'a, Message, crate::Renderer>; +} + +pub mod pane_grid { + //! Let your users split regions of your application and organize layout dynamically. + //! + //! [![Pane grid - Iced](https://thumbs.gfycat.com/MixedFlatJellyfish-small.gif)](https://gfycat.com/mixedflatjellyfish) + //! + //! # Example + //! The [`pane_grid` example] showcases how to use a [`PaneGrid`] with resizing, + //! drag and drop, and hotkey support. + //! + //! [`pane_grid` example]: https://github.com/iced-rs/iced/tree/0.3/examples/pane_grid + pub use iced_pure::widget::pane_grid::{ + Axis, Configuration, Direction, DragEvent, Line, Node, Pane, + ResizeEvent, Split, State, StyleSheet, + }; + + /// A collection of panes distributed using either vertical or horizontal splits + /// to completely fill the space available. + /// + /// [![Pane grid - Iced](https://thumbs.gfycat.com/MixedFlatJellyfish-small.gif)](https://gfycat.com/mixedflatjellyfish) + pub type PaneGrid<'a, Message> = + iced_pure::widget::PaneGrid<'a, Message, crate::Renderer>; + + /// The content of a [`Pane`]. + pub type Content<'a, Message> = + iced_pure::widget::pane_grid::Content<'a, Message, crate::Renderer>; + + /// The title bar of a [`Pane`]. + pub type TitleBar<'a, Message> = + iced_pure::widget::pane_grid::TitleBar<'a, Message, crate::Renderer>; +} + +pub mod pick_list { + //! Display a dropdown list of selectable values. + pub use iced_pure::overlay::menu::Style as Menu; + pub use iced_pure::widget::pick_list::{Style, StyleSheet}; + + /// A widget allowing the selection of a single value from a list of options. + pub type PickList<'a, T, Message> = + iced_pure::widget::PickList<'a, T, Message, crate::Renderer>; +} + +pub mod radio { + //! Create choices using radio buttons. + pub use iced_pure::widget::radio::{Style, StyleSheet}; + + /// A circular button representing a choice. + pub type Radio<'a, Message> = + iced_pure::widget::Radio<'a, Message, crate::Renderer>; +} + +pub mod scrollable { + //! Navigate an endless amount of content with a scrollbar. + pub use iced_pure::widget::scrollable::{Scrollbar, Scroller, StyleSheet}; + + /// A widget that can vertically display an infinite amount of content + /// with a scrollbar. + pub type Scrollable<'a, Message> = + iced_pure::widget::Scrollable<'a, Message, crate::Renderer>; +} + +pub mod toggler { + //! Show toggle controls using togglers. + pub use iced_pure::widget::toggler::{Style, StyleSheet}; + + /// A toggler widget. + pub type Toggler<'a, Message> = + iced_pure::widget::Toggler<'a, Message, crate::Renderer>; +} + +pub mod text_input { + //! Display fields that can be filled with text. + use crate::Renderer; + + pub use iced_pure::widget::text_input::{Style, StyleSheet}; + + /// A field that can be filled with text. + pub type TextInput<'a, Message> = + iced_pure::widget::TextInput<'a, Message, Renderer>; +} + +pub use iced_pure::widget::progress_bar; +pub use iced_pure::widget::rule; +pub use iced_pure::widget::slider; +pub use iced_pure::widget::Space; + +pub use button::Button; +pub use checkbox::Checkbox; +pub use container::Container; +pub use pane_grid::PaneGrid; +pub use pick_list::PickList; +pub use progress_bar::ProgressBar; +pub use radio::Radio; +pub use rule::Rule; +pub use scrollable::Scrollable; +pub use slider::Slider; +pub use text_input::TextInput; +pub use toggler::Toggler; + +#[cfg(feature = "canvas")] +pub use iced_graphics::widget::pure::canvas; + +#[cfg(feature = "image")] +pub mod image { + //! Display images in your user interface. + pub use iced_native::image::Handle; + + /// A frame that displays an image. + pub type Image = iced_pure::widget::Image; +} + +#[cfg(feature = "canvas")] +pub use canvas::Canvas; + +#[cfg(feature = "image")] +pub use image::Image; -- cgit