summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/Cargo.toml2
-rw-r--r--core/src/alignment.rs3
-rw-r--r--core/src/font.rs9
-rw-r--r--core/src/mouse/interaction.rs9
-rw-r--r--core/src/padding.rs10
-rw-r--r--examples/checkbox/README.md2
-rw-r--r--examples/component/src/main.rs5
-rw-r--r--examples/pick_list/src/main.rs9
-rw-r--r--examples/scrollable/src/main.rs1
-rw-r--r--examples/todos/src/main.rs32
-rw-r--r--examples/websocket/src/main.rs4
-rw-r--r--glow/src/settings.rs2
-rw-r--r--glutin/src/application.rs2
-rw-r--r--graphics/Cargo.toml12
-rw-r--r--graphics/src/image/vector.rs17
-rw-r--r--graphics/src/primitive.rs9
-rw-r--r--graphics/src/widget/canvas/cache.rs7
-rw-r--r--graphics/src/widget/canvas/stroke.rs18
-rw-r--r--lazy/src/component.rs236
-rw-r--r--native/src/layout/flex.rs67
-rw-r--r--native/src/layout/node.rs6
-rw-r--r--src/window.rs3
-rw-r--r--src/window/icon.rs8
-rw-r--r--src/window/settings.rs8
-rw-r--r--wgpu/src/settings.rs18
-rw-r--r--winit/Cargo.toml2
-rw-r--r--winit/src/application.rs22
-rw-r--r--winit/src/settings.rs23
-rw-r--r--winit/src/system.rs4
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"))