Draft iced_devtools subcrate structure

This commit is contained in:
Héctor Ramón Jiménez 2025-04-05 19:27:15 +02:00
parent 3f67044977
commit a719b0596c
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
5 changed files with 201 additions and 2 deletions

9
Cargo.lock generated
View file

@ -2403,6 +2403,7 @@ dependencies = [
"criterion",
"iced_core",
"iced_debug",
"iced_devtools",
"iced_futures",
"iced_highlighter",
"iced_renderer",
@ -2454,6 +2455,14 @@ dependencies = [
"iced_core",
]
[[package]]
name = "iced_devtools"
version = "0.14.0-dev"
dependencies = [
"iced_program",
"iced_widget",
]
[[package]]
name = "iced_futures"
version = "0.14.0-dev"

View file

@ -42,7 +42,7 @@ markdown = ["iced_widget/markdown"]
# Enables lazy widgets
lazy = ["iced_widget/lazy"]
# Enables a debug view in native platforms (press F12)
debug = ["iced_winit/debug"]
debug = ["iced_winit/debug", "iced_devtools"]
# Enables the `thread-pool` futures executor as the `executor::Default` on native platforms
thread-pool = ["iced_futures/thread-pool"]
# Enables `tokio` as the `executor::Default` on native platforms
@ -80,6 +80,9 @@ iced_widget.workspace = true
iced_winit.features = ["program"]
iced_winit.workspace = true
iced_devtools.workspace = true
iced_devtools.optional = true
iced_highlighter.workspace = true
iced_highlighter.optional = true
@ -112,6 +115,7 @@ members = [
"beacon",
"core",
"debug",
"devtools",
"futures",
"graphics",
"highlighter",
@ -142,6 +146,7 @@ iced = { version = "0.14.0-dev", path = "." }
iced_beacon = { version = "0.14.0-dev", path = "beacon" }
iced_core = { version = "0.14.0-dev", path = "core" }
iced_debug = { version = "0.14.0-dev", path = "debug" }
iced_devtools = { version = "0.14.0-dev", path = "devtools" }
iced_futures = { version = "0.14.0-dev", path = "futures" }
iced_graphics = { version = "0.14.0-dev", path = "graphics" }
iced_highlighter = { version = "0.14.0-dev", path = "highlighter" }

18
devtools/Cargo.toml Normal file
View file

@ -0,0 +1,18 @@
[package]
name = "iced_devtools"
version.workspace = true
authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
homepage.workspace = true
categories.workspace = true
keywords.workspace = true
rust-version.workspace = true
[lints]
workspace = true
[dependencies]
iced_program.workspace = true
iced_widget.workspace = true

161
devtools/src/lib.rs Normal file
View file

@ -0,0 +1,161 @@
#![allow(missing_docs)]
use crate::runtime::futures;
use iced_program as program;
use iced_widget::core;
use iced_widget::runtime;
use crate::core::Element;
use crate::core::theme;
use crate::core::window;
use crate::futures::Subscription;
use crate::program::Program;
use crate::runtime::Task;
use std::fmt;
pub fn attach(program: impl Program + 'static) -> impl Program {
struct Attach<P> {
program: P,
}
impl<P> Program for Attach<P>
where
P: Program + 'static,
{
type State = DevTools<P>;
type Message = Message<P>;
type Theme = P::Theme;
type Renderer = P::Renderer;
type Executor = P::Executor;
fn name() -> &'static str {
P::name()
}
fn boot(&self) -> (Self::State, Task<Self::Message>) {
let (state, task) = self.program.boot();
(DevTools { state }, task.map(Message::Program))
}
fn update(
&self,
state: &mut Self::State,
message: Self::Message,
) -> Task<Self::Message> {
state.update(&self.program, message)
}
fn view<'a>(
&self,
state: &'a Self::State,
window: window::Id,
) -> Element<'a, Self::Message, Self::Theme, Self::Renderer> {
state.view(&self.program, window)
}
fn title(&self, state: &Self::State, window: window::Id) -> String {
state.title(&self.program, window)
}
fn subscription(
&self,
state: &Self::State,
) -> runtime::futures::Subscription<Self::Message> {
state.subscription(&self.program)
}
fn theme(
&self,
state: &Self::State,
window: window::Id,
) -> Self::Theme {
state.theme(&self.program, window)
}
fn style(
&self,
state: &Self::State,
theme: &Self::Theme,
) -> theme::Style {
state.style(&self.program, theme)
}
fn scale_factor(&self, state: &Self::State, window: window::Id) -> f64 {
state.scale_factor(&self.program, window)
}
}
Attach { program }
}
struct DevTools<P>
where
P: Program,
{
state: P::State,
}
impl<P> DevTools<P>
where
P: Program + 'static,
{
pub fn title(&self, program: &P, window: window::Id) -> String {
program.title(&self.state, window)
}
pub fn update(
&mut self,
program: &P,
message: Message<P>,
) -> Task<Message<P>> {
match message {
Message::Program(message) => program
.update(&mut self.state, message)
.map(Message::Program),
}
}
pub fn view(
&self,
program: &P,
window: window::Id,
) -> Element<'_, Message<P>, P::Theme, P::Renderer> {
program.view(&self.state, window).map(Message::Program)
}
pub fn subscription(&self, program: &P) -> Subscription<Message<P>> {
program.subscription(&self.state).map(Message::Program)
}
pub fn theme(&self, program: &P, window: window::Id) -> P::Theme {
program.theme(&self.state, window)
}
pub fn style(&self, program: &P, theme: &P::Theme) -> theme::Style {
program.style(&self.state, theme)
}
pub fn scale_factor(&self, program: &P, window: window::Id) -> f64 {
program.scale_factor(&self.state, window)
}
}
#[derive(Clone)]
enum Message<P>
where
P: Program,
{
Program(P::Message),
}
impl<P> fmt::Debug for Message<P>
where
P: Program,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Message::Program(message) => message.fmt(f),
}
}
}

View file

@ -169,7 +169,13 @@ impl<P: Program> Application<P> {
where
Self: 'static,
{
Ok(shell::run(self.raw, self.settings, Some(self.window))?)
#[cfg(feature = "debug")]
let program = iced_devtools::attach(self.raw);
#[cfg(not(feature = "debug"))]
let program = self.raw;
Ok(shell::run(program, self.settings, Some(self.window))?)
}
/// Sets the [`Settings`] that will be used to run the [`Application`].