From f5c35e48c480355036778d26aacde498e5c15e68 Mon Sep 17 00:00:00 2001 From: pml68 Date: Sun, 22 Sep 2024 23:53:02 +0200 Subject: feat: restructure project, start drag and drop --- iced_drop/.gitignore | 3 + iced_drop/Cargo.toml | 8 + iced_drop/README.md | 73 +++++ iced_drop/src/lib.rs | 51 ++++ iced_drop/src/widget.rs | 2 + iced_drop/src/widget/droppable.rs | 497 +++++++++++++++++++++++++++++++++ iced_drop/src/widget/operation.rs | 1 + iced_drop/src/widget/operation/drop.rs | 89 ++++++ 8 files changed, 724 insertions(+) create mode 100644 iced_drop/.gitignore create mode 100644 iced_drop/Cargo.toml create mode 100644 iced_drop/README.md create mode 100644 iced_drop/src/lib.rs create mode 100644 iced_drop/src/widget.rs create mode 100644 iced_drop/src/widget/droppable.rs create mode 100644 iced_drop/src/widget/operation.rs create mode 100644 iced_drop/src/widget/operation/drop.rs (limited to 'iced_drop') diff --git a/iced_drop/.gitignore b/iced_drop/.gitignore new file mode 100644 index 0000000..ff0d847 --- /dev/null +++ b/iced_drop/.gitignore @@ -0,0 +1,3 @@ +/target +/.vscode +Cargo.lock diff --git a/iced_drop/Cargo.toml b/iced_drop/Cargo.toml new file mode 100644 index 0000000..8b9d88c --- /dev/null +++ b/iced_drop/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "iced_drop" +version = "0.1.0" +edition = "2021" + +[dependencies.iced] +version = "0.12.1" +features = ["advanced"] diff --git a/iced_drop/README.md b/iced_drop/README.md new file mode 100644 index 0000000..41b637b --- /dev/null +++ b/iced_drop/README.md @@ -0,0 +1,73 @@ +# iced_drop + +A small library which provides a custom widget and operation to make drag and drop easier to implement in [iced](https://github.com/iced-rs/iced/tree/master) + +## Usage + +To add drag and drog functionality, first define two messages with the following format + +```rust +enum Message { + Drop(iced::Point, iced::Rectangle) + HandleZones(Vec<(iced::advanced::widget::Id, iced::Rectangle)>) +} +``` + +The `Drop` message will be sent when the droppable is being dragged, and the left mouse button is released. This message provides the mouse position and layout boundaries of the droppable at the release point. + +The `HandleZones` message will be sent after an operation that finds the drop zones under the mouse position. It provides the Id and bounds for each drop zone. + +Next, create create a droppable in the view method and assign the on_drop message. The dropopable function takes an `impl Into` object, so it's easy to make a droppable from any iced widget. + +```rust +iced_drop::droppable("Drop me!").on_drop(Message::Drop); +``` + +Next, create a "drop zone." A drop zone is any widget that operates like a container andhas some assigned Id. It's important that the widget is assigned some Id or it won't be recognized as a drop zone. + +```rust +iced::widget::container("Drop zone") + .id(iced::widget::container::Id::new("drop_zone")); +``` + +Finally, handle the updates of the drop messages + +```rust +match message { + Message::Drop(cursor_pos, _) => { + return iced_drop::zones_on_point( + Message::HandleZonesFound, + point, + None, + None, + ); + } + Message::HandleZones(zones) => { + println!("{:?}", zones) + } +} +``` + +On Drop, we return a widget operation that looks for drop zones under the cursor_pos. When this operation finishes, it returns the zones found and sends the `HandleZones` message. In this example, we only defined one zone, so the zones vector will either be empty if the droppable was not dropped on the zone, or it will contain the `drop_zone` + +## Examples + +There are two examples: color, todo. + +The color example is a very basic drag/drop showcase where the user can drag colors into zones and change the zone's color. I would start here. + +[Link to video](https://drive.google.com/file/d/1K1CCi2Lc90IUyDufsvoUBZmUCbeg6_Fi/view?usp=sharing) + +To run this examples: `cargo run -p color` + +The todo example is a basic todo board application similar to Trello. This is a much much more complex example as it handles custom highlighting and nested droppables, but it just shows you can make some pretty cool things with iced. + +[Link to video](https://drive.google.com/file/d/1MLOCk4Imd_oUnrTj_psbpYbwua976HmR/view?usp=sharing) + +To run this example try: `cargo run -p todo` + +Note: the todo example might also be a good example on how one can use operations. Check examples/todo/src/operation.rs. I didn't find any other examples of this in the iced repo except for the built in focus operations. + +## Future Development + +Right now it's a little annoying having to work with iced's Id type. At some point, I will work on a drop_zone widget that can take some generic clonable type as an id, and I will create a seperate find_zones operation that will return a list of this custom Id. This should make it easier to determine which drop zones were found. diff --git a/iced_drop/src/lib.rs b/iced_drop/src/lib.rs new file mode 100644 index 0000000..fc559dc --- /dev/null +++ b/iced_drop/src/lib.rs @@ -0,0 +1,51 @@ +pub mod widget; + +use iced::{ + advanced::{graphics::futures::MaybeSend, renderer, widget::Id}, + Command, Element, Point, Rectangle, +}; + +use widget::droppable::*; +use widget::operation::drop; + +pub fn droppable<'a, Message, Theme, Renderer>( + content: impl Into>, +) -> Droppable<'a, Message, Theme, Renderer> +where + Message: Clone, + Renderer: renderer::Renderer, +{ + Droppable::new(content) +} + +pub fn zones_on_point( + msg: MF, + point: Point, + options: Option>, + depth: Option, +) -> Command +where + Message: 'static, + MF: Fn(Vec<(Id, Rectangle)>) -> Message + MaybeSend + Sync + Clone + 'static, +{ + Command::widget(drop::find_zones( + move |bounds| bounds.contains(point), + options, + depth, + )) + .map(move |id| msg(id)) +} + +pub fn find_zones( + msg: MF, + filter: F, + options: Option>, + depth: Option, +) -> Command +where + Message: 'static, + MF: Fn(Vec<(Id, Rectangle)>) -> Message + MaybeSend + Sync + Clone + 'static, + F: Fn(&Rectangle) -> bool + 'static, +{ + Command::widget(drop::find_zones(filter, options, depth)).map(move |id| msg(id)) +} diff --git a/iced_drop/src/widget.rs b/iced_drop/src/widget.rs new file mode 100644 index 0000000..6b3fed2 --- /dev/null +++ b/iced_drop/src/widget.rs @@ -0,0 +1,2 @@ +pub mod droppable; +pub mod operation; diff --git a/iced_drop/src/widget/droppable.rs b/iced_drop/src/widget/droppable.rs new file mode 100644 index 0000000..ed7dcbd --- /dev/null +++ b/iced_drop/src/widget/droppable.rs @@ -0,0 +1,497 @@ +//! Encapsulates a widget that can be dragged and dropped. +use std::fmt::Debug; +use std::vec; + +use iced::advanced::widget::{Operation, Tree, Widget}; +use iced::advanced::{self, layout, mouse, overlay, renderer, Layout}; +use iced::event::Status; +use iced::{Element, Point, Rectangle, Size, Vector}; + +/// An element that can be dragged and dropped on a [`DropZone`] +pub struct Droppable<'a, Message, Theme = iced::Theme, Renderer = iced::Renderer> +where + Message: Clone, + Renderer: renderer::Renderer, +{ + content: Element<'a, Message, Theme, Renderer>, + id: Option, + on_click: Option, + on_drop: Option Message + 'a>>, + on_drag: Option Message + 'a>>, + on_cancel: Option, + drag_mode: Option<(bool, bool)>, + drag_overlay: bool, + drag_hide: bool, + drag_center: bool, + drag_size: Option, + reset_delay: usize, +} + +impl<'a, Message, Theme, Renderer> Droppable<'a, Message, Theme, Renderer> +where + Message: Clone, + Renderer: renderer::Renderer, +{ + /// Creates a new [`Droppable`]. + pub fn new(content: impl Into>) -> Self { + Self { + content: content.into(), + id: None, + on_click: None, + on_drop: None, + on_drag: None, + on_cancel: None, + drag_mode: Some((true, true)), + drag_overlay: true, + drag_hide: false, + drag_center: false, + drag_size: None, + reset_delay: 0, + } + } + + /// Sets the unique identifier of the [`Droppable`]. + pub fn id(mut self, id: iced::advanced::widget::Id) -> Self { + self.id = Some(id); + self + } + + /// Sets the message that will be produced when the [`Droppable`] is clicked. + pub fn on_click(mut self, message: Message) -> Self { + self.on_click = Some(message); + self + } + + /// Sets the message that will be produced when the [`Droppable`] is dropped on a [`DropZone`]. + /// + /// Unless this is set, the [`Droppable`] will be disabled. + pub fn on_drop(mut self, message: F) -> Self + where + F: Fn(Point, Rectangle) -> Message + 'a, + { + self.on_drop = Some(Box::new(message)); + self + } + + /// Sets the message that will be produced when the [`Droppable`] is dragged. + pub fn on_drag(mut self, message: F) -> Self + where + F: Fn(Point, Rectangle) -> Message + 'a, + { + self.on_drag = Some(Box::new(message)); + self + } + + /// Sets the message that will be produced when the user right clicks while dragging the [`Droppable`]. + pub fn on_cancel(mut self, message: Message) -> Self { + self.on_cancel = Some(message); + self + } + + /// Sets whether the [`Droppable`] should be drawn under the cursor while dragging. + pub fn drag_overlay(mut self, drag_overlay: bool) -> Self { + self.drag_overlay = drag_overlay; + self + } + + /// Sets whether the [`Droppable`] should be hidden while dragging. + pub fn drag_hide(mut self, drag_hide: bool) -> Self { + self.drag_hide = drag_hide; + self + } + + /// Sets whether the [`Droppable`] should be centered on the cursor while dragging. + pub fn drag_center(mut self, drag_center: bool) -> Self { + self.drag_center = drag_center; + self + } + + // Sets whether the [`Droppable`] can be dragged along individual axes. + pub fn drag_mode(mut self, drag_x: bool, drag_y: bool) -> Self { + self.drag_mode = Some((drag_x, drag_y)); + self + } + + /// Sets whether the [`Droppable`] should be be resized to a given size while dragging. + pub fn drag_size(mut self, hide_size: Size) -> Self { + self.drag_size = Some(hide_size); + self + } + + /// Sets the number of frames/layout calls to wait before resetting the size of the [`Droppable`] after dropping. + /// + /// This is useful for cases where the [`Droppable`] is being moved to a new location after some widget operation. + /// In this case, the [`Droppable`] will mainting the 'drag_size' for the given number of frames before resetting to its original size. + /// This prevents the [`Droppable`] from 'jumping' back to its original size before the new location is rendered which + /// prevents flickering. + /// + /// Warning: this should only be set if there's is some noticeble flickering when the [`Droppable`] is dropped. That is, if the + /// [`Droppable`] returns to its original size before it's moved to it's new location. + pub fn reset_delay(mut self, reset_delay: usize) -> Self { + self.reset_delay = reset_delay; + self + } +} + +impl<'a, Message, Theme, Renderer> Widget + for Droppable<'a, Message, Theme, Renderer> +where + Message: Clone, + Renderer: renderer::Renderer, +{ + fn state(&self) -> iced::advanced::widget::tree::State { + advanced::widget::tree::State::new(State::default()) + } + + fn tag(&self) -> iced::advanced::widget::tree::Tag { + advanced::widget::tree::Tag::of::() + } + + fn children(&self) -> Vec { + vec![advanced::widget::Tree::new(&self.content)] + } + + fn diff(&self, tree: &mut iced::advanced::widget::Tree) { + tree.diff_children(std::slice::from_ref(&self.content)) + } + + fn size(&self) -> iced::Size { + self.content.as_widget().size() + } + + fn on_event( + &mut self, + tree: &mut iced::advanced::widget::Tree, + event: iced::Event, + layout: iced::advanced::Layout<'_>, + cursor: iced::advanced::mouse::Cursor, + _renderer: &Renderer, + _clipboard: &mut dyn iced::advanced::Clipboard, + shell: &mut iced::advanced::Shell<'_, Message>, + _viewport: &iced::Rectangle, + ) -> iced::advanced::graphics::core::event::Status { + // handle the on event of the content first, in case that the droppable is nested + let status = self.content.as_widget_mut().on_event( + &mut tree.children[0], + event.clone(), + layout, + cursor, + _renderer, + _clipboard, + shell, + _viewport, + ); + // this should really only be captured if the droppable is nested or it contains some other + // widget that captures the event + if status == Status::Captured { + return status; + }; + + if let Some(on_drop) = self.on_drop.as_deref() { + let state = tree.state.downcast_mut::(); + if let iced::Event::Mouse(mouse) = event { + match mouse { + mouse::Event::ButtonPressed(btn) => { + if btn == mouse::Button::Left && cursor.is_over(layout.bounds()) { + // select the droppable and store the position of the widget before dragging + state.action = Action::Select(cursor.position().unwrap()); + let bounds = layout.bounds(); + state.widget_pos = bounds.position(); + state.overlay_bounds.width = bounds.width; + state.overlay_bounds.height = bounds.height; + + if let Some(on_click) = self.on_click.clone() { + shell.publish(on_click); + } + return Status::Captured; + } else if btn == mouse::Button::Right { + if let Action::Drag(_, _) = state.action { + shell.invalidate_layout(); + state.action = Action::None; + if let Some(on_cancel) = self.on_cancel.clone() { + shell.publish(on_cancel); + } + } + } + } + mouse::Event::CursorMoved { mut position } => match state.action { + Action::Select(start) | Action::Drag(start, _) => { + // calculate the new position of the widget after dragging + + if let Some((drag_x, drag_y)) = self.drag_mode { + position = Point { + x: if drag_x { position.x } else { start.x }, + y: if drag_y { position.y } else { start.y }, + }; + } + + state.action = Action::Drag(start, position); + // update the position of the overlay since the cursor was moved + if self.drag_center { + state.overlay_bounds.x = position.x - state.overlay_bounds.width / 2.0; + state.overlay_bounds.y = position.y - state.overlay_bounds.height / 2.0; + } else { + state.overlay_bounds.x = state.widget_pos.x + position.x - start.x; + state.overlay_bounds.y = state.widget_pos.y + position.y - start.y; + } + // send on drag msg + if let Some(on_drag) = self.on_drag.as_deref() { + let message = (on_drag)(position, state.overlay_bounds); + shell.publish(message); + } + } + _ => (), + }, + mouse::Event::ButtonReleased(btn) => { + if btn == mouse::Button::Left { + match state.action { + Action::Select(_) => { + state.action = Action::None; + } + Action::Drag(_, current) => { + // send on drop msg + let message = (on_drop)(current, state.overlay_bounds); + shell.publish(message); + + if self.reset_delay == 0 { + state.action = Action::None; + } else { + state.action = Action::Wait(self.reset_delay); + } + } + _ => (), + } + } + } + _ => {} + } + } + } + Status::Ignored + } + + fn layout( + &self, + tree: &mut iced::advanced::widget::Tree, + renderer: &Renderer, + limits: &iced::advanced::layout::Limits, + ) -> iced::advanced::layout::Node { + let state: &mut State = tree.state.downcast_mut::(); + let content_node = self + .content + .as_widget() + .layout(&mut tree.children[0], renderer, limits); + + // Adjust the size of the original widget if it's being dragged or we're wating to reset the size + if let Some(new_size) = self.drag_size { + match state.action { + Action::Drag(_, _) => { + return iced::advanced::layout::Node::with_children( + new_size, + content_node.children().to_vec(), + ); + } + Action::Wait(reveal_index) => { + if reveal_index <= 1 { + state.action = Action::None; + } else { + state.action = Action::Wait(reveal_index - 1); + } + + return iced::advanced::layout::Node::with_children( + new_size, + content_node.children().to_vec(), + ); + } + _ => (), + } + } + + content_node + } + + fn operate( + &self, + tree: &mut Tree, + layout: Layout<'_>, + renderer: &Renderer, + operation: &mut dyn Operation, + ) { + let state = tree.state.downcast_mut::(); + operation.custom(state, self.id.as_ref()); + operation.container(self.id.as_ref(), layout.bounds(), &mut |operation| { + self.content + .as_widget() + .operate(&mut tree.children[0], layout, renderer, operation); + }); + } + + fn draw( + &self, + tree: &iced::advanced::widget::Tree, + renderer: &mut Renderer, + theme: &Theme, + style: &renderer::Style, + layout: iced::advanced::Layout<'_>, + cursor: iced::advanced::mouse::Cursor, + viewport: &iced::Rectangle, + ) { + let state: &State = tree.state.downcast_ref::(); + if let Action::Drag(_, _) = state.action { + if self.drag_hide { + return; + } + } + + self.content.as_widget().draw( + &tree.children[0], + renderer, + theme, + style, + layout, + cursor, + &viewport, + ); + } + + fn overlay<'b>( + &'b mut self, + tree: &'b mut Tree, + layout: Layout<'_>, + renderer: &Renderer, + _translation: Vector, + ) -> Option> { + let state: &mut State = tree.state.downcast_mut::(); + let mut children = tree.children.iter_mut(); + if self.drag_overlay { + if let Action::Drag(_, _) = state.action { + return Some(overlay::Element::new(Box::new(Overlay { + content: &self.content, + tree: children.next().unwrap(), + overlay_bounds: state.overlay_bounds, + }))); + } + } + self.content.as_widget_mut().overlay( + children.next().unwrap(), + layout, + renderer, + _translation, + ) + } + + fn mouse_interaction( + &self, + tree: &iced::advanced::widget::Tree, + layout: iced::advanced::Layout<'_>, + cursor: iced::advanced::mouse::Cursor, + _viewport: &iced::Rectangle, + _renderer: &Renderer, + ) -> iced::advanced::mouse::Interaction { + let child_interact = self.content.as_widget().mouse_interaction( + &tree.children[0], + layout, + cursor, + _viewport, + _renderer, + ); + if child_interact != mouse::Interaction::default() { + return child_interact; + } + + let state = tree.state.downcast_ref::(); + + if self.on_drop.is_none() { + return mouse::Interaction::NotAllowed; + } + if let Action::Drag(_, _) = state.action { + return mouse::Interaction::Grabbing; + } + if cursor.is_over(layout.bounds()) { + return mouse::Interaction::Pointer; + } + mouse::Interaction::default() + } +} + +impl<'a, Message, Theme, Renderer> From> + for Element<'a, Message, Theme, Renderer> +where + Message: 'a + Clone, + Theme: 'a, + Renderer: 'a + renderer::Renderer, +{ + fn from( + droppable: Droppable<'a, Message, Theme, Renderer>, + ) -> Element<'a, Message, Theme, Renderer> { + Element::new(droppable) + } +} + +#[derive(Default, Clone, Copy, PartialEq, Debug)] +pub struct State { + widget_pos: Point, + overlay_bounds: Rectangle, + action: Action, +} + +#[derive(Default, Clone, Copy, PartialEq, Debug)] +pub enum Action { + #[default] + None, + /// (point clicked) + Select(Point), + /// (start pos, current pos) + Drag(Point, Point), + /// (frames to wait) + Wait(usize), +} + +struct Overlay<'a, 'b, Message, Theme, Renderer> +where + Renderer: renderer::Renderer, +{ + content: &'b Element<'a, Message, Theme, Renderer>, + tree: &'b mut advanced::widget::Tree, + overlay_bounds: Rectangle, +} + +impl<'a, 'b, Message, Theme, Renderer> overlay::Overlay + for Overlay<'a, 'b, Message, Theme, Renderer> +where + Renderer: renderer::Renderer, +{ + fn layout(&mut self, renderer: &Renderer, _bounds: Size) -> layout::Node { + Widget::::layout( + self.content.as_widget(), + self.tree, + renderer, + &layout::Limits::new(Size::ZERO, self.overlay_bounds.size()), + ) + .move_to(self.overlay_bounds.position()) + } + + fn draw( + &self, + renderer: &mut Renderer, + theme: &Theme, + inherited_style: &renderer::Style, + layout: Layout<'_>, + cursor_position: mouse::Cursor, + ) { + Widget::::draw( + self.content.as_widget(), + self.tree, + renderer, + theme, + inherited_style, + layout, + cursor_position, + &Rectangle::with_size(Size::INFINITY), + ); + } + + fn is_over(&self, _layout: Layout<'_>, _renderer: &Renderer, _cursor_position: Point) -> bool { + false + } +} diff --git a/iced_drop/src/widget/operation.rs b/iced_drop/src/widget/operation.rs new file mode 100644 index 0000000..3d7dcff --- /dev/null +++ b/iced_drop/src/widget/operation.rs @@ -0,0 +1 @@ +pub mod drop; diff --git a/iced_drop/src/widget/operation/drop.rs b/iced_drop/src/widget/operation/drop.rs new file mode 100644 index 0000000..12a2e30 --- /dev/null +++ b/iced_drop/src/widget/operation/drop.rs @@ -0,0 +1,89 @@ +use iced::{ + advanced::widget::{ + operation::{Outcome, Scrollable}, + Id, Operation, + }, + Rectangle, Vector, +}; + +/// Produces an [`Operation`] that will find the drop zones that pass a filter on the zone's bounds. +/// For any drop zone to be considered, the Element must have some Id. +/// If `options` is `None`, all drop zones will be considered. +/// Depth determines how how deep into nested drop zones to go. +/// If 'depth' is `None`, nested dropzones will be fully explored +pub fn find_zones( + filter: F, + options: Option>, + depth: Option, +) -> impl Operation> +where + F: Fn(&Rectangle) -> bool + 'static, +{ + struct FindDropZone { + filter: F, + options: Option>, + zones: Vec<(Id, Rectangle)>, + max_depth: Option, + c_depth: usize, + offset: Vector, + } + + impl Operation> for FindDropZone + where + F: Fn(&Rectangle) -> bool + 'static, + { + fn container( + &mut self, + id: Option<&Id>, + bounds: iced::Rectangle, + operate_on_children: &mut dyn FnMut(&mut dyn Operation>), + ) { + match id { + Some(id) => { + let is_option = match &self.options { + Some(options) => options.contains(id), + None => true, + }; + let bounds = bounds - self.offset; + if is_option && (self.filter)(&bounds) { + self.c_depth += 1; + self.zones.push((id.clone(), bounds)); + } + } + None => (), + } + let goto_next = match &self.max_depth { + Some(m_depth) => self.c_depth < *m_depth, + None => true, + }; + if goto_next { + operate_on_children(self); + } + } + + fn finish(&self) -> Outcome> { + Outcome::Some(self.zones.clone()) + } + + fn scrollable( + &mut self, + _state: &mut dyn Scrollable, + _id: Option<&Id>, + bounds: Rectangle, + translation: Vector, + ) { + if (self.filter)(&bounds) { + self.offset = self.offset + translation; + } + } + } + + FindDropZone { + filter, + options, + zones: vec![], + max_depth: depth, + c_depth: 0, + offset: Vector { x: 0.0, y: 0.0 }, + } +} -- cgit v1.2.3 From 510d68b92972b99868e187dd5340f04780b4c354 Mon Sep 17 00:00:00 2001 From: pml68 Date: Fri, 4 Oct 2024 00:44:02 +0200 Subject: feat: update to iced 0.13.1, basic project state file, prepare for drag&drop --- .gitignore | 1 + Cargo.lock | 1564 ++++++++++++++++++++-------- iced_builder/Cargo.toml | 5 +- iced_builder/src/codegen/mod.rs | 122 ++- iced_builder/src/lib.rs | 85 ++ iced_builder/src/main.rs | 292 +++--- iced_builder/src/types/mod.rs | 10 +- iced_builder/src/types/project/mod.rs | 59 ++ iced_builder/src/types/rendered_element.rs | 124 ++- iced_drop/Cargo.toml | 2 +- iced_drop/LICENSE | 21 + iced_drop/README.md | 2 + iced_drop/src/lib.rs | 24 +- iced_drop/src/widget/droppable.rs | 8 +- iced_drop/src/widget/operation/drop.rs | 5 +- 15 files changed, 1652 insertions(+), 672 deletions(-) create mode 100644 iced_builder/src/types/project/mod.rs create mode 100644 iced_drop/LICENSE (limited to 'iced_drop') diff --git a/.gitignore b/.gitignore index f4ceea7..9545d1d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ **/target/ +**/*.json diff --git a/Cargo.lock b/Cargo.lock index baeab67..a341d35 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -39,6 +39,17 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + [[package]] name = "ahash" version = "0.8.11" @@ -60,9 +71,9 @@ checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "android-activity" -version = "0.5.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee91c0c2905bae44f84bfa4e044536541df26b7703fd0888deeb9060fcc44289" +checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" dependencies = [ "android-properties", "bitflags 2.6.0", @@ -74,7 +85,7 @@ dependencies = [ "log", "ndk", "ndk-context", - "ndk-sys", + "ndk-sys 0.6.0+11769913", "num_enum", "thiserror", ] @@ -130,6 +141,182 @@ dependencies = [ "libloading 0.7.4", ] +[[package]] +name = "ashpd" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfe7e0dd0ac5a401dc116ed9f9119cf9decc625600474cb41f0fc0a0050abc9a" +dependencies = [ + "async-fs", + "async-net", + "enumflags2", + "futures-channel", + "futures-util", + "rand", + "raw-window-handle", + "serde", + "serde_repr", + "url", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "zbus", +] + +[[package]] +name = "async-broadcast" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cd0e2e25ea8e5f7e9df04578dc6cf5c83577fd09b1a46aaf5c85e1c33f2a7e" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "slab", +] + +[[package]] +name = "async-fs" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a" +dependencies = [ + "async-lock", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-io" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" +dependencies = [ + "async-lock", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "async-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-net" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7" +dependencies = [ + "async-io", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-process" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix", + "tracing", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "async-signal" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix", + "signal-hook-registry", + "slab", + "windows-sys 0.59.0", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -138,9 +325,9 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" @@ -163,12 +350,6 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - [[package]] name = "base64" version = "0.22.1" @@ -234,31 +415,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" [[package]] -name = "block-sys" -version = "0.2.1" +name = "block-buffer" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae85a0696e7ea3b835a453750bf002770776609115e6d25c6d2ff28a8200f7e7" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "objc-sys", + "generic-array", ] [[package]] name = "block2" -version = "0.3.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15b55663a85f33501257357e6421bb33e769d5c9ffb5ba0921c975a123e35e68" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" dependencies = [ - "block-sys", - "objc2 0.4.1", + "objc2", ] [[package]] -name = "block2" -version = "0.5.1" +name = "blocking" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" dependencies = [ - "objc2 0.5.2", + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", ] [[package]] @@ -290,7 +474,7 @@ checksum = "0cc8b54b395f2fcfbb3d90c47b01c7f444d94d05bdeb775811dec868ac3bbc26" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -305,20 +489,6 @@ version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" -[[package]] -name = "calloop" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fba7adb4dd5aa98e5553510223000e7148f621165ec5f9acd7113f6ca4995298" -dependencies = [ - "bitflags 2.6.0", - "log", - "polling", - "rustix", - "slab", - "thiserror", -] - [[package]] name = "calloop" version = "0.13.0" @@ -333,25 +503,13 @@ dependencies = [ "thiserror", ] -[[package]] -name = "calloop-wayland-source" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f0ea9b9476c7fad82841a8dbb380e2eae480c21910feba80725b46931ed8f02" -dependencies = [ - "calloop 0.12.4", - "rustix", - "wayland-backend", - "wayland-client", -] - [[package]] name = "calloop-wayland-source" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" dependencies = [ - "calloop 0.13.0", + "calloop", "rustix", "wayland-backend", "wayland-client", @@ -359,9 +517,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.21" +version = "1.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" +checksum = "812acba72f0a070b003d3697490d2b55b837230ae7c6c6497f05cc2ddbb8d938" dependencies = [ "jobserver", "libc", @@ -407,7 +565,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b7f4aaa047ba3c3630b080bb9860894732ff23e2aee290a418909aa6d5df38f" dependencies = [ - "objc2 0.5.2", + "objc2", "objc2-app-kit", "objc2-foundation", ] @@ -573,25 +731,36 @@ dependencies = [ [[package]] name = "cosmic-text" -version = "0.10.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75acbfb314aeb4f5210d379af45ed1ec2c98c7f1790bf57b8a4c562ac0c51b71" +checksum = "59fd57d82eb4bfe7ffa9b1cec0c05e2fd378155b47f255a67983cb4afe0e80c2" dependencies = [ - "fontdb", - "libm", + "bitflags 2.6.0", + "fontdb 0.16.2", "log", "rangemap", - "rustc-hash", - "rustybuzz 0.11.0", + "rayon", + "rustc-hash 1.1.0", + "rustybuzz", "self_cell", "swash", "sys-locale", + "ttf-parser 0.21.1", "unicode-bidi", "unicode-linebreak", "unicode-script", "unicode-segmentation", ] +[[package]] +name = "cpufeatures" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.4.2" @@ -632,6 +801,16 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "ctor-lite" version = "0.1.0" @@ -655,12 +834,34 @@ dependencies = [ "winapi", ] +[[package]] +name = "dark-light" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a76fa97167fa740dcdbfe18e8895601e1bc36525f09b044e00916e717c03a3c" +dependencies = [ + "dconf_rs", + "detect-desktop-environment", + "dirs", + "objc", + "rust-ini", + "web-sys", + "winreg", + "zbus", +] + [[package]] name = "data-url" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a" +[[package]] +name = "dconf_rs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7046468a81e6a002061c01e6a7c83139daf91b11c30e66795b13217c2d885c8b" + [[package]] name = "deranged" version = "0.3.11" @@ -670,6 +871,42 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "detect-desktop-environment" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21d8ad60dd5b13a4ee6bd8fa2d5d88965c597c67bce32b5fc49c94f55cb50810" + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "dispatch" version = "0.2.0" @@ -685,12 +922,24 @@ dependencies = [ "libloading 0.8.5", ] +[[package]] +name = "dlv-list" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" + [[package]] name = "downcast-rs" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" +[[package]] +name = "dpi" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53" + [[package]] name = "drm" version = "0.12.0" @@ -736,6 +985,33 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +[[package]] +name = "endi" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" + +[[package]] +name = "enumflags2" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -777,6 +1053,27 @@ dependencies = [ "num-traits", ] +[[package]] +name = "event-listener" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +dependencies = [ + "event-listener", + "pin-project-lite", +] + [[package]] name = "exr" version = "1.72.0" @@ -807,18 +1104,18 @@ checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "fdeflate" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +checksum = "d8090f921a24b04994d9929e204f50b498a33ea6ba559ffaa05e04f7ee7fb5ab" dependencies = [ "simd-adler32", ] [[package]] name = "flate2" -version = "1.0.33" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", "miniz_oxide 0.8.0", @@ -866,21 +1163,35 @@ version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1fcfcd44ca6e90c921fee9fa665d530b21ef1327a4c1a6c5250ea44b776ada7" dependencies = [ - "roxmltree 0.20.0", + "roxmltree", ] [[package]] name = "fontdb" -version = "0.15.0" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020e203f177c0fb250fb19455a252e838d2bbbce1f80f25ecc42402aafa8cd38" +checksum = "b0299020c3ef3f60f526a4f64ab4a3d4ce116b1acbf24cdd22da0068e5d81dc3" dependencies = [ "fontconfig-parser", "log", - "memmap2 0.8.0", + "memmap2", "slotmap", "tinyvec", - "ttf-parser 0.19.2", + "ttf-parser 0.20.0", +] + +[[package]] +name = "fontdb" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e32eac81c1135c1df01d4e6d4233c47ba11f6a6d07f33e0bba09d18797077770" +dependencies = [ + "fontconfig-parser", + "log", + "memmap2", + "slotmap", + "tinyvec", + "ttf-parser 0.21.1", ] [[package]] @@ -901,7 +1212,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -910,6 +1221,15 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + [[package]] name = "futures" version = "0.3.30" @@ -959,6 +1279,19 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +[[package]] +name = "futures-lite" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + [[package]] name = "futures-macro" version = "0.3.30" @@ -967,7 +1300,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1000,6 +1333,16 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "gethostname" version = "0.4.3" @@ -1021,16 +1364,6 @@ dependencies = [ "wasi", ] -[[package]] -name = "gif" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045" -dependencies = [ - "color_quant", - "weezl", -] - [[package]] name = "gif" version = "0.13.1" @@ -1085,18 +1418,6 @@ dependencies = [ "gl_generator", ] -[[package]] -name = "glyphon" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a62d0338e4056db6a73221c2fb2e30619452f6ea9651bac4110f51b0f7a7581" -dependencies = [ - "cosmic-text", - "etagere", - "lru", - "wgpu", -] - [[package]] name = "gpu-alloc" version = "0.6.0" @@ -1137,7 +1458,7 @@ checksum = "cc11df1ace8e7e564511f53af41f3e42ddc95b56fd07b3f4445d2a6048bc682c" dependencies = [ "bitflags 2.6.0", "gpu-descriptor-types", - "hashbrown", + "hashbrown 0.14.5", ] [[package]] @@ -1169,16 +1490,31 @@ dependencies = [ "crunchy", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash 0.7.8", +] + [[package]] name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ - "ahash", + "ahash 0.8.11", "allocator-api2", ] +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + [[package]] name = "hassle-rs" version = "0.11.0" @@ -1206,6 +1542,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "hexf-parse" version = "0.2.1" @@ -1214,9 +1556,9 @@ checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" [[package]] name = "iced" -version = "0.12.1" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d4eb0fbbefb8c428b70680e77ed9013887b17c1d6be366b40f264f956d1a096" +checksum = "88acfabc84ec077eaf9ede3457ffa3a104626d79022a9bf7f296093b1d60c73f" dependencies = [ "iced_core", "iced_futures", @@ -1230,12 +1572,13 @@ dependencies = [ [[package]] name = "iced_aw" -version = "0.9.3" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e68c330918a95bd73176206d65b84efe9aee6581da0e6dea0390cd146d7214c" +checksum = "42e05df3019f20c6decea93d035b32a2afc7b329d89cc5a68cca097d0e0a1889" dependencies = [ "cfg-if", "iced", + "iced_fonts", ] [[package]] @@ -1245,6 +1588,7 @@ dependencies = [ "iced", "iced_aw", "iced_drop", + "rfd", "rust-format", "serde", "serde_json", @@ -1254,20 +1598,22 @@ dependencies = [ [[package]] name = "iced_core" -version = "0.12.3" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d7e6bbd197f311ed3d8b71651876b0ce01318fde52cda862a9a7a4373c9b930" +checksum = "0013a238275494641bf8f1732a23a808196540dc67b22ff97099c044ae4c8a1c" dependencies = [ "bitflags 2.6.0", + "bytes", + "dark-light", "glam", "log", "num-traits", + "once_cell", "palette", - "raw-window-handle", + "rustc-hash 2.0.0", "smol_str", "thiserror", "web-time", - "xxhash-rust", ] [[package]] @@ -1277,25 +1623,48 @@ dependencies = [ "iced", ] +[[package]] +name = "iced_fonts" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df7deb0800a850ee25c8a42559f72c0f249e577feb3aad37b9b65dc1e517e52a" +dependencies = [ + "iced_core", +] + [[package]] name = "iced_futures" -version = "0.12.0" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "370bad88fb3832cbeeb3fa6c486b4701fb7e8da32a753b3101d4ce81fc1d9497" +checksum = "0c04a6745ba2e80f32cf01e034fd00d853aa4f4cd8b91888099cb7aaee0d5d7c" dependencies = [ "futures", "iced_core", "log", + "rustc-hash 2.0.0", "tokio", "wasm-bindgen-futures", "wasm-timer", ] +[[package]] +name = "iced_glyphon" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41c3bb56f1820ca252bc1d0994ece33d233a55657c0c263ea7cb16895adbde82" +dependencies = [ + "cosmic-text", + "etagere", + "lru", + "rustc-hash 2.0.0", + "wgpu", +] + [[package]] name = "iced_graphics" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a044c193ef0840eacabfa05424717331d1fc5b3ecb9a89316200c75da2ba9a4" +checksum = "ba25a18cfa6d5cc160aca7e1b34f73ccdff21680fa8702168c09739767b6c66f" dependencies = [ "bitflags 2.6.0", "bytemuck", @@ -1309,17 +1678,16 @@ dependencies = [ "lyon_path", "once_cell", "raw-window-handle", - "rustc-hash", + "rustc-hash 2.0.0", "thiserror", "unicode-segmentation", - "xxhash-rust", ] [[package]] name = "iced_highlighter" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d27d1e5f526255ad4902907509f9ff9e98a40653dd31df36aba38d7c3905ad" +checksum = "bad88b25a1328cd4bb0b72d8e20f8207c0433649dc788f67e911423b9406f45c" dependencies = [ "iced_core", "once_cell", @@ -1328,9 +1696,9 @@ dependencies = [ [[package]] name = "iced_renderer" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c281e03001d566058f53dec9325bbe61c62da715341206d2627f57a3ecc7f69" +checksum = "73558208059f9e622df2bf434e044ee2f838ce75201a023cf0ca3e1244f46c2a" dependencies = [ "iced_graphics", "iced_tiny_skia", @@ -1341,32 +1709,22 @@ dependencies = [ [[package]] name = "iced_runtime" -version = "0.12.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a79f852c01cc6d61663c94379cb3974ac3ad315a28c504e847d573e094f46822" +checksum = "348b5b2c61c934d88ca3b0ed1ed913291e923d086a66fa288ce9669da9ef62b5" dependencies = [ + "bytes", "iced_core", "iced_futures", "raw-window-handle", "thiserror", ] -[[package]] -name = "iced_style" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ea42a740915d2a5a9ff9c3aa0bca28b16e9fb660bc8f675eed71d186cadb579" -dependencies = [ - "iced_core", - "once_cell", - "palette", -] - [[package]] name = "iced_tiny_skia" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2228781f4d381a1cbbd7905a9f077351aa8d37269094021d5d9e779f130aff" +checksum = "c625d368284fcc43b0b36b176f76eff1abebe7959dd58bd8ce6897d641962a50" dependencies = [ "bytemuck", "cosmic-text", @@ -1374,59 +1732,64 @@ dependencies = [ "kurbo 0.10.4", "log", "resvg", - "rustc-hash", + "rustc-hash 2.0.0", "softbuffer", "tiny-skia", - "xxhash-rust", ] [[package]] name = "iced_wgpu" -version = "0.12.1" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c243b6700452886aac1ee1987e84d9fb43b56b53fea9a1eb67713fd0fde244" +checksum = "15708887133671d2bcc6c1d01d1f176f43a64d6cdc3b2bf893396c3ee498295f" dependencies = [ "bitflags 2.6.0", "bytemuck", "futures", "glam", - "glyphon", "guillotiere", + "iced_glyphon", "iced_graphics", "log", "lyon", "once_cell", "resvg", + "rustc-hash 2.0.0", + "thiserror", "wgpu", ] [[package]] name = "iced_widget" -version = "0.12.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e01b2212adecf1cb80e2267f302c0e0c263e55f97812056949199ccf9f0b908" +checksum = "81429e1b950b0e4bca65be4c4278fea6678ea782030a411778f26fa9f8983e1d" dependencies = [ + "iced_highlighter", "iced_renderer", "iced_runtime", - "iced_style", "num-traits", + "once_cell", "qrcode", + "rustc-hash 2.0.0", "thiserror", "unicode-segmentation", ] [[package]] name = "iced_winit" -version = "0.12.2" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63f66831d0e399b93f631739121a6171780d344b275d56808b9504d8ca75c7d2" +checksum = "f44cd4e1c594b6334f409282937bf972ba14d31fedf03c23aa595d982a2fda28" dependencies = [ + "iced_futures", "iced_graphics", "iced_runtime", - "iced_style", "log", + "rustc-hash 2.0.0", "thiserror", "tracing", + "wasm-bindgen-futures", "web-sys", "winapi", "window_clipboard", @@ -1434,14 +1797,13 @@ dependencies = [ ] [[package]] -name = "icrate" -version = "0.0.4" +name = "idna" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d3aaff8a54577104bafdf686ff18565c3b6903ca5782a2026ef06e2c7aa319" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ - "block2 0.3.0", - "dispatch", - "objc2 0.4.1", + "unicode-bidi", + "unicode-normalization", ] [[package]] @@ -1454,7 +1816,7 @@ dependencies = [ "byteorder", "color_quant", "exr", - "gif 0.13.1", + "gif", "jpeg-decoder", "num-traits", "png", @@ -1470,12 +1832,12 @@ checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284" [[package]] name = "indexmap" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.15.0", ] [[package]] @@ -1570,18 +1932,19 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" [[package]] name = "kurbo" -version = "0.9.5" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd85a5776cd9500c2e2059c8c76c3b01528566b7fcbaf8098b55a33fc298849b" +checksum = "1618d4ebd923e97d67e7cd363d80aef35fe961005cbbbb3d2dad8bdd1bc63440" dependencies = [ "arrayvec", + "smallvec", ] [[package]] name = "kurbo" -version = "0.10.4" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1618d4ebd923e97d67e7cd363d80aef35fe961005cbbbb3d2dad8bdd1bc63440" +checksum = "89234b2cc610a7dd927ebde6b41dd1a5d4214cffaef4cf1fb2195d592f92518f" dependencies = [ "arrayvec", "smallvec", @@ -1601,9 +1964,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libloading" @@ -1642,6 +2005,16 @@ dependencies = [ "redox_syscall 0.4.1", ] +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", +] + [[package]] name = "linked-hash-map" version = "0.5.6" @@ -1681,9 +2054,6 @@ name = "lru" version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" -dependencies = [ - "hashbrown", -] [[package]] name = "lyon" @@ -1754,20 +2124,20 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" -version = "0.8.0" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a5a03cefb0d953ec0be133036f14e109412fa594edc2f77227249db66cc3ed" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" dependencies = [ "libc", ] [[package]] -name = "memmap2" -version = "0.9.5" +name = "memoffset" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" dependencies = [ - "libc", + "autocfg", ] [[package]] @@ -1792,7 +2162,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", - "simd-adler32", ] [[package]] @@ -1802,6 +2171,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ "adler2", + "simd-adler32", ] [[package]] @@ -1823,7 +2193,7 @@ dependencies = [ "indexmap", "log", "num-traits", - "rustc-hash", + "rustc-hash 1.1.0", "spirv", "termcolor", "thiserror", @@ -1832,14 +2202,14 @@ dependencies = [ [[package]] name = "ndk" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ "bitflags 2.6.0", "jni-sys", "log", - "ndk-sys", + "ndk-sys 0.6.0+11769913", "num_enum", "raw-window-handle", "thiserror", @@ -1860,6 +2230,28 @@ dependencies = [ "jni-sys", ] +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "cfg_aliases 0.2.1", + "libc", + "memoffset", +] + [[package]] name = "num-conv" version = "0.1.0" @@ -1904,7 +2296,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1923,16 +2315,6 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" -[[package]] -name = "objc2" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "559c5a40fdd30eb5e344fbceacf7595a81e242529fb4e21cf5f43fb4f11ff98d" -dependencies = [ - "objc-sys", - "objc2-encode 3.0.0", -] - [[package]] name = "objc2" version = "0.5.2" @@ -1940,7 +2322,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" dependencies = [ "objc-sys", - "objc2-encode 4.0.3", + "objc2-encode", ] [[package]] @@ -1950,15 +2332,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" dependencies = [ "bitflags 2.6.0", - "block2 0.5.1", + "block2", "libc", - "objc2 0.5.2", + "objc2", "objc2-core-data", "objc2-core-image", "objc2-foundation", "objc2-quartz-core", ] +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", +] + [[package]] name = "objc2-core-data" version = "0.2.2" @@ -1966,8 +2372,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" dependencies = [ "bitflags 2.6.0", - "block2 0.5.1", - "objc2 0.5.2", + "block2", + "objc2", "objc2-foundation", ] @@ -1977,17 +2383,23 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" dependencies = [ - "block2 0.5.1", - "objc2 0.5.2", + "block2", + "objc2", "objc2-foundation", "objc2-metal", ] [[package]] -name = "objc2-encode" -version = "3.0.0" +name = "objc2-core-location" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2", + "objc2", + "objc2-contacts", + "objc2-foundation", +] [[package]] name = "objc2-encode" @@ -2002,9 +2414,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ "bitflags 2.6.0", - "block2 0.5.1", + "block2", + "dispatch", "libc", - "objc2 0.5.2", + "objc2", +] + +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2", + "objc2", + "objc2-app-kit", + "objc2-foundation", ] [[package]] @@ -2014,8 +2439,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" dependencies = [ "bitflags 2.6.0", - "block2 0.5.1", - "objc2 0.5.2", + "block2", + "objc2", "objc2-foundation", ] @@ -2026,12 +2451,67 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ "bitflags 2.6.0", - "block2 0.5.1", - "objc2 0.5.2", + "block2", + "objc2", "objc2-foundation", "objc2-metal", ] +[[package]] +name = "objc2-symbols" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-image", + "objc2-core-location", + "objc2-foundation", + "objc2-link-presentation", + "objc2-quartz-core", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-uniform-type-identifiers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", +] + [[package]] name = "objc_exception" version = "0.1.2" @@ -2052,9 +2532,12 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1" +dependencies = [ + "portable-atomic", +] [[package]] name = "onig" @@ -2084,7 +2567,27 @@ version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52f0d54bde9774d3a51dcf281a5def240c71996bc6ca05d2c847ec8b2b216166" dependencies = [ - "libredox", + "libredox 0.0.2", +] + +[[package]] +name = "ordered-multimap" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a" +dependencies = [ + "dlv-list", + "hashbrown 0.12.3", +] + +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", ] [[package]] @@ -2117,9 +2620,15 @@ dependencies = [ "by_address", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + [[package]] name = "parking_lot" version = "0.11.2" @@ -2163,7 +2672,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.4", + "redox_syscall 0.5.7", "smallvec", "windows-targets 0.52.6", ] @@ -2210,7 +2719,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -2219,7 +2728,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" dependencies = [ - "siphasher", + "siphasher 0.3.11", ] [[package]] @@ -2228,6 +2737,26 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "pin-project-lite" version = "0.2.14" @@ -2240,11 +2769,22 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "piper" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "plist" @@ -2261,15 +2801,15 @@ dependencies = [ [[package]] name = "png" -version = "0.17.13" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" +checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0" dependencies = [ "bitflags 1.3.2", "crc32fast", "fdeflate", "flate2", - "miniz_oxide 0.7.4", + "miniz_oxide 0.8.0", ] [[package]] @@ -2287,12 +2827,33 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "pollster" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" + +[[package]] +name = "portable-atomic" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" + [[package]] name = "powerfmt" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + [[package]] name = "presser" version = "0.3.1" @@ -2371,6 +2932,18 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", "rand_core", ] @@ -2379,6 +2952,9 @@ name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] [[package]] name = "range-alloc" @@ -2418,12 +2994,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "rctree" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b42e27ef78c35d3998403c1d26f3efd9e135d3e5121b0a4845cc5cc27547f4f" - [[package]] name = "read-fonts" version = "0.20.0" @@ -2445,36 +3015,38 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", ] [[package]] -name = "redox_syscall" -version = "0.5.4" +name = "redox_users" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "bitflags 2.6.0", + "getrandom", + "libredox 0.1.3", + "thiserror", ] [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "renderdoc-sys" @@ -2484,21 +3056,42 @@ checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" [[package]] name = "resvg" -version = "0.36.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7980f653f9a7db31acff916a262c3b78c562919263edea29bf41a056e20497" +checksum = "944d052815156ac8fa77eaac055220e95ba0b01fa8887108ca710c03805d9051" dependencies = [ - "gif 0.12.0", + "gif", "jpeg-decoder", "log", "pico-args", - "png", "rgb", "svgtypes", "tiny-skia", "usvg", ] +[[package]] +name = "rfd" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8af382a047821a08aa6bfc09ab0d80ff48d45d8726f7cd8e44891f7cb4a4278e" +dependencies = [ + "ashpd", + "block2", + "js-sys", + "log", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "pollster", + "raw-window-handle", + "urlencoding", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-sys 0.48.0", +] + [[package]] name = "rgb" version = "0.8.50" @@ -2508,15 +3101,6 @@ dependencies = [ "bytemuck", ] -[[package]] -name = "roxmltree" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862340e351ce1b271a378ec53f304a5558f7db87f3769dc655a8f6ecbb68b302" -dependencies = [ - "xmlparser", -] - [[package]] name = "roxmltree" version = "0.20.0" @@ -2529,6 +3113,16 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60e7c00b6c3bf5e38a880eec01d7e829d12ca682079f8238a464def3c4b31627" +[[package]] +name = "rust-ini" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df" +dependencies = [ + "cfg-if", + "ordered-multimap", +] + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -2541,6 +3135,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc-hash" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" + [[package]] name = "rustix" version = "0.38.37" @@ -2556,31 +3156,15 @@ dependencies = [ [[package]] name = "rustybuzz" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71cd15fef9112a1f94ac64b58d1e4628192631ad6af4dc69997f995459c874e7" -dependencies = [ - "bitflags 1.3.2", - "bytemuck", - "smallvec", - "ttf-parser 0.19.2", - "unicode-bidi-mirroring", - "unicode-ccc", - "unicode-properties", - "unicode-script", -] - -[[package]] -name = "rustybuzz" -version = "0.11.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ee8fe2a8461a0854a37101fe7a1b13998d0cfa987e43248e81d2a5f4570f6fa" +checksum = "cfb9cf8877777222e4a3bc7eb247e398b56baba500c38c1c46842431adc8b55c" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "bytemuck", "libm", "smallvec", - "ttf-parser 0.20.0", + "ttf-parser 0.21.1", "unicode-bidi-mirroring", "unicode-ccc", "unicode-properties", @@ -2616,14 +3200,14 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sctk-adwaita" -version = "0.8.3" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70b31447ca297092c5a9916fc3b955203157b37c19ca8edde4f52e9843e602c7" +checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" dependencies = [ "ab_glyph", "log", - "memmap2 0.9.5", - "smithay-client-toolkit 0.18.1", + "memmap2", + "smithay-client-toolkit", "tiny-skia", ] @@ -2650,7 +3234,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -2665,12 +3249,43 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_repr" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + [[package]] name = "simd-adler32" version = "0.3.7" @@ -2692,6 +3307,12 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + [[package]] name = "skrifa" version = "0.20.0" @@ -2726,31 +3347,6 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" -[[package]] -name = "smithay-client-toolkit" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "922fd3eeab3bd820d76537ce8f582b1cf951eceb5475c28500c7457d9d17f53a" -dependencies = [ - "bitflags 2.6.0", - "calloop 0.12.4", - "calloop-wayland-source 0.2.0", - "cursor-icon", - "libc", - "log", - "memmap2 0.9.5", - "rustix", - "thiserror", - "wayland-backend", - "wayland-client", - "wayland-csd-frame", - "wayland-cursor", - "wayland-protocols 0.31.2", - "wayland-protocols-wlr 0.2.0", - "wayland-scanner", - "xkeysym", -] - [[package]] name = "smithay-client-toolkit" version = "0.19.2" @@ -2758,20 +3354,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" dependencies = [ "bitflags 2.6.0", - "calloop 0.13.0", - "calloop-wayland-source 0.3.0", + "calloop", + "calloop-wayland-source", "cursor-icon", "libc", "log", - "memmap2 0.9.5", + "memmap2", "rustix", "thiserror", "wayland-backend", "wayland-client", "wayland-csd-frame", "wayland-cursor", - "wayland-protocols 0.32.4", - "wayland-protocols-wlr 0.3.4", + "wayland-protocols", + "wayland-protocols-wlr", "wayland-scanner", "xkeysym", ] @@ -2783,7 +3379,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc8216eec463674a0e90f29e0ae41a4db573ec5b56b1c6c1c71615d249b6d846" dependencies = [ "libc", - "smithay-client-toolkit 0.19.2", + "smithay-client-toolkit", "wayland-backend", ] @@ -2811,12 +3407,12 @@ dependencies = [ "foreign-types", "js-sys", "log", - "memmap2 0.9.5", - "objc2 0.5.2", + "memmap2", + "objc2", "objc2-foundation", "objc2-quartz-core", "raw-window-handle", - "redox_syscall 0.5.4", + "redox_syscall 0.5.7", "rustix", "tiny-xlib", "wasm-bindgen", @@ -2869,12 +3465,12 @@ checksum = "20e16a0f46cf5fd675563ef54f26e83e20f2366bcf027bcb3cc3ed2b98aaf2ca" [[package]] name = "svgtypes" -version = "0.12.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71499ff2d42f59d26edb21369a308ede691421f79ebc0f001e2b1fd3a7c9e52" +checksum = "794de53cc48eaabeed0ab6a3404a65f40b3e38c067e4435883a65d2aa4ca000e" dependencies = [ - "kurbo 0.9.5", - "siphasher", + "kurbo 0.11.1", + "siphasher 1.0.1", ] [[package]] @@ -2901,9 +3497,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.77" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -2941,6 +3537,19 @@ dependencies = [ "libc", ] +[[package]] +name = "tempfile" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + [[package]] name = "termcolor" version = "1.4.1" @@ -2967,7 +3576,7 @@ checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -3084,9 +3693,9 @@ checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" [[package]] name = "toml_edit" -version = "0.22.21" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b072cee73c449a636ffd6f32bd8de3a9f7119139aff882f44943ce2986dc5cf" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ "indexmap", "toml_datetime", @@ -3112,7 +3721,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -3126,15 +3735,15 @@ dependencies = [ [[package]] name = "ttf-parser" -version = "0.19.2" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49d64318d8311fc2668e48b63969f4343e0a85c4a109aa8460d6672e364b8bd1" +checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4" [[package]] name = "ttf-parser" -version = "0.20.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4" +checksum = "2c591d83f69777866b9126b24c6dd9a18351f177e49d625920d19f989fd31cf8" [[package]] name = "ttf-parser" @@ -3142,23 +3751,40 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5be21190ff5d38e8b4a2d3b6a3ae57f612cc39c96e83cedeaf7abc338a8bac4a" +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "uds_windows" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" +dependencies = [ + "memoffset", + "tempfile", + "winapi", +] + [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-bidi-mirroring" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56d12260fb92d52f9008be7e4bca09f584780eb2266dc8fecc6a192bec561694" +checksum = "23cb788ffebc92c5948d0e997106233eeb1d8b9512f93f41651f52b6c5f5af86" [[package]] name = "unicode-ccc" -version = "0.1.2" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2520efa644f8268dce4dcd3050eaa7fc044fca03961e9998ac7e2e92b77cf1" +checksum = "1df77b101bcc4ea3d78dafc5ad7e4f58ceffe0b2b16bf446aeb50b6cb4157656" [[package]] name = "unicode-ident" @@ -3172,11 +3798,20 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + [[package]] name = "unicode-properties" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ea75f83c0137a9b98608359a5f1af8144876eb67bcb1ce837368e906a9f524" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" [[package]] name = "unicode-script" @@ -3220,64 +3855,48 @@ dependencies = [ ] [[package]] -name = "usvg" -version = "0.36.0" +name = "url" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51daa774fe9ee5efcf7b4fec13019b8119cda764d9a8b5b06df02bb1445c656" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ - "base64 0.21.7", - "log", - "pico-args", - "usvg-parser", - "usvg-text-layout", - "usvg-tree", - "xmlwriter", + "form_urlencoded", + "idna", + "percent-encoding", + "serde", ] [[package]] -name = "usvg-parser" -version = "0.36.0" +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + +[[package]] +name = "usvg" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45c88a5ffaa338f0e978ecf3d4e00d8f9f493e29bed0752e1a808a1db16afc40" +checksum = "b84ea542ae85c715f07b082438a4231c3760539d902e11d093847a0b22963032" dependencies = [ + "base64 0.22.1", "data-url", "flate2", + "fontdb 0.18.0", "imagesize", - "kurbo 0.9.5", + "kurbo 0.11.1", "log", - "roxmltree 0.18.1", + "pico-args", + "roxmltree", + "rustybuzz", "simplecss", - "siphasher", + "siphasher 1.0.1", + "strict-num", "svgtypes", - "usvg-tree", -] - -[[package]] -name = "usvg-text-layout" -version = "0.36.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d2374378cb7a3fb8f33894e0fdb8625e1bbc4f25312db8d91f862130b541593" -dependencies = [ - "fontdb", - "kurbo 0.9.5", - "log", - "rustybuzz 0.10.0", + "tiny-skia-path", "unicode-bidi", "unicode-script", "unicode-vo", - "usvg-tree", -] - -[[package]] -name = "usvg-tree" -version = "0.36.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cacb0c5edeaf3e80e5afcf5b0d4004cc1d36318befc9a7c6606507e5d0f4062" -dependencies = [ - "rctree", - "strict-num", - "svgtypes", - "tiny-skia-path", + "xmlwriter", ] [[package]] @@ -3333,7 +3952,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", "wasm-bindgen-shared", ] @@ -3367,7 +3986,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3441,18 +4060,6 @@ dependencies = [ "xcursor", ] -[[package]] -name = "wayland-protocols" -version = "0.31.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4" -dependencies = [ - "bitflags 2.6.0", - "wayland-backend", - "wayland-client", - "wayland-scanner", -] - [[package]] name = "wayland-protocols" version = "0.32.4" @@ -3467,27 +4074,14 @@ dependencies = [ [[package]] name = "wayland-protocols-plasma" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23803551115ff9ea9bce586860c5c5a971e360825a0309264102a9495a5ff479" -dependencies = [ - "bitflags 2.6.0", - "wayland-backend", - "wayland-client", - "wayland-protocols 0.31.2", - "wayland-scanner", -] - -[[package]] -name = "wayland-protocols-wlr" -version = "0.2.0" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" +checksum = "8a0a41a6875e585172495f7a96dfa42ca7e0213868f4f15c313f7c33221a7eff" dependencies = [ "bitflags 2.6.0", "wayland-backend", "wayland-client", - "wayland-protocols 0.31.2", + "wayland-protocols", "wayland-scanner", ] @@ -3500,7 +4094,7 @@ dependencies = [ "bitflags 2.6.0", "wayland-backend", "wayland-client", - "wayland-protocols 0.32.4", + "wayland-protocols", "wayland-scanner", ] @@ -3529,9 +4123,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.67" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" dependencies = [ "js-sys", "wasm-bindgen", @@ -3539,9 +4133,9 @@ dependencies = [ [[package]] name = "web-time" -version = "0.2.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa30049b1c872b72c89866d458eae9f20380ab280ffd1b1e18df2d3e2d98cfe0" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ "js-sys", "wasm-bindgen", @@ -3596,7 +4190,7 @@ dependencies = [ "parking_lot 0.12.3", "profiling", "raw-window-handle", - "rustc-hash", + "rustc-hash 1.1.0", "smallvec", "thiserror", "web-sys", @@ -3632,7 +4226,7 @@ dependencies = [ "log", "metal", "naga", - "ndk-sys", + "ndk-sys 0.5.0+25.2.9519653", "objc", "once_cell", "parking_lot 0.12.3", @@ -3640,7 +4234,7 @@ dependencies = [ "range-alloc", "raw-window-handle", "renderdoc-sys", - "rustc-hash", + "rustc-hash 1.1.0", "smallvec", "thiserror", "wasm-bindgen", @@ -3946,47 +4540,51 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winit" -version = "0.29.15" +version = "0.30.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d59ad965a635657faf09c8f062badd885748428933dad8e8bdd64064d92e5ca" +checksum = "0be9e76a1f1077e04a411f0b989cbd3c93339e1771cb41e71ac4aee95bfd2c67" dependencies = [ - "ahash", + "ahash 0.8.11", "android-activity", "atomic-waker", "bitflags 2.6.0", + "block2", "bytemuck", - "calloop 0.12.4", - "cfg_aliases 0.1.1", + "calloop", + "cfg_aliases 0.2.1", + "concurrent-queue", "core-foundation 0.9.4", "core-graphics 0.23.2", "cursor-icon", - "icrate", + "dpi", "js-sys", "libc", - "log", - "memmap2 0.9.5", + "memmap2", "ndk", - "ndk-sys", - "objc2 0.4.1", - "once_cell", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "objc2-ui-kit", "orbclient", "percent-encoding", + "pin-project", "raw-window-handle", - "redox_syscall 0.3.5", + "redox_syscall 0.4.1", "rustix", "sctk-adwaita", - "smithay-client-toolkit 0.18.1", + "smithay-client-toolkit", "smol_str", + "tracing", "unicode-segmentation", "wasm-bindgen", "wasm-bindgen-futures", "wayland-backend", "wayland-client", - "wayland-protocols 0.31.2", + "wayland-protocols", "wayland-protocols-plasma", "web-sys", "web-time", - "windows-sys 0.48.0", + "windows-sys 0.52.0", "x11-dl", "x11rb", "xkbcommon-dl", @@ -3994,13 +4592,22 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.18" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] + [[package]] name = "x11-dl" version = "2.21.0" @@ -4039,6 +4646,16 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ef33da6b1660b4ddbfb3aef0ade110c8b8a781a3b6382fa5f2b5b040fd55f61" +[[package]] +name = "xdg-home" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "xkbcommon-dl" version = "0.4.2" @@ -4064,24 +4681,12 @@ version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26" -[[package]] -name = "xmlparser" -version = "0.13.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" - [[package]] name = "xmlwriter" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" -[[package]] -name = "xxhash-rust" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984" - [[package]] name = "yaml-rust" version = "0.4.5" @@ -4097,6 +4702,68 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c94451ac9513335b5e23d7a8a2b61a7102398b8cca5160829d313e84c9d98be1" +[[package]] +name = "zbus" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725" +dependencies = [ + "async-broadcast", + "async-executor", + "async-fs", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "enumflags2", + "event-listener", + "futures-core", + "futures-sink", + "futures-util", + "hex", + "nix", + "ordered-stream", + "rand", + "serde", + "serde_repr", + "sha1", + "static_assertions", + "tracing", + "uds_windows", + "windows-sys 0.52.0", + "xdg-home", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267db9407081e90bbfa46d841d3cbc60f59c0351838c4bc65199ecd79ab1983e" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.79", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" +dependencies = [ + "serde", + "static_assertions", + "zvariant", +] + [[package]] name = "zeno" version = "0.2.3" @@ -4109,6 +4776,7 @@ version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] @@ -4120,7 +4788,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -4131,3 +4799,41 @@ checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" dependencies = [ "simd-adler32", ] + +[[package]] +name = "zvariant" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2084290ab9a1c471c38fc524945837734fbf124487e105daec2bb57fd48c81fe" +dependencies = [ + "endi", + "enumflags2", + "serde", + "static_assertions", + "url", + "zvariant_derive", +] + +[[package]] +name = "zvariant_derive" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73e2ba546bda683a90652bac4a279bc146adad1386f25379cf73200d2002c449" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.79", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] diff --git a/iced_builder/Cargo.toml b/iced_builder/Cargo.toml index 8106b09..a7b1e7b 100644 --- a/iced_builder/Cargo.toml +++ b/iced_builder/Cargo.toml @@ -9,12 +9,13 @@ license = "GPL-3.0-or-later" keywords = ["gui", "iced"] [dependencies] -iced = { version = "0.12.1", features = [ "image","svg","canvas","qr_code","advanced","tokio","highlighter"] } -iced_aw = { version = "0.9.3", default-features = false, features = ["menu","color_picker"] } +iced = { version = "0.13.1", features = [ "image","svg","canvas","qr_code","advanced","tokio","highlighter"] } +iced_aw = { version = "0.11.0", default-features = false, features = ["menu","color_picker"] } iced_drop = { path = "../iced_drop" } serde = { version = "1.0.210", features = ["derive"] } serde_json = "1.0.128" tokio = { version = "1.40.0", features = ["fs"] } +rfd = "0.15.0" rust-format = "0.3.4" unique_id = "0.1.5" diff --git a/iced_builder/src/codegen/mod.rs b/iced_builder/src/codegen/mod.rs index 927b6e4..38e8ec3 100644 --- a/iced_builder/src/codegen/mod.rs +++ b/iced_builder/src/codegen/mod.rs @@ -1,8 +1,12 @@ use rust_format::{Config, Edition, Formatter, RustFmt}; -use crate::types::{ - rendered_element::{container, row, svg, text, RenderedElement}, - ElementName, +use crate::{ + types::{ + project::Project, + rendered_element::{container, row, svg, text, RenderedElement}, + ElementName, + }, + Error, }; impl RenderedElement { @@ -10,8 +14,8 @@ impl RenderedElement { let mut props_string = String::new(); for (k, v) in self.props.clone() { - if let Some(value) = v { - props_string = format!("{props_string}.{k}({value})"); + if let Some(v) = v { + props_string = format!("{props_string}.{k}({v})"); } } @@ -81,70 +85,62 @@ impl RenderedElement { (imports, view) } - pub fn app_code( - &self, - title: &str, - theme: Option, - ) -> Result> { - let (imports, view) = self.codegen(); - let mut app_code = format!("use iced::{{widget::{{{imports}}},Sandbox,Settings,Element}};"); - - app_code = format!( - r#"// Automatically generated by iced Builder - {app_code} - - fn main() -> iced::Result {{ - App::run(Settings::default()) - }} - - struct App; - - impl Sandbox for App {{ - type Message = (); - - fn new() -> Self {{ - Self {{}} - }} - - fn title(&self) -> String {{ - "{title}".into() - }} - - fn theme(&self) -> iced::Theme {{ - iced::Theme::{} - }} - - fn update(&mut self, message: Self::Message) {{ - - }} - - fn view(&self) -> Element {{ - {view}.into() - }} - }}"#, - if let Some(c) = theme { - c.to_string().replace(' ', "") - } else { - "default()".to_owned() - } - ); - let config = Config::new_str() - .edition(Edition::Rust2021) - .option("trailing_comma", "Never") - .option("imports_granularity", "Crate"); - let rustfmt = RustFmt::from_config(config); - Ok(rustfmt.format_str(app_code)?) - } - pub fn test() -> RenderedElement { - let text1 = text("wow").option("height", "120.5").option("width", "230"); + let mut text1 = text("wow"); + text1.option("height", "120.5"); + text1.option("width", "230"); - let element = container(row(vec![ + let element = container(Some(row(Some(vec![ text1, text("heh"), svg("/mnt/drive_d/git/obs-website/src/lib/assets/bars-solid.svg"), - ])); + ])))); element } } + +impl Project { + pub fn app_code(self) -> Result { + match &self.content { + Some(el) => { + let (imports, view) = el.codegen(); + let mut app_code = format!("use iced::{{widget::{{{imports}}},Element}};"); + + app_code = format!( + r#"// Automatically generated by iced Builder + {app_code} + + fn main() -> iced::Result {{ + iced::run("{}", State::update, State::view) + }} + + #[derive(Default)] + struct State; + + #[derive(Debug, Clone)] + enum Message {{}} + + impl State {{ + fn update(&mut self, _message: Message) {{}} + + fn view(&self) -> Element {{ + {view}.into() + }} + }}"#, + match &self.title { + Some(t) => t, + None => "New app", + } + ); + let config = Config::new_str() + .edition(Edition::Rust2021) + .option("trailing_comma", "Never") + .option("imports_granularity", "Crate"); + let rustfmt = RustFmt::from_config(config); + Ok(rustfmt.format_str(app_code)?) + } + None => Err("No element tree present".into()), + } + } +} diff --git a/iced_builder/src/lib.rs b/iced_builder/src/lib.rs index e69de29..971e0e3 100644 --- a/iced_builder/src/lib.rs +++ b/iced_builder/src/lib.rs @@ -0,0 +1,85 @@ +pub mod codegen; +pub mod types; + +use std::path::PathBuf; + +use iced::widget::{pane_grid, text_editor}; +use types::{project::Project, rendered_element::RenderedElement, DesignerPage}; + +#[derive(Debug, Clone)] +pub enum Error { + IOError(std::io::ErrorKind), + SerdeError(String), + FormatError(String), + DialogClosed, + String(String), +} + +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::SerdeError(string) | Self::FormatError(string) | Self::String(string) => { + write!(f, "{}", string) + } + Self::IOError(kind) => { + write!(f, "{}", kind) + } + Self::DialogClosed => { + write!( + f, + "The file dialog has been closed without selecting a valid option." + ) + } + } + } +} + +impl From for Error { + fn from(value: std::io::Error) -> Self { + Self::IOError(value.kind()) + } +} + +impl From for Error { + fn from(value: serde_json::Error) -> Self { + Self::SerdeError(value.to_string()) + } +} + +impl From for Error { + fn from(value: rust_format::Error) -> Self { + Self::FormatError(value.to_string()) + } +} + +impl From<&'static str> for Error { + fn from(value: &'static str) -> Self { + Self::String(value.to_owned()) + } +} + +#[derive(Debug, Clone)] +pub enum Message { + ToggleTheme, + CopyCode, + SwitchPage(DesignerPage), + EditorAction(text_editor::Action), + DropNewElement(types::ElementName, iced::Point, iced::Rectangle), + HandleNew( + types::ElementName, + Vec<(iced::advanced::widget::Id, iced::Rectangle)>, + ), + MoveElement(RenderedElement, iced::Point, iced::Rectangle), + HandleMove( + RenderedElement, + Vec<(iced::advanced::widget::Id, iced::Rectangle)>, + ), + Resized(pane_grid::ResizeEvent), + Clicked(pane_grid::Pane), + PaneDragged(pane_grid::DragEvent), + NewFile, + OpenFile, + FileOpened(Result<(PathBuf, Project), Error>), + SaveFile, + FileSaved(Result), +} diff --git a/iced_builder/src/main.rs b/iced_builder/src/main.rs index f0f58cc..aeb5ea6 100644 --- a/iced_builder/src/main.rs +++ b/iced_builder/src/main.rs @@ -1,67 +1,50 @@ -mod codegen; -mod types; +use std::path::PathBuf; use iced::{ - clipboard, executor, - highlighter::{self, Highlighter}, - theme, + clipboard, highlighter, keyboard, widget::{ button, column, container, pane_grid::{self, Pane, PaneGrid}, row, text, text_editor, tooltip, Column, Space, }, - Alignment, Application, Color, Command, Element, Font, Length, Settings, + Alignment, Element, Font, Length, Settings, Task, Theme, }; +use iced_builder::types::{project::Project, DesignerPage, ElementName}; +use iced_builder::Message; use iced_drop::droppable; -use types::{rendered_element::RenderedElement, DesignerPage, DesignerState}; fn main() -> iced::Result { - App::run(Settings { - fonts: vec![include_bytes!("../fonts/icons.ttf").as_slice().into()], - ..Settings::default() - }) + iced::application(App::title, App::update, App::view) + .settings(Settings { + fonts: vec![include_bytes!("../fonts/icons.ttf").as_slice().into()], + ..Settings::default() + }) + .theme(App::theme) + .subscription(App::subscription) + .run_with(App::new) } struct App { - is_saved: bool, - current_project: Option, + is_dirty: bool, + is_loading: bool, + project_path: Option, + project: Project, dark_theme: bool, pane_state: pane_grid::State, focus: Option, - designer_state: DesignerState, - element_list: Vec, + designer_page: DesignerPage, + element_list: Vec, editor_content: text_editor::Content, } -#[derive(Debug, Clone)] -enum Message { - ToggleTheme, - CopyCode, - SwitchPage(DesignerPage), - EditorAction(text_editor::Action), - Drop(types::ElementName, iced::Point, iced::Rectangle), - HandleZones( - types::ElementName, - Vec<(iced::advanced::widget::Id, iced::Rectangle)>, - ), - Resized(pane_grid::ResizeEvent), - Clicked(pane_grid::Pane), - PaneDragged(pane_grid::DragEvent), -} - #[derive(Clone, Debug)] enum Panes { Designer, ElementList, } -impl Application for App { - type Message = Message; - type Theme = theme::Theme; - type Executor = executor::Default; - type Flags = (); - - fn new(_flags: ()) -> (Self, Command) { +impl App { + fn new() -> (Self, Task) { let state = pane_grid::State::with_configuration(pane_grid::Configuration::Split { axis: pane_grid::Axis::Vertical, ratio: 0.8, @@ -70,26 +53,25 @@ impl Application for App { }); ( Self { - is_saved: true, - current_project: None, + is_dirty: false, + is_loading: false, + project_path: None, + project: Project::new(), dark_theme: true, pane_state: state, focus: None, - designer_state: DesignerState { - designer_content: Some(RenderedElement::test()), - designer_page: DesignerPage::Designer, - }, - element_list: types::ElementName::ALL.to_vec(), + designer_page: DesignerPage::Designer, + element_list: ElementName::ALL.to_vec(), editor_content: text_editor::Content::new(), }, - Command::none(), + Task::none(), ) } fn title(&self) -> String { - let saved_state = if self.is_saved { "" } else { " *" }; + let saved_state = if !self.is_dirty { "" } else { " *" }; - let project_name = match &self.current_project { + let project_name = match &self.project.title { Some(n) => { format!( " - {}", @@ -108,17 +90,17 @@ impl Application for App { fn theme(&self) -> iced::Theme { if self.dark_theme { - theme::Theme::CatppuccinMocha + Theme::SolarizedDark } else { - theme::Theme::CatppuccinLatte + Theme::SolarizedLight } } - fn update(&mut self, message: Message) -> Command { + fn update(&mut self, message: Message) -> Task { match message { Message::ToggleTheme => self.dark_theme = !self.dark_theme, Message::CopyCode => return clipboard::write(self.editor_content.text()), - Message::SwitchPage(page) => self.designer_state.designer_page = page, + Message::SwitchPage(page) => self.designer_page = page, Message::EditorAction(action) => { if let text_editor::Action::Scroll { lines: _ } = action { self.editor_content.perform(action); @@ -130,38 +112,103 @@ impl Application for App { Message::Clicked(pane) => { self.focus = Some(pane); } - Message::Drop(name, point, _) => { + Message::DropNewElement(name, point, _) => { return iced_drop::zones_on_point( - move |zones| Message::HandleZones(name.clone(), zones), + move |zones| Message::HandleNew(name.clone(), zones), point, None, None, ) .into() } - Message::HandleZones(name, zones) => { - println!("{:?}\n{name}", zones); - println!("{:?}\n{name}\n{:?}", zones, self.title()); - if let Some(el) = &self.designer_state.designer_content { - self.editor_content = text_editor::Content::with_text( - &el.app_code( - match &self.current_project { - Some(title) => &title, - None => "New App", - }, - None, - ) - .unwrap(), - ); - } + Message::HandleNew(name, zones) => { + println!("\n\n{:?}\n{name}\n{:?}", zones, self.title()); + let code = self + .project + .clone() + .app_code() + .unwrap_or_else(|err| err.to_string()); + self.editor_content = text_editor::Content::with_text(&code); + } + Message::MoveElement(element, point, _) => { + return iced_drop::zones_on_point( + move |zones| Message::HandleMove(element.clone(), zones), + point, + None, + None, + ) + .into() + } + Message::HandleMove(element, zones) => { + println!( + "\n\n{:?}\n{element:0.4}", + zones + .into_iter() + .map(|c| c.0) + .collect::>() + ); } Message::PaneDragged(pane_grid::DragEvent::Dropped { pane, target }) => { self.pane_state.drop(pane, target); } Message::PaneDragged(_) => {} + Message::NewFile => { + if !self.is_loading { + self.project = Project::new(); + self.project_path = None; + self.editor_content = text_editor::Content::new(); + } + } + Message::OpenFile => { + if !self.is_loading { + self.is_loading = true; + + return Task::perform(Project::from_file(), Message::FileOpened); + } + } + Message::FileOpened(result) => { + self.is_loading = false; + self.is_dirty = false; + + if let Ok((path, project)) = result { + self.project = project.clone(); + self.project_path = Some(path); + self.editor_content = text_editor::Content::with_text( + &project.app_code().unwrap_or_else(|err| err.to_string()), + ); + } + } + Message::SaveFile => { + if !self.is_loading { + self.is_loading = true; + + return Task::perform( + self.project + .clone() + .write_to_file(self.project_path.clone()), + Message::FileSaved, + ); + } + } + Message::FileSaved(result) => { + self.is_loading = false; + + if let Ok(path) = result { + self.project_path = Some(path); + self.is_dirty = false; + } + } } - Command::none() + Task::none() + } + + fn subscription(&self) -> iced::Subscription { + keyboard::on_key_press(|key, modifiers| match key.as_ref() { + keyboard::Key::Character("o") if modifiers.command() => Some(Message::OpenFile), + keyboard::Key::Character("s") if modifiers.command() => Some(Message::SaveFile), + _ => None, + }) } fn view(&self) -> Element { @@ -172,28 +219,23 @@ impl Application for App { let pane_grid = PaneGrid::new(&self.pane_state, |id, pane, _is_maximized| { let is_focused = Some(id) == self.focus; match pane { - Panes::Designer => match &self.designer_state.designer_page { + Panes::Designer => match &self.designer_page { DesignerPage::Designer => { - let content = container(text(format!( - "{:0.4}", - self.designer_state - .designer_content - .clone() - .expect("Designer content hasn't been set yet."), - ))) - .id(iced::widget::container::Id::new("drop_zone")) - .height(Length::Fill) - .width(Length::Fill); + let el_tree = match self.project.content.clone() { + Some(tree) => tree.as_element(), + None => text("Open a project or begin creating one").into(), + }; + let content = container(el_tree) + .id(iced::widget::container::Id::new("drop_zone")) + .height(Length::Fill) + .width(Length::Fill); let title = row![ - text("Designer").style(if is_focused { - PANE_ID_COLOR_FOCUSED - } else { - PANE_ID_COLOR_UNFOCUSED - }), + text("Designer"), Space::with_width(Length::Fill), button("Switch to Code view") .on_press(Message::SwitchPage(DesignerPage::CodeView)), - ]; + ] + .align_y(Alignment::Center); let title_bar = pane_grid::TitleBar::new(title) .padding(10) .style(style::title_bar); @@ -207,44 +249,37 @@ impl Application for App { } DesignerPage::CodeView => { let title = row![ - text("Generated Code").style(if is_focused { - PANE_ID_COLOR_FOCUSED - } else { - PANE_ID_COLOR_UNFOCUSED - }), + text("Generated Code"), Space::with_width(Length::Fill), tooltip( button( container( text('\u{0e801}').font(Font::with_name("editor-icons")) ) - .width(30) - .center_x() + .center_x(30) ) .on_press(Message::CopyCode), "Copy code to clipboard", - tooltip::Position::Left + tooltip::Position::FollowCursor ), Space::with_width(20), button("Switch to Designer view") .on_press(Message::SwitchPage(DesignerPage::Designer)) - ]; + ] + .align_y(Alignment::Center); let title_bar = pane_grid::TitleBar::new(title) .padding(10) .style(style::title_bar); pane_grid::Content::new( text_editor(&self.editor_content) .on_action(Message::EditorAction) - .highlight::( - highlighter::Settings { - theme: if self.dark_theme { - highlighter::Theme::Base16Mocha - } else { - highlighter::Theme::InspiredGitHub - }, - extension: "rs".to_string(), + .highlight( + "rs", + if self.dark_theme { + highlighter::Theme::SolarizedDark + } else { + highlighter::Theme::InspiredGitHub }, - |highlight, _theme| highlight.to_format(), ) .height(Length::Fill) .padding(20), @@ -260,14 +295,10 @@ impl Application for App { Panes::ElementList => { let items_list = items_list_view(self.element_list.clone()); let content = column![items_list] - .align_items(Alignment::Center) + .align_x(Alignment::Center) .height(Length::Fill) .width(Length::Fill); - let title = text("Element List").style(if is_focused { - PANE_ID_COLOR_FOCUSED - } else { - PANE_ID_COLOR_UNFOCUSED - }); + let title = text("Element List"); let title_bar = pane_grid::TitleBar::new(title) .padding(10) .style(style::title_bar); @@ -292,39 +323,24 @@ impl Application for App { .push(header) .push(pane_grid) .spacing(5) - .align_items(Alignment::Center) + .align_x(Alignment::Center) .width(Length::Fill); container(content).height(Length::Fill).into() } } -const fn from_grayscale(grayscale: f32) -> Color { - Color { - r: grayscale, - g: grayscale, - b: grayscale, - a: 1.0, - } -} - -// #ffffff -const PANE_ID_COLOR_FOCUSED: Color = from_grayscale(1.0); - -// #e8e8e8 -const PANE_ID_COLOR_UNFOCUSED: Color = from_grayscale(0xE8 as f32 / 255.0); - -fn items_list_view(items: Vec) -> Element<'static, Message> { +fn items_list_view<'a>(items: Vec) -> Element<'a, Message> { let mut column = Column::new() .spacing(20) - .align_items(Alignment::Center) + .align_x(Alignment::Center) .width(Length::Fill); for item in items { let value = item.clone(); column = column.push( droppable(text(value.to_string())) - .on_drop(move |point, rect| Message::Drop(value.clone(), point, rect)), + .on_drop(move |point, rect| Message::DropNewElement(value.clone(), point, rect)), ); } @@ -332,23 +348,23 @@ fn items_list_view(items: Vec) -> Element<'static, Message> } mod style { - use iced::widget::container; - use iced::{Border, Theme}; + use iced::widget::{container::Style as CStyle, text::Style as TStyle}; + use iced::{color, Border, Theme}; - pub fn title_bar(theme: &Theme) -> container::Appearance { + pub fn title_bar(theme: &Theme) -> CStyle { let palette = theme.extended_palette(); - container::Appearance { + CStyle { text_color: Some(palette.background.strong.text), background: Some(palette.background.strong.color.into()), ..Default::default() } } - pub fn pane_active(theme: &Theme) -> container::Appearance { + pub fn pane_active(theme: &Theme) -> CStyle { let palette = theme.extended_palette(); - container::Appearance { + CStyle { background: Some(palette.background.weak.color.into()), border: Border { width: 1.0, @@ -359,10 +375,10 @@ mod style { } } - pub fn pane_focused(theme: &Theme) -> container::Appearance { + pub fn pane_focused(theme: &Theme) -> CStyle { let palette = theme.extended_palette(); - container::Appearance { + CStyle { background: Some(palette.background.weak.color.into()), border: Border { width: 4.0, diff --git a/iced_builder/src/types/mod.rs b/iced_builder/src/types/mod.rs index 344f543..2d6cd8f 100644 --- a/iced_builder/src/types/mod.rs +++ b/iced_builder/src/types/mod.rs @@ -1,15 +1,9 @@ +pub mod project; pub mod rendered_element; -use rendered_element::RenderedElement; use serde::{Deserialize, Serialize}; -#[derive(Clone)] -pub struct DesignerState { - pub designer_content: Option, - pub designer_page: DesignerPage, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum ElementName { Text(String), Button(String), diff --git a/iced_builder/src/types/project/mod.rs b/iced_builder/src/types/project/mod.rs new file mode 100644 index 0000000..557fa92 --- /dev/null +++ b/iced_builder/src/types/project/mod.rs @@ -0,0 +1,59 @@ +use std::path::{Path, PathBuf}; + +use serde::{Deserialize, Serialize}; + +use crate::Error; + +use super::rendered_element::RenderedElement; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Project { + pub title: Option, + pub content: Option, +} + +impl Project { + pub fn new() -> Self { + Self { + title: None, + content: None, + } + } + + pub async fn from_file() -> Result<(PathBuf, Self), Error> { + let picked_file = rfd::AsyncFileDialog::new() + .set_title("Open a JSON file...") + .add_filter("*.JSON, *.json", &["JSON", "json"]) + .pick_file() + .await + .ok_or(Error::DialogClosed)?; + + let path = picked_file.path().to_owned(); + + let contents = tokio::fs::read_to_string(&path).await?; + let element: Self = serde_json::from_str(&contents)?; + + Ok((path, element)) + } + + pub async fn write_to_file(self, path: Option) -> Result { + let path = if let Some(p) = path { + p + } else { + rfd::AsyncFileDialog::new() + .set_title("Save to JSON file...") + .add_filter("*.JSON, *.json", &["JSON", "json"]) + .save_file() + .await + .as_ref() + .map(rfd::FileHandle::path) + .map(Path::to_owned) + .ok_or(Error::DialogClosed)? + }; + + let contents = serde_json::to_string(&self.clone())?; + tokio::fs::write(&path, contents).await?; + + Ok(path) + } +} diff --git a/iced_builder/src/types/rendered_element.rs b/iced_builder/src/types/rendered_element.rs index 2d5c81a..967352b 100644 --- a/iced_builder/src/types/rendered_element.rs +++ b/iced_builder/src/types/rendered_element.rs @@ -1,11 +1,15 @@ use std::collections::HashMap; +use iced::advanced::widget::Id; +use iced::{widget, Element, Length}; use serde::{Deserialize, Serialize}; use unique_id::{string::StringGenerator, Generator}; +use crate::Message; + use super::ElementName; -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct RenderedElement { pub id: String, pub child_elements: Option>, @@ -34,27 +38,104 @@ impl RenderedElement { } } - fn preset_options(mut self, options: Vec<&str>) -> Self { - for opt in options { - self.props.insert(opt.to_owned(), None); + pub fn find_by_id(&mut self, id: Id) -> Option<&mut Self> { + if Id::new(self.id.clone()) == id.clone() { + println!(""); + return Some(self); + } else if let Some(child_elements) = self.child_elements.as_mut() { + for element in child_elements { + let element = element.find_by_id(id.clone()); + if element.is_some() { + return element; + } + } + return None; + } else { + return None; } - self } - pub fn push(mut self, element: RenderedElement) -> Self { - if let Some(els) = self.child_elements.as_mut() { - els.push(element); + pub fn find_parent(&mut self, child_element: &RenderedElement) -> Option<&mut Self> { + if child_element == self { + return Some(self); + } else if self.child_elements.is_some() { + if self.child_elements.clone()?.contains(child_element) { + return Some(self); + } else { + if let Some(child_elements) = self.child_elements.as_mut() { + for element in child_elements { + let element: Option<&mut Self> = element.find_parent(child_element); + if element.is_some() { + return element; + } + } + } + return None; + } } else { - self.child_elements = Some(vec![element]); + return None; + } + } + + pub fn remove(&mut self, element: &RenderedElement) { + let parent = self.find_parent(element); + if let Some(child_elements) = parent.unwrap().child_elements.as_mut() { + if let Some(index) = child_elements.iter().position(|x| x == element) { + child_elements.remove(index); + } + } + } + + pub fn push(&mut self, element: RenderedElement) { + if let Some(child_elements) = self.child_elements.as_mut() { + child_elements.push(element); + } + } + + pub fn insert_after(&mut self, id: Id, element: RenderedElement) { + if let Some(child_elements) = self.child_elements.as_mut() { + if let Some(index) = child_elements + .iter() + .position(|x| Id::new(x.id.clone()) == id) + { + child_elements.insert(index, element); + } else { + child_elements.push(element); + } + } + } + + fn preset_options(mut self, options: Vec<&str>) -> Self { + for opt in options { + self.props.insert(opt.to_owned(), None); } self } - pub fn option(mut self, option: &'static str, value: &'static str) -> Self { + pub fn option(&mut self, option: &'static str, value: &'static str) { self.props .entry(option.to_owned()) .and_modify(|opt| *opt = Some(value.to_owned())); - self + } + + pub fn as_element(self) -> Element<'static, Message> { + let mut children = widget::column![]; + + if let Some(els) = self.child_elements.clone() { + for el in els { + children = children.push(el.clone().as_element()); + } + } + iced_drop::droppable( + widget::container( + widget::column![widget::text(self.name.clone().to_string()), children] + .width(Length::Fill), + ) + .style(widget::container::bordered_box), + ) + .id(Id::new(self.id.clone())) + .on_drop(move |point, rect| Message::MoveElement(self.clone(), point, rect)) + .into() } } @@ -121,10 +202,23 @@ pub fn image(path: &str) -> RenderedElement { RenderedElement::new(ElementName::Image(path.to_owned())) } -pub fn container(content: RenderedElement) -> RenderedElement { - RenderedElement::from_vec(ElementName::Container, vec![content]) +pub fn container(content: Option) -> RenderedElement { + match content { + Some(el) => RenderedElement::from_vec(ElementName::Container, vec![el]), + None => RenderedElement::from_vec(ElementName::Container, vec![]), + } } -pub fn row(child_elements: Vec) -> RenderedElement { - RenderedElement::from_vec(ElementName::Row, child_elements) +pub fn row(child_elements: Option>) -> RenderedElement { + match child_elements { + Some(els) => RenderedElement::from_vec(ElementName::Row, els), + None => RenderedElement::from_vec(ElementName::Row, vec![]), + } +} + +pub fn column(child_elements: Option>) -> RenderedElement { + match child_elements { + Some(els) => RenderedElement::from_vec(ElementName::Column, els), + None => RenderedElement::from_vec(ElementName::Column, vec![]), + } } diff --git a/iced_drop/Cargo.toml b/iced_drop/Cargo.toml index 8b9d88c..40beeb0 100644 --- a/iced_drop/Cargo.toml +++ b/iced_drop/Cargo.toml @@ -4,5 +4,5 @@ version = "0.1.0" edition = "2021" [dependencies.iced] -version = "0.12.1" +version = "0.13.1" features = ["advanced"] diff --git a/iced_drop/LICENSE b/iced_drop/LICENSE new file mode 100644 index 0000000..89d9fee --- /dev/null +++ b/iced_drop/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 jhannyj + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/iced_drop/README.md b/iced_drop/README.md index 41b637b..3768d54 100644 --- a/iced_drop/README.md +++ b/iced_drop/README.md @@ -1,5 +1,7 @@ # iced_drop +# Modified to use iced 0.13.1 for compatibility + A small library which provides a custom widget and operation to make drag and drop easier to implement in [iced](https://github.com/iced-rs/iced/tree/master) ## Usage diff --git a/iced_drop/src/lib.rs b/iced_drop/src/lib.rs index fc559dc..9906cbe 100644 --- a/iced_drop/src/lib.rs +++ b/iced_drop/src/lib.rs @@ -1,8 +1,10 @@ pub mod widget; use iced::{ - advanced::{graphics::futures::MaybeSend, renderer, widget::Id}, - Command, Element, Point, Rectangle, + advanced::widget::{operate, Id}, + advanced::{graphics::futures::MaybeSend, renderer}, + task::Task, + Element, Point, Rectangle, }; use widget::droppable::*; @@ -18,17 +20,17 @@ where Droppable::new(content) } -pub fn zones_on_point( +pub fn zones_on_point( msg: MF, point: Point, options: Option>, depth: Option, -) -> Command +) -> Task where - Message: 'static, - MF: Fn(Vec<(Id, Rectangle)>) -> Message + MaybeSend + Sync + Clone + 'static, + T: Send + 'static, + MF: Fn(Vec<(Id, Rectangle)>) -> T + MaybeSend + Sync + Clone + 'static, { - Command::widget(drop::find_zones( + operate(drop::find_zones( move |bounds| bounds.contains(point), options, depth, @@ -41,11 +43,11 @@ pub fn find_zones( filter: F, options: Option>, depth: Option, -) -> Command +) -> Task where - Message: 'static, + Message: Send + 'static, MF: Fn(Vec<(Id, Rectangle)>) -> Message + MaybeSend + Sync + Clone + 'static, - F: Fn(&Rectangle) -> bool + 'static, + F: Fn(&Rectangle) -> bool + Send + 'static, { - Command::widget(drop::find_zones(filter, options, depth)).map(move |id| msg(id)) + operate(drop::find_zones(filter, options, depth)).map(move |id| msg(id)) } diff --git a/iced_drop/src/widget/droppable.rs b/iced_drop/src/widget/droppable.rs index ed7dcbd..80d8600 100644 --- a/iced_drop/src/widget/droppable.rs +++ b/iced_drop/src/widget/droppable.rs @@ -228,8 +228,10 @@ where state.action = Action::Drag(start, position); // update the position of the overlay since the cursor was moved if self.drag_center { - state.overlay_bounds.x = position.x - state.overlay_bounds.width / 2.0; - state.overlay_bounds.y = position.y - state.overlay_bounds.height / 2.0; + state.overlay_bounds.x = + position.x - state.overlay_bounds.width / 2.0; + state.overlay_bounds.y = + position.y - state.overlay_bounds.height / 2.0; } else { state.overlay_bounds.x = state.widget_pos.x + position.x - start.x; state.overlay_bounds.y = state.widget_pos.y + position.y - start.y; @@ -315,7 +317,7 @@ where tree: &mut Tree, layout: Layout<'_>, renderer: &Renderer, - operation: &mut dyn Operation, + operation: &mut dyn Operation, ) { let state = tree.state.downcast_mut::(); operation.custom(state, self.id.as_ref()); diff --git a/iced_drop/src/widget/operation/drop.rs b/iced_drop/src/widget/operation/drop.rs index 12a2e30..a76181c 100644 --- a/iced_drop/src/widget/operation/drop.rs +++ b/iced_drop/src/widget/operation/drop.rs @@ -17,7 +17,7 @@ pub fn find_zones( depth: Option, ) -> impl Operation> where - F: Fn(&Rectangle) -> bool + 'static, + F: Fn(&Rectangle) -> bool + Send + 'static, { struct FindDropZone { filter: F, @@ -30,7 +30,7 @@ where impl Operation> for FindDropZone where - F: Fn(&Rectangle) -> bool + 'static, + F: Fn(&Rectangle) -> bool + Send + 'static, { fn container( &mut self, @@ -70,6 +70,7 @@ where _state: &mut dyn Scrollable, _id: Option<&Id>, bounds: Rectangle, + _content_bounds: Rectangle, translation: Vector, ) { if (self.filter)(&bounds) { -- cgit v1.2.3