From bd880987871663318fa89beb60a923428761439d Mon Sep 17 00:00:00 2001 From: genusistimelord Date: Mon, 6 Nov 2023 17:02:05 -0500 Subject: [PATCH 01/22] fixed color picker for newest iced --- Cargo.toml | 104 ++++++++--------- src/native/color_picker.rs | 4 +- src/native/overlay/color_picker.rs | 178 ++++++++++++++++++----------- 3 files changed, 164 insertions(+), 122 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 29a46688..0734fdd6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,27 +40,27 @@ context_menu = [] segmented_button = [] default = [ - "badge", - "card", - "number_input", - "date_picker", + #"badge", + #"card", + #"number_input", + #"date_picker", "color_picker", - "floating_element", - "icon_text", - "grid", - "modal", - "tab_bar", - "tabs", - "time_picker", - "wrap", - "selection_list", - "split", - "menu", - "quad", - "context_menu", - "spinner", - "cupertino", - "segmented_button", + #"floating_element", + #"icon_text", + #"grid", + #"modal", + #"tab_bar", + #"tabs", + #"time_picker", + #"wrap", + #"selection_list", + #"split", + #"menu", + #"quad", + #"context_menu", + #"spinner", + #"cupertino", + #"segmented_button", ] [dependencies] @@ -72,48 +72,48 @@ itertools = { version = "0.11.0", optional = true } [dependencies.iced_widget] -#git = "https://github.com/iced-rs/iced.git" -#rev = "8221794" -version = "0.1.1" +git = "https://github.com/iced-rs/iced.git" +rev = "751ea77c29f6eb3d00f45f0a04c833a1d03a425c" +#version = "0.1.1" [profile.dev.package."*"] opt-level = 2 [workspace] members = [ - "examples/badge", - "examples/card", + #"examples/badge", + #"examples/card", "examples/color_picker", - "examples/cupertino/cupertino_alert", - "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/menu", - "examples/spinner", - "examples/context_menu", - "examples/WidgetIDReturn", - "examples/segmented_button", + #"examples/cupertino/cupertino_alert", + #"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/menu", + #"examples/spinner", + #"examples/context_menu", + #"examples/WidgetIDReturn", + #"examples/segmented_button", ] [workspace.dependencies.iced] -#git = "https://github.com/iced-rs/iced.git" -#rev = "8221794" -version = "0.10.0" +git = "https://github.com/iced-rs/iced.git" +rev = "751ea77c29f6eb3d00f45f0a04c833a1d03a425c" +#version = "0.10.0" features = ["advanced", "lazy", "tokio"] [workspace.dependencies.iced_aw] diff --git a/src/native/color_picker.rs b/src/native/color_picker.rs index db5facf6..4dba9c88 100644 --- a/src/native/color_picker.rs +++ b/src/native/color_picker.rs @@ -174,8 +174,8 @@ where self.underlay.as_widget().width() } - fn layout(&self, renderer: &Renderer, limits: &Limits) -> Node { - self.underlay.as_widget().layout(renderer, limits) + fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { + self.underlay.as_widget().layout(&mut tree.children[0], renderer, limits) } fn on_event( diff --git a/src/native/overlay/color_picker.rs b/src/native/overlay/color_picker.rs index 949aeb23..4a6ff026 100644 --- a/src/native/overlay/color_picker.rs +++ b/src/native/overlay/color_picker.rs @@ -27,8 +27,8 @@ use iced_widget::{ text::Renderer as _, touch, widget::{self, tree::Tree}, - Alignment, Clipboard, Color, Element, Event, Layout, Length, Overlay, Padding, Point, - Rectangle, Renderer as _, Shell, Size, Text, Vector, Widget, + Alignment, Clipboard, Color, Element, Event, Layout, Length, Overlay, Padding, Pixels, + Point, Rectangle, Renderer as _, Shell, Size, Text, Vector, Widget, }, graphics::geometry::Renderer as _, renderer::Renderer, @@ -544,7 +544,7 @@ where Message: 'static + Clone, Theme: 'a + StyleSheet + button::StyleSheet + widget::text::StyleSheet, { - fn layout(&self, renderer: &Renderer, bounds: Size, position: Point) -> Node { + fn layout(&mut self, renderer: &Renderer, bounds: Size, position: Point) -> Node { let (max_width, max_height) = if bounds.width > bounds.height { (600.0, 300.0) } else { @@ -563,13 +563,13 @@ where .spacing(SPACING) .push(Row::new().width(Length::Fill).height(Length::Fill)) .push(Row::new().width(Length::Fill).height(Length::Fill)) - .layout(renderer, &limits) + .layout(self.tree, renderer, &limits) } else { Column::<(), Renderer>::new() .spacing(SPACING) .push(Row::new().width(Length::Fill).height(Length::Fill)) .push(Row::new().width(Length::Fill).height(Length::Fill)) - .layout(renderer, &limits) + .layout(self.tree, renderer, &limits) }; let mut divider_children = divider.children().iter(); @@ -793,7 +793,7 @@ where .next() .expect("Graphics: Layout should have a cancel button layout for a ColorPicker"); let cancel_mouse_interaction = self.cancel_button.mouse_interaction( - &self.tree.children[0], + &self.tree.children[1], cancel_button_layout, cursor, viewport, @@ -881,7 +881,7 @@ where /// Defines the layout of the 1. block of the color picker containing the HSV part. fn block1_layout<'a, Message, Theme>( - _color_picker: &ColorPickerOverlay<'a, Message, Theme>, + color_picker: &mut ColorPickerOverlay<'a, Message, Theme>, renderer: &Renderer, bounds: Rectangle, _position: Point, @@ -906,7 +906,7 @@ where .width(Length::Fill) .height(Length::FillPortion(1)), ) - .layout(renderer, &block1_limits); + .layout(&mut color_picker.tree, renderer, &block1_limits); block1_node.move_to(Point::new(bounds.x + PADDING, bounds.y + PADDING)); @@ -915,7 +915,7 @@ where /// Defines the layout of the 2. block of the color picker containing the RGBA part, Hex and buttons. fn block2_layout<'a, Message, Theme>( - color_picker: &ColorPickerOverlay<'a, Message, Theme>, + color_picker: &mut ColorPickerOverlay<'a, Message, Theme>, renderer: &Renderer, bounds: Rectangle, _position: Point, @@ -930,21 +930,41 @@ where // Pre-Buttons TODO: get rid of it let cancel_limits = block2_limits; - let cancel_button = color_picker.cancel_button.layout(renderer, &cancel_limits); + let cancel_button = color_picker.cancel_button.layout( + &mut color_picker.tree.children[0], + renderer, + &cancel_limits, + ); let hex_text_limits = block2_limits; - let mut hex_text = Row::<(), Renderer>::new() + + let mut hex_text = Row::>::new() .width(Length::Fill) - .height(Length::Fixed(renderer.default_size() + 2.0 * PADDING)) - .layout(renderer, &hex_text_limits); + .height(Length::Fixed(renderer.default_size().0 + 2.0 * PADDING)); + + let element: Element> = Element::new(hex_text); + let mut rgba_tree = if let Some(child_tree) = color_picker.tree.children.get_mut(2) { + child_tree.diff(element.as_widget()); + child_tree + } else { + let child_tree = Tree::new(element.as_widget()); + color_picker.tree.children.insert(2, child_tree); + color_picker.tree.children.get_mut(2).unwrap() + }; + + let mut hex_text_layout = + element + .as_widget() + .layout(color_picker.tree, renderer, &hex_text_limits); let block2_limits = block2_limits.shrink(Size::new( 0.0, - cancel_button.bounds().height + hex_text.bounds().height + 2.0 * SPACING, + cancel_button.bounds().height + hex_text_layout.bounds().height + 2.0 * SPACING, )); // RGBA Colors - let mut rgba_colors = Column::<(), Renderer>::new(); + let mut rgba_colors: Column<'_, Message, Renderer> = + Column::>::new(); for _ in 0..4 { rgba_colors = rgba_colors.push( @@ -970,8 +990,19 @@ where ), ); } + let element: Element> = Element::new(rgba_colors); + let mut rgba_tree = if let Some(child_tree) = color_picker.tree.children.get_mut(3) { + child_tree.diff(element.as_widget()); + child_tree + } else { + let child_tree = Tree::new(element.as_widget()); + color_picker.tree.children.insert(3, child_tree); + color_picker.tree.children.get_mut(3).unwrap() + }; - let mut rgba_colors = rgba_colors.layout(renderer, &block2_limits); + let mut rgba_colors = element + .as_widget() + .layout(&mut rgba_tree, renderer, &block2_limits); rgba_colors.move_to(Point::new( rgba_colors.bounds().x + PADDING, @@ -979,27 +1010,35 @@ where )); // Hex text - hex_text.move_to(Point::new( - hex_text.bounds().x + PADDING, - hex_text.bounds().y + rgba_colors.bounds().height + PADDING + SPACING, + hex_text_layout.move_to(Point::new( + hex_text_layout.bounds().x + PADDING, + hex_text_layout.bounds().y + rgba_colors.bounds().height + PADDING + SPACING, )); // Buttons let cancel_limits = block2_limits.max_width(((rgba_colors.bounds().width / 2.0) - BUTTON_SPACING).max(0.0)); - let mut cancel_button = color_picker.cancel_button.layout(renderer, &cancel_limits); + let mut cancel_button = color_picker.cancel_button.layout( + &mut color_picker.tree.children[0], + renderer, + &cancel_limits, + ); let submit_limits = block2_limits.max_width(((rgba_colors.bounds().width / 2.0) - BUTTON_SPACING).max(0.0)); - let mut submit_button = color_picker.submit_button.layout(renderer, &submit_limits); + let mut submit_button = color_picker.submit_button.layout( + &mut color_picker.tree.children[1], + renderer, + &submit_limits, + ); cancel_button.move_to(Point::new( cancel_button.bounds().x + PADDING, cancel_button.bounds().y + rgba_colors.bounds().height - + hex_text.bounds().height + + hex_text_layout.bounds().height + PADDING + 2.0 * SPACING, )); @@ -1009,7 +1048,7 @@ where + PADDING, submit_button.bounds().y + rgba_colors.bounds().height - + hex_text.bounds().height + + hex_text_layout.bounds().height + PADDING + 2.0 * SPACING, )); @@ -1018,12 +1057,12 @@ where Size::new( rgba_colors.bounds().width + (2.0 * PADDING), rgba_colors.bounds().height - + hex_text.bounds().height + + hex_text_layout.bounds().height + cancel_button.bounds().height + (2.0 * PADDING) + (2.0 * SPACING), ), - vec![rgba_colors, hex_text, cancel_button, submit_button], + vec![rgba_colors, hex_text_layout, cancel_button, submit_button], ); block2_node.move_to(Point::new(bounds.x, bounds.y)); @@ -1376,21 +1415,23 @@ fn rgba_color( .expect("Graphics: Layout should have a value layout"); // Label - renderer.fill_text(Text { - content: label, - bounds: Rectangle { - x: label_layout.bounds().center_x(), - y: label_layout.bounds().center_y(), - ..label_layout.bounds() + renderer.fill_text( + Text { + content: label, + bounds: Size::new(label_layout.bounds().width, label_layout.bounds().height), + size: renderer.default_size(), + font: crate::ICON_FONT, + horizontal_alignment: Horizontal::Center, + vertical_alignment: Vertical::Center, + line_height: text::LineHeight::Relative(1.3), + shaping: text::Shaping::Advanced, }, - size: renderer.default_size(), - font: crate::ICON_FONT, - horizontal_alignment: Horizontal::Center, - vertical_alignment: Vertical::Center, - line_height: text::LineHeight::Relative(1.3), - shaping: text::Shaping::Advanced, - color: style.text_color, - }); + Point::new( + label_layout.bounds().center_x(), + label_layout.bounds().center_y(), + ), + style.text_color, + ); let bounds = bar_layout.bounds(); @@ -1445,21 +1486,23 @@ fn rgba_color( ); // Value - renderer.fill_text(Text { - content: &format!("{}", (255.0 * value) as u8), - bounds: Rectangle { - x: value_layout.bounds().center_x(), - y: value_layout.bounds().center_y(), - ..value_layout.bounds() + renderer.fill_text( + Text { + content: &format!("{}", (255.0 * value) as u8), + bounds: Size::new(value_layout.bounds().width, value_layout.bounds().height), + size: renderer.default_size(), + font: renderer.default_font(), + horizontal_alignment: Horizontal::Center, + vertical_alignment: Vertical::Center, + line_height: iced_widget::text::LineHeight::Relative(1.3), + shaping: iced_widget::text::Shaping::Advanced, }, - size: renderer.default_size(), - font: renderer.default_font(), - horizontal_alignment: Horizontal::Center, - vertical_alignment: Vertical::Center, - line_height: iced_widget::text::LineHeight::Relative(1.3), - shaping: iced_widget::text::Shaping::Advanced, - color: style.text_color, - }); + Point::new( + value_layout.bounds().center_x(), + value_layout.bounds().center_y(), + ), + style.text_color, + ); if focus == target { renderer.fill_quad( @@ -1575,15 +1618,19 @@ fn hex_text( *color, ); - renderer.fill_text(Text { - content: &color.as_hex_string(), - bounds: Rectangle { - x: layout.bounds().center_x(), - y: layout.bounds().center_y(), - ..layout.bounds() + renderer.fill_text( + Text { + content: &color.as_hex_string(), + bounds: Size::new(layout.bounds().width, layout.bounds().height), + size: renderer.default_size(), + font: renderer.default_font(), + horizontal_alignment: Horizontal::Center, + vertical_alignment: Vertical::Center, + line_height: iced_widget::text::LineHeight::Relative(1.3), + shaping: iced_widget::text::Shaping::Basic, }, - size: renderer.default_size(), - color: Color { + Point::new(layout.bounds().center_x(), layout.bounds().center_y()), + Color { a: 1.0, ..Hsv { hue: 0, @@ -1592,12 +1639,7 @@ fn hex_text( } .into() }, - font: renderer.default_font(), - horizontal_alignment: Horizontal::Center, - vertical_alignment: Vertical::Center, - line_height: iced_widget::text::LineHeight::Relative(1.3), - shaping: iced_widget::text::Shaping::Basic, - }); + ); } /// The state of the [`ColorPickerOverlay`]. @@ -1699,7 +1741,7 @@ where unimplemented!("This should never be reached!") } - fn layout(&self, _renderer: &Renderer, _limits: &Limits) -> Node { + fn layout(&self, _tree: &mut Tree, _renderer: &Renderer, _limits: &Limits) -> Node { unimplemented!("This should never be reached!") } From 772ba4696b6b8abcd645611edeac5d3bf2f15802 Mon Sep 17 00:00:00 2001 From: genusistimelord Date: Tue, 7 Nov 2023 07:46:02 -0500 Subject: [PATCH 02/22] Fixed Badge --- Cargo.toml | 4 ++-- src/native/badge.rs | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0734fdd6..98ba0bf9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,7 +40,7 @@ context_menu = [] segmented_button = [] default = [ - #"badge", + "badge", #"card", #"number_input", #"date_picker", @@ -81,7 +81,7 @@ opt-level = 2 [workspace] members = [ - #"examples/badge", + "examples/badge", #"examples/card", "examples/color_picker", #"examples/cupertino/cupertino_alert", diff --git a/src/native/badge.rs b/src/native/badge.rs index 0873af76..7af5e2ab 100644 --- a/src/native/badge.rs +++ b/src/native/badge.rs @@ -139,7 +139,7 @@ where self.height } - fn layout(&self, renderer: &Renderer, limits: &Limits) -> Node { + fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { let padding = self.padding.into(); let limits = limits .loose() @@ -147,7 +147,10 @@ where .height(self.height) .pad(padding); - let mut content = self.content.as_widget().layout(renderer, &limits.loose()); + let mut content = + self.content + .as_widget() + .layout(&mut tree.children[0], renderer, &limits.loose()); let size = limits.resolve(content.size()); content.move_to(Point::new(padding.left, padding.top)); From 6c0365e7aec493872832fbd3a4a2f308a5fa4f88 Mon Sep 17 00:00:00 2001 From: genusistimelord Date: Tue, 7 Nov 2023 08:35:17 -0500 Subject: [PATCH 03/22] Fixed Number input and card --- Cargo.toml | 8 +- examples/number_input/src/main.rs | 2 +- src/native/card.rs | 67 ++++++++++------ src/native/number_input.rs | 128 +++++++++++++++++------------- 4 files changed, 122 insertions(+), 83 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 98ba0bf9..a95a200c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,8 +41,8 @@ segmented_button = [] default = [ "badge", - #"card", - #"number_input", + "card", + "number_input", #"date_picker", "color_picker", #"floating_element", @@ -82,7 +82,7 @@ opt-level = 2 [workspace] members = [ "examples/badge", - #"examples/card", + "examples/card", "examples/color_picker", #"examples/cupertino/cupertino_alert", #"examples/cupertino/cupertino_button", @@ -99,7 +99,7 @@ members = [ #"examples/tabs", #"examples/time_picker", #"examples/wrap", - #"examples/number_input", + "examples/number_input", #"examples/selection_list", #"examples/split", #"examples/split_scroller", diff --git a/examples/number_input/src/main.rs b/examples/number_input/src/main.rs index 7132949a..06aa9325 100644 --- a/examples/number_input/src/main.rs +++ b/examples/number_input/src/main.rs @@ -26,7 +26,7 @@ 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: (250, 200), ..Default::default() diff --git a/src/native/card.rs b/src/native/card.rs index caf8a6e8..c35a62c1 100644 --- a/src/native/card.rs +++ b/src/native/card.rs @@ -13,8 +13,8 @@ use iced_widget::{ mouse::{self, Cursor}, renderer, touch, widget::{Operation, Tree}, - Alignment, BorderRadius, Clipboard, Color, Element, Event, Layout, Length, Padding, Point, - Rectangle, Shell, Size, Widget, + Alignment, BorderRadius, Clipboard, Color, Element, Event, Layout, Length, Padding, Pixels, + Point, Rectangle, Shell, Size, Widget, }, text::LineHeight, }; @@ -241,7 +241,7 @@ where self.height } - fn layout(&self, renderer: &Renderer, limits: &Limits) -> Node { + fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { let limits = limits.max_width(self.max_width).max_height(self.max_height); let head_node = head_node( @@ -252,9 +252,17 @@ where self.width, self.on_close.is_some(), self.close_size, + tree, ); - let mut body_node = body_node(renderer, &limits, &self.body, self.padding_body, self.width); + let mut body_node = body_node( + renderer, + &limits, + &self.body, + self.padding_body, + self.width, + tree, + ); body_node.move_to(Point::new( body_node.bounds().x, @@ -262,7 +270,7 @@ where )); let mut foot_node = self.foot.as_ref().map_or_else(Node::default, |foot| { - foot_node(renderer, &limits, foot, self.padding_foot, self.width) + foot_node(renderer, &limits, foot, self.padding_foot, self.width, tree) }); foot_node.move_to(Point::new( @@ -595,6 +603,7 @@ fn head_node( width: Length, on_close: bool, close_size: Option, + tree: &mut Tree, ) -> Node where Renderer: core::Renderer + core::text::Renderer, @@ -606,7 +615,7 @@ where .height(head.as_widget().height()) .pad(pad); - let close_size = close_size.unwrap_or_else(|| renderer.default_size()); + let close_size = close_size.unwrap_or_else(|| renderer.default_size().0); let mut close = if on_close { limits = limits.shrink(Size::new(close_size, 0.0)); Some(Node::new(Size::new(close_size + 1.0, close_size + 1.0))) @@ -614,7 +623,9 @@ where None }; - let mut head = head.as_widget().layout(renderer, &limits); + let mut head = head + .as_widget() + .layout(&mut tree.children[0], renderer, &limits); let mut size = limits.resolve(head.size()); head.move_to(Point::new(padding, padding)); @@ -643,6 +654,7 @@ fn body_node( body: &Element<'_, Message, Renderer>, padding: f32, width: Length, + tree: &mut Tree, ) -> Node where Renderer: core::Renderer, @@ -655,7 +667,9 @@ where .height(body.as_widget().height()) .pad(pad); - let mut body = body.as_widget().layout(renderer, &limits); + let mut body = body + .as_widget() + .layout(&mut tree.children[1], renderer, &limits); let size = limits.resolve(body.size()); body.move_to(Point::new(padding, padding)); @@ -671,6 +685,7 @@ fn foot_node( foot: &Element<'_, Message, Renderer>, padding: f32, width: Length, + tree: &mut Tree, ) -> Node where Renderer: core::Renderer, @@ -683,7 +698,9 @@ where .height(foot.as_widget().height()) .pad(pad); - let mut foot = foot.as_widget().layout(renderer, &limits); + let mut foot = foot + .as_widget() + .layout(&mut tree.children[2], renderer, &limits); let size = limits.resolve(foot.size()); foot.move_to(Point::new(padding, padding)); @@ -758,23 +775,23 @@ fn draw_head( let close_bounds = close_layout.bounds(); let is_mouse_over_close = close_bounds.contains(cursor.position().unwrap_or_default()); - renderer.fill_text(core::text::Text { - content: &Icon::X.to_string(), - bounds: Rectangle { - x: close_bounds.center_x(), - y: close_bounds.center_y(), - height: close_bounds.height, - ..close_bounds + renderer.fill_text( + core::text::Text { + content: &Icon::X.to_string(), + bounds: Size::new(close_bounds.width, close_bounds.height), + size: Pixels( + close_size.unwrap_or_else(|| renderer.default_size().0) + + if is_mouse_over_close { 1.0 } else { 0.0 }, + ), + font: ICON_FONT, + horizontal_alignment: Horizontal::Center, + vertical_alignment: Vertical::Center, + line_height: LineHeight::Relative(1.3), + shaping: iced_widget::text::Shaping::Advanced, }, - size: close_size.unwrap_or_else(|| renderer.default_size()) - + if is_mouse_over_close { 1.0 } else { 0.0 }, - color: style_sheet.close_color, - font: ICON_FONT, - horizontal_alignment: Horizontal::Center, - vertical_alignment: Vertical::Center, - line_height: LineHeight::Relative(1.3), - shaping: iced_widget::text::Shaping::Advanced, - }); + Point::new(close_bounds.center_x(), close_bounds.center_y()), + style_sheet.close_color, + ); } } diff --git a/src/native/number_input.rs b/src/native/number_input.rs index 7590a2bc..479d3e71 100644 --- a/src/native/number_input.rs +++ b/src/native/number_input.rs @@ -14,8 +14,8 @@ use iced_widget::{ tree::{State, Tag}, Operation, Tree, }, - Alignment, Background, Clipboard, Color, Element, Event, Layout, Length, Padding, - Rectangle, Shell, Size, Widget, + Alignment, Background, Clipboard, Color, Element, Event, Layout, Length, Padding, Pixels, + Point, Rectangle, Shell, Size, Widget, }, text, text::LineHeight, @@ -295,37 +295,55 @@ where Length::Shrink } - fn layout(&self, renderer: &Renderer, limits: &Limits) -> Node { + fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { let padding = Padding::from(self.padding); let limits = limits .width(self.width()) .height(Length::Shrink) .pad(padding); - let content = self.content.layout(renderer, &limits); + let content = self + .content + .layout(&mut tree.children[0], renderer, &limits, None); let limits2 = Limits::new(Size::new(0.0, 0.0), content.size()); - let txt_size = self.size.unwrap_or_else(|| renderer.default_size()); + let txt_size = self.size.unwrap_or_else(|| renderer.default_size().0); let icon_size = txt_size * 2.5 / 4.0; let btn_mod = |c| { - Container::<(), Renderer>::new(Text::new(format!(" {c} ")).size(icon_size)) + Container::::new(Text::new(format!(" {c} ")).size(icon_size)) .center_y() .center_x() }; - let mut modifier = if self.padding < DEFAULT_PADDING { - Row::<(), Renderer>::new() - .spacing(1) - .width(Length::Shrink) - .push(btn_mod('+')) - .push(btn_mod('-')) - .layout(renderer, &limits2.loose()) + + let mut element = if self.padding < DEFAULT_PADDING { + Element::new( + Row::::new() + .spacing(1) + .width(Length::Shrink) + .push(btn_mod('+')) + .push(btn_mod('-')), + ) + } else { + Element::new( + Column::::new() + .spacing(1) + .width(Length::Shrink) + .push(btn_mod('▲')) + .push(btn_mod('▼')), + ) + }; + + let mut input_tree = if let Some(child_tree) = tree.children.get_mut(1) { + child_tree.diff(element.as_widget()); + child_tree } else { - Column::<(), Renderer>::new() - .spacing(1) - .width(Length::Shrink) - .push(btn_mod('▲')) - .push(btn_mod('▼')) - .layout(renderer, &limits2.loose()) + let child_tree = Tree::new(element.as_widget()); + tree.children.insert(1, child_tree); + &mut tree.children[1] }; + + let mut modifier = element + .as_widget() + .layout(&mut input_tree, renderer, &limits2.loose()); let intrinsic = Size::new( content.size().width - 1.0, content.size().height.max(modifier.size().height), @@ -424,13 +442,16 @@ where } else { match event { Event::Keyboard(keyboard::Event::CharacterReceived(c)) - if child.state.downcast_mut::().is_focused() + if child + .state + .downcast_mut::>() + .is_focused() && c.is_numeric() => { let mut new_val = self.value.to_string(); match child .state - .downcast_mut::() + .downcast_mut::>() .cursor() .state(&Value::new(&new_val)) { @@ -476,7 +497,10 @@ where } } Event::Keyboard(keyboard::Event::KeyPressed { key_code, .. }) - if child.state.downcast_mut::().is_focused() => + if child + .state + .downcast_mut::>() + .is_focused() => { match key_code { keyboard::KeyCode::Up => { @@ -494,7 +518,7 @@ where let mut new_val = self.value.to_string(); match child .state - .downcast_mut::() + .downcast_mut::>() .cursor() .state(&Value::new(&new_val)) { @@ -682,9 +706,9 @@ where theme.active(&self.style) }; - let txt_size = self.size.unwrap_or_else(|| renderer.default_size()); + let txt_size = self.size.unwrap_or_else(|| renderer.default_size().0); - let icon_size = txt_size * 2.5 / 4.0; + let icon_size = Pixels(txt_size * 2.5 / 4.0); // decrease button section renderer.fill_quad( @@ -701,21 +725,20 @@ where let mut buffer = [0; 4]; - renderer.fill_text(core::text::Text { - content: char::from(Icon::CaretDownFill).encode_utf8(&mut buffer), - bounds: Rectangle { - x: dec_bounds.center_x(), - y: dec_bounds.center_y(), - ..dec_bounds + renderer.fill_text( + core::text::Text { + content: char::from(Icon::CaretDownFill).encode_utf8(&mut buffer), + bounds: Size::new(dec_bounds.width, dec_bounds.height), + size: icon_size, + font: ICON_FONT, + horizontal_alignment: Horizontal::Center, + vertical_alignment: Vertical::Center, + line_height: LineHeight::Relative(1.3), + shaping: iced_widget::text::Shaping::Advanced, }, - size: icon_size, - color: decrease_btn_style.icon_color, - font: ICON_FONT, - horizontal_alignment: Horizontal::Center, - vertical_alignment: Vertical::Center, - line_height: LineHeight::Relative(1.3), - shaping: iced_widget::text::Shaping::Advanced, - }); + Point::new(dec_bounds.center_x(), dec_bounds.center_y()), + decrease_btn_style.icon_color, + ); // increase button section renderer.fill_quad( @@ -730,21 +753,20 @@ where .unwrap_or(Background::Color(Color::TRANSPARENT)), ); - renderer.fill_text(core::text::Text { - content: char::from(Icon::CaretUpFill).encode_utf8(&mut buffer), - bounds: Rectangle { - x: inc_bounds.center_x(), - y: inc_bounds.center_y(), - ..inc_bounds + renderer.fill_text( + core::text::Text { + content: char::from(Icon::CaretUpFill).encode_utf8(&mut buffer), + bounds: Size::new(inc_bounds.width, inc_bounds.height), + size: icon_size, + font: ICON_FONT, + horizontal_alignment: Horizontal::Center, + vertical_alignment: Vertical::Center, + line_height: LineHeight::Relative(1.3), + shaping: iced_widget::text::Shaping::Advanced, }, - size: icon_size, - color: increase_btn_style.icon_color, - font: ICON_FONT, - horizontal_alignment: Horizontal::Center, - vertical_alignment: Vertical::Center, - line_height: LineHeight::Relative(1.3), - shaping: iced_widget::text::Shaping::Advanced, - }); + Point::new(inc_bounds.center_x(), inc_bounds.center_y()), + increase_btn_style.icon_color, + ); } } From 74579cf882fffbc6d31be396ee9dc96b0661e958 Mon Sep 17 00:00:00 2001 From: genusistimelord Date: Tue, 7 Nov 2023 09:23:04 -0500 Subject: [PATCH 04/22] fixed date_picker --- Cargo.toml | 4 +- src/native/date_picker.rs | 6 +- src/native/number_input.rs | 2 +- src/native/overlay/color_picker.rs | 30 +--- src/native/overlay/date_picker.rs | 254 ++++++++++++++--------------- 5 files changed, 137 insertions(+), 159 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a95a200c..b0af6983 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,7 +43,7 @@ default = [ "badge", "card", "number_input", - #"date_picker", + "date_picker", "color_picker", #"floating_element", #"icon_text", @@ -88,7 +88,7 @@ members = [ #"examples/cupertino/cupertino_button", #"examples/cupertino/cupertino_spinner", #"examples/cupertino/cupertino_switch", - #"examples/date_picker", + "examples/date_picker", #"examples/floating_element", #"examples/floating_element_anchors", #"examples/grid", diff --git a/src/native/date_picker.rs b/src/native/date_picker.rs index 914a6267..ef53775e 100644 --- a/src/native/date_picker.rs +++ b/src/native/date_picker.rs @@ -181,8 +181,10 @@ where self.underlay.as_widget().width() } - fn layout(&self, renderer: &Renderer, limits: &Limits) -> Node { - self.underlay.as_widget().layout(renderer, limits) + fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { + self.underlay + .as_widget() + .layout(&mut tree.children[0], renderer, limits) } fn on_event( diff --git a/src/native/number_input.rs b/src/native/number_input.rs index 479d3e71..0135538a 100644 --- a/src/native/number_input.rs +++ b/src/native/number_input.rs @@ -314,7 +314,7 @@ where .center_x() }; - let mut element = if self.padding < DEFAULT_PADDING { + let element = if self.padding < DEFAULT_PADDING { Element::new( Row::::new() .spacing(1) diff --git a/src/native/overlay/color_picker.rs b/src/native/overlay/color_picker.rs index 4a6ff026..cd0e7d01 100644 --- a/src/native/overlay/color_picker.rs +++ b/src/native/overlay/color_picker.rs @@ -27,8 +27,8 @@ use iced_widget::{ text::Renderer as _, touch, widget::{self, tree::Tree}, - Alignment, Clipboard, Color, Element, Event, Layout, Length, Overlay, Padding, Pixels, - Point, Rectangle, Renderer as _, Shell, Size, Text, Vector, Widget, + Alignment, Clipboard, Color, Element, Event, Layout, Length, Overlay, Padding, Point, + Rectangle, Renderer as _, Shell, Size, Text, Vector, Widget, }, graphics::geometry::Renderer as _, renderer::Renderer, @@ -938,24 +938,10 @@ where let hex_text_limits = block2_limits; - let mut hex_text = Row::>::new() + let mut hex_text_layout = Row::>::new() .width(Length::Fill) - .height(Length::Fixed(renderer.default_size().0 + 2.0 * PADDING)); - - let element: Element> = Element::new(hex_text); - let mut rgba_tree = if let Some(child_tree) = color_picker.tree.children.get_mut(2) { - child_tree.diff(element.as_widget()); - child_tree - } else { - let child_tree = Tree::new(element.as_widget()); - color_picker.tree.children.insert(2, child_tree); - color_picker.tree.children.get_mut(2).unwrap() - }; - - let mut hex_text_layout = - element - .as_widget() - .layout(color_picker.tree, renderer, &hex_text_limits); + .height(Length::Fixed(renderer.default_size().0 + 2.0 * PADDING)) + .layout(color_picker.tree, renderer, &hex_text_limits); let block2_limits = block2_limits.shrink(Size::new( 0.0, @@ -991,13 +977,13 @@ where ); } let element: Element> = Element::new(rgba_colors); - let mut rgba_tree = if let Some(child_tree) = color_picker.tree.children.get_mut(3) { + let mut rgba_tree = if let Some(child_tree) = color_picker.tree.children.get_mut(2) { child_tree.diff(element.as_widget()); child_tree } else { let child_tree = Tree::new(element.as_widget()); - color_picker.tree.children.insert(3, child_tree); - color_picker.tree.children.get_mut(3).unwrap() + color_picker.tree.children.insert(2, child_tree); + &mut color_picker.tree.children[2] }; let mut rgba_colors = element diff --git a/src/native/overlay/date_picker.rs b/src/native/overlay/date_picker.rs index c0cb0afc..c4360473 100644 --- a/src/native/overlay/date_picker.rs +++ b/src/native/overlay/date_picker.rs @@ -368,7 +368,7 @@ where Theme: 'a + StyleSheet + button::StyleSheet + text::StyleSheet + container::StyleSheet, { #[allow(clippy::too_many_lines)] - fn layout(&self, renderer: &Renderer, bounds: Size, position: Point) -> Node { + fn layout(&mut self, renderer: &Renderer, bounds: Size, position: Point) -> Node { let limits = Limits::new(Size::ZERO, bounds) .pad(Padding::from(PADDING)) .width(Length::Fill) @@ -378,86 +378,68 @@ where // Pre-Buttons TODO: get rid of it let cancel_limits = limits; - let cancel_button = self.cancel_button.layout(renderer, &cancel_limits); + let cancel_button = + self.cancel_button + .layout(&mut self.tree.children[0], renderer, &cancel_limits); let limits = limits.shrink(Size::new(0.0, cancel_button.bounds().height + SPACING)); // Month/Year let font_size = renderer.default_size(); - let month_year = Row::<(), Renderer>::new() + let month_year = Row::>::new() .width(Length::Fill) .spacing(SPACING) .push( Row::new() .width(Length::Fill) - .push( - Container::new( - Row::new() // Left Month arrow - .width(Length::Shrink) - .push( - Text::new(char::from(Icon::CaretLeftFill).to_string()) - .size(font_size + 1.0) - .font(ICON_FONT), - ), - ) - .height(Length::Shrink), - ) + .push(Container::new( + Row::new().push( + Text::new(char::from(Icon::CaretLeftFill).to_string()) + .size(font_size.0 + 1.0) + .font(ICON_FONT), + ), + )) .push( // Month - Text::new("October") - .width(Length::Fill) - .height(Length::Shrink), + Text::new("October").width(Length::Fill), ) .push( // Right Month arrow Container::new( Text::new(char::from(Icon::CaretRightFill).to_string()) - .size(font_size + 1.0) + .size(font_size.0 + 1.0) .font(ICON_FONT), - ) - .height(Length::Shrink) - .width(Length::Shrink), + ), ), ) .push( Row::new() .width(Length::Fill) - .push( - Container::new( - Row::new() // Left Year arrow - .width(Length::Shrink) - .push( - Text::new(char::from(Icon::CaretLeftFill).to_string()) - .size(font_size + 1.0) - .font(ICON_FONT), - ), - ) - .height(Length::Shrink) - .width(Length::Shrink), - ) + .push(Container::new( + Row::new().push( + Text::new(char::from(Icon::CaretLeftFill).to_string()) + .size(font_size.0 + 1.0) + .font(ICON_FONT), + ), + )) .push( // Year - Text::new("9999").width(Length::Fill).height(Length::Shrink), + Text::new("9999").width(Length::Fill), ) .push( // Right Year arrow Container::new( - Row::new() - .width(Length::Shrink) - .height(Length::Shrink) - .push( - Text::new(char::from(Icon::CaretRightFill).to_string()) - .size(font_size + 1.0) - .font(ICON_FONT), - ), - ) - .height(Length::Shrink) - .width(Length::Shrink), + Row::new().push( + Text::new(char::from(Icon::CaretRightFill).to_string()) + .size(font_size.0 + 1.0) + .font(ICON_FONT), + ), + ), ), ); - let days = Container::<(), Renderer>::new((0..7).fold( + let days = Container::>::new((0..7).fold( Column::new().width(Length::Fill).height(Length::Fill), |column, _y| { column.push( @@ -468,14 +450,9 @@ where .padding(DAY_CELL_PADDING), |row, _x| { row.push( - Container::new( - Row::new() - .width(Length::Shrink) - .height(Length::Shrink) - .push(Text::new("31").size(font_size)), - ) - .width(Length::Fill) - .height(Length::Shrink), + Container::new(Row::new().push(Text::new("31").size(font_size))) + .width(Length::Fill) + .height(Length::Fill), ) }, ), @@ -486,13 +463,23 @@ where .height(Length::Fill) .center_y(); - let mut col = Column::<(), Renderer>::new() + let col = Column::>::new() .spacing(SPACING) .align_items(Alignment::Center) .push(month_year) - .push(days) - .layout(renderer, &limits); + .push(days); + + let element: Element> = Element::new(col); + let mut col_tree = if let Some(child_tree) = self.tree.children.get_mut(2) { + child_tree.diff(element.as_widget()); + child_tree + } else { + let child_tree = Tree::new(element.as_widget()); + self.tree.children.insert(2, child_tree); + &mut self.tree.children[2] + }; + let mut col = element.as_widget().layout(&mut col_tree, renderer, &limits); col.move_to(Point::new( col.bounds().x + PADDING, col.bounds().y + PADDING, @@ -502,12 +489,16 @@ where let cancel_limits = limits.max_width(((col.bounds().width / 2.0) - BUTTON_SPACING).max(0.0)); - let mut cancel_button = self.cancel_button.layout(renderer, &cancel_limits); + let mut cancel_button = + self.cancel_button + .layout(&mut self.tree.children[0], renderer, &cancel_limits); let submit_limits = limits.max_width(((col.bounds().width / 2.0) - BUTTON_SPACING).max(0.0)); - let mut submit_button = self.submit_button.layout(renderer, &submit_limits); + let mut submit_button = + self.submit_button + .layout(&mut self.tree.children[1], renderer, &submit_limits); cancel_button.move_to(Point { x: cancel_button.bounds().x + PADDING, @@ -960,7 +951,7 @@ where unimplemented!("This should never be reached!") } - fn layout(&self, _renderer: &Renderer, _limits: &Limits) -> Node { + fn layout(&self, _tree: &mut Tree, _renderer: &Renderer, _limits: &Limits) -> Node { unimplemented!("This should never be reached!") } @@ -1124,64 +1115,65 @@ fn month_year( let mut buffer = [0; 4]; // Left caret - renderer.fill_text(core::text::Text { - content: char::from(Icon::CaretLeftFill).encode_utf8(&mut buffer), - bounds: Rectangle { - x: left_bounds.center_x(), - y: left_bounds.center_y(), - ..left_bounds + renderer.fill_text( + core::text::Text { + content: char::from(Icon::CaretLeftFill).encode_utf8(&mut buffer), + bounds: Size::new(left_bounds.width, left_bounds.height), + size: core::Pixels( + renderer.default_size().0 + if left_arrow_hovered { 1.0 } else { 0.0 }, + ), + font: ICON_FONT, + horizontal_alignment: Horizontal::Center, + vertical_alignment: Vertical::Center, + line_height: text::LineHeight::Relative(1.3), + shaping: text::Shaping::Advanced, }, - size: renderer.default_size() + if left_arrow_hovered { 1.0 } else { 0.0 }, - color: style + Point::new(left_bounds.center_x(), left_bounds.center_y()), + style .get(&style_state) .expect("Style Sheet not found.") .text_color, - font: ICON_FONT, - horizontal_alignment: Horizontal::Center, - vertical_alignment: Vertical::Center, - line_height: text::LineHeight::Relative(1.3), - shaping: text::Shaping::Advanced, - }); + ); // Text - renderer.fill_text(core::text::Text { - content: text, - bounds: Rectangle { - x: center_bounds.center_x(), - y: center_bounds.center_y(), - ..center_bounds + renderer.fill_text( + core::text::Text { + content: text, + bounds: Size::new(center_bounds.width, center_bounds.height), + size: renderer.default_size(), + font: renderer.default_font(), + horizontal_alignment: Horizontal::Center, + vertical_alignment: Vertical::Center, + line_height: text::LineHeight::Relative(1.3), + shaping: text::Shaping::Basic, }, - size: renderer.default_size(), - color: style + Point::new(center_bounds.center_x(), center_bounds.center_y()), + style .get(&style_state) .expect("Style Sheet not found.") .text_color, - font: renderer.default_font(), - horizontal_alignment: Horizontal::Center, - vertical_alignment: Vertical::Center, - line_height: text::LineHeight::Relative(1.3), - shaping: text::Shaping::Basic, - }); + ); // Right caret - renderer.fill_text(core::text::Text { - content: char::from(Icon::CaretRightFill).encode_utf8(&mut buffer), - bounds: Rectangle { - x: right_bounds.center_x(), - y: right_bounds.center_y(), - ..right_bounds + renderer.fill_text( + core::text::Text { + content: char::from(Icon::CaretRightFill).encode_utf8(&mut buffer), + bounds: Size::new(right_bounds.width, right_bounds.height), + size: core::Pixels( + renderer.default_size().0 + if right_arrow_hovered { 1.0 } else { 0.0 }, + ), + font: ICON_FONT, + horizontal_alignment: Horizontal::Center, + vertical_alignment: Vertical::Center, + line_height: text::LineHeight::Relative(1.3), + shaping: text::Shaping::Advanced, }, - size: renderer.default_size() + if right_arrow_hovered { 1.0 } else { 0.0 }, - color: style + Point::new(right_bounds.center_x(), right_bounds.center_y()), + style .get(&style_state) .expect("Style Sheet not found.") .text_color, - font: ICON_FONT, - horizontal_alignment: Horizontal::Center, - vertical_alignment: Vertical::Center, - line_height: text::LineHeight::Relative(1.3), - shaping: text::Shaping::Advanced, - }); + ); }; // Draw month @@ -1225,24 +1217,23 @@ fn day_labels( for (i, label) in layout.children().enumerate() { let bounds = label.bounds(); - renderer.fill_text(core::text::Text { - content: &crate::core::date::WEEKDAY_LABELS[i], - bounds: Rectangle { - x: bounds.center_x(), - y: bounds.center_y(), - ..bounds + renderer.fill_text( + core::text::Text { + content: &crate::core::date::WEEKDAY_LABELS[i], + bounds: Size::new(bounds.width, bounds.height), + size: renderer.default_size(), + font: renderer.default_font(), + horizontal_alignment: Horizontal::Center, + vertical_alignment: Vertical::Center, + line_height: text::LineHeight::Relative(1.3), + shaping: text::Shaping::Basic, }, - size: renderer.default_size(), - color: style + Point::new(bounds.center_x(), bounds.center_y()), + style .get(&StyleState::Active) .expect("Style Sheet not found.") .text_color, - font: renderer.default_font(), - horizontal_alignment: Horizontal::Center, - vertical_alignment: Vertical::Center, - line_height: text::LineHeight::Relative(1.3), - shaping: text::Shaping::Basic, - }); + ); } } @@ -1310,15 +1301,19 @@ fn day_table( ); } - renderer.fill_text(core::text::Text { - content: &format!("{number:02}"), // Todo: is there some way of static format as this has a fixed size? - bounds: Rectangle { - x: bounds.center_x(), - y: bounds.center_y(), - ..bounds + renderer.fill_text( + core::text::Text { + content: &format!("{number:02}"), // Todo: is there some way of static format as this has a fixed size? + bounds: Size::new(bounds.width, bounds.height), + size: renderer.default_size(), + font: renderer.default_font(), + horizontal_alignment: Horizontal::Center, + vertical_alignment: Vertical::Center, + line_height: text::LineHeight::Relative(1.3), + shaping: text::Shaping::Basic, }, - size: renderer.default_size(), - color: if is_in_month == IsInMonth::Same { + Point::new(bounds.center_x(), bounds.center_y()), + if is_in_month == IsInMonth::Same { style .get(&style_state) .expect("Style Sheet not found.") @@ -1329,12 +1324,7 @@ fn day_table( .expect("Style Sheet not found.") .text_attenuated_color }, - font: renderer.default_font(), - horizontal_alignment: Horizontal::Center, - vertical_alignment: Vertical::Center, - line_height: text::LineHeight::Relative(1.3), - shaping: text::Shaping::Basic, - }); + ); } } } From fed6e4b2b784d66bb91104fc5ad1d26439462c93 Mon Sep 17 00:00:00 2001 From: genusistimelord Date: Tue, 7 Nov 2023 09:27:12 -0500 Subject: [PATCH 05/22] fixed floating element --- Cargo.toml | 6 +++--- src/native/floating_element.rs | 6 ++++-- src/native/overlay/floating_element.rs | 7 +++++-- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b0af6983..4b41ecf0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,7 +45,7 @@ default = [ "number_input", "date_picker", "color_picker", - #"floating_element", + "floating_element", #"icon_text", #"grid", #"modal", @@ -89,8 +89,8 @@ members = [ #"examples/cupertino/cupertino_spinner", #"examples/cupertino/cupertino_switch", "examples/date_picker", - #"examples/floating_element", - #"examples/floating_element_anchors", + "examples/floating_element", + "examples/floating_element_anchors", #"examples/grid", #"examples/modal", #"examples/modal_component", diff --git a/src/native/floating_element.rs b/src/native/floating_element.rs index 32a83665..128b9dce 100644 --- a/src/native/floating_element.rs +++ b/src/native/floating_element.rs @@ -126,8 +126,10 @@ where self.underlay.as_widget().height() } - fn layout(&self, renderer: &Renderer, limits: &Limits) -> Node { - self.underlay.as_widget().layout(renderer, limits) + fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { + self.underlay + .as_widget() + .layout(&mut tree.children[0], renderer, limits) } fn on_event( diff --git a/src/native/overlay/floating_element.rs b/src/native/overlay/floating_element.rs index da783e43..72e6a10a 100644 --- a/src/native/overlay/floating_element.rs +++ b/src/native/overlay/floating_element.rs @@ -56,12 +56,15 @@ impl<'a, 'b, Message, Renderer> core::Overlay where Renderer: core::Renderer, { - fn layout(&self, renderer: &Renderer, _bounds: Size, position: Point) -> layout::Node { + fn layout(&mut self, renderer: &Renderer, _bounds: Size, position: Point) -> layout::Node { // Constrain overlay to fit inside the underlay's bounds let limits = layout::Limits::new(Size::ZERO, self.underlay_bounds.size()) .width(Length::Fill) .height(Length::Fill); - let mut node = self.element.as_widget().layout(renderer, &limits); + let mut node = self + .element + .as_widget() + .layout(&mut self.state, renderer, &limits); let position = match self.anchor { Anchor::NorthWest => Point::new(position.x + self.offset.x, position.y + self.offset.y), From 10fc6ffbc7110b891b1ff0aa85808d33fc49baf1 Mon Sep 17 00:00:00 2001 From: genusistimelord Date: Tue, 7 Nov 2023 09:47:15 -0500 Subject: [PATCH 06/22] fixed grid --- Cargo.toml | 12 +++++------- examples/menu/Cargo.toml | 2 +- src/native/grid/layout.rs | 19 +++++++++++++++---- src/native/grid/widget.rs | 3 ++- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4b41ecf0..044c4734 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,18 +17,17 @@ categories = ["gui"] [features] badge = [] card = [] -date_picker = ["chrono", "once_cell", "icon_text"] -color_picker = ["icon_text", "iced_widget/canvas"] +date_picker = ["chrono", "once_cell", "icons"] +color_picker = ["icons", "iced_widget/canvas"] cupertino = ["iced_widget/canvas", "time"] floating_element = [] grid = ["itertools"] glow = [] # TODO -icon_text = ["icons"] icons = [] modal = [] tab_bar = [] tabs = ["tab_bar"] -time_picker = ["chrono", "icon_text", "iced_widget/canvas"] +time_picker = ["chrono", "icons", "iced_widget/canvas"] wrap = [] number_input = ["num-traits"] selection_list = [] @@ -46,8 +45,7 @@ default = [ "date_picker", "color_picker", "floating_element", - #"icon_text", - #"grid", + "grid", #"modal", #"tab_bar", #"tabs", @@ -91,7 +89,7 @@ members = [ "examples/date_picker", "examples/floating_element", "examples/floating_element_anchors", - #"examples/grid", + "examples/grid", #"examples/modal", #"examples/modal_component", #"examples/multiple_modals", diff --git a/examples/menu/Cargo.toml b/examples/menu/Cargo.toml index a612f3a4..562ae245 100644 --- a/examples/menu/Cargo.toml +++ b/examples/menu/Cargo.toml @@ -8,6 +8,6 @@ publish = false iced_aw = { workspace = true, features = [ "menu", "quad", - "icon_text" + "icons" ] } iced = {workspace = true, features = ["svg"]} \ No newline at end of file diff --git a/src/native/grid/layout.rs b/src/native/grid/layout.rs index 1bde7e27..2ffa8a1d 100644 --- a/src/native/grid/layout.rs +++ b/src/native/grid/layout.rs @@ -3,6 +3,7 @@ use std::cmp::Ordering; use iced_widget::core::{ alignment::{Horizontal, Vertical}, layout::{Limits, Node}, + widget::Tree, Length, Padding, Pixels, Point, Size, }; use itertools::{Itertools, Position}; @@ -11,6 +12,7 @@ use super::types::GridRow; #[allow(clippy::too_many_arguments)] pub(super) fn layout( + tree: &mut Tree, renderer: &Renderer, limits: &Limits, column_count: usize, @@ -34,7 +36,7 @@ where let mut row_heights = Vec::::with_capacity(row_count); // Measure the minimum row and column size to fit the contents - minimum_row_column_sizes(renderer, &mut column_widths, &mut row_heights, rows); + minimum_row_column_sizes(tree, renderer, &mut column_widths, &mut row_heights, rows); // Adjust for fixed row and column sizes adjust_size_for_fixed_length(&mut column_widths, column_lengths); @@ -62,6 +64,7 @@ where // Lay out the widgets create_grid_layout( + tree, element_count, rows, &row_heights, @@ -77,6 +80,7 @@ where } fn minimum_row_column_sizes( + tree: &mut Tree, renderer: &Renderer, column_widths: &mut Vec, row_heights: &mut Vec, @@ -84,12 +88,16 @@ fn minimum_row_column_sizes( ) where Renderer: iced_widget::core::Renderer, { - for row in rows { + let mut children = tree.children.iter_mut(); + for row in rows.iter() { let mut row_height = 0.0f32; for (col_idx, element) in row.elements.iter().enumerate() { let child_limits = Limits::NONE.width(Length::Shrink).height(Length::Shrink); - let Size { width, height } = element.as_widget().layout(renderer, &child_limits).size(); + let Size { width, height } = element + .as_widget() + .layout(children.next().unwrap(), renderer, &child_limits) + .size(); #[allow(clippy::option_if_let_else)] match column_widths.get_mut(col_idx) { @@ -160,6 +168,7 @@ fn allocate_space(current_sizes: &mut [f32], length_settings: &[Length], availab #[allow(clippy::too_many_arguments)] fn create_grid_layout( + tree: &mut Tree, element_count: usize, rows: &[GridRow<'_, Message, Renderer>], row_heights: &[f32], @@ -177,6 +186,8 @@ where { let mut y = padding.top; let mut nodes = Vec::with_capacity(element_count); + let mut children = tree.children.iter_mut(); + for (row_position, (row, &row_height)) in rows.iter().zip(row_heights).with_position() { let mut x = padding.left; for (col_position, (element, &column_width)) in @@ -189,7 +200,7 @@ where .max_width(column_width) .max_height(row_height); - let mut node = widget.layout(renderer, &widget_limits); + let mut node = widget.layout(children.next().unwrap(), renderer, &widget_limits); node.move_to(Point::new(x, y)); node.align( horizontal_alignment.into(), diff --git a/src/native/grid/widget.rs b/src/native/grid/widget.rs index a6fe011d..19fce036 100644 --- a/src/native/grid/widget.rs +++ b/src/native/grid/widget.rs @@ -22,7 +22,7 @@ where self.height } - fn layout(&self, renderer: &Renderer, limits: &Limits) -> Node { + fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { if self.element_count() == 0 { return Node::new(Size::ZERO); } @@ -37,6 +37,7 @@ where ); layout( + tree, renderer, limits, self.column_count(), From 96f7616874c572925819cdd201cf8c9d95f040af Mon Sep 17 00:00:00 2001 From: genusistimelord Date: Tue, 7 Nov 2023 10:10:31 -0500 Subject: [PATCH 07/22] modal fixed --- Cargo.toml | 6 +++--- examples/modal/src/main.rs | 2 +- src/native/modal.rs | 6 ++++-- src/native/overlay/modal.rs | 7 +++++-- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 044c4734..7a35695d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,7 @@ default = [ "color_picker", "floating_element", "grid", - #"modal", + "modal", #"tab_bar", #"tabs", #"time_picker", @@ -90,8 +90,8 @@ members = [ "examples/floating_element", "examples/floating_element_anchors", "examples/grid", - #"examples/modal", - #"examples/modal_component", + "examples/modal", + "examples/modal_component", #"examples/multiple_modals", #"examples/tab_bar", #"examples/tabs", diff --git a/examples/modal/src/main.rs b/examples/modal/src/main.rs index 56018dec..e348c07e 100644 --- a/examples/modal/src/main.rs +++ b/examples/modal/src/main.rs @@ -151,7 +151,7 @@ impl Application for ModalExample { modal(underlay, overlay) .backdrop(Message::CloseModal) .on_esc(Message::CloseModal) - .align_y(alignment::Vertical::Top) + .align_y(alignment::Vertical::Center) .into() } } diff --git a/src/native/modal.rs b/src/native/modal.rs index b0bb718f..cb71194f 100644 --- a/src/native/modal.rs +++ b/src/native/modal.rs @@ -155,8 +155,10 @@ where self.underlay.as_widget().height() } - fn layout(&self, renderer: &Renderer, limits: &Limits) -> Node { - self.underlay.as_widget().layout(renderer, limits) + fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { + self.underlay + .as_widget() + .layout(&mut tree.children[0], renderer, limits) } fn on_event( diff --git a/src/native/overlay/modal.rs b/src/native/overlay/modal.rs index 0f5e3c3b..da084239 100644 --- a/src/native/overlay/modal.rs +++ b/src/native/overlay/modal.rs @@ -68,9 +68,12 @@ where Renderer: core::Renderer, Renderer::Theme: StyleSheet, { - fn layout(&self, renderer: &Renderer, bounds: Size, _position: Point) -> layout::Node { + fn layout(&mut self, renderer: &Renderer, bounds: Size, _position: Point) -> layout::Node { let limits = layout::Limits::new(Size::ZERO, bounds); - let mut content = self.content.as_widget().layout(renderer, &limits); + let mut content = self + .content + .as_widget() + .layout(&mut self.state, renderer, &limits); let max_size = limits.max(); content.align( From 8ee32c0fb8671a2fd48aabbd71c4646150c65e11 Mon Sep 17 00:00:00 2001 From: genusistimelord Date: Tue, 7 Nov 2023 11:16:47 -0500 Subject: [PATCH 08/22] fixed tab_bar --- Cargo.toml | 4 +- src/native/tab_bar.rs | 168 +++++++++++++++++++++++------------------- 2 files changed, 94 insertions(+), 78 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7a35695d..3e584273 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,7 +47,7 @@ default = [ "floating_element", "grid", "modal", - #"tab_bar", + "tab_bar", #"tabs", #"time_picker", #"wrap", @@ -93,7 +93,7 @@ members = [ "examples/modal", "examples/modal_component", #"examples/multiple_modals", - #"examples/tab_bar", + "examples/tab_bar", #"examples/tabs", #"examples/time_picker", #"examples/wrap", diff --git a/src/native/tab_bar.rs b/src/native/tab_bar.rs index 621cbb72..b2d645cc 100644 --- a/src/native/tab_bar.rs +++ b/src/native/tab_bar.rs @@ -16,7 +16,8 @@ use iced_widget::{ mouse::{self, Cursor}, renderer, touch, widget::Tree, - Alignment, Clipboard, Color, Element, Event, Layout, Length, Rectangle, Shell, Widget, + Alignment, Clipboard, Color, Element, Event, Layout, Length, Point, Rectangle, Shell, Size, + Widget, }, runtime::Font, text::{self, LineHeight}, @@ -350,7 +351,12 @@ where self.height } - fn layout(&self, renderer: &Renderer, limits: &layout::Limits) -> layout::Node { + fn layout( + &self, + tree: &mut Tree, + renderer: &Renderer, + limits: &layout::Limits, + ) -> layout::Node { fn layout_icon(icon: &char, size: f32, font: Option) -> Text<'_, Renderer> where Renderer: iced_widget::core::text::Renderer, @@ -377,7 +383,8 @@ where .vertical_alignment(alignment::Vertical::Center) } - self.tab_labels + let row = self + .tab_labels .iter() .fold(Row::::new(), |row, tab_label| { let mut label_row = Row::new() @@ -470,8 +477,21 @@ where }) .width(self.width) .height(self.height) - .spacing(self.spacing) - .layout(renderer, &limits.loose()) + .spacing(self.spacing); + + let element: Element = Element::new(row); + let tab_tree = if let Some(child_tree) = tree.children.get_mut(0) { + child_tree.diff(element.as_widget()); + child_tree + } else { + let child_tree = Tree::new(element.as_widget()); + tree.children.insert(0, child_tree); + &mut tree.children[0] + }; + + element + .as_widget() + .layout(tab_tree, renderer, &limits.loose()) } fn on_event( @@ -664,40 +684,39 @@ fn draw_tab( TabLabel::Icon(icon) => { let icon_bounds = icon_bound_rectangle(label_layout_children.next()); - renderer.fill_text(core::text::Text { - content: &icon.to_string(), - bounds: Rectangle { - x: icon_bounds.center_x(), - y: icon_bounds.center_y(), - ..icon_bounds + renderer.fill_text( + core::text::Text { + content: &icon.to_string(), + bounds: Size::new(icon_bounds.width, icon_bounds.height), + size: core::Pixels(icon_data.1), + font: icon_data.0, + horizontal_alignment: Horizontal::Center, + vertical_alignment: Vertical::Center, + line_height: LineHeight::Relative(1.3), + shaping: iced_widget::text::Shaping::Advanced, }, - size: icon_data.1, - color: style.icon_color, - font: icon_data.0, - horizontal_alignment: Horizontal::Left, - vertical_alignment: Vertical::Center, - line_height: LineHeight::Relative(1.3), - shaping: iced_widget::text::Shaping::Advanced, - }); + Point::new(icon_bounds.center_x(), icon_bounds.center_y()), + style.icon_color, + ); } + TabLabel::Text(text) => { let text_bounds = text_bound_rectangle(label_layout_children.next()); - renderer.fill_text(core::text::Text { - content: &text[..], - bounds: Rectangle { - x: text_bounds.center_x(), - y: text_bounds.center_y(), - ..text_bounds + renderer.fill_text( + core::text::Text { + content: &text[..], + bounds: Size::new(text_bounds.width, text_bounds.height), + size: core::Pixels(text_data.1), + font: text_data.0, + horizontal_alignment: Horizontal::Center, + vertical_alignment: Vertical::Center, + line_height: LineHeight::Relative(1.3), + shaping: iced_widget::text::Shaping::Advanced, }, - size: text_data.1, - color: style.text_color, - font: text_data.0, - horizontal_alignment: Horizontal::Center, - vertical_alignment: Vertical::Center, - line_height: LineHeight::Relative(1.3), - shaping: iced_widget::text::Shaping::Advanced, - }); + Point::new(text_bounds.center_x(), text_bounds.center_y()), + style.text_color, + ); } TabLabel::IconText(icon, text) => { let icon_bounds: Rectangle; @@ -730,37 +749,35 @@ fn draw_tab( } } - renderer.fill_text(core::text::Text { - content: &icon.to_string(), - bounds: Rectangle { - x: icon_bounds.center_x(), - y: icon_bounds.center_y(), - ..icon_bounds + renderer.fill_text( + core::text::Text { + content: &icon.to_string(), + bounds: Size::new(icon_bounds.width, icon_bounds.height), + size: core::Pixels(icon_data.1), + font: icon_data.0, + horizontal_alignment: Horizontal::Center, + vertical_alignment: Vertical::Center, + line_height: LineHeight::Relative(1.3), + shaping: iced_widget::text::Shaping::Advanced, }, - size: icon_data.1, - color: style.icon_color, - font: icon_data.0, - horizontal_alignment: Horizontal::Center, - vertical_alignment: Vertical::Center, - line_height: LineHeight::Relative(1.3), - shaping: iced_widget::text::Shaping::Advanced, - }); - - renderer.fill_text(core::text::Text { - content: &text[..], - bounds: Rectangle { - x: text_bounds.center_x(), - y: text_bounds.center_y(), - ..text_bounds + Point::new(icon_bounds.center_x(), icon_bounds.center_y()), + style.icon_color, + ); + + renderer.fill_text( + core::text::Text { + content: &text[..], + bounds: Size::new(text_bounds.width, text_bounds.height), + size: core::Pixels(text_data.1), + font: text_data.0, + horizontal_alignment: Horizontal::Center, + vertical_alignment: Vertical::Center, + line_height: LineHeight::Relative(1.3), + shaping: iced_widget::text::Shaping::Advanced, }, - size: text_data.1, - color: style.text_color, - font: text_data.0, - horizontal_alignment: Horizontal::Center, - vertical_alignment: Vertical::Center, - line_height: LineHeight::Relative(1.3), - shaping: iced_widget::text::Shaping::Advanced, - }); + Point::new(text_bounds.center_x(), text_bounds.center_y()), + style.text_color, + ); } }; @@ -768,21 +785,20 @@ fn draw_tab( let cross_bounds = cross_layout.bounds(); let is_mouse_over_cross = cursor.is_over(cross_bounds); - renderer.fill_text(core::text::Text { - content: &icons::icon_to_char(icons::Icon::X).to_string(), - bounds: Rectangle { - x: cross_bounds.center_x(), - y: cross_bounds.center_y(), - ..cross_bounds + renderer.fill_text( + core::text::Text { + content: &icons::icon_to_char(icons::Icon::X).to_string(), + bounds: Size::new(cross_bounds.width, cross_bounds.height), + size: core::Pixels(close_size + if is_mouse_over_cross { 1.0 } else { 0.0 }), + font: icons::ICON_FONT, + horizontal_alignment: Horizontal::Center, + vertical_alignment: Vertical::Center, + line_height: LineHeight::Relative(1.3), + shaping: iced_widget::text::Shaping::Basic, }, - size: close_size + if is_mouse_over_cross { 1.0 } else { 0.0 }, - color: style.icon_color, - font: icons::ICON_FONT, - horizontal_alignment: Horizontal::Center, - vertical_alignment: Vertical::Center, - line_height: LineHeight::Relative(1.3), - shaping: iced_widget::text::Shaping::Basic, - }); + Point::new(cross_bounds.center_x(), cross_bounds.center_y()), + style.text_color, + ); if is_mouse_over_cross { renderer.fill_quad( From c0510775010d0e142e302dac16c6a8a1b568b172 Mon Sep 17 00:00:00 2001 From: genusistimelord Date: Tue, 7 Nov 2023 13:20:32 -0500 Subject: [PATCH 09/22] Fixed tabs --- Cargo.toml | 4 +-- src/native/tab_bar.rs | 52 +++++++++++++++++++++-------------- src/native/tabs.rs | 63 +++++++++++++++++++++++++++---------------- 3 files changed, 74 insertions(+), 45 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3e584273..a43ed883 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,7 +48,7 @@ default = [ "grid", "modal", "tab_bar", - #"tabs", + "tabs", #"time_picker", #"wrap", #"selection_list", @@ -94,7 +94,7 @@ members = [ "examples/modal_component", #"examples/multiple_modals", "examples/tab_bar", - #"examples/tabs", + "examples/tabs", #"examples/time_picker", #"examples/wrap", "examples/number_input", diff --git a/src/native/tab_bar.rs b/src/native/tab_bar.rs index b2d645cc..f6a39065 100644 --- a/src/native/tab_bar.rs +++ b/src/native/tab_bar.rs @@ -29,7 +29,7 @@ pub use crate::style::tab_bar::{Appearance, StyleSheet}; pub use tab_label::TabLabel; /// The default icon size. -const DEFAULT_ICON_SIZE: f32 = 32.0; +const DEFAULT_ICON_SIZE: f32 = 16.0; /// The default text size. const DEFAULT_TEXT_SIZE: f32 = 16.0; /// The default size of the close icon. @@ -367,7 +367,8 @@ where .size(size) .font(font.unwrap_or_default()) .horizontal_alignment(alignment::Horizontal::Center) - .vertical_alignment(alignment::Vertical::Center) + .vertical_alignment(alignment::Vertical::Bottom) + .shaping(text::Shaping::Advanced) } fn layout_text(text: &str, size: f32, font: Option) -> Text<'_, Renderer> @@ -380,7 +381,8 @@ where .size(size) .font(font.unwrap_or_default()) .horizontal_alignment(alignment::Horizontal::Center) - .vertical_alignment(alignment::Vertical::Center) + .vertical_alignment(alignment::Vertical::Bottom) + .shaping(text::Shaping::Advanced) } let row = self @@ -392,11 +394,12 @@ where match tab_label { TabLabel::Icon(icon) => Column::new() .align_items(Alignment::Center) - .push(layout_icon(icon, self.icon_size, self.icon_font)), + .push(layout_icon(icon, self.icon_size + 1.0, self.icon_font)), TabLabel::Text(text) => Column::new() + .padding(5.0) .align_items(Alignment::Center) - .push(layout_text(text, self.icon_size, self.icon_font)), + .push(layout_text(text, self.text_size + 1.0, self.text_font)), TabLabel::IconText(icon, text) => { let mut column = Column::new().align_items(Alignment::Center); @@ -404,11 +407,15 @@ where match self.position { Position::Top => { column = column - .push(layout_icon(icon, self.icon_size, self.icon_font)) + .push(layout_icon( + icon, + self.icon_size + 1.0, + self.icon_font, + )) .push(layout_text( text, - self.icon_size, - self.icon_font, + self.text_size + 1.0, + self.text_font, )); } Position::Right => { @@ -417,13 +424,13 @@ where .align_items(Alignment::Center) .push(layout_icon( icon, - self.icon_size, + self.icon_size + 1.0, self.icon_font, )) .push(layout_text( text, - self.icon_size, - self.icon_font, + self.text_size + 1.0, + self.text_font, )), ); } @@ -433,23 +440,27 @@ where .align_items(Alignment::Center) .push(layout_text( text, - self.icon_size, + self.icon_size + 1.0, self.icon_font, )) .push(layout_icon( icon, - self.icon_size, - self.icon_font, + self.text_size + 1.0, + self.text_font, )), ); } Position::Bottom => { column = column - .push(layout_text(text, self.icon_size, self.icon_font)) + .push(layout_text( + text, + self.icon_size + 1.0, + self.icon_font, + )) .push(layout_icon( icon, - self.icon_size, - self.icon_font, + self.text_size + 1.0, + self.text_font, )); } } @@ -477,7 +488,8 @@ where }) .width(self.width) .height(self.height) - .spacing(self.spacing); + .spacing(self.spacing) + .align_items(Alignment::Center); let element: Element = Element::new(row); let tab_tree = if let Some(child_tree) = tree.children.get_mut(0) { @@ -695,7 +707,7 @@ fn draw_tab( line_height: LineHeight::Relative(1.3), shaping: iced_widget::text::Shaping::Advanced, }, - Point::new(icon_bounds.center_x(), icon_bounds.center_y()), + Point::new(icon_bounds.x, icon_bounds.center_y()), style.icon_color, ); } @@ -714,7 +726,7 @@ fn draw_tab( line_height: LineHeight::Relative(1.3), shaping: iced_widget::text::Shaping::Advanced, }, - Point::new(text_bounds.center_x(), text_bounds.center_y()), + Point::new(text_bounds.x, text_bounds.center_y()), style.text_color, ); } diff --git a/src/native/tabs.rs b/src/native/tabs.rs index d0f4fa72..6711ea8a 100644 --- a/src/native/tabs.rs +++ b/src/native/tabs.rs @@ -15,7 +15,10 @@ use iced_widget::{ layout::{Limits, Node}, mouse::{self, Cursor}, renderer, - widget::{Operation, Tree}, + widget::{ + tree::{State, Tag}, + Operation, Tree, + }, Clipboard, Element, Event, Layout, Length, Point, Rectangle, Shell, Size, Widget, }, runtime::Font, @@ -276,11 +279,23 @@ where TabId: Eq + Clone, { fn children(&self) -> Vec { - self.tabs.iter().map(Tree::new).collect() + let tabs = Tree { + tag: Tag::stateless(), + state: State::None, + children: self.tabs.iter().map(Tree::new).collect(), + }; + + let bar = Tree { + tag: self.tab_bar.tag(), + state: self.tab_bar.state(), + children: self.tab_bar.children(), + }; + + vec![bar, tabs] } fn diff(&self, tree: &mut Tree) { - tree.diff_children(&self.tabs); + tree.children[1].diff_children(&self.tabs); } fn width(&self) -> Length { @@ -291,25 +306,27 @@ where self.height } - fn layout(&self, renderer: &Renderer, limits: &Limits) -> Node { + fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { let tab_bar_limits = limits.width(self.width).height(Length::Shrink); - - let mut tab_bar_node = self.tab_bar.layout(renderer, &tab_bar_limits); + let mut tab_bar_node = + self.tab_bar + .layout(&mut tree.children[0], renderer, &tab_bar_limits); let tab_content_limits = limits.width(self.width).height(self.height); - let mut tab_content_node = self - .tabs - .get(self.tab_bar.get_active_tab_idx()) - .map_or_else( - || { - Row::::new() - .width(Length::Fill) - .height(Length::Fill) - .layout(renderer, &tab_content_limits) - }, - |element| element.as_widget().layout(renderer, &tab_content_limits), - ); + let mut tab_content_node = + if let Some(element) = self.tabs.get(self.tab_bar.get_active_tab_idx()) { + element.as_widget().layout( + &mut tree.children[1].children[self.tab_bar.get_active_tab_idx()], + renderer, + &tab_content_limits, + ) + } else { + Row::::new() + .width(Length::Fill) + .height(Length::Fill) + .layout(tree, renderer, &tab_content_limits) + }; tab_bar_node.move_to(Point::new( tab_bar_node.bounds().x, @@ -390,7 +407,7 @@ where .get_mut(idx) .map_or(event::Status::Ignored, |element| { element.as_widget_mut().on_event( - &mut state.children[idx], + &mut state.children[1].children[idx], event, tab_content_layout, cursor, @@ -449,7 +466,7 @@ where let idx = self.tab_bar.get_active_tab_idx(); if let Some(element) = self.tabs.get(idx) { let new_mouse_interaction = element.as_widget().mouse_interaction( - &state.children[idx], + &state.children[1].children[idx], tab_content_layout, cursor, viewport, @@ -508,7 +525,7 @@ where let idx = self.tab_bar.get_active_tab_idx(); if let Some(element) = self.tabs.get(idx) { element.as_widget().draw( - &state.children[idx], + &state.children[1].children[idx], renderer, theme, style, @@ -535,7 +552,7 @@ where self.tabs .get_mut(idx) .map(Element::as_widget_mut) - .and_then(|w| w.overlay(&mut state.children[idx], layout, renderer)) + .and_then(|w| w.overlay(&mut state.children[1].children[idx], layout, renderer)) }) } @@ -549,7 +566,7 @@ where let active_tab = self.tab_bar.get_active_tab_idx(); operation.container(None, layout.bounds(), &mut |operation| { self.tabs[active_tab].as_widget().operate( - &mut tree.children[active_tab], + &mut tree.children[1].children[active_tab], layout .children() .nth(1) From 34ab848bf6b046d4d45f8ec551182917e29e72a2 Mon Sep 17 00:00:00 2001 From: genusistimelord Date: Tue, 7 Nov 2023 14:24:09 -0500 Subject: [PATCH 10/22] fix time picker --- Cargo.toml | 4 +- src/native/overlay/time_picker.rs | 246 ++++++++++++++++-------------- src/native/time_picker.rs | 6 +- 3 files changed, 141 insertions(+), 115 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a43ed883..581ea0fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,7 +49,7 @@ default = [ "modal", "tab_bar", "tabs", - #"time_picker", + "time_picker", #"wrap", #"selection_list", #"split", @@ -95,7 +95,7 @@ members = [ #"examples/multiple_modals", "examples/tab_bar", "examples/tabs", - #"examples/time_picker", + "examples/time_picker", #"examples/wrap", "examples/number_input", #"examples/selection_list", diff --git a/src/native/overlay/time_picker.rs b/src/native/overlay/time_picker.rs index b3dde92e..46f44a91 100644 --- a/src/native/overlay/time_picker.rs +++ b/src/native/overlay/time_picker.rs @@ -503,7 +503,7 @@ where Message: 'static + Clone, Theme: 'a + StyleSheet + button::StyleSheet + text::StyleSheet + container::StyleSheet, { - fn layout(&self, renderer: &Renderer, bounds: Size, position: Point) -> Node { + fn layout(&mut self, renderer: &Renderer, bounds: Size, position: Point) -> Node { let limits = Limits::new(Size::ZERO, bounds) .pad(Padding::from(PADDING)) .width(Length::Fill) @@ -517,7 +517,9 @@ where // Pre-Buttons TODO: get rid of it let cancel_limits = limits; - let cancel_button = self.cancel_button.layout(renderer, &cancel_limits); + let cancel_button = + self.cancel_button + .layout(&mut self.tree.children[0], renderer, &cancel_limits); let limits = limits.shrink(Size::new( 0.0, @@ -528,7 +530,7 @@ where let mut clock = Row::<(), Renderer>::new() .width(Length::Fill) .height(Length::Fill) - .layout(renderer, &limits); + .layout(&mut self.tree, renderer, &limits); clock.move_to(Point::new( clock.bounds().x + PADDING, @@ -544,12 +546,16 @@ where let cancel_limits = limits.max_width(((clock.bounds().width / 2.0) - BUTTON_SPACING).max(0.0)); - let mut cancel_button = self.cancel_button.layout(renderer, &cancel_limits); + let mut cancel_button = + self.cancel_button + .layout(&mut self.tree.children[0], renderer, &cancel_limits); let submit_limits = limits.max_width(((clock.bounds().width / 2.0) - BUTTON_SPACING).max(0.0)); - let mut submit_button = self.submit_button.layout(renderer, &submit_limits); + let mut submit_button = + self.submit_button + .layout(&mut self.tree.children[1], renderer, &submit_limits); cancel_button.move_to(Point { x: cancel_button.bounds().x + PADDING, @@ -919,7 +925,7 @@ where /// Defines the layout of the digital clock of the time picker. fn digital_clock( - time_picker: &TimePickerOverlay<'_, Message, Theme>, + time_picker: &mut TimePickerOverlay<'_, Message, Theme>, renderer: &Renderer, limits: Limits, ) -> Node @@ -927,10 +933,10 @@ where Message: 'static + Clone, Theme: StyleSheet + button::StyleSheet + text::StyleSheet + container::StyleSheet, { - let arrow_size = renderer.default_size(); - let font_size = 1.2 * renderer.default_size(); + let arrow_size = renderer.default_size().0; + let font_size = 1.2 * renderer.default_size().0; - let mut digital_clock_row = Row::<(), Renderer>::new() + let mut digital_clock_row = Row::>::new() .align_items(Alignment::Center) .height(Length::Shrink) .width(Length::Shrink) @@ -1032,12 +1038,25 @@ where ); } - Container::new(digital_clock_row) + let container = Container::new(digital_clock_row) .width(Length::Fill) .height(Length::Shrink) .center_x() - .center_y() - .layout(renderer, &limits) + .center_y(); + + let element: Element> = Element::new(container); + let container_tree = if let Some(child_tree) = time_picker.tree.children.get_mut(2) { + child_tree.diff(element.as_widget()); + child_tree + } else { + let child_tree = Tree::new(element.as_widget()); + time_picker.tree.children.insert(2, child_tree); + &mut time_picker.tree.children[2] + }; + + element + .as_widget() + .layout(container_tree, renderer, &limits) } /// Draws the analog clock. @@ -1189,7 +1208,7 @@ fn draw_clock( .get(&clock_style_state) .expect("Style Sheet not found.") .clock_number_color, - size: period_size, + size: core::Pixels(period_size), font: renderer.default_font(), horizontal_alignment: Horizontal::Center, vertical_alignment: Vertical::Center, @@ -1234,7 +1253,7 @@ fn draw_clock( .get(&style_state) .expect("Style Sheet not found.") .clock_number_color, - size: number_size, + size: core::Pixels(number_size), font: renderer.default_font(), horizontal_alignment: Horizontal::Center, vertical_alignment: Vertical::Center, @@ -1269,7 +1288,7 @@ fn draw_clock( .get(&style_state) .expect("Style Sheet not found.") .clock_number_color, - size: number_size, + size: core::Pixels(number_size), font: renderer.default_font(), horizontal_alignment: Horizontal::Center, vertical_alignment: Vertical::Center, @@ -1315,7 +1334,7 @@ fn draw_clock( .get(&style_state) .expect("Style Sheet not found.") .clock_number_color, - size: number_size, + size: core::Pixels(number_size), font: renderer.default_font(), horizontal_alignment: Horizontal::Center, vertical_alignment: Vertical::Center, @@ -1417,64 +1436,65 @@ fn draw_digital_clock( let mut buffer = [0; 4]; // Caret up - renderer.fill_text(core::Text { - content: char::from(Icon::CaretUpFill).encode_utf8(&mut buffer), - bounds: Rectangle { - x: up_bounds.center_x(), - y: up_bounds.center_y(), - ..up_bounds + renderer.fill_text( + core::Text { + content: char::from(Icon::CaretUpFill).encode_utf8(&mut buffer), + bounds: Size::new(up_bounds.width, up_bounds.height), + size: core::Pixels( + renderer.default_size().0 + if up_arrow_hovered { 1.0 } else { 0.0 }, + ), + font: crate::graphics::icons::ICON_FONT, + horizontal_alignment: Horizontal::Center, + vertical_alignment: Vertical::Center, + line_height: text::LineHeight::Relative(1.3), + shaping: text::Shaping::Basic, }, - size: renderer.default_size() + if up_arrow_hovered { 1.0 } else { 0.0 }, - color: style + Point::new(up_bounds.center_x(), up_bounds.center_y()), + style .get(&StyleState::Active) .expect("Style Sheet not found.") .text_color, - font: crate::graphics::icons::ICON_FONT, - horizontal_alignment: Horizontal::Center, - vertical_alignment: Vertical::Center, - line_height: text::LineHeight::Relative(1.3), - shaping: text::Shaping::Basic, - }); + ); // Text - renderer.fill_text(core::Text { - content: &text, - bounds: Rectangle { - x: center_bounds.center_x(), - y: center_bounds.center_y(), - ..center_bounds + renderer.fill_text( + core::Text { + content: &text, + bounds: Size::new(center_bounds.width, center_bounds.height), + size: renderer.default_size(), + font: renderer.default_font(), + horizontal_alignment: Horizontal::Center, + vertical_alignment: Vertical::Center, + line_height: text::LineHeight::Relative(1.3), + shaping: text::Shaping::Basic, }, - size: renderer.default_size(), - color: style + Point::new(center_bounds.center_x(), center_bounds.center_y()), + style .get(&StyleState::Active) .expect("Style Sheet not found.") .text_color, - font: renderer.default_font(), - horizontal_alignment: Horizontal::Center, - vertical_alignment: Vertical::Center, - line_height: text::LineHeight::Relative(1.3), - shaping: text::Shaping::Basic, - }); + ); // Down caret - renderer.fill_text(core::Text { - content: char::from(Icon::CaretDownFill).encode_utf8(&mut buffer), - bounds: Rectangle { - x: down_bounds.center_x(), - y: down_bounds.center_y(), - ..down_bounds + renderer.fill_text( + core::Text { + content: char::from(Icon::CaretDownFill).encode_utf8(&mut buffer), + bounds: Size::new(down_bounds.width, down_bounds.height), + size: core::Pixels( + renderer.default_size().0 + if down_arrow_hovered { 1.0 } else { 0.0 }, + ), + font: crate::graphics::icons::ICON_FONT, + horizontal_alignment: Horizontal::Center, + vertical_alignment: Vertical::Center, + line_height: text::LineHeight::Relative(1.3), + shaping: text::Shaping::Basic, }, - size: renderer.default_size() + if down_arrow_hovered { 1.0 } else { 0.0 }, - color: style + Point::new(down_bounds.center_x(), down_bounds.center_y()), + style .get(&StyleState::Active) .expect("Style Sheet not found.") .text_color, - font: crate::graphics::icons::ICON_FONT, - horizontal_alignment: Horizontal::Center, - vertical_alignment: Vertical::Center, - line_height: text::LineHeight::Relative(1.3), - shaping: text::Shaping::Basic, - }); + ); }; if !time_picker.state.use_24h { @@ -1504,21 +1524,27 @@ fn draw_digital_clock( let hour_minute_separator = children .next() .expect("Graphics: Layout should have a hour/minute separator layout"); - renderer.fill_text(core::Text { - content: ":", - bounds: Rectangle { - x: hour_minute_separator.bounds().center_x(), - y: hour_minute_separator.bounds().center_y(), - ..hour_minute_separator.bounds() + + renderer.fill_text( + core::Text { + content: ":", + bounds: Size::new( + hour_minute_separator.bounds().width, + hour_minute_separator.bounds().height, + ), + size: renderer.default_size(), + font: renderer.default_font(), + horizontal_alignment: Horizontal::Center, + vertical_alignment: Vertical::Center, + line_height: text::LineHeight::Relative(1.3), + shaping: text::Shaping::Basic, }, - size: renderer.default_size(), - color: style[&StyleState::Active].text_color, - font: renderer.default_font(), - horizontal_alignment: Horizontal::Center, - vertical_alignment: Vertical::Center, - line_height: text::LineHeight::Relative(1.3), - shaping: text::Shaping::Basic, - }); + Point::new( + hour_minute_separator.bounds().center_x(), + hour_minute_separator.bounds().center_y(), + ), + style[&StyleState::Active].text_color, + ); // Draw minutes let minute_layout = children @@ -1536,24 +1562,26 @@ fn draw_digital_clock( let minute_second_separator = children .next() .expect("Graphics: Layout should have a minute/second separator layout"); - renderer.fill_text(core::Text { - content: ":", - bounds: Rectangle { - x: minute_second_separator.bounds().center_x(), - y: minute_second_separator.bounds().center_y(), - ..minute_second_separator.bounds() + renderer.fill_text( + core::Text { + content: ":", + bounds: Size::new( + minute_second_separator.bounds().width, + minute_second_separator.bounds().height, + ), + size: renderer.default_size(), + font: renderer.default_font(), + horizontal_alignment: Horizontal::Center, + vertical_alignment: Vertical::Center, + line_height: text::LineHeight::Relative(1.3), + shaping: text::Shaping::Basic, }, - size: renderer.default_size(), - color: style - .get(&StyleState::Active) - .expect("Style Sheet not found.") - .text_color, - font: renderer.default_font(), - horizontal_alignment: Horizontal::Center, - vertical_alignment: Vertical::Center, - line_height: text::LineHeight::Relative(1.3), - shaping: text::Shaping::Basic, - }); + Point::new( + minute_second_separator.bounds().center_x(), + minute_second_separator.bounds().center_y(), + ), + style[&StyleState::Active].text_color, + ); // Draw seconds let second_layout = children @@ -1572,28 +1600,24 @@ fn draw_digital_clock( let period = children .next() .expect("Graphics: Layout should have a period layout"); - renderer.fill_text(core::Text { - content: if time_picker.state.time.hour12().0 { - "PM" - } else { - "AM" - }, - bounds: Rectangle { - x: period.bounds().center_x(), - y: period.bounds().center_y(), - ..period.bounds() + renderer.fill_text( + core::Text { + content: if time_picker.state.time.hour12().0 { + "PM" + } else { + "AM" + }, + bounds: Size::new(period.bounds().width, period.bounds().height), + size: renderer.default_size(), + font: renderer.default_font(), + horizontal_alignment: Horizontal::Center, + vertical_alignment: Vertical::Center, + line_height: text::LineHeight::Relative(1.3), + shaping: text::Shaping::Basic, }, - size: renderer.default_size(), - color: style - .get(&StyleState::Active) - .expect("Style Sheet not found.") - .text_color, - font: renderer.default_font(), - horizontal_alignment: Horizontal::Center, - vertical_alignment: Vertical::Center, - line_height: text::LineHeight::Relative(1.3), - shaping: text::Shaping::Basic, - }); + Point::new(period.bounds().center_x(), period.bounds().center_y()), + style[&StyleState::Active].text_color, + ); } } @@ -1708,7 +1732,7 @@ where unimplemented!("This should never be reached!") } - fn layout(&self, _renderer: &Renderer, _limits: &Limits) -> Node { + fn layout(&self, _tree: &mut Tree, _renderer: &Renderer, _limits: &Limits) -> Node { unimplemented!("This should never be reached!") } diff --git a/src/native/time_picker.rs b/src/native/time_picker.rs index a0dfe3df..533d3a41 100644 --- a/src/native/time_picker.rs +++ b/src/native/time_picker.rs @@ -197,8 +197,10 @@ where self.underlay.as_widget().height() } - fn layout(&self, renderer: &Renderer, limits: &Limits) -> Node { - self.underlay.as_widget().layout(renderer, limits) + fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { + self.underlay + .as_widget() + .layout(&mut tree.children[0], renderer, limits) } fn on_event( From 1af18140814d1668d80193afc3509a14a32038f5 Mon Sep 17 00:00:00 2001 From: genusistimelord Date: Tue, 7 Nov 2023 14:34:04 -0500 Subject: [PATCH 11/22] Fixed wrap --- Cargo.toml | 4 ++-- src/native/wrap.rs | 20 +++++++++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 581ea0fc..fc379ac9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,7 +50,7 @@ default = [ "tab_bar", "tabs", "time_picker", - #"wrap", + "wrap", #"selection_list", #"split", #"menu", @@ -96,7 +96,7 @@ members = [ "examples/tab_bar", "examples/tabs", "examples/time_picker", - #"examples/wrap", + "examples/wrap", "examples/number_input", #"examples/selection_list", #"examples/split", diff --git a/src/native/wrap.rs b/src/native/wrap.rs index e80a4e75..43003122 100644 --- a/src/native/wrap.rs +++ b/src/native/wrap.rs @@ -176,8 +176,8 @@ where self.height } - fn layout(&self, renderer: &Renderer, limits: &Limits) -> Node { - self.inner_layout(renderer, limits) + fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { + self.inner_layout(tree, renderer, limits) } fn on_event( @@ -337,7 +337,7 @@ where Renderer: core::Renderer, { /// A inner layout of the [`Wrap`]. - fn inner_layout(&self, renderer: &Renderer, limits: &Limits) -> Node; + fn inner_layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node; } impl<'a, Message, Renderer> WrapLayout @@ -347,7 +347,7 @@ where { #[allow(clippy::inline_always)] #[inline(always)] - fn inner_layout(&self, renderer: &Renderer, limits: &Limits) -> Node { + fn inner_layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { let padding = Padding::from(self.padding); let spacing = self.spacing; let line_spacing = self.line_spacing; @@ -361,6 +361,7 @@ where .max_height(self.max_height); let max_width = limits.max().width; + let mut children = tree.children.iter_mut(); let mut curse = padding.left; let mut deep_curse = padding.left; let mut current_line_height = line_minimal_length; @@ -376,7 +377,9 @@ where Size::new(limits.min().width, line_minimal_length), limits.max(), ); - let mut node = elem.as_widget().layout(renderer, &node_limit); + let mut node = + elem.as_widget() + .layout(&mut children.next().unwrap(), renderer, &node_limit); let size = node.size(); @@ -429,7 +432,7 @@ where { #[allow(clippy::inline_always)] #[inline(always)] - fn inner_layout(&self, renderer: &Renderer, limits: &Limits) -> Node { + fn inner_layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { let padding = Padding::from(self.padding); let spacing = self.spacing; let line_spacing = self.line_spacing; @@ -443,6 +446,7 @@ where .max_height(self.max_height); let max_height = limits.max().height; + let mut children = tree.children.iter_mut(); let mut curse = padding.left; let mut wide_curse = padding.left; let mut current_line_width = line_minimal_length; @@ -458,7 +462,9 @@ where Size::new(line_minimal_length, limits.min().height), limits.max(), ); - let mut node = elem.as_widget().layout(renderer, &node_limit); + let mut node = + elem.as_widget() + .layout(&mut children.next().unwrap(), renderer, &node_limit); let size = node.size(); From e8bdd33596d49a946271dd8c33eb4ace0a531a53 Mon Sep 17 00:00:00 2001 From: genusistimelord Date: Wed, 8 Nov 2023 09:25:16 -0500 Subject: [PATCH 12/22] Fixed Selection list --- Cargo.toml | 4 +-- examples/selection_list/src/main.rs | 6 ++--- src/native/selection_list.rs | 36 +++++++++++++++++---------- src/native/selection_list/list.rs | 38 ++++++++++++++++------------- 4 files changed, 49 insertions(+), 35 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fc379ac9..754ea434 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,7 +51,7 @@ default = [ "tabs", "time_picker", "wrap", - #"selection_list", + "selection_list", #"split", #"menu", #"quad", @@ -98,7 +98,7 @@ members = [ "examples/time_picker", "examples/wrap", "examples/number_input", - #"examples/selection_list", + "examples/selection_list", #"examples/split", #"examples/split_scroller", #"examples/menu", diff --git a/examples/selection_list/src/main.rs b/examples/selection_list/src/main.rs index 11fc0bbf..cb4e11af 100644 --- a/examples/selection_list/src/main.rs +++ b/examples/selection_list/src/main.rs @@ -61,10 +61,10 @@ impl Sandbox for Example { self.manual_select = None; } Message::ManualSelection => { - if let Some(option) = self.vec.get(0) { + if let Some(option) = self.vec.get(2) { self.selected_language = option.to_owned(); - self.selected_index = 0; - self.manual_select = Some(0); + self.selected_index = 2; + self.manual_select = Some(2); } } } diff --git a/src/native/selection_list.rs b/src/native/selection_list.rs index cdbfcc38..7b53a0ac 100644 --- a/src/native/selection_list.rs +++ b/src/native/selection_list.rs @@ -5,13 +5,17 @@ use crate::style::selection_list::StyleSheet; use iced_widget::{ container, core::{ - self, event, + self, + alignment::{Horizontal, Vertical}, + event, layout::{Limits, Node}, mouse::{self, Cursor}, renderer, + text::{Paragraph, Text}, widget::Tree, - Clipboard, Element, Event, Layout, Length, Rectangle, Shell, Size, Widget, + Clipboard, Element, Event, Layout, Length, Pixels, Rectangle, Shell, Size, Widget, }, + graphics, runtime::Font, scrollable, text, text::LineHeight, @@ -168,7 +172,7 @@ where Length::Shrink } - fn layout(&self, renderer: &Renderer, limits: &Limits) -> Node { + fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { use std::f32; let limits = limits.width(self.width).height(self.height); @@ -179,16 +183,20 @@ where labels .map(|label| { - let size = renderer.measure( - &label, - self.text_size, - LineHeight::default(), - self.font, - Size::new(f32::INFINITY, f32::INFINITY), - text::Shaping::Advanced, - ); + let text = Text { + content: &label, + size: Pixels(self.text_size), + line_height: LineHeight::default(), + bounds: Size::INFINITY, + font: self.font, + horizontal_alignment: Horizontal::Left, + vertical_alignment: Vertical::Top, + shaping: text::Shaping::Advanced, + }; - size.width.round() as u32 + self.padding as u32 * 2 + let mut paragraph = graphics::text::Paragraph::new(); + paragraph.update(text); + paragraph.min_bounds().width.round() as u32 + self.padding as u32 * 2 }) .max() .unwrap_or(100) @@ -198,7 +206,9 @@ where let limits = limits.max_width(max_width as f32 + self.padding * 2.0); - let content = self.container.layout(renderer, &limits); + let content = self + .container + .layout(&mut tree.children[0], renderer, &limits); let size = limits.resolve(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 2de9a5bc..4c36dad1 100644 --- a/src/native/selection_list/list.rs +++ b/src/native/selection_list/list.rs @@ -13,7 +13,8 @@ use iced_widget::{ tree::{State, Tag}, Tree, }, - Clipboard, Color, Element, Event, Layout, Length, Rectangle, Shell, Size, Widget, + Clipboard, Color, Element, Event, Layout, Length, Pixels, Point, Rectangle, Shell, Size, + Widget, }, text::LineHeight, }; @@ -109,7 +110,12 @@ where Length::Shrink } - fn layout(&self, _renderer: &Renderer, limits: &layout::Limits) -> layout::Node { + fn layout( + &self, + _tree: &mut Tree, + _renderer: &Renderer, + limits: &layout::Limits, + ) -> layout::Node { use std::f32; let limits = limits.height(Length::Fill).width(Length::Fill); @@ -255,22 +261,20 @@ where theme.style(&self.style).text_color }; - renderer.fill_text(core::text::Text { - content: &option.to_string(), - bounds: Rectangle { - x: bounds.x, - y: bounds.center_y(), - width: f32::INFINITY, - ..bounds + renderer.fill_text( + core::text::Text { + content: &option.to_string(), + bounds: Size::new(f32::INFINITY, bounds.height), + size: Pixels(self.text_size), + font: self.font, + horizontal_alignment: Horizontal::Left, + vertical_alignment: Vertical::Center, + line_height: LineHeight::default(), + shaping: iced_widget::text::Shaping::Advanced, }, - size: self.text_size, - color: text_color, - font: self.font, - horizontal_alignment: Horizontal::Left, - vertical_alignment: Vertical::Center, - line_height: LineHeight::default(), - shaping: iced_widget::text::Shaping::Advanced, - }); + Point::new(bounds.x, bounds.center_y()), + text_color, + ); } } } From f81ae2107572f4f67d44fa7567f67d2c1cdc67c3 Mon Sep 17 00:00:00 2001 From: genusistimelord Date: Wed, 8 Nov 2023 09:30:44 -0500 Subject: [PATCH 13/22] Fixed split --- Cargo.toml | 6 +++--- src/native/split.rs | 36 ++++++++++++++++++++++++++++-------- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 754ea434..41c01b3b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,7 +52,7 @@ default = [ "time_picker", "wrap", "selection_list", - #"split", + "split", #"menu", #"quad", #"context_menu", @@ -99,8 +99,8 @@ members = [ "examples/wrap", "examples/number_input", "examples/selection_list", - #"examples/split", - #"examples/split_scroller", + "examples/split", + "examples/split_scroller", #"examples/menu", #"examples/spinner", #"examples/context_menu", diff --git a/src/native/split.rs b/src/native/split.rs index 7b3a76af..31f82aac 100644 --- a/src/native/split.rs +++ b/src/native/split.rs @@ -200,15 +200,15 @@ where self.height } - fn layout(&self, renderer: &Renderer, limits: &Limits) -> Node { + fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { let space = Row::::new() .width(Length::Fill) .height(Length::Fill) - .layout(renderer, limits); + .layout(tree, renderer, limits); match self.axis { - Axis::Horizontal => horizontal_split(self, renderer, limits, &space), - Axis::Vertical => vertical_split(self, renderer, limits, &space), + Axis::Horizontal => horizontal_split(tree, self, renderer, limits, &space), + Axis::Vertical => vertical_split(tree, self, renderer, limits, &space), } } @@ -515,6 +515,7 @@ where /// Do a horizontal split. fn horizontal_split<'a, Message, Renderer>( + tree: &mut Tree, split: &Split<'a, Message, Renderer>, renderer: &Renderer, limits: &Limits, @@ -531,11 +532,13 @@ where space.bounds().size(), vec![ split.first.as_widget().layout( + &mut tree.children[0], renderer, &limits.clone().shrink(Size::new(0.0, space.bounds().height)), ), Node::new(Size::new(space.bounds().height, split.spacing)), split.second.as_widget().layout( + &mut tree.children[1], renderer, &limits.clone().shrink(Size::new(0.0, space.bounds().width)), ), @@ -560,7 +563,10 @@ where space.bounds().height - f32::from(divider_position), )) .pad(padding); - let mut first = split.first.as_widget().layout(renderer, &first_limits); + let mut first = split + .first + .as_widget() + .layout(&mut tree.children[0], renderer, &first_limits); first.move_to(Point::new( space.bounds().x + split.padding, space.bounds().y + split.padding, @@ -573,7 +579,11 @@ where .clone() .shrink(Size::new(0.0, f32::from(divider_position) + split.spacing)) .pad(padding); - let mut second = split.second.as_widget().layout(renderer, &second_limits); + let mut second = + split + .second + .as_widget() + .layout(&mut tree.children[1], renderer, &second_limits); second.move_to(Point::new( space.bounds().x + split.padding, space.bounds().y + f32::from(divider_position) + split.spacing + split.padding, @@ -584,6 +594,7 @@ where /// Do a vertical split. fn vertical_split<'a, Message, Renderer>( + tree: &mut Tree, split: &Split<'a, Message, Renderer>, renderer: &Renderer, limits: &Limits, @@ -600,11 +611,13 @@ where space.bounds().size(), vec![ split.first.as_widget().layout( + &mut tree.children[0], renderer, &limits.clone().shrink(Size::new(space.bounds().width, 0.0)), ), Node::new(Size::new(split.spacing, space.bounds().height)), split.second.as_widget().layout( + &mut tree.children[1], renderer, &limits.clone().shrink(Size::new(space.bounds().width, 0.0)), ), @@ -629,7 +642,10 @@ where 0.0, )) .pad(padding); - let mut first = split.first.as_widget().layout(renderer, &first_limits); + let mut first = split + .first + .as_widget() + .layout(&mut tree.children[0], renderer, &first_limits); first.move_to(Point::new( space.bounds().x + split.padding, space.bounds().y + split.padding, @@ -642,7 +658,11 @@ where .clone() .shrink(Size::new(f32::from(divider_position) + split.spacing, 0.0)) .pad(padding); - let mut second = split.second.as_widget().layout(renderer, &second_limits); + let mut second = + split + .second + .as_widget() + .layout(&mut tree.children[1], renderer, &second_limits); second.move_to(Point::new( space.bounds().x + f32::from(divider_position) + split.spacing + split.padding, space.bounds().y + split.padding, From 2393df10a3c42d619203ad497f94f4fb9ab8ae64 Mon Sep 17 00:00:00 2001 From: genusistimelord Date: Wed, 8 Nov 2023 09:33:24 -0500 Subject: [PATCH 14/22] fixed spinner --- Cargo.toml | 4 ++-- src/native/spinner.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 41c01b3b..6798a06d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,7 +56,7 @@ default = [ #"menu", #"quad", #"context_menu", - #"spinner", + "spinner", #"cupertino", #"segmented_button", ] @@ -102,7 +102,7 @@ members = [ "examples/split", "examples/split_scroller", #"examples/menu", - #"examples/spinner", + "examples/spinner", #"examples/context_menu", #"examples/WidgetIDReturn", #"examples/segmented_button", diff --git a/src/native/spinner.rs b/src/native/spinner.rs index 4e425da9..3ea3c21f 100644 --- a/src/native/spinner.rs +++ b/src/native/spinner.rs @@ -127,7 +127,7 @@ where self.height } - fn layout(&self, _renderer: &Renderer, limits: &Limits) -> Node { + fn layout(&self, _tree: &mut Tree, _renderer: &Renderer, limits: &Limits) -> Node { Node::new( limits .width(self.width) From 14850b93519553afd596825805996ad887fb7a91 Mon Sep 17 00:00:00 2001 From: genusistimelord Date: Wed, 8 Nov 2023 10:13:53 -0500 Subject: [PATCH 15/22] fixed cupertino button, spinner and switch. Removed Alert due to Element creation loop in render. --- Cargo.toml | 9 +++---- .../cupertino/cupertino_switch/src/main.rs | 10 +++++-- src/native/cupertino/cupertino_alert.rs | 17 ++++++++---- src/native/cupertino/cupertino_button.rs | 27 +++++++++++++++---- src/native/cupertino/cupertino_spinner.rs | 2 +- src/native/cupertino/cupertino_switch.rs | 2 +- src/native/cupertino/mod.rs | 3 ++- 7 files changed, 50 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6798a06d..4e8ee070 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,7 +57,7 @@ default = [ #"quad", #"context_menu", "spinner", - #"cupertino", + "cupertino", #"segmented_button", ] @@ -82,10 +82,9 @@ members = [ "examples/badge", "examples/card", "examples/color_picker", - #"examples/cupertino/cupertino_alert", - #"examples/cupertino/cupertino_button", - #"examples/cupertino/cupertino_spinner", - #"examples/cupertino/cupertino_switch", + "examples/cupertino/cupertino_button", + "examples/cupertino/cupertino_spinner", + "examples/cupertino/cupertino_switch", "examples/date_picker", "examples/floating_element", "examples/floating_element_anchors", diff --git a/examples/cupertino/cupertino_switch/src/main.rs b/examples/cupertino/cupertino_switch/src/main.rs index b5afa204..4b901c5d 100644 --- a/examples/cupertino/cupertino_switch/src/main.rs +++ b/examples/cupertino/cupertino_switch/src/main.rs @@ -49,10 +49,16 @@ impl Application for Switch { fn view(&self) -> Element { let toggle_1: CupertinoSwitch = CupertinoSwitch::new().on_changed(Some(Box::new( Message::LeftSwitchChanged - ))); + ))).value(match self { + Switch::LeftSwitchChanged(v) => *v, + _ => true, + }); let toggle_2: CupertinoSwitch = CupertinoSwitch::new() - .value(false) + .value(match self { + Switch::LeftSwitchChanged(v) => *v, + _ => false, + }) .on_changed(Some(Box::new(Message::RightSwitchChanged))); let left_text: String = match self { diff --git a/src/native/cupertino/cupertino_alert.rs b/src/native/cupertino/cupertino_alert.rs index c4d791ee..334e102d 100644 --- a/src/native/cupertino/cupertino_alert.rs +++ b/src/native/cupertino/cupertino_alert.rs @@ -267,7 +267,7 @@ where } } - fn layout(&self, _renderer: &Renderer, limits: &Limits) -> Node { + fn layout(&self, _tree: &mut Tree, _renderer: &Renderer, limits: &Limits) -> Node { Node::new( limits .width(if self.is_hidden { @@ -284,6 +284,13 @@ where ) } + fn children(&self) -> Vec { + self.actions + .iter() + .map(|action| Tree::new(&action.child)) + .collect() + } + fn draw( &self, state: &Tree, @@ -438,7 +445,7 @@ where }); child_1.draw( - state, + &state.children[0], r, theme, style, @@ -448,7 +455,7 @@ where ); child_2.draw( - state, + &state.children[1], r, theme, style, @@ -477,7 +484,7 @@ where y: center.y - height / 3.0, }); - let title: Element<'a, Message, Renderer> = + /*let title: Element<'a, Message, Renderer> = CupertinoAlert::<'a, Message, Renderer>::text_with_font( Text::new(self.title.clone()).horizontal_alignment(Horizontal::Center), ); @@ -505,7 +512,7 @@ where Layout::new(&content_node), cursor, viewport, - ); + );*/ }; renderer.with_layer(rectangle, draw_element); diff --git a/src/native/cupertino/cupertino_button.rs b/src/native/cupertino/cupertino_button.rs index 9804bf49..d9a8c39e 100644 --- a/src/native/cupertino/cupertino_button.rs +++ b/src/native/cupertino/cupertino_button.rs @@ -127,8 +127,19 @@ where self.body.as_widget().height() } - fn layout(&self, renderer: &Renderer, limits: &Limits) -> Node { - return self.body.as_widget().layout(renderer, limits); + fn children(&self) -> Vec { + vec![Tree::new(&self.body)] + } + + fn diff(&self, tree: &mut Tree) { + tree.diff_children(std::slice::from_ref(&self.body)); + } + + fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { + return self + .body + .as_widget() + .layout(&mut tree.children[0], renderer, limits); } fn draw( @@ -189,9 +200,15 @@ where new_style.text_color = secondary_system_fill(); } - self.body - .as_widget() - .draw(state, renderer, theme, new_style, layout, cursor, viewport); + self.body.as_widget().draw( + &state.children[0], + renderer, + theme, + new_style, + layout, + cursor, + viewport, + ); } fn on_event( diff --git a/src/native/cupertino/cupertino_spinner.rs b/src/native/cupertino/cupertino_spinner.rs index b897ae85..2a42bca2 100644 --- a/src/native/cupertino/cupertino_spinner.rs +++ b/src/native/cupertino/cupertino_spinner.rs @@ -98,7 +98,7 @@ impl Widget> for CupertinoSpinner { self.height } - fn layout(&self, _renderer: &Renderer, limits: &Limits) -> Node { + fn layout(&self, _tree: &mut Tree, _renderer: &Renderer, limits: &Limits) -> Node { Node::new( limits .width(self.width) diff --git a/src/native/cupertino/cupertino_switch.rs b/src/native/cupertino/cupertino_switch.rs index f2cf0bb2..be3b624b 100644 --- a/src/native/cupertino/cupertino_switch.rs +++ b/src/native/cupertino/cupertino_switch.rs @@ -166,7 +166,7 @@ where self.height } - fn layout(&self, _renderer: &Renderer, limits: &Limits) -> Node { + fn layout(&self, _tree: &mut Tree, _renderer: &Renderer, limits: &Limits) -> Node { Node::new( limits .width(self.width) diff --git a/src/native/cupertino/mod.rs b/src/native/cupertino/mod.rs index c138f3c7..674a8a5e 100644 --- a/src/native/cupertino/mod.rs +++ b/src/native/cupertino/mod.rs @@ -1,7 +1,8 @@ /// Use a Cupertino-style alert. /// /// *This API requires the following crate features to be activated: `cupertino`* -pub mod cupertino_alert; +/// Depreciated due to Element loop. +//pub mod cupertino_alert; /// Use a Cupertino-style button. /// From b4671fb251bab1c5fcf57b9968cd4f2fff6fb33f Mon Sep 17 00:00:00 2001 From: genusistimelord Date: Wed, 8 Nov 2023 10:30:09 -0500 Subject: [PATCH 16/22] Fixed context menu --- .vscode/launch.json | 18 ++++++++++++++++++ Cargo.toml | 10 +++++----- src/native/context_menu.rs | 6 ++++-- src/native/overlay/context_menu.rs | 7 +++++-- src/native/quad.rs | 2 +- src/native/segmented_button.rs | 7 +++++-- 6 files changed, 38 insertions(+), 12 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 5b94a8d7..f84a46b4 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -22,6 +22,24 @@ "args": [], "cwd": "${workspaceFolder}" }, + { + "type": "lldb", + "request": "launch", + "name": "Debug executable 'segmented_button'", + "cargo": { + "args": [ + "build", + "--bin=segmented_button", + "--package=segmented_button" + ], + "filter": { + "name": "segmented_button", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + }, { "type": "lldb", "request": "launch", diff --git a/Cargo.toml b/Cargo.toml index 4e8ee070..f727ef88 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,11 +54,11 @@ default = [ "selection_list", "split", #"menu", - #"quad", - #"context_menu", + "quad", + "context_menu", "spinner", "cupertino", - #"segmented_button", + "segmented_button", ] [dependencies] @@ -102,9 +102,9 @@ members = [ "examples/split_scroller", #"examples/menu", "examples/spinner", - #"examples/context_menu", + "examples/context_menu", #"examples/WidgetIDReturn", - #"examples/segmented_button", + "examples/segmented_button", ] [workspace.dependencies.iced] diff --git a/src/native/context_menu.rs b/src/native/context_menu.rs index 7b60d001..93127a74 100644 --- a/src/native/context_menu.rs +++ b/src/native/context_menu.rs @@ -95,8 +95,10 @@ where self.underlay.as_widget().height() } - fn layout(&self, renderer: &Renderer, limits: &Limits) -> Node { - self.underlay.as_widget().layout(renderer, limits) + fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { + self.underlay + .as_widget() + .layout(&mut tree.children[0], renderer, limits) } fn draw( diff --git a/src/native/overlay/context_menu.rs b/src/native/overlay/context_menu.rs index 34ee7911..0c2caad7 100644 --- a/src/native/overlay/context_menu.rs +++ b/src/native/overlay/context_menu.rs @@ -70,11 +70,14 @@ where Renderer: 'a + core::Renderer, Renderer::Theme: StyleSheet, { - fn layout(&self, renderer: &Renderer, bounds: Size, position: Point) -> Node { + fn layout(&mut self, renderer: &Renderer, bounds: Size, position: Point) -> Node { let limits = Limits::new(Size::ZERO, bounds); let max_size = limits.max(); - let mut content = self.content.as_widget().layout(renderer, &limits); + let mut content = self + .content + .as_widget() + .layout(self.tree, renderer, &limits); // Try to stay inside borders let mut position = position; diff --git a/src/native/quad.rs b/src/native/quad.rs index 6946eb34..962a6486 100644 --- a/src/native/quad.rs +++ b/src/native/quad.rs @@ -115,7 +115,7 @@ where self.height } - fn layout(&self, _renderer: &Renderer, limits: &Limits) -> Node { + fn layout(&self, _tree: &mut Tree, _renderer: &Renderer, limits: &Limits) -> Node { let limits = limits.width(self.width).height(self.height); Node::new(limits.max()) } diff --git a/src/native/segmented_button.rs b/src/native/segmented_button.rs index ef02d26e..e716a47c 100644 --- a/src/native/segmented_button.rs +++ b/src/native/segmented_button.rs @@ -141,7 +141,7 @@ where self.height } - fn layout(&self, renderer: &Renderer, limits: &Limits) -> Node { + fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { let padding = self.padding; let limits = limits .loose() @@ -149,7 +149,10 @@ where .height(self.height) .pad(padding); - let mut content = self.content.as_widget().layout(renderer, &limits.loose()); + let mut content = + self.content + .as_widget() + .layout(&mut tree.children[0], renderer, &limits.loose()); let size = limits.resolve(content.size()); content.move_to(Point::new(padding.left, padding.top)); From b7f8dabb4d976b5df2830b1e192c2625a7bbbe0f Mon Sep 17 00:00:00 2001 From: genusistimelord Date: Wed, 8 Nov 2023 11:01:49 -0500 Subject: [PATCH 17/22] clippy changes --- Cargo.toml | 9 +++++++-- src/native/card.rs | 1 + src/native/grid/layout.rs | 14 +++++++++++--- src/native/mod.rs | 1 + src/native/number_input.rs | 4 ++-- src/native/overlay/color_picker.rs | 6 +++--- src/native/overlay/date_picker.rs | 4 ++-- src/native/overlay/floating_element.rs | 2 +- src/native/overlay/modal.rs | 2 +- src/native/overlay/time_picker.rs | 2 +- src/native/wrap.rs | 16 ++++++++++------ 11 files changed, 40 insertions(+), 21 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f727ef88..f6885e89 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -68,12 +68,17 @@ chrono = { version = "0.4.26", optional = true } once_cell = { version = "1.18.0", optional = true } itertools = { version = "0.11.0", optional = true } - [dependencies.iced_widget] git = "https://github.com/iced-rs/iced.git" rev = "751ea77c29f6eb3d00f45f0a04c833a1d03a425c" #version = "0.1.1" +#[dependencies.iced_renderer] +#git = "https://github.com/iced-rs/iced.git" +#rev = "751ea77c29f6eb3d00f45f0a04c833a1d03a425c" +#features = ["wgpu"] +#version = "0.1.1" + [profile.dev.package."*"] opt-level = 2 @@ -91,7 +96,7 @@ members = [ "examples/grid", "examples/modal", "examples/modal_component", - #"examples/multiple_modals", + "examples/multiple_modals", "examples/tab_bar", "examples/tabs", "examples/time_picker", diff --git a/src/native/card.rs b/src/native/card.rs index c35a62c1..3a6df0b1 100644 --- a/src/native/card.rs +++ b/src/native/card.rs @@ -595,6 +595,7 @@ where } /// Calculates the layout of the head. +#[allow(clippy::too_many_arguments)] fn head_node( renderer: &Renderer, limits: &Limits, diff --git a/src/native/grid/layout.rs b/src/native/grid/layout.rs index 2ffa8a1d..adbc240e 100644 --- a/src/native/grid/layout.rs +++ b/src/native/grid/layout.rs @@ -89,14 +89,18 @@ fn minimum_row_column_sizes( Renderer: iced_widget::core::Renderer, { let mut children = tree.children.iter_mut(); - for row in rows.iter() { + for row in rows { let mut row_height = 0.0f32; for (col_idx, element) in row.elements.iter().enumerate() { let child_limits = Limits::NONE.width(Length::Shrink).height(Length::Shrink); let Size { width, height } = element .as_widget() - .layout(children.next().unwrap(), renderer, &child_limits) + .layout( + children.next().expect("grid missing expected child"), + renderer, + &child_limits, + ) .size(); #[allow(clippy::option_if_let_else)] @@ -200,7 +204,11 @@ where .max_width(column_width) .max_height(row_height); - let mut node = widget.layout(children.next().unwrap(), renderer, &widget_limits); + let mut node = widget.layout( + children.next().expect("Grid missing child"), + renderer, + &widget_limits, + ); node.move_to(Point::new(x, y)); node.align( horizontal_alignment.into(), diff --git a/src/native/mod.rs b/src/native/mod.rs index 306f4b18..7c496feb 100644 --- a/src/native/mod.rs +++ b/src/native/mod.rs @@ -1,6 +1,7 @@ //! Stateless, pure widgets for iced //use iced_widget::{renderer, style}; pub mod helpers; +#[allow(unused_imports)] pub use helpers::*; pub mod overlay; diff --git a/src/native/number_input.rs b/src/native/number_input.rs index 0135538a..b2440dbf 100644 --- a/src/native/number_input.rs +++ b/src/native/number_input.rs @@ -332,7 +332,7 @@ where ) }; - let mut input_tree = if let Some(child_tree) = tree.children.get_mut(1) { + let input_tree = if let Some(child_tree) = tree.children.get_mut(1) { child_tree.diff(element.as_widget()); child_tree } else { @@ -343,7 +343,7 @@ where let mut modifier = element .as_widget() - .layout(&mut input_tree, renderer, &limits2.loose()); + .layout(input_tree, renderer, &limits2.loose()); let intrinsic = Size::new( content.size().width - 1.0, content.size().height.max(modifier.size().height), diff --git a/src/native/overlay/color_picker.rs b/src/native/overlay/color_picker.rs index cd0e7d01..c096deac 100644 --- a/src/native/overlay/color_picker.rs +++ b/src/native/overlay/color_picker.rs @@ -906,7 +906,7 @@ where .width(Length::Fill) .height(Length::FillPortion(1)), ) - .layout(&mut color_picker.tree, renderer, &block1_limits); + .layout(color_picker.tree, renderer, &block1_limits); block1_node.move_to(Point::new(bounds.x + PADDING, bounds.y + PADDING)); @@ -977,7 +977,7 @@ where ); } let element: Element> = Element::new(rgba_colors); - let mut rgba_tree = if let Some(child_tree) = color_picker.tree.children.get_mut(2) { + let rgba_tree = if let Some(child_tree) = color_picker.tree.children.get_mut(2) { child_tree.diff(element.as_widget()); child_tree } else { @@ -988,7 +988,7 @@ where let mut rgba_colors = element .as_widget() - .layout(&mut rgba_tree, renderer, &block2_limits); + .layout(rgba_tree, renderer, &block2_limits); rgba_colors.move_to(Point::new( rgba_colors.bounds().x + PADDING, diff --git a/src/native/overlay/date_picker.rs b/src/native/overlay/date_picker.rs index c4360473..3b7787f1 100644 --- a/src/native/overlay/date_picker.rs +++ b/src/native/overlay/date_picker.rs @@ -470,7 +470,7 @@ where .push(days); let element: Element> = Element::new(col); - let mut col_tree = if let Some(child_tree) = self.tree.children.get_mut(2) { + let col_tree = if let Some(child_tree) = self.tree.children.get_mut(2) { child_tree.diff(element.as_widget()); child_tree } else { @@ -479,7 +479,7 @@ where &mut self.tree.children[2] }; - let mut col = element.as_widget().layout(&mut col_tree, renderer, &limits); + let mut col = element.as_widget().layout(col_tree, renderer, &limits); col.move_to(Point::new( col.bounds().x + PADDING, col.bounds().y + PADDING, diff --git a/src/native/overlay/floating_element.rs b/src/native/overlay/floating_element.rs index 72e6a10a..fc7c6baf 100644 --- a/src/native/overlay/floating_element.rs +++ b/src/native/overlay/floating_element.rs @@ -64,7 +64,7 @@ where let mut node = self .element .as_widget() - .layout(&mut self.state, renderer, &limits); + .layout(self.state, renderer, &limits); let position = match self.anchor { Anchor::NorthWest => Point::new(position.x + self.offset.x, position.y + self.offset.y), diff --git a/src/native/overlay/modal.rs b/src/native/overlay/modal.rs index da084239..92d5e635 100644 --- a/src/native/overlay/modal.rs +++ b/src/native/overlay/modal.rs @@ -73,7 +73,7 @@ where let mut content = self .content .as_widget() - .layout(&mut self.state, renderer, &limits); + .layout(self.state, renderer, &limits); let max_size = limits.max(); content.align( diff --git a/src/native/overlay/time_picker.rs b/src/native/overlay/time_picker.rs index 46f44a91..3ed42e17 100644 --- a/src/native/overlay/time_picker.rs +++ b/src/native/overlay/time_picker.rs @@ -530,7 +530,7 @@ where let mut clock = Row::<(), Renderer>::new() .width(Length::Fill) .height(Length::Fill) - .layout(&mut self.tree, renderer, &limits); + .layout(self.tree, renderer, &limits); clock.move_to(Point::new( clock.bounds().x + PADDING, diff --git a/src/native/wrap.rs b/src/native/wrap.rs index 43003122..52a7060f 100644 --- a/src/native/wrap.rs +++ b/src/native/wrap.rs @@ -377,9 +377,11 @@ where Size::new(limits.min().width, line_minimal_length), limits.max(), ); - let mut node = - elem.as_widget() - .layout(&mut children.next().unwrap(), renderer, &node_limit); + let mut node = elem.as_widget().layout( + children.next().expect("wrap missing expected child"), + renderer, + &node_limit, + ); let size = node.size(); @@ -462,9 +464,11 @@ where Size::new(line_minimal_length, limits.min().height), limits.max(), ); - let mut node = - elem.as_widget() - .layout(&mut children.next().unwrap(), renderer, &node_limit); + let mut node = elem.as_widget().layout( + children.next().expect("wrap missing expected child"), + renderer, + &node_limit, + ); let size = node.size(); From 4c097316789644ee35cfc0a579d5c90eaf759e91 Mon Sep 17 00:00:00 2001 From: genusistimelord Date: Tue, 14 Nov 2023 09:46:22 -0500 Subject: [PATCH 18/22] updated iced repo commit to latest --- Cargo.toml | 4 ++-- examples/tab_bar/src/main.rs | 9 ++++++--- src/native/tab_bar.rs | 4 ++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f6885e89..b50e0b37 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -70,7 +70,7 @@ itertools = { version = "0.11.0", optional = true } [dependencies.iced_widget] git = "https://github.com/iced-rs/iced.git" -rev = "751ea77c29f6eb3d00f45f0a04c833a1d03a425c" +rev = "817f72868746461891ca4e74473c555f3b5c5703" #version = "0.1.1" #[dependencies.iced_renderer] @@ -114,7 +114,7 @@ members = [ [workspace.dependencies.iced] git = "https://github.com/iced-rs/iced.git" -rev = "751ea77c29f6eb3d00f45f0a04c833a1d03a425c" +rev = "817f72868746461891ca4e74473c555f3b5c5703" #version = "0.10.0" features = ["advanced", "lazy", "tokio"] diff --git a/examples/tab_bar/src/main.rs b/examples/tab_bar/src/main.rs index 8999de75..4a0a4d7c 100644 --- a/examples/tab_bar/src/main.rs +++ b/examples/tab_bar/src/main.rs @@ -6,7 +6,10 @@ use iced::{ use iced_aw::{TabBar, TabLabel}; fn main() -> iced::Result { - TabBarExample::run(Settings::default()) + TabBarExample::run(Settings { + default_text_size: 12.into(), + ..Default::default() + }) } #[derive(Debug, Clone)] @@ -131,13 +134,13 @@ impl Application for TabBarExample { .push( TextInput::new("Tab label", &state.new_tab_label) .on_input(Message::TabLabelInputChanged) - .size(22) + .size(16) .padding(5.0), ) .push( TextInput::new("Tab content", &state.new_tab_content) .on_input(Message::TabContentInputChanged) - .size(22) + .size(12) .padding(5.0), ) .push(Button::new(Text::new("New")).on_press(Message::NewTab)) diff --git a/src/native/tab_bar.rs b/src/native/tab_bar.rs index f6a39065..000cf004 100644 --- a/src/native/tab_bar.rs +++ b/src/native/tab_bar.rs @@ -707,7 +707,7 @@ fn draw_tab( line_height: LineHeight::Relative(1.3), shaping: iced_widget::text::Shaping::Advanced, }, - Point::new(icon_bounds.x, icon_bounds.center_y()), + Point::new(icon_bounds.center_x(), icon_bounds.center_y()), style.icon_color, ); } @@ -726,7 +726,7 @@ fn draw_tab( line_height: LineHeight::Relative(1.3), shaping: iced_widget::text::Shaping::Advanced, }, - Point::new(text_bounds.x, text_bounds.center_y()), + Point::new(text_bounds.center_x(), text_bounds.center_y()), style.text_color, ); } From 5cd7efb03f6f5c23cccc38be3b4f06c3e22acafc Mon Sep 17 00:00:00 2001 From: genusistimelord Date: Tue, 14 Nov 2023 11:14:58 -0500 Subject: [PATCH 19/22] Add paragraph and string cache for Selectionlist --- src/native/selection_list.rs | 87 ++++++++++++++++++++++--------- src/native/selection_list/list.rs | 16 +++--- 2 files changed, 72 insertions(+), 31 deletions(-) diff --git a/src/native/selection_list.rs b/src/native/selection_list.rs index 7b53a0ac..82162ab1 100644 --- a/src/native/selection_list.rs +++ b/src/native/selection_list.rs @@ -12,7 +12,7 @@ use iced_widget::{ mouse::{self, Cursor}, renderer, text::{Paragraph, Text}, - widget::Tree, + widget::{tree, Tree}, Clipboard, Element, Event, Layout, Length, Pixels, Rectangle, Shell, Size, Widget, }, graphics, @@ -151,7 +151,7 @@ where impl<'a, T, Message, Renderer> Widget for SelectionList<'a, T, Message, Renderer> where - T: 'a + Clone + ToString + Eq + Hash, + T: 'a + Clone + ToString + Eq + Hash + Display, Message: 'static, Renderer: core::Renderer + core::text::Renderer + 'a, Renderer::Theme: StyleSheet + container::StyleSheet, @@ -162,6 +162,13 @@ where fn diff(&self, tree: &mut Tree) { tree.diff_children(&[&self.container as &dyn Widget<_, _>]); + let state = tree.state.downcast_mut::(); + + state.values = self + .options + .iter() + .map(|_| graphics::text::Paragraph::new()) + .collect() } fn width(&self) -> Length { @@ -172,35 +179,43 @@ where Length::Shrink } + fn tag(&self) -> tree::Tag { + tree::Tag::of::() + } + + fn state(&self) -> tree::State { + tree::State::new(State::new(self.options)) + } + fn layout(&self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node { use std::f32; + let state = tree.state.downcast_mut::(); + let limits = limits.width(self.width).height(self.height); let max_width = match self.width { - Length::Shrink => { - let labels = self.options.iter().map(ToString::to_string); + Length::Shrink => self + .options + .iter() + .enumerate() + .map(|(id, val)| { + let text = Text { + content: &val.to_string(), + size: Pixels(self.text_size), + line_height: LineHeight::default(), + bounds: Size::INFINITY, + font: self.font, + horizontal_alignment: Horizontal::Left, + vertical_alignment: Vertical::Top, + shaping: text::Shaping::Advanced, + }; - labels - .map(|label| { - let text = Text { - content: &label, - size: Pixels(self.text_size), - line_height: LineHeight::default(), - bounds: Size::INFINITY, - font: self.font, - horizontal_alignment: Horizontal::Left, - vertical_alignment: Vertical::Top, - shaping: text::Shaping::Advanced, - }; - - let mut paragraph = graphics::text::Paragraph::new(); - paragraph.update(text); - paragraph.min_bounds().width.round() as u32 + self.padding as u32 * 2 - }) - .max() - .unwrap_or(100) - } + state.values[id].update(text); + state.values[id].min_bounds().width.round() as u32 + self.padding as u32 * 2 + }) + .max() + .unwrap_or(100), _ => limits.max().width as u32, }; @@ -289,7 +304,7 @@ where impl<'a, T, Message, Renderer> From> for Element<'a, Message, Renderer> where - T: Clone + ToString + Eq + Hash, + T: Clone + ToString + Eq + Hash + Display, Message: 'static, Renderer: 'a + core::Renderer + core::text::Renderer, Renderer::Theme: StyleSheet + container::StyleSheet, @@ -298,3 +313,25 @@ where Element::new(selection_list) } } + +/// A Paragraph cache to enhance speed of layouting. +#[derive(Debug, Default, Clone)] +pub struct State { + values: Vec, +} + +impl State { + /// Creates a new [`State`], representing an unfocused [`TextInput`]. + pub fn new<'a, T>(options: &'a [T]) -> Self + where + T: Clone + Display + Eq + Hash, + [T]: ToOwned>, + { + Self { + values: options + .iter() + .map(|_| graphics::text::Paragraph::new()) + .collect(), + } + } +} diff --git a/src/native/selection_list/list.rs b/src/native/selection_list/list.rs index 4c36dad1..d50d86f9 100644 --- a/src/native/selection_list/list.rs +++ b/src/native/selection_list/list.rs @@ -60,6 +60,8 @@ pub struct ListState { pub hovered_option: Option, /// The index in the list of options of the last chosen Item Clicked for Processing pub last_selected_index: Option<(usize, u64)>, + /// String Build Cache + pub options: Vec, } impl<'a, T, Message, Renderer> Widget for List<'a, T, Message, Renderer> @@ -73,7 +75,10 @@ where } fn state(&self) -> State { - State::new(ListState::default()) + State::new(ListState { + options: self.options.iter().map(ToString::to_string).collect(), + ..ListState::default() + }) } fn diff(&self, state: &mut Tree) { @@ -100,6 +105,8 @@ where list_state.last_selected_index = None; } } + + list_state.options = self.options.iter().map(ToString::to_string).collect(); } fn width(&self) -> Length { @@ -218,12 +225,9 @@ where let offset = viewport.y - bounds.y; let start = (offset / option_height) as usize; let end = ((offset + viewport.height) / option_height).ceil() as usize; - - let visible_options = &self.options[start..end.min(self.options.len())]; let list_state = state.state.downcast_ref::(); - for (i, option) in visible_options.iter().enumerate() { - let i = start + i; + for i in start..end.min(self.options.len()) { let is_selected = list_state .last_selected_index .map(|u| u.0 == i) @@ -263,7 +267,7 @@ where renderer.fill_text( core::text::Text { - content: &option.to_string(), + content: &list_state.options[i], bounds: Size::new(f32::INFINITY, bounds.height), size: Pixels(self.text_size), font: self.font, From 529199c822f2327409c8b3faae513c8ae9bfac62 Mon Sep 17 00:00:00 2001 From: genusistimelord Date: Tue, 14 Nov 2023 15:02:56 -0500 Subject: [PATCH 20/22] update to latest commit for iced --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b50e0b37..d963ff30 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -70,7 +70,7 @@ itertools = { version = "0.11.0", optional = true } [dependencies.iced_widget] git = "https://github.com/iced-rs/iced.git" -rev = "817f72868746461891ca4e74473c555f3b5c5703" +rev = "b474a2b7a763dcde6a377cb409001a7b5285ee8d" #version = "0.1.1" #[dependencies.iced_renderer] @@ -114,7 +114,7 @@ members = [ [workspace.dependencies.iced] git = "https://github.com/iced-rs/iced.git" -rev = "817f72868746461891ca4e74473c555f3b5c5703" +rev = "b474a2b7a763dcde6a377cb409001a7b5285ee8d" #version = "0.10.0" features = ["advanced", "lazy", "tokio"] From 5f56c7e0bda448e6cfc4d882e82c25c68f20c7d7 Mon Sep 17 00:00:00 2001 From: genusistimelord Date: Mon, 20 Nov 2023 13:14:12 -0500 Subject: [PATCH 21/22] add slider bar --- .vscode/launch.json | 18 ++ Cargo.toml | 6 +- examples/sliderbar/Cargo.toml | 11 + examples/sliderbar/src/main.rs | 57 ++++++ src/lib.rs | 2 + src/native/common.rs | 62 ++++++ src/native/mod.rs | 8 + src/native/quad.rs | 60 +----- src/native/slide_bar.rs | 357 +++++++++++++++++++++++++++++++++ 9 files changed, 522 insertions(+), 59 deletions(-) create mode 100644 examples/sliderbar/Cargo.toml create mode 100644 examples/sliderbar/src/main.rs create mode 100644 src/native/common.rs create mode 100644 src/native/slide_bar.rs diff --git a/.vscode/launch.json b/.vscode/launch.json index f84a46b4..a6a3713f 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -22,6 +22,24 @@ "args": [], "cwd": "${workspaceFolder}" }, + { + "type": "lldb", + "request": "launch", + "name": "Debug executable 'slidebar'", + "cargo": { + "args": [ + "build", + "--bin=slidebar", + "--package=slidebar" + ], + "filter": { + "name": "slidebar", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + }, { "type": "lldb", "request": "launch", diff --git a/Cargo.toml b/Cargo.toml index d963ff30..22029d43 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,15 +59,17 @@ default = [ "spinner", "cupertino", "segmented_button", + "num-traits" ] [dependencies] -num-traits = { version = "0.2.16", optional = true } +num-traits = {version = "0.2.16", optional = true} time = { version = "0.3.23", features = ["local-offset"], optional = true } chrono = { version = "0.4.26", optional = true } once_cell = { version = "1.18.0", optional = true } itertools = { version = "0.11.0", optional = true } + [dependencies.iced_widget] git = "https://github.com/iced-rs/iced.git" rev = "b474a2b7a763dcde6a377cb409001a7b5285ee8d" @@ -110,6 +112,7 @@ members = [ "examples/context_menu", #"examples/WidgetIDReturn", "examples/segmented_button", + "examples/sliderbar", ] [workspace.dependencies.iced] @@ -121,3 +124,4 @@ features = ["advanced", "lazy", "tokio"] [workspace.dependencies.iced_aw] path = "./" default-features = false +features = ["num-traits"] \ No newline at end of file diff --git a/examples/sliderbar/Cargo.toml b/examples/sliderbar/Cargo.toml new file mode 100644 index 00000000..22276daa --- /dev/null +++ b/examples/sliderbar/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "slidebar" +version = "0.1.0" +authors = ["Andrew Wheeler "] +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +iced_aw.workspace = true +iced.workspace = true diff --git a/examples/sliderbar/src/main.rs b/examples/sliderbar/src/main.rs new file mode 100644 index 00000000..0b8bb667 --- /dev/null +++ b/examples/sliderbar/src/main.rs @@ -0,0 +1,57 @@ +use iced::{ + widget::{Column, Container, Text}, + Element, Length, Sandbox, Settings, +}; + +use iced_aw::SlideBar; + +fn main() -> iced::Result { + SlideBarExample::run(Settings::default()) +} + +#[derive(Debug, Clone)] +enum Message { + SliderBarChange(u32), +} + +struct SlideBarExample { + value: u32, +} + +impl Sandbox for SlideBarExample { + type Message = Message; + + fn new() -> Self { + SlideBarExample { value: 1 } + } + + fn title(&self) -> String { + String::from("Slider Bar example") + } + + fn update(&mut self, message: Message) { + let Message::SliderBarChange(v) = message; + self.value = v; + } + + fn view(&self) -> Element { + let bar = SlideBar::new(0..=100, self.value, Message::SliderBarChange).width(100.0); + + let content_all = Column::new() + .spacing(10) + .push( + Text::new(format!("Value is {}", self.value)) + .width(Length::Fill) + .vertical_alignment(iced::alignment::Vertical::Center).horizontal_alignment(iced::alignment::Horizontal::Center), + ) + .push(bar) + .align_items(iced::Alignment::Center); + + Container::new(content_all) + .width(Length::Fill) + .height(Length::Fill) + .center_x() + .center_y() + .into() + } +} diff --git a/src/lib.rs b/src/lib.rs index 7950b925..a96c9405 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -148,6 +148,8 @@ mod platform { #[cfg(feature = "spinner")] pub use {crate::native::spinner, crate::style::SpinnerStyle, spinner::Spinner}; + pub use crate::native::SlideBar; + #[doc(no_inline)] #[cfg(feature = "context_menu")] pub use { diff --git a/src/native/common.rs b/src/native/common.rs new file mode 100644 index 00000000..9c930bb9 --- /dev/null +++ b/src/native/common.rs @@ -0,0 +1,62 @@ +//! Common types for reuse. +//! + +use iced_widget::core::{Padding, Rectangle}; + +/// Methods for creating inner bounds +#[allow(missing_debug_implementations)] +pub enum InnerBounds { + /// Create inner bounds ratio to the outer bounds + Ratio(f32, f32), + /// Create inner bounds by padding the outer bounds + Padding(Padding), + /// Create square inner bounds + Square(f32), + /// Create inner bounds with a custom function + Custom(Box Rectangle>), +} +impl InnerBounds { + /// Gets the inner bounds of the Set type. + pub fn get_bounds(&self, outer_bounds: Rectangle) -> Rectangle { + use InnerBounds::{Custom, Padding, Ratio, Square}; + match self { + Ratio(w, h) => { + let width = w * outer_bounds.width; + let height = h * outer_bounds.height; + let x = outer_bounds.x + (outer_bounds.width - width) * 0.5; + let y = outer_bounds.y + (outer_bounds.height - height) * 0.5; + Rectangle { + x, + y, + width, + height, + } + } + Padding(p) => { + let x = outer_bounds.x + p.left; + let y = outer_bounds.y + p.top; + let width = outer_bounds.width - p.horizontal(); + let height = outer_bounds.width - p.vertical(); + Rectangle { + x, + y, + width, + height, + } + } + Square(l) => { + let width = *l; + let height = *l; + let x = outer_bounds.x + (outer_bounds.width - width) * 0.5; + let y = outer_bounds.y + (outer_bounds.height - height) * 0.5; + Rectangle { + x, + y, + width, + height, + } + } + Custom(f) => f(outer_bounds), + } + } +} diff --git a/src/native/mod.rs b/src/native/mod.rs index 7c496feb..776752f2 100644 --- a/src/native/mod.rs +++ b/src/native/mod.rs @@ -6,6 +6,10 @@ pub use helpers::*; pub mod overlay; +pub mod common; + +pub use common::InnerBounds; + #[cfg(feature = "badge")] pub mod badge; #[cfg(feature = "badge")] @@ -133,3 +137,7 @@ pub mod segmented_button; /// A badge for color highlighting small information. pub type SegmentedButton<'a, Message, Renderer> = segmented_button::SegmentedButton<'a, Message, Renderer>; + +pub mod slide_bar; + +pub use slide_bar::SlideBar; diff --git a/src/native/quad.rs b/src/native/quad.rs index 962a6486..a09eb0e1 100644 --- a/src/native/quad.rs +++ b/src/native/quad.rs @@ -7,66 +7,10 @@ use iced_widget::core::{ mouse::Cursor, renderer, widget::Tree, - Color, Element, Layout, Length, Padding, Rectangle, Widget, + Color, Element, Layout, Length, Rectangle, Widget, }; -/// Methods for creating inner bounds -#[allow(missing_debug_implementations)] -pub enum InnerBounds { - /// Create inner bounds ratio to the outer bounds - Ratio(f32, f32), - /// Create inner bounds by padding the outer bounds - Padding(Padding), - /// Create square inner bounds - Square(f32), - /// Create inner bounds with a custom function - Custom(Box Rectangle>), -} -impl InnerBounds { - /// Gets the inner bounds of the Set type. - fn get_bounds(&self, outer_bounds: Rectangle) -> Rectangle { - use InnerBounds::{Custom, Padding, Ratio, Square}; - match self { - Ratio(w, h) => { - let width = w * outer_bounds.width; - let height = h * outer_bounds.height; - let x = outer_bounds.x + (outer_bounds.width - width) * 0.5; - let y = outer_bounds.y + (outer_bounds.height - height) * 0.5; - Rectangle { - x, - y, - width, - height, - } - } - Padding(p) => { - let x = outer_bounds.x + p.left; - let y = outer_bounds.y + p.top; - let width = outer_bounds.width - p.horizontal(); - let height = outer_bounds.width - p.vertical(); - Rectangle { - x, - y, - width, - height, - } - } - Square(l) => { - let width = *l; - let height = *l; - let x = outer_bounds.x + (outer_bounds.width - width) * 0.5; - let y = outer_bounds.y + (outer_bounds.height - height) * 0.5; - Rectangle { - x, - y, - width, - height, - } - } - Custom(f) => f(outer_bounds), - } - } -} +use crate::native::InnerBounds; /// A dummy widget that draws a quad #[allow(missing_debug_implementations)] diff --git a/src/native/slide_bar.rs b/src/native/slide_bar.rs new file mode 100644 index 00000000..e420e774 --- /dev/null +++ b/src/native/slide_bar.rs @@ -0,0 +1,357 @@ +//! A dummy widget that draws a quad +//! +//! *This API requires the following crate features to be activated: `quad`* + +use iced_widget::core::{ + event, + layout::{Limits, Node}, + mouse::{self, Cursor}, + renderer, touch, + widget::{tree, Tree}, + Clipboard, Color, Element, Event, Layout, Length, Point, Rectangle, Shell, Size, Widget, +}; + +use std::ops::RangeInclusive; + +/// Constant Default height of SliderBar. +pub const DEFAULT_HEIGHT: f32 = 30.0; + +/// A widget that draws a SlideBar +#[allow(missing_debug_implementations)] +pub struct SlideBar<'a, T, Message> +where + Message: Clone, +{ + /// Width of the bar + pub width: Length, + /// Height of the bar + pub height: Option, + /// Color of the bar + pub color: Color, + /// Background color of the bar + pub background: Option, + /// Border radius of the bar + pub border_radius: [f32; 4], + /// Border width of the bar + pub border_width: f32, + /// Border color of the bar + pub border_color: Color, + /// value Range + pub range: RangeInclusive, + /// smallest value within moveable limitations. + step: T, + /// Value of the bar + value: T, + /// Change event of the bar when a value is modified + on_change: Box Message + 'a>, + /// Release event when the mouse is released. + on_release: Option, +} + +impl<'a, T, Message> SlideBar<'a, T, Message> +where + T: Copy + From + std::cmp::PartialOrd, + Message: Clone, +{ + /// Creates a new [`SliderBar`]. + /// + /// It expects: + /// * an inclusive range of possible values + /// * the current value of the [`SliderBar`] + /// * a function that will be called when the [`SliderBar`] is dragged. + /// It receives the new value of the [`SliderBar`] and must produce a + /// `Message`. + pub fn new(range: RangeInclusive, value: T, on_change: F) -> Self + where + F: 'a + Fn(T) -> Message, + { + let value = if value >= *range.start() { + value + } else { + *range.start() + }; + + let value = if value <= *range.end() { + value + } else { + *range.end() + }; + + Self { + width: Length::Fill, + height: None, + color: Color::from([0.5; 3]), + background: None, + border_radius: [5.0; 4], + border_width: 1.0, + border_color: Color::BLACK, + step: T::from(1), + value, + range, + on_change: Box::new(on_change), + on_release: None, + } + } + + /// Sets the release message of the [`Slider`]. + /// This is called when the mouse is released from the slider. + /// + /// Typically, the user's interaction with the slider is finished when this message is produced. + /// This is useful if you need to spawn a long-running task from the slider's result, where + /// the default on_change message could create too many events. + pub fn on_release(mut self, on_release: Message) -> Self { + self.on_release = Some(on_release); + self + } + + /// Sets the width of the [`Slider`]. + pub fn width(mut self, width: impl Into) -> Self { + self.width = width.into(); + self + } + + /// Sets the height of the [`Slider`]. + pub fn height(mut self, height: Option) -> Self { + self.height = height; + self + } + + /// Sets the step size of the [`Slider`]. + pub fn step(mut self, step: impl Into) -> Self { + self.step = step.into(); + self + } +} + +impl<'a, T, Message, Renderer> Widget for SlideBar<'a, T, Message> +where + T: Copy + Into + num_traits::FromPrimitive, + Message: Clone, + Renderer: renderer::Renderer, +{ + fn tag(&self) -> tree::Tag { + tree::Tag::of::() + } + + fn state(&self) -> tree::State { + tree::State::new(State::new()) + } + + fn width(&self) -> Length { + self.width + } + + fn height(&self) -> Length { + self.height.unwrap_or(Length::Fixed(DEFAULT_HEIGHT)) + } + + fn layout(&self, _tree: &mut Tree, _renderer: &Renderer, limits: &Limits) -> Node { + let limits = limits + .width(self.width) + .height(self.height.unwrap_or(Length::Fixed(DEFAULT_HEIGHT))); + + let size = limits.resolve(Size::ZERO); + + Node::new(size) + } + + fn on_event( + &mut self, + tree: &mut Tree, + event: Event, + layout: Layout<'_>, + cursor: mouse::Cursor, + _renderer: &Renderer, + _clipboard: &mut dyn Clipboard, + shell: &mut Shell<'_, Message>, + _viewport: &Rectangle, + ) -> event::Status { + update( + event, + layout, + cursor, + shell, + tree.state.downcast_mut::(), + &mut self.value, + &self.range, + self.step, + self.on_change.as_ref(), + &self.on_release, + ) + } + + fn draw( + &self, + _tree: &Tree, + renderer: &mut Renderer, + _theme: &::Theme, + _style: &renderer::Style, + layout: Layout<'_>, + _cursor: Cursor, + _viewport: &Rectangle, + ) { + draw(renderer, layout, &self); + } +} + +/// Processes an [`Event`] and updates the [`State`] of a [`SliderBar`] +/// accordingly. +pub fn update( + event: Event, + layout: Layout<'_>, + cursor: mouse::Cursor, + shell: &mut Shell<'_, Message>, + state: &mut State, + value: &mut T, + range: &RangeInclusive, + step: T, + on_change: &dyn Fn(T) -> Message, + on_release: &Option, +) -> event::Status +where + T: Copy + Into + num_traits::FromPrimitive, + Message: Clone, +{ + let is_dragging = state.is_dragging; + + let mut change = |cursor_position: Point| { + let bounds = layout.bounds(); + let new_value = if cursor_position.x <= bounds.x { + *range.start() + } else if cursor_position.x >= bounds.x + bounds.width { + *range.end() + } else { + let step = step.into(); + let start = (*range.start()).into(); + let end = (*range.end()).into(); + + let percent = f64::from(cursor_position.x - bounds.x) / f64::from(bounds.width); + + let steps = (percent * (end - start) / step).round(); + let value = steps * step + start; + + if let Some(value) = T::from_f64(value) { + value + } else { + return; + } + }; + + if ((*value).into() - new_value.into()).abs() > f64::EPSILON { + shell.publish((on_change)(new_value)); + + *value = new_value; + } + }; + + match event { + Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) + | Event::Touch(touch::Event::FingerPressed { .. }) => { + if let Some(cursor_position) = cursor.position_over(layout.bounds()) { + change(cursor_position); + state.is_dragging = true; + + return event::Status::Captured; + } + } + Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)) + | Event::Touch(touch::Event::FingerLifted { .. }) + | Event::Touch(touch::Event::FingerLost { .. }) => { + if is_dragging { + if let Some(on_release) = on_release.clone() { + shell.publish(on_release); + } + state.is_dragging = false; + + return event::Status::Captured; + } + } + Event::Mouse(mouse::Event::CursorMoved { .. }) + | Event::Touch(touch::Event::FingerMoved { .. }) => { + if is_dragging { + let _ = cursor.position().map(change); + + return event::Status::Captured; + } + } + _ => {} + } + + event::Status::Ignored +} + +/// Draws a [`SliderBar`]. +pub fn draw(renderer: &mut R, layout: Layout<'_>, slider: &SlideBar) +where + T: Into + Copy, + Message: Clone, + R: renderer::Renderer, +{ + let bounds = layout.bounds(); + let value = slider.value.into() as f32; + let (range_start, range_end) = { + let (start, end) = slider.range.clone().into_inner(); + + (start.into() as f32, end.into() as f32) + }; + + let active_progress_bounds = if range_start >= range_end { + Rectangle { + width: 0.0, + ..bounds + } + } else { + Rectangle { + width: bounds.width * (value - range_start) / (range_end - range_start), + ..bounds + } + }; + + let background = slider.background.unwrap_or(Color::from([1.0; 3])); + + renderer.fill_quad( + renderer::Quad { + bounds: layout.bounds(), + border_radius: slider.border_radius.into(), + border_width: slider.border_width, + border_color: slider.border_color, + }, + background, + ); + + if active_progress_bounds.width > 0.0 { + renderer.fill_quad( + renderer::Quad { + bounds: active_progress_bounds, + border_radius: slider.border_radius.into(), + border_width: 0.0, + border_color: Color::TRANSPARENT, + }, + slider.color, + ); + } +} + +impl<'a, T, Message, Renderer> From> for Element<'a, Message, Renderer> +where + T: 'a + Copy + Into + num_traits::FromPrimitive, + Renderer: 'a + renderer::Renderer, + Message: 'a + Clone, +{ + fn from(value: SlideBar<'a, T, Message>) -> Self { + Self::new(value) + } +} + +/// The local state of a [`SliderBar`]. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +pub struct State { + is_dragging: bool, +} + +impl State { + /// Creates a new [`State`]. + pub fn new() -> State { + State::default() + } +} From 9ea1b245041178ecf4db8e08629c7f1e985be8e0 Mon Sep 17 00:00:00 2001 From: genusistimelord Date: Mon, 18 Dec 2023 13:36:46 -0500 Subject: [PATCH 22/22] updated to match iced Revision dd249a1d11c68b8fee1828d58bae158946ee2ebd --- Cargo.toml | 4 ++-- examples/multiple_modals/src/main.rs | 7 +++++-- examples/number_input/src/main.rs | 5 ++++- src/native/card.rs | 1 + src/native/cupertino/cupertino_spinner.rs | 2 +- src/native/cupertino/cupertino_switch.rs | 2 +- src/native/number_input.rs | 5 ++++- src/native/overlay/color_picker.rs | 11 ++++++++++- src/native/overlay/context_menu.rs | 12 +++++++++--- src/native/overlay/date_picker.rs | 15 +++++++++++++-- src/native/overlay/floating_element.rs | 10 ++++++++-- src/native/overlay/modal.rs | 9 ++++++++- src/native/overlay/time_picker.rs | 14 +++++++++++++- src/native/selection_list/list.rs | 1 + src/native/spinner.rs | 2 +- src/native/tab_bar.rs | 5 +++++ 16 files changed, 86 insertions(+), 19 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 22029d43..30ea7707 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,7 +72,7 @@ itertools = { version = "0.11.0", optional = true } [dependencies.iced_widget] git = "https://github.com/iced-rs/iced.git" -rev = "b474a2b7a763dcde6a377cb409001a7b5285ee8d" +#rev = "b474a2b7a763dcde6a377cb409001a7b5285ee8d" #version = "0.1.1" #[dependencies.iced_renderer] @@ -117,7 +117,7 @@ members = [ [workspace.dependencies.iced] git = "https://github.com/iced-rs/iced.git" -rev = "b474a2b7a763dcde6a377cb409001a7b5285ee8d" +#rev = "b474a2b7a763dcde6a377cb409001a7b5285ee8d" #version = "0.10.0" features = ["advanced", "lazy", "tokio"] diff --git a/examples/multiple_modals/src/main.rs b/examples/multiple_modals/src/main.rs index d5d143a6..d8e930fb 100644 --- a/examples/multiple_modals/src/main.rs +++ b/examples/multiple_modals/src/main.rs @@ -6,7 +6,10 @@ use iced_aw::{card, modal, CardStyles}; fn main() -> iced::Result { MultipleModalsExample::run(Settings { window: window::Settings { - size: (500, 150), + size: iced::Size { + width: 500.0, + height: 150.0, + }, position: window::Position::Centered, ..Default::default() }, @@ -114,7 +117,7 @@ impl Application for MultipleModalsExample { self.state = State::Button1; Command::none() } - Message::ButtonQuitPressed => window::close(), + Message::ButtonQuitPressed => window::close(window::Id::MAIN), Message::CloseOverlay => { match (&self.state, &self.button_pressed) { (State::Button1, Some(ButtonPressed::Correct)) => self.state = State::Button2, diff --git a/examples/number_input/src/main.rs b/examples/number_input/src/main.rs index 06aa9325..d445aa2a 100644 --- a/examples/number_input/src/main.rs +++ b/examples/number_input/src/main.rs @@ -28,7 +28,10 @@ fn main() -> iced::Result { NumberInputDemo::run(Settings { default_text_size: iced::Pixels(12.0), window: window::Settings { - size: (250, 200), + size: iced::Size { + width: 250.0, + height: 200.0, + }, ..Default::default() }, ..Settings::default() diff --git a/src/native/card.rs b/src/native/card.rs index 3a6df0b1..9a0a3ea5 100644 --- a/src/native/card.rs +++ b/src/native/card.rs @@ -792,6 +792,7 @@ fn draw_head( }, Point::new(close_bounds.center_x(), close_bounds.center_y()), style_sheet.close_color, + close_bounds, ); } } diff --git a/src/native/cupertino/cupertino_spinner.rs b/src/native/cupertino/cupertino_spinner.rs index 2a42bca2..408e1788 100644 --- a/src/native/cupertino/cupertino_spinner.rs +++ b/src/native/cupertino/cupertino_spinner.rs @@ -192,7 +192,7 @@ impl Widget> for CupertinoSpinner { ) -> event::Status { let state: &mut SpinnerState = state.state.downcast_mut::(); - if let Event::Window(window::Event::RedrawRequested(_now)) = &event { + if let Event::Window(_id, window::Event::RedrawRequested(_now)) = &event { // if is_visible(&bounds) { state.now = time::OffsetDateTime::now_local() .unwrap_or_else(|_| time::OffsetDateTime::now_utc()); diff --git a/src/native/cupertino/cupertino_switch.rs b/src/native/cupertino/cupertino_switch.rs index be3b624b..94b2043a 100644 --- a/src/native/cupertino/cupertino_switch.rs +++ b/src/native/cupertino/cupertino_switch.rs @@ -340,7 +340,7 @@ where let state: &mut SwitchState = state.state.downcast_mut::(); match event { - Event::Window(window::Event::RedrawRequested(_now)) => { + Event::Window(_id, window::Event::RedrawRequested(_now)) => { if state.toggle_staged { state.animation_frame += 1; diff --git a/src/native/number_input.rs b/src/native/number_input.rs index b2440dbf..f8f1074b 100644 --- a/src/native/number_input.rs +++ b/src/native/number_input.rs @@ -663,7 +663,7 @@ where _style: &renderer::Style, layout: Layout<'_>, cursor: Cursor, - _viewport: &Rectangle, + viewport: &Rectangle, ) { let mut children = layout.children(); let content_layout = children.next().expect("fail to get content layout"); @@ -686,6 +686,7 @@ where content_layout, cursor, None, + viewport, ); let is_decrease_disabled = self.value <= self.bounds.0 || self.bounds.0 == self.bounds.1; let is_increase_disabled = self.value >= self.bounds.1 || self.bounds.0 == self.bounds.1; @@ -738,6 +739,7 @@ where }, Point::new(dec_bounds.center_x(), dec_bounds.center_y()), decrease_btn_style.icon_color, + dec_bounds, ); // increase button section @@ -766,6 +768,7 @@ where }, Point::new(inc_bounds.center_x(), inc_bounds.center_y()), increase_btn_style.icon_color, + inc_bounds, ); } } diff --git a/src/native/overlay/color_picker.rs b/src/native/overlay/color_picker.rs index c096deac..7d0d3ad9 100644 --- a/src/native/overlay/color_picker.rs +++ b/src/native/overlay/color_picker.rs @@ -544,7 +544,13 @@ where Message: 'static + Clone, Theme: 'a + StyleSheet + button::StyleSheet + widget::text::StyleSheet, { - fn layout(&mut self, renderer: &Renderer, bounds: Size, position: Point) -> Node { + fn layout( + &mut self, + renderer: &Renderer, + bounds: Size, + position: Point, + _translation: Vector, + ) -> Node { let (max_width, max_height) = if bounds.width > bounds.height { (600.0, 300.0) } else { @@ -1417,6 +1423,7 @@ fn rgba_color( label_layout.bounds().center_y(), ), style.text_color, + label_layout.bounds(), ); let bounds = bar_layout.bounds(); @@ -1488,6 +1495,7 @@ fn rgba_color( value_layout.bounds().center_y(), ), style.text_color, + value_layout.bounds(), ); if focus == target { @@ -1625,6 +1633,7 @@ fn hex_text( } .into() }, + layout.bounds(), ); } diff --git a/src/native/overlay/context_menu.rs b/src/native/overlay/context_menu.rs index 0c2caad7..dbfbe630 100644 --- a/src/native/overlay/context_menu.rs +++ b/src/native/overlay/context_menu.rs @@ -12,7 +12,7 @@ use iced_widget::core::{ mouse::{self, Cursor}, overlay, renderer, touch, widget::tree::Tree, - window, Clipboard, Color, Element, Event, Layout, Point, Rectangle, Shell, Size, + window, Clipboard, Color, Element, Event, Layout, Point, Rectangle, Shell, Size, Vector, }; /// The overlay of the [`ContextMenu`](crate::native::ContextMenu). @@ -70,7 +70,13 @@ where Renderer: 'a + core::Renderer, Renderer::Theme: StyleSheet, { - fn layout(&mut self, renderer: &Renderer, bounds: Size, position: Point) -> Node { + fn layout( + &mut self, + renderer: &Renderer, + bounds: Size, + position: Point, + _translation: Vector, + ) -> Node { let limits = Limits::new(Size::ZERO, bounds); let max_size = limits.max(); @@ -177,7 +183,7 @@ where Status::Captured } - Event::Window(window::Event::Resized { .. }) => { + Event::Window(_id, window::Event::Resized { .. }) => { self.state.show = false; forward_event_to_children = false; Status::Captured diff --git a/src/native/overlay/date_picker.rs b/src/native/overlay/date_picker.rs index 3b7787f1..0c42d28b 100644 --- a/src/native/overlay/date_picker.rs +++ b/src/native/overlay/date_picker.rs @@ -29,7 +29,7 @@ use iced_widget::{ touch, widget::tree::Tree, Alignment, Clipboard, Color, Element, Event, Layout, Length, Overlay, Padding, Point, - Rectangle, Renderer as _, Shell, Size, Widget, + Rectangle, Renderer as _, Shell, Size, Vector, Widget, }, renderer::Renderer, text, Button, Column, Container, Row, Text, @@ -368,7 +368,13 @@ where Theme: 'a + StyleSheet + button::StyleSheet + text::StyleSheet + container::StyleSheet, { #[allow(clippy::too_many_lines)] - fn layout(&mut self, renderer: &Renderer, bounds: Size, position: Point) -> Node { + fn layout( + &mut self, + renderer: &Renderer, + bounds: Size, + position: Point, + _translation: Vector, + ) -> Node { let limits = Limits::new(Size::ZERO, bounds) .pad(Padding::from(PADDING)) .width(Length::Fill) @@ -1133,6 +1139,7 @@ fn month_year( .get(&style_state) .expect("Style Sheet not found.") .text_color, + left_bounds, ); // Text @@ -1152,6 +1159,7 @@ fn month_year( .get(&style_state) .expect("Style Sheet not found.") .text_color, + center_bounds, ); // Right caret @@ -1173,6 +1181,7 @@ fn month_year( .get(&style_state) .expect("Style Sheet not found.") .text_color, + right_bounds, ); }; @@ -1233,6 +1242,7 @@ fn day_labels( .get(&StyleState::Active) .expect("Style Sheet not found.") .text_color, + bounds, ); } } @@ -1324,6 +1334,7 @@ fn day_table( .expect("Style Sheet not found.") .text_attenuated_color }, + bounds, ); } } diff --git a/src/native/overlay/floating_element.rs b/src/native/overlay/floating_element.rs index fc7c6baf..14a35869 100644 --- a/src/native/overlay/floating_element.rs +++ b/src/native/overlay/floating_element.rs @@ -9,7 +9,7 @@ use iced_widget::core::{ mouse::{self, Cursor}, overlay, renderer, widget::Tree, - Clipboard, Element, Event, Layout, Length, Point, Rectangle, Shell, Size, + Clipboard, Element, Event, Layout, Length, Point, Rectangle, Shell, Size, Vector, }; /// The internal overlay of a [`FloatingElement`](crate::FloatingElement) for @@ -56,7 +56,13 @@ impl<'a, 'b, Message, Renderer> core::Overlay where Renderer: core::Renderer, { - fn layout(&mut self, renderer: &Renderer, _bounds: Size, position: Point) -> layout::Node { + fn layout( + &mut self, + renderer: &Renderer, + _bounds: Size, + position: Point, + _translation: Vector, + ) -> layout::Node { // Constrain overlay to fit inside the underlay's bounds let limits = layout::Limits::new(Size::ZERO, self.underlay_bounds.size()) .width(Length::Fill) diff --git a/src/native/overlay/modal.rs b/src/native/overlay/modal.rs index 92d5e635..15d6d021 100644 --- a/src/native/overlay/modal.rs +++ b/src/native/overlay/modal.rs @@ -7,6 +7,7 @@ use iced_widget::core::{ renderer, touch, widget::Tree, Alignment, Clipboard, Color, Element, Event, Layout, Overlay, Point, Rectangle, Shell, Size, + Vector, }; use crate::style::modal::StyleSheet; @@ -68,7 +69,13 @@ where Renderer: core::Renderer, Renderer::Theme: StyleSheet, { - fn layout(&mut self, renderer: &Renderer, bounds: Size, _position: Point) -> layout::Node { + fn layout( + &mut self, + renderer: &Renderer, + bounds: Size, + _position: Point, + _translation: Vector, + ) -> layout::Node { let limits = layout::Limits::new(Size::ZERO, bounds); let mut content = self .content diff --git a/src/native/overlay/time_picker.rs b/src/native/overlay/time_picker.rs index 3ed42e17..d7873060 100644 --- a/src/native/overlay/time_picker.rs +++ b/src/native/overlay/time_picker.rs @@ -503,7 +503,13 @@ where Message: 'static + Clone, Theme: 'a + StyleSheet + button::StyleSheet + text::StyleSheet + container::StyleSheet, { - fn layout(&mut self, renderer: &Renderer, bounds: Size, position: Point) -> Node { + fn layout( + &mut self, + renderer: &Renderer, + bounds: Size, + position: Point, + _translation: Vector, + ) -> Node { let limits = Limits::new(Size::ZERO, bounds) .pad(Padding::from(PADDING)) .width(Length::Fill) @@ -1454,6 +1460,7 @@ fn draw_digital_clock( .get(&StyleState::Active) .expect("Style Sheet not found.") .text_color, + up_bounds, ); // Text @@ -1473,6 +1480,7 @@ fn draw_digital_clock( .get(&StyleState::Active) .expect("Style Sheet not found.") .text_color, + center_bounds, ); // Down caret @@ -1494,6 +1502,7 @@ fn draw_digital_clock( .get(&StyleState::Active) .expect("Style Sheet not found.") .text_color, + down_bounds, ); }; @@ -1544,6 +1553,7 @@ fn draw_digital_clock( hour_minute_separator.bounds().center_y(), ), style[&StyleState::Active].text_color, + hour_minute_separator.bounds(), ); // Draw minutes @@ -1581,6 +1591,7 @@ fn draw_digital_clock( minute_second_separator.bounds().center_y(), ), style[&StyleState::Active].text_color, + minute_second_separator.bounds(), ); // Draw seconds @@ -1617,6 +1628,7 @@ fn draw_digital_clock( }, Point::new(period.bounds().center_x(), period.bounds().center_y()), style[&StyleState::Active].text_color, + period.bounds(), ); } } diff --git a/src/native/selection_list/list.rs b/src/native/selection_list/list.rs index d50d86f9..fd70c671 100644 --- a/src/native/selection_list/list.rs +++ b/src/native/selection_list/list.rs @@ -278,6 +278,7 @@ where }, Point::new(bounds.x, bounds.center_y()), text_color, + bounds, ); } } diff --git a/src/native/spinner.rs b/src/native/spinner.rs index 3ea3c21f..18cbccb8 100644 --- a/src/native/spinner.rs +++ b/src/native/spinner.rs @@ -195,7 +195,7 @@ where let bounds = layout.bounds(); - if let Event::Window(window::Event::RedrawRequested(now)) = event { + if let Event::Window(_id, window::Event::RedrawRequested(now)) = event { if is_visible(&bounds) { let state = state.state.downcast_mut::(); let duration = (now - state.last_update).as_secs_f32(); diff --git a/src/native/tab_bar.rs b/src/native/tab_bar.rs index 000cf004..e850a8bd 100644 --- a/src/native/tab_bar.rs +++ b/src/native/tab_bar.rs @@ -709,6 +709,7 @@ fn draw_tab( }, Point::new(icon_bounds.center_x(), icon_bounds.center_y()), style.icon_color, + icon_bounds, ); } @@ -728,6 +729,7 @@ fn draw_tab( }, Point::new(text_bounds.center_x(), text_bounds.center_y()), style.text_color, + text_bounds, ); } TabLabel::IconText(icon, text) => { @@ -774,6 +776,7 @@ fn draw_tab( }, Point::new(icon_bounds.center_x(), icon_bounds.center_y()), style.icon_color, + icon_bounds, ); renderer.fill_text( @@ -789,6 +792,7 @@ fn draw_tab( }, Point::new(text_bounds.center_x(), text_bounds.center_y()), style.text_color, + text_bounds, ); } }; @@ -810,6 +814,7 @@ fn draw_tab( }, Point::new(cross_bounds.center_x(), cross_bounds.center_y()), style.text_color, + cross_bounds, ); if is_mouse_over_cross {