diff options
29 files changed, 298 insertions, 252 deletions
diff --git a/core/Cargo.toml b/core/Cargo.toml index 43865e4d..0d6310d3 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "iced_core" -version = "0.8.0" +version = "0.8.1" authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"] edition = "2021" description = "The essential concepts of Iced" diff --git a/core/src/alignment.rs b/core/src/alignment.rs index 73f41d3f..51b7fca9 100644 --- a/core/src/alignment.rs +++ b/core/src/alignment.rs @@ -11,9 +11,6 @@ pub enum Alignment { /// Align at the end of the axis. End, - - /// Fill the entire axis. - Fill, } impl From<Horizontal> for Alignment { diff --git a/core/src/font.rs b/core/src/font.rs index 3f9ad2b5..d8c34e5a 100644 --- a/core/src/font.rs +++ b/core/src/font.rs @@ -1,10 +1,11 @@ /// A font. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Default)] pub enum Font { /// The default font. /// /// This is normally a font configured in a renderer or loaded from the /// system. + #[default] Default, /// An external font. @@ -16,9 +17,3 @@ pub enum Font { bytes: &'static [u8], }, } - -impl Default for Font { - fn default() -> Font { - Font::Default - } -} diff --git a/core/src/mouse/interaction.rs b/core/src/mouse/interaction.rs index 664147a7..57da93fe 100644 --- a/core/src/mouse/interaction.rs +++ b/core/src/mouse/interaction.rs @@ -1,7 +1,8 @@ /// The interaction of a mouse cursor. -#[derive(Debug, Eq, PartialEq, Clone, Copy, PartialOrd, Ord)] +#[derive(Debug, Eq, PartialEq, Clone, Copy, PartialOrd, Ord, Default)] #[allow(missing_docs)] pub enum Interaction { + #[default] Idle, Pointer, Grab, @@ -12,9 +13,3 @@ pub enum Interaction { ResizingHorizontally, ResizingVertically, } - -impl Default for Interaction { - fn default() -> Interaction { - Interaction::Idle - } -} diff --git a/core/src/padding.rs b/core/src/padding.rs index 752b2b86..0b1bba13 100644 --- a/core/src/padding.rs +++ b/core/src/padding.rs @@ -77,12 +77,14 @@ impl Padding { /// Fits the [`Padding`] between the provided `inner` and `outer` [`Size`]. pub fn fit(self, inner: Size, outer: Size) -> Self { let available = (outer - inner).max(Size::ZERO); + let new_top = self.top.min(available.height); + let new_left = self.left.min(available.width); Padding { - top: self.top.min(available.height / 2.0), - right: self.right.min(available.width / 2.0), - bottom: self.bottom.min(available.height / 2.0), - left: self.left.min(available.width / 2.0), + top: new_top, + bottom: self.bottom.min(available.height - new_top), + left: new_left, + right: self.right.min(available.width - new_left), } } } diff --git a/examples/checkbox/README.md b/examples/checkbox/README.md index b7f85684..76e6764c 100644 --- a/examples/checkbox/README.md +++ b/examples/checkbox/README.md @@ -6,7 +6,7 @@ The __[`main`]__ file contains all the code of the example. You can run it with `cargo run`: ``` -cargo run --package pick_list +cargo run --package checkbox ``` [`main`]: src/main.rs diff --git a/examples/component/src/main.rs b/examples/component/src/main.rs index c407bb06..bbf549e7 100644 --- a/examples/component/src/main.rs +++ b/examples/component/src/main.rs @@ -127,7 +127,8 @@ mod numeric_input { .horizontal_alignment(alignment::Horizontal::Center) .vertical_alignment(alignment::Vertical::Center), ) - .width(50) + .width(40) + .height(40) .on_press(on_press) }; @@ -145,7 +146,7 @@ mod numeric_input { .padding(10), button("+", Event::IncrementPressed), ] - .align_items(Alignment::Fill) + .align_items(Alignment::Center) .spacing(10) .into() } diff --git a/examples/pick_list/src/main.rs b/examples/pick_list/src/main.rs index 62a4ef88..21200621 100644 --- a/examples/pick_list/src/main.rs +++ b/examples/pick_list/src/main.rs @@ -61,8 +61,9 @@ impl Sandbox for Example { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] pub enum Language { + #[default] Rust, Elm, Ruby, @@ -84,12 +85,6 @@ impl Language { ]; } -impl Default for Language { - fn default() -> Language { - Language::Rust - } -} - impl std::fmt::Display for Language { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( diff --git a/examples/scrollable/src/main.rs b/examples/scrollable/src/main.rs index f8c5aa74..2e99b1ac 100644 --- a/examples/scrollable/src/main.rs +++ b/examples/scrollable/src/main.rs @@ -254,7 +254,6 @@ impl Application for ScrollableDemo { scroll_to_beginning_button(), vertical_space(40), ] - .align_items(Alignment::Fill) .spacing(40), horizontal_space(1200), text("Horizontal - End!"), diff --git a/examples/todos/src/main.rs b/examples/todos/src/main.rs index 6408f09c..6361667e 100644 --- a/examples/todos/src/main.rs +++ b/examples/todos/src/main.rs @@ -1,6 +1,6 @@ use iced::alignment::{self, Alignment}; use iced::event::{self, Event}; -use iced::keyboard; +use iced::keyboard::{self, KeyCode, Modifiers}; use iced::subscription; use iced::theme::{self, Theme}; use iced::widget::{ @@ -50,6 +50,7 @@ enum Message { FilterChanged(Filter), TaskMessage(usize, TaskMessage), TabPressed { shift: bool }, + ToggleFullscreen(window::Mode), } impl Application for Todos { @@ -156,6 +157,9 @@ impl Application for Todos { widget::focus_next() } } + Message::ToggleFullscreen(mode) => { + window::change_mode(mode) + } _ => Command::none(), }; @@ -266,6 +270,21 @@ impl Application for Todos { ) => Some(Message::TabPressed { shift: modifiers.shift(), }), + ( + Event::Keyboard(keyboard::Event::KeyPressed { + key_code, + modifiers: Modifiers::SHIFT, + }), + event::Status::Ignored, + ) => match key_code { + KeyCode::Up => { + Some(Message::ToggleFullscreen(window::Mode::Fullscreen)) + } + KeyCode::Down => { + Some(Message::ToggleFullscreen(window::Mode::Windowed)) + } + _ => None, + }, _ => None, }) } @@ -416,19 +435,16 @@ fn view_controls(tasks: &[Task], current_filter: Filter) -> Element<Message> { .into() } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive( + Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize, +)] pub enum Filter { + #[default] All, Active, Completed, } -impl Default for Filter { - fn default() -> Self { - Filter::All - } -} - impl Filter { fn matches(&self, task: &Task) -> bool { match self { diff --git a/examples/websocket/src/main.rs b/examples/websocket/src/main.rs index ccd9c815..e617b8ce 100644 --- a/examples/websocket/src/main.rs +++ b/examples/websocket/src/main.rs @@ -146,7 +146,9 @@ impl Application for WebSocket { } } - row![input, button].spacing(10).align_items(Alignment::Fill) + row![input, button] + .spacing(10) + .align_items(Alignment::Center) }; column![message_log, new_message_input] diff --git a/glow/src/settings.rs b/glow/src/settings.rs index 8ccffbad..6aaa0d55 100644 --- a/glow/src/settings.rs +++ b/glow/src/settings.rs @@ -43,7 +43,7 @@ impl std::fmt::Debug for Settings { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("Settings") // Instead of printing the font bytes, we simply show a `bool` indicating if using a default font or not. - .field("default_font", &self.default_font.is_none()) + .field("default_font", &self.default_font.is_some()) .field("default_text_size", &self.default_text_size) .field("text_multithreading", &self.text_multithreading) .field("antialiasing", &self.antialiasing) diff --git a/glutin/src/application.rs b/glutin/src/application.rs index b7bf21c3..5921bdd0 100644 --- a/glutin/src/application.rs +++ b/glutin/src/application.rs @@ -71,7 +71,7 @@ where settings.id, ); - log::info!("Window builder: {:#?}", builder); + log::debug!("Window builder: {:#?}", builder); let opengl_builder = ContextBuilder::new() .with_vsync(true) diff --git a/graphics/Cargo.toml b/graphics/Cargo.toml index 13ab61d8..a37c99a2 100644 --- a/graphics/Cargo.toml +++ b/graphics/Cargo.toml @@ -11,7 +11,7 @@ keywords = ["gui", "ui", "graphics", "interface", "widgets"] categories = ["gui"] [features] -svg = ["resvg", "usvg", "tiny-skia"] +svg = ["resvg"] image = ["png", "jpeg", "jpeg_rayon", "gif", "webp", "bmp"] png = ["image_rs/png"] jpeg = ["image_rs/jpeg"] @@ -71,15 +71,7 @@ default-features = false optional = true [dependencies.resvg] -version = "0.18" -optional = true - -[dependencies.usvg] -version = "0.18" -optional = true - -[dependencies.tiny-skia] -version = "0.6" +version = "0.29" optional = true [dependencies.kamadak-exif] diff --git a/graphics/src/image/vector.rs b/graphics/src/image/vector.rs index 82d77aff..c950ccd6 100644 --- a/graphics/src/image/vector.rs +++ b/graphics/src/image/vector.rs @@ -5,6 +5,8 @@ use crate::Color; use iced_native::svg; use iced_native::Size; +use resvg::tiny_skia; +use resvg::usvg; use std::collections::{HashMap, HashSet}; use std::fs; @@ -21,7 +23,7 @@ impl Svg { pub fn viewport_dimensions(&self) -> Size<u32> { match self { Svg::Loaded(tree) => { - let size = tree.svg_node().size; + let size = tree.size; Size::new(size.width() as u32, size.height() as u32) } @@ -51,20 +53,14 @@ impl<T: Storage> Cache<T> { let svg = match handle.data() { svg::Data::Path(path) => { let tree = fs::read_to_string(path).ok().and_then(|contents| { - usvg::Tree::from_str( - &contents, - &usvg::Options::default().to_ref(), - ) - .ok() + usvg::Tree::from_str(&contents, &usvg::Options::default()) + .ok() }); tree.map(Svg::Loaded).unwrap_or(Svg::NotFound) } svg::Data::Bytes(bytes) => { - match usvg::Tree::from_data( - bytes, - &usvg::Options::default().to_ref(), - ) { + match usvg::Tree::from_data(bytes, &usvg::Options::default()) { Ok(tree) => Svg::Loaded(tree), Err(_) => Svg::NotFound, } @@ -125,6 +121,7 @@ impl<T: Storage> Cache<T> { } else { usvg::FitTo::Height(height) }, + tiny_skia::Transform::default(), img.as_mut(), )?; diff --git a/graphics/src/primitive.rs b/graphics/src/primitive.rs index 5a163a2f..cef422a2 100644 --- a/graphics/src/primitive.rs +++ b/graphics/src/primitive.rs @@ -9,9 +9,10 @@ use crate::triangle; use std::sync::Arc; /// A rendering primitive. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Default)] pub enum Primitive { /// An empty primitive + #[default] None, /// A group of primitives Group { @@ -117,9 +118,3 @@ pub enum Primitive { cache: Arc<Primitive>, }, } - -impl Default for Primitive { - fn default() -> Primitive { - Primitive::None - } -} diff --git a/graphics/src/widget/canvas/cache.rs b/graphics/src/widget/canvas/cache.rs index 52217bbb..678b0f92 100644 --- a/graphics/src/widget/canvas/cache.rs +++ b/graphics/src/widget/canvas/cache.rs @@ -4,7 +4,9 @@ use crate::Primitive; use iced_native::Size; use std::{cell::RefCell, sync::Arc}; +#[derive(Default)] enum State { + #[default] Empty, Filled { bounds: Size, @@ -12,11 +14,6 @@ enum State { }, } -impl Default for State { - fn default() -> Self { - State::Empty - } -} /// A simple cache that stores generated [`Geometry`] to avoid recomputation. /// /// A [`Cache`] will not redraw its geometry unless the dimensions of its layer diff --git a/graphics/src/widget/canvas/stroke.rs b/graphics/src/widget/canvas/stroke.rs index 4c19251d..49f5701c 100644 --- a/graphics/src/widget/canvas/stroke.rs +++ b/graphics/src/widget/canvas/stroke.rs @@ -59,9 +59,10 @@ impl<'a> Default for Stroke<'a> { } /// The shape used at the end of open subpaths when they are stroked. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Default)] pub enum LineCap { /// The stroke for each sub-path does not extend beyond its two endpoints. + #[default] Butt, /// At the end of each sub-path, the shape representing the stroke will be /// extended by a square. @@ -71,12 +72,6 @@ pub enum LineCap { Round, } -impl Default for LineCap { - fn default() -> LineCap { - LineCap::Butt - } -} - impl From<LineCap> for lyon::tessellation::LineCap { fn from(line_cap: LineCap) -> lyon::tessellation::LineCap { match line_cap { @@ -89,9 +84,10 @@ impl From<LineCap> for lyon::tessellation::LineCap { /// The shape used at the corners of paths or basic shapes when they are /// stroked. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Default)] pub enum LineJoin { /// A sharp corner. + #[default] Miter, /// A round corner. Round, @@ -99,12 +95,6 @@ pub enum LineJoin { Bevel, } -impl Default for LineJoin { - fn default() -> LineJoin { - LineJoin::Miter - } -} - impl From<LineJoin> for lyon::tessellation::LineJoin { fn from(line_join: LineJoin) -> lyon::tessellation::LineJoin { match line_join { diff --git a/lazy/src/component.rs b/lazy/src/component.rs index b23da9f7..f6c331b9 100644 --- a/lazy/src/component.rs +++ b/lazy/src/component.rs @@ -13,6 +13,7 @@ use iced_native::{ use ouroboros::self_referencing; use std::cell::RefCell; use std::marker::PhantomData; +use std::rc::Rc; /// A reusable, custom widget that uses The Elm Architecture. /// @@ -58,6 +59,8 @@ pub trait Component<Message, Renderer> { } } +struct Tag<T>(T); + /// Turns an implementor of [`Component`] into an [`Element`] that can be /// embedded in any application. pub fn view<'a, C, Message, Renderer>( @@ -79,11 +82,13 @@ where } .build(), )), + tree: RefCell::new(Rc::new(RefCell::new(None))), }) } struct Instance<'a, Message, Renderer, Event, S> { state: RefCell<Option<State<'a, Message, Renderer, Event, S>>>, + tree: RefCell<Rc<RefCell<Option<Tree>>>>, } #[self_referencing] @@ -100,40 +105,91 @@ struct State<'a, Message: 'a, Renderer: 'a, Event: 'a, S: 'a> { impl<'a, Message, Renderer, Event, S> Instance<'a, Message, Renderer, Event, S> where - S: Default, + S: Default + 'static, + Renderer: iced_native::Renderer, { - fn rebuild_element(&self, state: &S) { - let heads = self.state.borrow_mut().take().unwrap().into_heads(); + fn diff_self(&self) { + self.with_element(|element| { + self.tree + .borrow_mut() + .borrow_mut() + .as_mut() + .unwrap() + .diff_children(std::slice::from_ref(&element)); + }); + } - *self.state.borrow_mut() = Some( - StateBuilder { - component: heads.component, - message: PhantomData, - state: PhantomData, - element_builder: |component| Some(component.view(state)), - } - .build(), - ); + fn rebuild_element_if_necessary(&self) { + let inner = self.state.borrow_mut().take().unwrap(); + if inner.borrow_element().is_none() { + let heads = inner.into_heads(); + + *self.state.borrow_mut() = Some( + StateBuilder { + component: heads.component, + message: PhantomData, + state: PhantomData, + element_builder: |component| { + Some( + component.view( + self.tree + .borrow() + .borrow() + .as_ref() + .unwrap() + .state + .downcast_ref::<S>(), + ), + ) + }, + } + .build(), + ); + self.diff_self(); + } else { + *self.state.borrow_mut() = Some(inner); + } } fn rebuild_element_with_operation( &self, - state: &mut S, operation: &mut dyn widget::Operation<Message>, ) { let heads = self.state.borrow_mut().take().unwrap().into_heads(); - heads.component.operate(state, operation); + heads.component.operate( + self.tree + .borrow_mut() + .borrow_mut() + .as_mut() + .unwrap() + .state + .downcast_mut(), + operation, + ); *self.state.borrow_mut() = Some( StateBuilder { component: heads.component, message: PhantomData, state: PhantomData, - element_builder: |component| Some(component.view(state)), + element_builder: |component| { + Some( + component.view( + self.tree + .borrow() + .borrow() + .as_ref() + .unwrap() + .state + .downcast_ref(), + ), + ) + }, } .build(), ); + self.diff_self(); } fn with_element<T>( @@ -147,6 +203,7 @@ where &self, f: impl FnOnce(&mut Element<'_, Event, Renderer>) -> T, ) -> T { + self.rebuild_element_if_necessary(); self.state .borrow_mut() .as_mut() @@ -162,24 +219,27 @@ where Renderer: iced_native::Renderer, { fn tag(&self) -> tree::Tag { - struct Tag<T>(T); tree::Tag::of::<Tag<S>>() } fn state(&self) -> tree::State { - tree::State::new(S::default()) + let state = Rc::new(RefCell::new(Some(Tree { + tag: tree::Tag::of::<Tag<S>>(), + state: tree::State::new(S::default()), + children: vec![Tree::empty()], + }))); + *self.tree.borrow_mut() = state.clone(); + tree::State::new(state) } fn children(&self) -> Vec<Tree> { - self.rebuild_element(&S::default()); - self.with_element(|element| vec![Tree::new(element)]) + vec![] } fn diff(&self, tree: &mut Tree) { - self.rebuild_element(tree.state.downcast_ref()); - self.with_element(|element| { - tree.diff_children(std::slice::from_ref(&element)) - }) + let tree = tree.state.downcast_ref::<Rc<RefCell<Option<Tree>>>>(); + *self.tree.borrow_mut() = tree.clone(); + self.rebuild_element_if_necessary(); } fn width(&self) -> Length { @@ -213,9 +273,10 @@ where let mut local_messages = Vec::new(); let mut local_shell = Shell::new(&mut local_messages); + let t = tree.state.downcast_mut::<Rc<RefCell<Option<Tree>>>>(); let event_status = self.with_element_mut(|element| { element.as_widget_mut().on_event( - &mut tree.children[0], + &mut t.borrow_mut().as_mut().unwrap().children[0], event, layout, cursor_position, @@ -235,9 +296,10 @@ where let mut heads = self.state.take().unwrap().into_heads(); for message in local_messages.into_iter().filter_map(|message| { - heads - .component - .update(tree.state.downcast_mut::<S>(), message) + heads.component.update( + t.borrow_mut().as_mut().unwrap().state.downcast_mut(), + message, + ) }) { shell.publish(message); } @@ -247,17 +309,11 @@ where component: heads.component, message: PhantomData, state: PhantomData, - element_builder: |state| { - Some(state.view(tree.state.downcast_ref::<S>())) - }, + element_builder: |_| None, } .build(), )); - self.with_element(|element| { - tree.diff_children(std::slice::from_ref(&element)) - }); - shell.invalidate_layout(); } @@ -271,10 +327,7 @@ where renderer: &Renderer, operation: &mut dyn widget::Operation<Message>, ) { - self.rebuild_element_with_operation( - tree.state.downcast_mut(), - operation, - ); + self.rebuild_element_with_operation(operation); struct MapOperation<'a, B> { operation: &'a mut dyn widget::Operation<B>, @@ -310,11 +363,10 @@ where } } + let tree = tree.state.downcast_mut::<Rc<RefCell<Option<Tree>>>>(); self.with_element(|element| { - tree.diff_children(std::slice::from_ref(&element)); - element.as_widget().operate( - &mut tree.children[0], + &mut tree.borrow_mut().as_mut().unwrap().children[0], layout, renderer, &mut MapOperation { operation }, @@ -332,9 +384,10 @@ where cursor_position: Point, viewport: &Rectangle, ) { + let tree = tree.state.downcast_ref::<Rc<RefCell<Option<Tree>>>>(); self.with_element(|element| { element.as_widget().draw( - &tree.children[0], + &tree.borrow().as_ref().unwrap().children[0], renderer, theme, style, @@ -353,9 +406,10 @@ where viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { + let tree = tree.state.downcast_ref::<Rc<RefCell<Option<Tree>>>>(); self.with_element(|element| { element.as_widget().mouse_interaction( - &tree.children[0], + &tree.borrow().as_ref().unwrap().children[0], layout, cursor_position, viewport, @@ -370,25 +424,34 @@ where layout: Layout<'_>, renderer: &Renderer, ) -> Option<overlay::Element<'b, Message, Renderer>> { - let overlay = OverlayBuilder { - instance: self, - tree, - types: PhantomData, - overlay_builder: |instance, tree| { - instance.state.get_mut().as_mut().unwrap().with_element_mut( - move |element| { - element.as_mut().unwrap().as_widget_mut().overlay( - &mut tree.children[0], - layout, - renderer, - ) - }, - ) - }, - } - .build(); + self.rebuild_element_if_necessary(); + let tree = tree + .state + .downcast_mut::<Rc<RefCell<Option<Tree>>>>() + .borrow_mut() + .take() + .unwrap(); + let overlay = Overlay(Some( + InnerBuilder { + instance: self, + tree, + types: PhantomData, + overlay_builder: |instance, tree| { + instance.state.get_mut().as_mut().unwrap().with_element_mut( + move |element| { + element.as_mut().unwrap().as_widget_mut().overlay( + &mut tree.children[0], + layout, + renderer, + ) + }, + ) + }, + } + .build(), + )); - let has_overlay = overlay.with_overlay(|overlay| { + let has_overlay = overlay.0.as_ref().unwrap().with_overlay(|overlay| { overlay.as_ref().map(overlay::Element::position) }); @@ -403,10 +466,24 @@ where } } +struct Overlay<'a, 'b, Message, Renderer, Event, S>( + Option<Inner<'a, 'b, Message, Renderer, Event, S>>, +); + +impl<'a, 'b, Message, Renderer, Event, S> Drop + for Overlay<'a, 'b, Message, Renderer, Event, S> +{ + fn drop(&mut self) { + if let Some(heads) = self.0.take().map(|inner| inner.into_heads()) { + *heads.instance.tree.borrow_mut().borrow_mut() = Some(heads.tree); + } + } +} + #[self_referencing] -struct Overlay<'a, 'b, Message, Renderer, Event, S> { +struct Inner<'a, 'b, Message, Renderer, Event, S> { instance: &'a mut Instance<'b, Message, Renderer, Event, S>, - tree: &'a mut Tree, + tree: Tree, types: PhantomData<(Message, Event, S)>, #[borrows(mut instance, mut tree)] @@ -428,6 +505,9 @@ impl<'a, 'b, Message, Renderer, Event, S> self.overlay .as_ref() .unwrap() + .0 + .as_ref() + .unwrap() .borrow_overlay() .as_ref() .map(f) @@ -440,6 +520,9 @@ impl<'a, 'b, Message, Renderer, Event, S> self.overlay .as_mut() .unwrap() + .0 + .as_mut() + .unwrap() .with_overlay_mut(|overlay| overlay.as_mut().map(f)) } } @@ -523,42 +606,37 @@ where local_shell.revalidate_layout(|| shell.invalidate_layout()); if !local_messages.is_empty() { - let overlay = self.overlay.take().unwrap().into_heads(); - let mut heads = overlay.instance.state.take().unwrap().into_heads(); + let mut inner = + self.overlay.take().unwrap().0.take().unwrap().into_heads(); + let mut heads = inner.instance.state.take().unwrap().into_heads(); for message in local_messages.into_iter().filter_map(|message| { heads .component - .update(overlay.tree.state.downcast_mut::<S>(), message) + .update(inner.tree.state.downcast_mut(), message) }) { shell.publish(message); } - *overlay.instance.state.borrow_mut() = Some( + *inner.instance.state.borrow_mut() = Some( StateBuilder { component: heads.component, message: PhantomData, state: PhantomData, - element_builder: |state| { - Some(state.view(overlay.tree.state.downcast_ref::<S>())) - }, + element_builder: |_| None, } .build(), ); - overlay.instance.with_element(|element| { - overlay.tree.diff_children(std::slice::from_ref(&element)) - }); - - self.overlay = Some( - OverlayBuilder { - instance: overlay.instance, - tree: overlay.tree, + self.overlay = Some(Overlay(Some( + InnerBuilder { + instance: inner.instance, + tree: inner.tree, types: PhantomData, overlay_builder: |_, _| None, } .build(), - ); + ))); shell.invalidate_layout(); } diff --git a/native/src/layout/flex.rs b/native/src/layout/flex.rs index 5d70c2fc..8b967849 100644 --- a/native/src/layout/flex.rs +++ b/native/src/layout/flex.rs @@ -81,32 +81,6 @@ where let mut nodes: Vec<Node> = Vec::with_capacity(items.len()); nodes.resize(items.len(), Node::default()); - if align_items == Alignment::Fill { - let mut fill_cross = axis.cross(limits.min()); - - items.iter().for_each(|child| { - let cross_fill_factor = match axis { - Axis::Horizontal => child.as_widget().height(), - Axis::Vertical => child.as_widget().width(), - } - .fill_factor(); - - if cross_fill_factor == 0 { - let (max_width, max_height) = axis.pack(available, max_cross); - - let child_limits = - Limits::new(Size::ZERO, Size::new(max_width, max_height)); - - let layout = child.as_widget().layout(renderer, &child_limits); - let size = layout.size(); - - fill_cross = fill_cross.max(axis.cross(size)); - } - }); - - cross = fill_cross; - } - for (i, child) in items.iter().enumerate() { let fill_factor = match axis { Axis::Horizontal => child.as_widget().width(), @@ -115,31 +89,16 @@ where .fill_factor(); if fill_factor == 0 { - let (min_width, min_height) = if align_items == Alignment::Fill { - axis.pack(0.0, cross) - } else { - axis.pack(0.0, 0.0) - }; + let (max_width, max_height) = axis.pack(available, max_cross); - let (max_width, max_height) = if align_items == Alignment::Fill { - axis.pack(available, cross) - } else { - axis.pack(available, max_cross) - }; - - let child_limits = Limits::new( - Size::new(min_width, min_height), - Size::new(max_width, max_height), - ); + let child_limits = + Limits::new(Size::ZERO, Size::new(max_width, max_height)); let layout = child.as_widget().layout(renderer, &child_limits); let size = layout.size(); available -= axis.main(size); - - if align_items != Alignment::Fill { - cross = cross.max(axis.cross(size)); - } + cross = cross.max(axis.cross(size)); nodes[i] = layout; } else { @@ -164,17 +123,10 @@ where max_main }; - let (min_width, min_height) = if align_items == Alignment::Fill { - axis.pack(min_main, cross) - } else { - axis.pack(min_main, axis.cross(limits.min())) - }; + let (min_width, min_height) = + axis.pack(min_main, axis.cross(limits.min())); - let (max_width, max_height) = if align_items == Alignment::Fill { - axis.pack(max_main, cross) - } else { - axis.pack(max_main, max_cross) - }; + let (max_width, max_height) = axis.pack(max_main, max_cross); let child_limits = Limits::new( Size::new(min_width, min_height), @@ -182,10 +134,7 @@ where ); let layout = child.as_widget().layout(renderer, &child_limits); - - if align_items != Alignment::Fill { - cross = cross.max(axis.cross(layout.size())); - } + cross = cross.max(axis.cross(layout.size())); nodes[i] = layout; } diff --git a/native/src/layout/node.rs b/native/src/layout/node.rs index e0c7dcb2..2b44a7d5 100644 --- a/native/src/layout/node.rs +++ b/native/src/layout/node.rs @@ -56,9 +56,6 @@ impl Node { Alignment::End => { self.bounds.x += space.width - self.bounds.width; } - Alignment::Fill => { - self.bounds.width = space.width; - } } match vertical_alignment { @@ -69,9 +66,6 @@ impl Node { Alignment::End => { self.bounds.y += space.height - self.bounds.height; } - Alignment::Fill => { - self.bounds.height = space.height; - } } } diff --git a/src/window.rs b/src/window.rs index 2018053f..aba4bce8 100644 --- a/src/window.rs +++ b/src/window.rs @@ -6,7 +6,6 @@ pub mod icon; pub use icon::Icon; pub use position::Position; -pub use settings::Settings; +pub use settings::{PlatformSpecific, Settings}; -#[cfg(not(target_arch = "wasm32"))] pub use crate::runtime::window::*; diff --git a/src/window/icon.rs b/src/window/icon.rs index d57eb79c..659d2b64 100644 --- a/src/window/icon.rs +++ b/src/window/icon.rs @@ -6,9 +6,15 @@ use std::io; use std::path::Path; /// The icon of a window. -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct Icon(iced_winit::winit::window::Icon); +impl fmt::Debug for Icon { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Icon").field(&format_args!("_")).finish() + } +} + impl Icon { /// Creates an icon from 32bpp RGBA data. pub fn from_rgba( diff --git a/src/window/settings.rs b/src/window/settings.rs index 24d0f4f9..3c8da62f 100644 --- a/src/window/settings.rs +++ b/src/window/settings.rs @@ -1,5 +1,7 @@ use crate::window::{Icon, Position}; +pub use iced_winit::settings::PlatformSpecific; + /// The window settings of an application. #[derive(Debug, Clone)] pub struct Settings { @@ -32,6 +34,9 @@ pub struct Settings { /// The icon of the window. pub icon: Option<Icon>, + + /// Platform specific settings. + pub platform_specific: PlatformSpecific, } impl Default for Settings { @@ -47,6 +52,7 @@ impl Default for Settings { transparent: false, always_on_top: false, icon: None, + platform_specific: Default::default(), } } } @@ -64,7 +70,7 @@ impl From<Settings> for iced_winit::settings::Window { transparent: settings.transparent, always_on_top: settings.always_on_top, icon: settings.icon.map(Icon::into), - platform_specific: Default::default(), + platform_specific: settings.platform_specific, } } } diff --git a/wgpu/src/settings.rs b/wgpu/src/settings.rs index fd3b990a..5ef79499 100644 --- a/wgpu/src/settings.rs +++ b/wgpu/src/settings.rs @@ -1,10 +1,12 @@ //! Configure a renderer. +use std::fmt; + pub use crate::Antialiasing; /// The settings of a [`Backend`]. /// /// [`Backend`]: crate::Backend -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Clone, Copy, PartialEq)] pub struct Settings { /// The present mode of the [`Backend`]. /// @@ -36,6 +38,20 @@ pub struct Settings { pub antialiasing: Option<Antialiasing>, } +impl fmt::Debug for Settings { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Settings") + .field("present_mode", &self.present_mode) + .field("internal_backend", &self.internal_backend) + // Instead of printing the font bytes, we simply show a `bool` indicating if using a default font or not. + .field("default_font", &self.default_font.is_some()) + .field("default_text_size", &self.default_text_size) + .field("text_multithreading", &self.text_multithreading) + .field("antialiasing", &self.antialiasing) + .finish() + } +} + impl Settings { /// Creates new [`Settings`] using environment configuration. /// diff --git a/winit/Cargo.toml b/winit/Cargo.toml index 60e464c6..dd5c12c2 100644 --- a/winit/Cargo.toml +++ b/winit/Cargo.toml @@ -65,5 +65,5 @@ version = "0.3" features = ["Document", "Window"] [dependencies.sysinfo] -version = "0.23" +version = "0.28" optional = true diff --git a/winit/src/application.rs b/winit/src/application.rs index 3fdec658..31654f26 100644 --- a/winit/src/application.rs +++ b/winit/src/application.rs @@ -157,7 +157,7 @@ where ) .with_visible(false); - log::info!("Window builder: {:#?}", builder); + log::debug!("Window builder: {:#?}", builder); let window = builder .build(&event_loop) @@ -179,13 +179,17 @@ where .unwrap_or(None) }); - let _ = match target { - Some(node) => node - .replace_child(&canvas, &node) - .expect(&format!("Could not replace #{}", node.id())), - None => body - .append_child(&canvas) - .expect("Append canvas to HTML body"), + match target { + Some(node) => { + let _ = node + .replace_with_with_node_1(&canvas) + .expect(&format!("Could not replace #{}", node.id())); + } + None => { + let _ = body + .append_child(&canvas) + .expect("Append canvas to HTML body"); + } }; } @@ -762,7 +766,7 @@ pub fn run_command<A, E>( window::Action::ChangeMode(mode) => { window.set_visible(conversion::visible(mode)); window.set_fullscreen(conversion::fullscreen( - window.primary_monitor(), + window.current_monitor(), mode, )); } diff --git a/winit/src/settings.rs b/winit/src/settings.rs index 45f38833..78d58000 100644 --- a/winit/src/settings.rs +++ b/winit/src/settings.rs @@ -23,9 +23,12 @@ pub use platform::PlatformSpecific; use crate::conversion; use crate::Position; + use winit::monitor::MonitorHandle; use winit::window::WindowBuilder; +use std::fmt; + /// The settings of an application. #[derive(Debug, Clone, Default)] pub struct Settings<Flags> { @@ -59,7 +62,7 @@ pub struct Settings<Flags> { } /// The window settings of an application. -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct Window { /// The size of the window. pub size: (u32, u32), @@ -95,6 +98,24 @@ pub struct Window { pub platform_specific: platform::PlatformSpecific, } +impl fmt::Debug for Window { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Window") + .field("size", &self.size) + .field("position", &self.position) + .field("min_size", &self.min_size) + .field("max_size", &self.max_size) + .field("visible", &self.visible) + .field("resizable", &self.resizable) + .field("decorations", &self.decorations) + .field("transparent", &self.transparent) + .field("always_on_top", &self.always_on_top) + .field("icon", &self.icon.is_some()) + .field("platform_specific", &self.platform_specific) + .finish() + } +} + impl Window { /// Converts the window settings into a `WindowBuilder` from `winit`. pub fn into_builder( diff --git a/winit/src/system.rs b/winit/src/system.rs index 619086b8..8d8b018c 100644 --- a/winit/src/system.rs +++ b/winit/src/system.rs @@ -16,11 +16,11 @@ pub fn fetch_information<Message>( pub(crate) fn information( graphics_info: compositor::Information, ) -> Information { - use sysinfo::{ProcessExt, ProcessorExt, System, SystemExt}; + use sysinfo::{CpuExt, ProcessExt, System, SystemExt}; let mut system = System::new_all(); system.refresh_all(); - let cpu = system.global_processor_info(); + let cpu = system.global_cpu_info(); let memory_used = sysinfo::get_current_pid() .and_then(|pid| system.process(pid).ok_or("Process not found")) |