summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/audit.yml20
-rw-r--r--.github/workflows/document.yml6
-rw-r--r--.github/workflows/test.yml2
-rw-r--r--.github/workflows/verify.yml19
-rw-r--r--CHANGELOG.md14
-rw-r--r--Cargo.toml137
-rw-r--r--README.md14
-rw-r--r--clippy.toml1
-rw-r--r--core/Cargo.toml31
-rw-r--r--core/src/angle.rs62
-rw-r--r--core/src/gradient.rs4
-rw-r--r--core/src/lib.rs5
-rw-r--r--core/src/shell.rs4
-rw-r--r--core/src/window/icon.rs2
-rw-r--r--core/src/window/redraw_request.rs2
-rw-r--r--examples/README.md20
-rw-r--r--examples/arc/Cargo.toml3
-rw-r--r--examples/bezier_tool/Cargo.toml3
-rw-r--r--examples/bezier_tool/README.md4
-rw-r--r--examples/checkbox/Cargo.toml2
-rw-r--r--examples/clock/Cargo.toml6
-rw-r--r--examples/color_palette/Cargo.toml6
-rw-r--r--examples/color_palette/README.md6
-rw-r--r--examples/combo_box/Cargo.toml3
-rw-r--r--examples/component/Cargo.toml3
-rw-r--r--examples/counter/Cargo.toml6
-rw-r--r--examples/counter/README.md12
-rw-r--r--examples/custom_quad/Cargo.toml3
-rw-r--r--examples/custom_widget/Cargo.toml3
-rw-r--r--examples/custom_widget/README.md4
-rw-r--r--examples/download_progress/Cargo.toml3
-rw-r--r--examples/download_progress/README.md4
-rw-r--r--examples/events/Cargo.toml3
-rw-r--r--examples/events/README.md6
-rw-r--r--examples/events/src/main.rs5
-rw-r--r--examples/exit/Cargo.toml2
-rw-r--r--examples/game_of_life/Cargo.toml12
-rw-r--r--examples/game_of_life/README.md4
-rw-r--r--examples/game_of_life/src/main.rs10
-rw-r--r--examples/geometry/Cargo.toml3
-rw-r--r--examples/geometry/README.md4
-rw-r--r--examples/gradient/Cargo.toml8
-rw-r--r--examples/gradient/src/main.rs99
-rw-r--r--examples/integration/Cargo.toml23
-rw-r--r--examples/integration/README.md4
-rw-r--r--examples/integration/src/main.rs5
-rw-r--r--examples/lazy/Cargo.toml3
-rw-r--r--examples/loading_spinners/Cargo.toml8
-rw-r--r--examples/loading_spinners/README.md6
-rw-r--r--examples/modal/Cargo.toml3
-rw-r--r--examples/modal/src/main.rs8
-rw-r--r--examples/multitouch/Cargo.toml7
-rw-r--r--examples/multitouch/src/main.rs2
-rw-r--r--examples/pane_grid/Cargo.toml3
-rw-r--r--examples/pane_grid/README.md4
-rw-r--r--examples/pane_grid/src/main.rs14
-rw-r--r--examples/pick_list/Cargo.toml3
-rw-r--r--examples/pokedex/Cargo.toml11
-rw-r--r--examples/pokedex/README.md4
-rw-r--r--examples/pokedex/src/main.rs2
-rw-r--r--examples/progress_bar/Cargo.toml2
-rw-r--r--examples/progress_bar/README.md4
-rw-r--r--examples/qr_code/Cargo.toml3
-rw-r--r--examples/qr_code/README.md4
-rw-r--r--examples/screenshot/Cargo.toml8
-rw-r--r--examples/screenshot/src/main.rs9
-rw-r--r--examples/scrollable/Cargo.toml6
-rw-r--r--examples/sierpinski_triangle/Cargo.toml6
-rw-r--r--examples/sierpinski_triangle/README.md4
-rw-r--r--examples/slider/Cargo.toml2
-rw-r--r--examples/solar_system/Cargo.toml6
-rw-r--r--examples/solar_system/README.md4
-rw-r--r--examples/solar_system/src/main.rs2
-rw-r--r--examples/stopwatch/Cargo.toml3
-rw-r--r--examples/stopwatch/README.md4
-rw-r--r--examples/stopwatch/src/main.rs16
-rw-r--r--examples/styling/Cargo.toml2
-rw-r--r--examples/styling/README.md4
-rw-r--r--examples/styling/src/main.rs1
-rw-r--r--examples/svg/Cargo.toml3
-rw-r--r--examples/system_information/Cargo.toml6
-rw-r--r--examples/toast/Cargo.toml3
-rw-r--r--examples/toast/src/main.rs8
-rw-r--r--examples/todos/Cargo.toml19
-rw-r--r--examples/todos/README.md13
-rw-r--r--examples/todos/src/main.rs40
-rw-r--r--examples/tooltip/Cargo.toml3
-rw-r--r--examples/tour/Cargo.toml14
-rw-r--r--examples/tour/README.md4
-rw-r--r--examples/tour/src/main.rs9
-rw-r--r--examples/url_handler/Cargo.toml2
-rw-r--r--examples/url_handler/src/main.rs13
-rw-r--r--examples/visible_bounds/Cargo.toml6
-rw-r--r--examples/visible_bounds/src/main.rs8
-rw-r--r--examples/websocket/Cargo.toml12
-rw-r--r--futures/Cargo.toml61
-rw-r--r--futures/src/event.rs59
-rw-r--r--futures/src/keyboard.rs61
-rw-r--r--futures/src/lib.rs7
-rw-r--r--futures/src/runtime.rs5
-rw-r--r--futures/src/subscription.rs97
-rw-r--r--futures/src/subscription/tracker.rs3
-rw-r--r--graphics/Cargo.toml86
-rw-r--r--graphics/src/compositor.rs2
-rw-r--r--graphics/src/geometry.rs4
-rw-r--r--graphics/src/geometry/fill.rs4
-rw-r--r--graphics/src/geometry/stroke.rs4
-rw-r--r--graphics/src/gradient.rs11
-rw-r--r--graphics/src/lib.rs5
-rw-r--r--graphics/src/mesh.rs2
-rw-r--r--graphics/src/text/cache.rs5
-rw-r--r--renderer/Cargo.toml40
-rw-r--r--renderer/src/geometry.rs14
-rw-r--r--renderer/src/lib.rs13
-rw-r--r--renderer/src/settings.rs4
-rw-r--r--runtime/Cargo.toml28
-rw-r--r--runtime/src/lib.rs30
-rw-r--r--runtime/src/overlay/nested.rs4
-rw-r--r--runtime/src/program/state.rs2
-rw-r--r--runtime/src/user_interface.rs4
-rw-r--r--runtime/src/window.rs5
-rw-r--r--src/lib.rs27
-rw-r--r--src/settings.rs2
-rw-r--r--src/window/icon.rs11
-rw-r--r--style/Cargo.toml30
-rw-r--r--style/src/lib.rs8
-rw-r--r--style/src/theme.rs27
-rw-r--r--tiny_skia/Cargo.toml54
-rw-r--r--tiny_skia/src/geometry.rs14
-rw-r--r--tiny_skia/src/lib.rs13
-rw-r--r--tiny_skia/src/raster.rs4
-rw-r--r--tiny_skia/src/text.rs4
-rw-r--r--tiny_skia/src/vector.rs8
-rw-r--r--tiny_skia/src/window/compositor.rs1
-rw-r--r--wgpu/Cargo.toml79
-rw-r--r--wgpu/src/geometry.rs20
-rw-r--r--wgpu/src/lib.rs5
-rw-r--r--wgpu/src/quad/gradient.rs19
-rw-r--r--wgpu/src/quad/solid.rs6
-rw-r--r--wgpu/src/shader/color/linear_rgb.wgsl3
-rw-r--r--wgpu/src/shader/color/oklab.wgsl26
-rw-r--r--wgpu/src/shader/quad.wgsl306
-rw-r--r--wgpu/src/shader/quad/gradient.wgsl205
-rw-r--r--wgpu/src/shader/quad/solid.wgsl99
-rw-r--r--wgpu/src/shader/triangle.wgsl160
-rw-r--r--wgpu/src/shader/triangle/gradient.wgsl134
-rw-r--r--wgpu/src/shader/triangle/solid.wgsl24
-rw-r--r--wgpu/src/triangle.rs35
-rw-r--r--wgpu/src/window/compositor.rs22
-rw-r--r--widget/Cargo.toml57
-rw-r--r--widget/src/button.rs4
-rw-r--r--widget/src/canvas/event.rs2
-rw-r--r--widget/src/canvas/program.rs11
-rw-r--r--widget/src/checkbox.rs6
-rw-r--r--widget/src/combo_box.rs8
-rw-r--r--widget/src/helpers.rs52
-rw-r--r--widget/src/lib.rs5
-rw-r--r--widget/src/overlay/menu.rs2
-rw-r--r--widget/src/pane_grid.rs4
-rw-r--r--widget/src/pane_grid/configuration.rs4
-rw-r--r--widget/src/pane_grid/content.rs4
-rw-r--r--widget/src/pane_grid/node.rs2
-rw-r--r--widget/src/pane_grid/pane.rs2
-rw-r--r--widget/src/pane_grid/split.rs2
-rw-r--r--widget/src/pane_grid/state.rs40
-rw-r--r--widget/src/pane_grid/title_bar.rs6
-rw-r--r--widget/src/pick_list.rs2
-rw-r--r--widget/src/qr_code.rs2
-rw-r--r--widget/src/radio.rs2
-rw-r--r--widget/src/scrollable.rs10
-rw-r--r--widget/src/slider.rs4
-rw-r--r--widget/src/text_input.rs2
-rw-r--r--widget/src/text_input/value.rs2
-rw-r--r--widget/src/toggler.rs6
-rw-r--r--winit/Cargo.toml91
-rw-r--r--winit/src/application/state.rs4
-rw-r--r--winit/src/conversion.rs2
-rw-r--r--winit/src/lib.rs5
178 files changed, 1781 insertions, 1401 deletions
diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml
index ba5dc190..e9f4b0c5 100644
--- a/.github/workflows/audit.yml
+++ b/.github/workflows/audit.yml
@@ -1,12 +1,26 @@
name: Audit
-on: [push]
+on:
+ push: {}
+ pull_request: {}
+ schedule:
+ - cron: '0 0 * * *'
jobs:
- dependencies:
+ vulnerabilities:
runs-on: ubuntu-latest
steps:
- uses: hecrj/setup-rust-action@v1
- name: Install cargo-audit
run: cargo install cargo-audit
- uses: actions/checkout@master
- - name: Audit dependencies
+ - name: Audit vulnerabilities
run: cargo audit
+
+ artifacts:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: hecrj/setup-rust-action@v1
+ - name: Install cargo-outdated
+ run: cargo install cargo-outdated
+ - uses: actions/checkout@master
+ - name: Find outdated dependencies
+ run: cargo outdated --workspace --exit-code 1
diff --git a/.github/workflows/document.yml b/.github/workflows/document.yml
index 09a7a4d5..230c5cb0 100644
--- a/.github/workflows/document.yml
+++ b/.github/workflows/document.yml
@@ -1,8 +1,5 @@
name: Document
-on:
- push:
- branches:
- - master
+on: [push, pull_request]
jobs:
all:
runs-on: ubuntu-20.04
@@ -31,6 +28,7 @@ jobs:
- name: Write CNAME file
run: echo 'docs.iced.rs' > ./target/doc/CNAME
- name: Publish documentation
+ if: github.ref == 'refs/heads/master'
uses: peaceiris/actions-gh-pages@v3
with:
deploy_key: ${{ secrets.DOCS_DEPLOY_KEY }}
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index a9a9b3f9..ac8d27f9 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -25,6 +25,8 @@ jobs:
web:
runs-on: ubuntu-latest
+ env:
+ RUSTFLAGS: --cfg=web_sys_unstable_apis
steps:
- uses: hecrj/setup-rust-action@v1
with:
diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml
deleted file mode 100644
index 089dd5c9..00000000
--- a/.github/workflows/verify.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-name: Verify
-on:
- pull_request:
- branches:
- - master
-jobs:
- changelog:
- runs-on: ubuntu-20.04
- steps:
- - uses: actions/checkout@v2
- with:
- fetch-depth: 0
- - name: Check `CHANGELOG.md` has changes
- run: |
- ! git diff --exit-code origin/master HEAD -- CHANGELOG.md
- - name: Check `CHANGELOG.md` thanks the PR author
- if: ${{ github.event.pull_request.user.login != 'hecrj' }}
- run: |
- sed -n '/## \[Unreleased\]/,/^## /p' CHANGELOG.md | sed -n '/Many thanks to.../,//p' | grep '@${{ github.event.pull_request.user.login }}'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d80dc5e0..ed02baf7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
+### Added
+- `Theme::Custom::with_fn` for custom extended palette generation. [#2067](https://github.com/iced-rs/iced/pull/2067)
+
+### Changed
+- Updated `wgpu` to `0.17`. [#2065](https://github.com/iced-rs/iced/pull/2065)
+- Changed `Button::style` to take an `impl Into<...>` for consistency. [#2046](https://github.com/iced-rs/iced/pull/2046)
+
+### Fixed
+- Missing `width` attribute in `styling` example. [#2062](https://github.com/iced-rs/iced/pull/2062)
+
+Many thanks to...
+
+- @akshayr-mecha
+- @dtzxporter
### Added
- Explicit text caching. [#2058](https://github.com/iced-rs/iced/pull/2058)
diff --git a/Cargo.toml b/Cargo.toml
index 71484b7a..af74a3cf 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,22 +1,28 @@
[package]
name = "iced"
-version = "0.10.0"
-authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
-edition = "2021"
description = "A cross-platform GUI library inspired by Elm"
-license = "MIT"
-repository = "https://github.com/iced-rs/iced"
-documentation = "https://docs.rs/iced"
-readme = "README.md"
-keywords = ["gui", "ui", "graphics", "interface", "widgets"]
-categories = ["gui"]
+version.workspace = true
+edition.workspace = true
+authors.workspace = true
+license.workspace = true
+repository.workspace = true
+homepage.workspace = true
+categories.workspace = true
+keywords.workspace = true
+
+[package.metadata.docs.rs]
+rustdoc-args = ["--cfg", "docsrs"]
+all-features = true
+
+[badges]
+maintenance = { status = "actively-developed" }
[features]
default = ["wgpu"]
# Enable the `wgpu` GPU-accelerated renderer backend
wgpu = ["iced_renderer/wgpu"]
# Enables the `Image` widget
-image = ["iced_widget/image", "image_rs"]
+image = ["iced_widget/image", "dep:image"]
# Enables the `Svg` widget
svg = ["iced_widget/svg"]
# Enables the `Canvas` widget
@@ -39,11 +45,33 @@ palette = ["iced_core/palette"]
system = ["iced_winit/system"]
# Enables broken "sRGB linear" blending to reproduce color management of the Web
web-colors = ["iced_renderer/web-colors"]
+# Enables the WebGL backend, replacing WebGPU
+webgl = ["iced_renderer/webgl"]
# Enables the advanced module
advanced = []
-[badges]
-maintenance = { status = "actively-developed" }
+[dependencies]
+iced_core.workspace = true
+iced_futures.workspace = true
+iced_renderer.workspace = true
+iced_widget.workspace = true
+iced_winit.features = ["application"]
+iced_winit.workspace = true
+
+thiserror.workspace = true
+
+image.workspace = true
+image.optional = true
+
+[profile.release-opt]
+inherits = "release"
+codegen-units = 1
+debug = false
+lto = true
+incremental = false
+opt-level = 3
+overflow-checks = false
+strip = "debuginfo"
[workspace]
members = [
@@ -60,29 +88,66 @@ members = [
"examples/*",
]
-[dependencies]
-iced_core = { version = "0.10", path = "core" }
-iced_futures = { version = "0.7", path = "futures" }
-iced_renderer = { version = "0.1", path = "renderer" }
-iced_widget = { version = "0.1", path = "widget" }
-iced_winit = { version = "0.10", path = "winit", features = ["application"] }
-thiserror = "1"
+[workspace.package]
+version = "0.12.0"
+authors = ["Héctor Ramón Jiménez <hector@hecrj.dev>"]
+edition = "2021"
+license = "MIT"
+repository = "https://github.com/iced-rs/iced"
+homepage = "https://iced.rs"
+categories = ["gui"]
+keywords = ["gui", "ui", "graphics", "interface", "widgets"]
-[dependencies.image_rs]
-version = "0.24"
-package = "image"
-optional = true
+[workspace.dependencies]
+iced = { version = "0.12", path = "." }
+iced_core = { version = "0.12", path = "core" }
+iced_futures = { version = "0.12", path = "futures" }
+iced_graphics = { version = "0.12", path = "graphics" }
+iced_renderer = { version = "0.12", path = "renderer" }
+iced_runtime = { version = "0.12", path = "runtime" }
+iced_style = { version = "0.12", path = "style" }
+iced_tiny_skia = { version = "0.12", path = "tiny_skia" }
+iced_wgpu = { version = "0.12", path = "wgpu" }
+iced_widget = { version = "0.12", path = "widget" }
+iced_winit = { version = "0.12", path = "winit" }
-[package.metadata.docs.rs]
-rustdoc-args = ["--cfg", "docsrs"]
-all-features = true
-
-[profile.release-opt]
-inherits = "release"
-codegen-units = 1
-debug = false
-lto = true
-incremental = false
-opt-level = 3
-overflow-checks = false
-strip = "debuginfo"
+async-std = "1.0"
+bitflags = "1.0"
+bytemuck = { version = "1.0", features = ["derive"] }
+cosmic-text = "0.9"
+futures = "0.3"
+glam = "0.24"
+glyphon = { git = "https://github.com/grovesNL/glyphon.git", rev = "20f0f8fa80e0d0df4c63634ce9176fa489546ca9" }
+guillotiere = "0.6"
+half = "2.2"
+image = "0.24"
+instant = "0.1"
+kamadak-exif = "0.5"
+kurbo = "0.9"
+log = "0.4"
+lyon = "1.0"
+lyon_path = "1.0"
+num-traits = "0.2"
+once_cell = "1.0"
+ouroboros = "0.17"
+palette = "0.7"
+qrcode = { version = "0.12", default-features = false }
+raw-window-handle = "0.5"
+resvg = "0.35"
+rustc-hash = "1.0"
+smol = "1.0"
+softbuffer = "0.2"
+sysinfo = "0.28"
+thiserror = "1.0"
+tiny-skia = "0.10"
+tokio = "1.0"
+tracing = "0.1"
+twox-hash = { version = "1.0", default-features = false }
+unicode-segmentation = "1.0"
+wasm-bindgen-futures = "0.4"
+wasm-timer = "0.2"
+web-sys = "0.3"
+wgpu = "0.17"
+winapi = "0.3"
+window_clipboard = "0.3"
+winit = { git = "https://github.com/iced-rs/winit.git", rev = "c52db2045d0a2f1b8d9923870de1d4ab1994146e", default-features = false }
diff --git a/README.md b/README.md
index 431f14f9..825219aa 100644
--- a/README.md
+++ b/README.md
@@ -15,11 +15,11 @@
A cross-platform GUI library for Rust focused on simplicity and type-safety.
Inspired by [Elm].
-<a href="https://gfycat.com/littlesanehalicore">
- <img src="https://thumbs.gfycat.com/LittleSaneHalicore-small.gif" width="275px">
+<a href="https://iced.rs/examples/todos.mp4">
+ <img src="https://iced.rs/examples/todos.gif" width="275px">
</a>
-<a href="https://gfycat.com/politeadorableiberianmole">
- <img src="https://thumbs.gfycat.com/PoliteAdorableIberianmole-small.gif" width="273px">
+<a href="https://iced.rs/examples/tour.mp4">
+ <img src="https://iced.rs/examples/tour.gif" width="273px">
</a>
</div>
@@ -47,9 +47,9 @@ __Iced is currently experimental software.__ [Take a look at the roadmap],
[Cross-platform support]: https://raw.githubusercontent.com/iced-rs/iced/master/docs/images/todos_desktop.jpg
[the Web]: https://github.com/iced-rs/iced_web
-[text inputs]: https://gfycat.com/alertcalmcrow-rust-gui
-[scrollables]: https://gfycat.com/perkybaggybaboon-rust-gui
-[Debug overlay with performance metrics]: https://gfycat.com/incredibledarlingbee
+[text inputs]: https://iced.rs/examples/text_input.mp4
+[scrollables]: https://iced.rs/examples/scrollable.mp4
+[Debug overlay with performance metrics]: https://iced.rs/examples/debug.mp4
[Modular ecosystem]: ECOSYSTEM.md
[renderer-agnostic native runtime]: runtime/
[`wgpu`]: https://github.com/gfx-rs/wgpu
diff --git a/clippy.toml b/clippy.toml
index 0d4e02f0..02f00a06 100644
--- a/clippy.toml
+++ b/clippy.toml
@@ -1 +1,2 @@
too-many-arguments-threshold = 20
+enum-variant-name-threshold = 10
diff --git a/core/Cargo.toml b/core/Cargo.toml
index 8bb37309..7acb7511 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -1,24 +1,27 @@
[package]
name = "iced_core"
-version = "0.10.0"
-authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
-edition = "2021"
-description = "The essential concepts of Iced"
-license = "MIT"
-repository = "https://github.com/iced-rs/iced"
+description = "The essential ideas of iced"
+version.workspace = true
+edition.workspace = true
+authors.workspace = true
+license.workspace = true
+repository.workspace = true
+homepage.workspace = true
+categories.workspace = true
+keywords.workspace = true
[dependencies]
-bitflags = "1.2"
-thiserror = "1"
-log = "0.4.17"
-twox-hash = { version = "1.5", default-features = false }
+bitflags.workspace = true
+log.workspace = true
+thiserror.workspace = true
+twox-hash.workspace = true
+num-traits.workspace = true
-[dependencies.palette]
-version = "0.7"
-optional = true
+palette.workspace = true
+palette.optional = true
[target.'cfg(target_arch = "wasm32")'.dependencies]
-instant = "0.1"
+instant.workspace = true
[dev-dependencies]
approx = "0.5"
diff --git a/core/src/angle.rs b/core/src/angle.rs
index 75a57c76..102b69cf 100644
--- a/core/src/angle.rs
+++ b/core/src/angle.rs
@@ -1,32 +1,72 @@
use crate::{Point, Rectangle, Vector};
-use std::f32::consts::PI;
-#[derive(Debug, Copy, Clone, PartialEq)]
+use std::f32::consts::{FRAC_PI_2, PI};
+use std::ops::RangeInclusive;
+
/// Degrees
+#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
pub struct Degrees(pub f32);
-#[derive(Debug, Copy, Clone, PartialEq)]
/// Radians
+#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
pub struct Radians(pub f32);
+impl Radians {
+ /// The range of radians of a circle.
+ pub const RANGE: RangeInclusive<Radians> = Radians(0.0)..=Radians(2.0 * PI);
+}
+
impl From<Degrees> for Radians {
fn from(degrees: Degrees) -> Self {
- Radians(degrees.0 * PI / 180.0)
+ Self(degrees.0 * PI / 180.0)
+ }
+}
+
+impl From<f32> for Radians {
+ fn from(radians: f32) -> Self {
+ Self(radians)
+ }
+}
+
+impl From<u8> for Radians {
+ fn from(radians: u8) -> Self {
+ Self(f32::from(radians))
+ }
+}
+
+impl From<Radians> for f64 {
+ fn from(radians: Radians) -> Self {
+ Self::from(radians.0)
+ }
+}
+
+impl num_traits::FromPrimitive for Radians {
+ fn from_i64(n: i64) -> Option<Self> {
+ Some(Self(n as f32))
+ }
+
+ fn from_u64(n: u64) -> Option<Self> {
+ Some(Self(n as f32))
+ }
+
+ fn from_f64(n: f64) -> Option<Self> {
+ Some(Self(n as f32))
}
}
impl Radians {
- /// Calculates the line in which the [`Angle`] intercepts the `bounds`.
+ /// Calculates the line in which the angle intercepts the `bounds`.
pub fn to_distance(&self, bounds: &Rectangle) -> (Point, Point) {
- let v1 = Vector::new(f32::cos(self.0), f32::sin(self.0));
+ let angle = self.0 - FRAC_PI_2;
+ let r = Vector::new(f32::cos(angle), f32::sin(angle));
- let distance_to_rect = f32::min(
- f32::abs((bounds.y - bounds.center().y) / v1.y),
- f32::abs(((bounds.x + bounds.width) - bounds.center().x) / v1.x),
+ let distance_to_rect = f32::max(
+ f32::abs(r.x * bounds.width / 2.0),
+ f32::abs(r.y * bounds.height / 2.0),
);
- let start = bounds.center() + v1 * distance_to_rect;
- let end = bounds.center() - v1 * distance_to_rect;
+ let start = bounds.center() - r * distance_to_rect;
+ let end = bounds.center() + r * distance_to_rect;
(start, end)
}
diff --git a/core/src/gradient.rs b/core/src/gradient.rs
index e19622fb..4a0d5ea0 100644
--- a/core/src/gradient.rs
+++ b/core/src/gradient.rs
@@ -6,10 +6,8 @@ use std::cmp::Ordering;
#[derive(Debug, Clone, Copy, PartialEq)]
/// A fill which transitions colors progressively along a direction, either linearly, radially (TBD),
/// or conically (TBD).
-///
-/// For a gradient which can be used as a fill on a canvas, see [`iced_graphics::Gradient`].
pub enum Gradient {
- /// A linear gradient interpolates colors along a direction at a specific [`Angle`].
+ /// A linear gradient interpolates colors along a direction at a specific angle.
Linear(Linear),
}
diff --git a/core/src/lib.rs b/core/src/lib.rs
index c1c8424b..1bfba7bd 100644
--- a/core/src/lib.rs
+++ b/core/src/lib.rs
@@ -9,6 +9,7 @@
#![doc(
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
)]
+#![forbid(unsafe_code, rust_2018_idioms)]
#![deny(
missing_debug_implementations,
missing_docs,
@@ -17,9 +18,9 @@
clippy::from_over_into,
clippy::needless_borrow,
clippy::new_without_default,
- clippy::useless_conversion
+ clippy::useless_conversion,
+ rustdoc::broken_intra_doc_links
)]
-#![forbid(unsafe_code, rust_2018_idioms)]
#![allow(clippy::inherent_to_string, clippy::type_complexity)]
pub mod alignment;
pub mod clipboard;
diff --git a/core/src/shell.rs b/core/src/shell.rs
index 74a5c616..246c937a 100644
--- a/core/src/shell.rs
+++ b/core/src/shell.rs
@@ -35,7 +35,7 @@ impl<'a, Message> Shell<'a, Message> {
self.messages.push(message);
}
- /// Requests a new frame to be drawn at the given [`Instant`].
+ /// Requests a new frame to be drawn.
pub fn request_redraw(&mut self, request: window::RedrawRequest) {
match self.redraw_request {
None => {
@@ -48,7 +48,7 @@ impl<'a, Message> Shell<'a, Message> {
}
}
- /// Returns the requested [`Instant`] a redraw should happen, if any.
+ /// Returns the request a redraw should happen, if any.
pub fn redraw_request(&self) -> Option<window::RedrawRequest> {
self.redraw_request
}
diff --git a/core/src/window/icon.rs b/core/src/window/icon.rs
index 31868ecf..2fc48e3b 100644
--- a/core/src/window/icon.rs
+++ b/core/src/window/icon.rs
@@ -49,7 +49,7 @@ impl Icon {
}
#[derive(Debug, thiserror::Error)]
-/// An error produced when using [`Icon::from_rgba`] with invalid arguments.
+/// An error produced when using [`from_rgba`] with invalid arguments.
pub enum Error {
/// Produced when the length of the `rgba` argument isn't divisible by 4, thus `rgba` can't be
/// safely interpreted as 32bpp RGBA pixels.
diff --git a/core/src/window/redraw_request.rs b/core/src/window/redraw_request.rs
index 3b4f0fd3..8a59e83c 100644
--- a/core/src/window/redraw_request.rs
+++ b/core/src/window/redraw_request.rs
@@ -13,7 +13,7 @@ pub enum RedrawRequest {
#[cfg(test)]
mod tests {
use super::*;
- use std::time::{Duration, Instant};
+ use crate::time::{Duration, Instant};
#[test]
fn ordering() {
diff --git a/examples/README.md b/examples/README.md
index 111e8910..71dad13e 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -10,8 +10,8 @@ A simple UI tour that can run both on native platforms and the web! It showcases
The __[`main`](tour/src/main.rs)__ file contains all the code of the example! All the cross-platform GUI is defined in terms of __state__, __messages__, __update logic__ and __view logic__.
<div align="center">
- <a href="https://gfycat.com/politeadorableiberianmole">
- <img src="https://thumbs.gfycat.com/PoliteAdorableIberianmole-small.gif">
+ <a href="https://iced.rs/examples/tour.mp4">
+ <img src="https://iced.rs/examples/tour.gif">
</a>
</div>
@@ -33,8 +33,8 @@ A todos tracker inspired by [TodoMVC]. It showcases dynamic layout, text input,
The example code is located in the __[`main`](todos/src/main.rs)__ file.
<div align="center">
- <a href="https://gfycat.com/littlesanehalicore">
- <img src="https://thumbs.gfycat.com/LittleSaneHalicore-small.gif" height="400px">
+ <a href="https://iced.rs/examples/todos.mp4">
+ <img src="https://iced.rs/examples/todos.gif" height="400px">
</a>
</div>
@@ -53,9 +53,7 @@ It runs a simulation in a background thread while allowing interaction with a `C
The relevant code is located in the __[`main`](game_of_life/src/main.rs)__ file.
<div align="center">
- <a href="https://gfycat.com/briefaccurateaardvark">
- <img src="https://thumbs.gfycat.com/BriefAccurateAardvark-size_restricted.gif">
- </a>
+ <img src="https://iced.rs/examples/game_of_life.gif">
</div>
You can run it with `cargo run`:
@@ -72,9 +70,7 @@ An example showcasing custom styling with a light and dark theme.
The example code is located in the __[`main`](styling/src/main.rs)__ file.
<div align="center">
- <a href="https://user-images.githubusercontent.com/518289/71867993-acff4300-310c-11ea-85a3-d01d8f884346.gif">
- <img src="https://user-images.githubusercontent.com/518289/71867993-acff4300-310c-11ea-85a3-d01d8f884346.gif" height="400px">
- </a>
+ <img src="https://iced.rs/examples/styling.gif">
</div>
You can run it with `cargo run`:
@@ -120,9 +116,7 @@ Since [Iced was born in May 2019], it has been powering the user interfaces in
<div align="center">
- <a href="https://gfycat.com/gloomyweakhammerheadshark">
- <img src="https://thumbs.gfycat.com/GloomyWeakHammerheadshark-small.gif">
- </a>
+ <img src="https://iced.rs/examples/coffee.gif">
</div>
[Iced was born in May 2019]: https://github.com/hecrj/coffee/pull/35
diff --git a/examples/arc/Cargo.toml b/examples/arc/Cargo.toml
index e6e74363..5012ff82 100644
--- a/examples/arc/Cargo.toml
+++ b/examples/arc/Cargo.toml
@@ -6,4 +6,5 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["canvas", "tokio", "debug"] }
+iced.workspace = true
+iced.features = ["canvas", "tokio", "debug"]
diff --git a/examples/bezier_tool/Cargo.toml b/examples/bezier_tool/Cargo.toml
index 890e3027..b2547ff1 100644
--- a/examples/bezier_tool/Cargo.toml
+++ b/examples/bezier_tool/Cargo.toml
@@ -6,4 +6,5 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["canvas"] }
+iced.workspace = true
+iced.features = ["canvas"]
diff --git a/examples/bezier_tool/README.md b/examples/bezier_tool/README.md
index ebbb12cc..6dc13785 100644
--- a/examples/bezier_tool/README.md
+++ b/examples/bezier_tool/README.md
@@ -5,9 +5,7 @@ A Paint-like tool for drawing Bézier curves using the `Canvas` widget.
The __[`main`]__ file contains all the code of the example.
<div align="center">
- <a href="https://gfycat.com/soulfulinfiniteantbear">
- <img src="https://thumbs.gfycat.com/SoulfulInfiniteAntbear-small.gif">
- </a>
+ <img src="https://iced.rs/examples/bezier_tool.gif">
</div>
You can run it with `cargo run`:
diff --git a/examples/checkbox/Cargo.toml b/examples/checkbox/Cargo.toml
index dde8f910..1e027c4c 100644
--- a/examples/checkbox/Cargo.toml
+++ b/examples/checkbox/Cargo.toml
@@ -6,4 +6,4 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../.." }
+iced.workspace = true
diff --git a/examples/clock/Cargo.toml b/examples/clock/Cargo.toml
index 5e869eb5..2d3d5908 100644
--- a/examples/clock/Cargo.toml
+++ b/examples/clock/Cargo.toml
@@ -6,5 +6,7 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["canvas", "tokio", "debug"] }
-time = { version = "0.3.5", features = ["local-offset"] }
+iced.workspace = true
+iced.features = ["canvas", "tokio", "debug"]
+
+time = { version = "0.3", features = ["local-offset"] }
diff --git a/examples/color_palette/Cargo.toml b/examples/color_palette/Cargo.toml
index 3be732bb..2da6c6ed 100644
--- a/examples/color_palette/Cargo.toml
+++ b/examples/color_palette/Cargo.toml
@@ -6,5 +6,7 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["canvas", "palette"] }
-palette = "0.7.0"
+iced.workspace = true
+iced.features = ["canvas", "palette"]
+
+palette.workspace = true
diff --git a/examples/color_palette/README.md b/examples/color_palette/README.md
index f90020b1..9c135937 100644
--- a/examples/color_palette/README.md
+++ b/examples/color_palette/README.md
@@ -3,13 +3,11 @@
A color palette generator, based on a user-defined root color.
<div align="center">
- <a href="https://gfycat.com/dirtylonebighornsheep">
- <img src="screenshot.png">
- </a>
+ <img src="screenshot.png">
</div>
You can run it with `cargo run`:
```
-cargo run --package pure_color_palette
+cargo run --package color_palette
```
diff --git a/examples/combo_box/Cargo.toml b/examples/combo_box/Cargo.toml
index be1b5e32..0f5ecf2a 100644
--- a/examples/combo_box/Cargo.toml
+++ b/examples/combo_box/Cargo.toml
@@ -6,4 +6,5 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["debug"] }
+iced.workspace = true
+iced.features = ["debug"]
diff --git a/examples/component/Cargo.toml b/examples/component/Cargo.toml
index 9db1e6b4..83b7b8a4 100644
--- a/examples/component/Cargo.toml
+++ b/examples/component/Cargo.toml
@@ -6,4 +6,5 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["debug", "lazy"] }
+iced.workspace = true
+iced.features = ["debug", "lazy"]
diff --git a/examples/counter/Cargo.toml b/examples/counter/Cargo.toml
index e31f440f..22f86064 100644
--- a/examples/counter/Cargo.toml
+++ b/examples/counter/Cargo.toml
@@ -6,4 +6,8 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../.." }
+iced.workspace = true
+
+[target.'cfg(target_arch = "wasm32")'.dependencies]
+iced.workspace = true
+iced.features = ["webgl"]
diff --git a/examples/counter/README.md b/examples/counter/README.md
index 4d9fc5b9..18761bba 100644
--- a/examples/counter/README.md
+++ b/examples/counter/README.md
@@ -5,9 +5,7 @@ The classic counter example explained in the [`README`](../../README.md).
The __[`main`]__ file contains all the code of the example.
<div align="center">
- <a href="https://gfycat.com/fairdeadcatbird">
- <img src="https://thumbs.gfycat.com/FairDeadCatbird-small.gif">
- </a>
+ <img src="https://iced.rs/examples/counter.gif">
</div>
You can run it with `cargo run`:
@@ -15,4 +13,12 @@ You can run it with `cargo run`:
cargo run --package counter
```
+The web version can be run with [`trunk`]:
+
+```
+cd examples/counter
+trunk serve
+```
+
[`main`]: src/main.rs
+[`trunk`]: https://trunkrs.dev/
diff --git a/examples/custom_quad/Cargo.toml b/examples/custom_quad/Cargo.toml
index f097c2dd..31b5055d 100644
--- a/examples/custom_quad/Cargo.toml
+++ b/examples/custom_quad/Cargo.toml
@@ -6,4 +6,5 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["advanced"] }
+iced.workspace = true
+iced.features = ["advanced"]
diff --git a/examples/custom_widget/Cargo.toml b/examples/custom_widget/Cargo.toml
index dda0efe8..1e94bc52 100644
--- a/examples/custom_widget/Cargo.toml
+++ b/examples/custom_widget/Cargo.toml
@@ -6,4 +6,5 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["advanced"] }
+iced.workspace = true
+iced.features = ["advanced"]
diff --git a/examples/custom_widget/README.md b/examples/custom_widget/README.md
index 3d6cf902..b80e898f 100644
--- a/examples/custom_widget/README.md
+++ b/examples/custom_widget/README.md
@@ -5,9 +5,7 @@ A demonstration of how to build a custom widget that draws a circle.
The __[`main`]__ file contains all the code of the example.
<div align="center">
- <a href="https://gfycat.com/jealouscornyhomalocephale">
- <img src="https://thumbs.gfycat.com/JealousCornyHomalocephale-small.gif">
- </a>
+ <img src="https://iced.rs/examples/custom_widget.gif">
</div>
You can run it with `cargo run`:
diff --git a/examples/download_progress/Cargo.toml b/examples/download_progress/Cargo.toml
index 212832f4..18a49f66 100644
--- a/examples/download_progress/Cargo.toml
+++ b/examples/download_progress/Cargo.toml
@@ -6,7 +6,8 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["tokio"] }
+iced.workspace = true
+iced.features = ["tokio"]
[dependencies.reqwest]
version = "0.11"
diff --git a/examples/download_progress/README.md b/examples/download_progress/README.md
index 7999ce94..19cb2966 100644
--- a/examples/download_progress/README.md
+++ b/examples/download_progress/README.md
@@ -5,9 +5,7 @@ A basic application that asynchronously downloads multiple dummy files of 100 MB
The example implements a custom `Subscription` in the __[`download`](src/download.rs)__ module. This subscription downloads and produces messages that can be used to keep track of its progress.
<div align="center">
- <a href="https://gfycat.com/wildearlyafricanwilddog">
- <img src="https://thumbs.gfycat.com/WildEarlyAfricanwilddog-small.gif">
- </a>
+ <img src="https://iced.rs/examples/download_progress.gif">
</div>
You can run it with `cargo run`:
diff --git a/examples/events/Cargo.toml b/examples/events/Cargo.toml
index 15ffc0af..87315a10 100644
--- a/examples/events/Cargo.toml
+++ b/examples/events/Cargo.toml
@@ -6,4 +6,5 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["debug"] }
+iced.workspace = true
+iced.features = ["debug"]
diff --git a/examples/events/README.md b/examples/events/README.md
index 3c9a1cab..fd7f9b47 100644
--- a/examples/events/README.md
+++ b/examples/events/README.md
@@ -4,12 +4,6 @@ A log of native events displayed using a conditional `Subscription`.
The __[`main`]__ file contains all the code of the example.
-<div align="center">
- <a href="https://gfycat.com/infamousicyermine">
- <img src="https://thumbs.gfycat.com/InfamousIcyErmine-small.gif">
- </a>
-</div>
-
You can run it with `cargo run`:
```
cargo run --package events
diff --git a/examples/events/src/main.rs b/examples/events/src/main.rs
index 7f3a5e1d..32d0da2c 100644
--- a/examples/events/src/main.rs
+++ b/examples/events/src/main.rs
@@ -1,9 +1,8 @@
use iced::alignment;
+use iced::event::{self, Event};
use iced::executor;
-use iced::subscription;
use iced::widget::{button, checkbox, container, text, Column};
use iced::window;
-use iced::Event;
use iced::{
Alignment, Application, Command, Element, Length, Settings, Subscription,
Theme,
@@ -71,7 +70,7 @@ impl Application for Events {
}
fn subscription(&self) -> Subscription<Message> {
- subscription::events().map(Message::EventOccurred)
+ event::listen().map(Message::EventOccurred)
}
fn view(&self) -> Element<Message> {
diff --git a/examples/exit/Cargo.toml b/examples/exit/Cargo.toml
index 34d0789a..b06fbadc 100644
--- a/examples/exit/Cargo.toml
+++ b/examples/exit/Cargo.toml
@@ -5,4 +5,4 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../.." }
+iced.workspace = true
diff --git a/examples/game_of_life/Cargo.toml b/examples/game_of_life/Cargo.toml
index 6de45db6..9b291de8 100644
--- a/examples/game_of_life/Cargo.toml
+++ b/examples/game_of_life/Cargo.toml
@@ -6,8 +6,10 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["canvas", "tokio", "debug"] }
-tokio = { version = "1.0", features = ["sync"] }
-itertools = "0.9"
-rustc-hash = "1.1"
-env_logger = "0.10"
+iced.workspace = true
+iced.features = ["debug", "canvas", "tokio"]
+
+itertools = "0.11"
+rustc-hash.workspace = true
+tokio = { workspace = true, features = ["sync"] }
+tracing-subscriber = "0.3"
diff --git a/examples/game_of_life/README.md b/examples/game_of_life/README.md
index aa39201c..60033c1a 100644
--- a/examples/game_of_life/README.md
+++ b/examples/game_of_life/README.md
@@ -7,9 +7,7 @@ It runs a simulation in a background thread while allowing interaction with a `C
The __[`main`]__ file contains the relevant code of the example.
<div align="center">
- <a href="https://gfycat.com/WhichPaltryChick">
- <img src="https://thumbs.gfycat.com/WhichPaltryChick-size_restricted.gif">
- </a>
+ <img src="https://iced.rs/examples/game_of_life.gif">
</div>
You can run it with `cargo run`:
diff --git a/examples/game_of_life/src/main.rs b/examples/game_of_life/src/main.rs
index fa711744..e451cb06 100644
--- a/examples/game_of_life/src/main.rs
+++ b/examples/game_of_life/src/main.rs
@@ -18,7 +18,7 @@ use iced::{
use std::time::{Duration, Instant};
pub fn main() -> iced::Result {
- env_logger::builder().format_timestamp(None).init();
+ tracing_subscriber::fmt::init();
GameOfLife::run(Settings {
antialiasing: true,
@@ -550,7 +550,7 @@ mod grid {
frame.translate(center);
frame.scale(self.scaling);
frame.translate(self.translation);
- frame.scale(Cell::SIZE as f32);
+ frame.scale(Cell::SIZE);
let region = self.visible_region(frame.size());
@@ -576,7 +576,7 @@ mod grid {
frame.translate(center);
frame.scale(self.scaling);
frame.translate(self.translation);
- frame.scale(Cell::SIZE as f32);
+ frame.scale(Cell::SIZE);
frame.fill_rectangle(
Point::new(cell.j as f32, cell.i as f32),
@@ -630,7 +630,7 @@ mod grid {
frame.translate(center);
frame.scale(self.scaling);
frame.translate(self.translation);
- frame.scale(Cell::SIZE as f32);
+ frame.scale(Cell::SIZE);
let region = self.visible_region(frame.size());
let rows = region.rows();
@@ -834,7 +834,7 @@ mod grid {
}
impl Cell {
- const SIZE: usize = 20;
+ const SIZE: u16 = 20;
fn at(position: Point) -> Cell {
let i = (position.y / Cell::SIZE as f32).ceil() as isize;
diff --git a/examples/geometry/Cargo.toml b/examples/geometry/Cargo.toml
index 6068d651..9606dcb3 100644
--- a/examples/geometry/Cargo.toml
+++ b/examples/geometry/Cargo.toml
@@ -6,4 +6,5 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["advanced"] }
+iced.workspace = true
+iced.features = ["advanced"]
diff --git a/examples/geometry/README.md b/examples/geometry/README.md
index 4d5c81cb..16be8d19 100644
--- a/examples/geometry/README.md
+++ b/examples/geometry/README.md
@@ -5,9 +5,7 @@ A custom widget showcasing how to draw geometry with the `Mesh2D` primitive in [
The __[`main`]__ file contains all the code of the example.
<div align="center">
- <a href="https://gfycat.com/activeunfitkangaroo">
- <img src="https://thumbs.gfycat.com/ActiveUnfitKangaroo-small.gif">
- </a>
+ <img src="https://iced.rs/examples/geometry.gif">
</div>
You can run it with `cargo run`:
diff --git a/examples/gradient/Cargo.toml b/examples/gradient/Cargo.toml
new file mode 100644
index 00000000..2dea2c4f
--- /dev/null
+++ b/examples/gradient/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "gradient"
+version = "0.1.0"
+edition = "2021"
+publish = false
+
+[dependencies]
+iced = { path = "../.." }
diff --git a/examples/gradient/src/main.rs b/examples/gradient/src/main.rs
new file mode 100644
index 00000000..1bf5822d
--- /dev/null
+++ b/examples/gradient/src/main.rs
@@ -0,0 +1,99 @@
+use iced::gradient;
+use iced::widget::{column, container, horizontal_space, row, slider, text};
+use iced::{
+ Alignment, Background, Color, Element, Length, Radians, Sandbox, Settings,
+};
+
+pub fn main() -> iced::Result {
+ Gradient::run(Settings::default())
+}
+
+#[derive(Debug, Clone, Copy)]
+struct Gradient {
+ start: Color,
+ end: Color,
+ angle: Radians,
+}
+
+#[derive(Debug, Clone, Copy)]
+enum Message {
+ StartChanged(Color),
+ EndChanged(Color),
+ AngleChanged(Radians),
+}
+
+impl Sandbox for Gradient {
+ type Message = Message;
+
+ fn new() -> Self {
+ Self {
+ start: Color::WHITE,
+ end: Color::new(0.0, 0.0, 1.0, 1.0),
+ angle: Radians(0.0),
+ }
+ }
+
+ fn title(&self) -> String {
+ String::from("Gradient")
+ }
+
+ fn update(&mut self, message: Message) {
+ match message {
+ Message::StartChanged(color) => self.start = color,
+ Message::EndChanged(color) => self.end = color,
+ Message::AngleChanged(angle) => self.angle = angle,
+ }
+ }
+
+ fn view(&self) -> Element<Message> {
+ let Self { start, end, angle } = *self;
+
+ let gradient_box = container(horizontal_space(Length::Fill))
+ .width(Length::Fill)
+ .height(Length::Fill)
+ .style(move |_: &_| {
+ let gradient = gradient::Linear::new(angle)
+ .add_stop(0.0, start)
+ .add_stop(1.0, end)
+ .into();
+
+ container::Appearance {
+ background: Some(Background::Gradient(gradient)),
+ ..Default::default()
+ }
+ });
+
+ let angle_picker = row![
+ text("Angle").width(64),
+ slider(Radians::RANGE, self.angle, Message::AngleChanged)
+ .step(0.01)
+ ]
+ .spacing(8)
+ .padding(8)
+ .align_items(Alignment::Center);
+
+ column![
+ color_picker("Start", self.start).map(Message::StartChanged),
+ color_picker("End", self.end).map(Message::EndChanged),
+ angle_picker,
+ gradient_box
+ ]
+ .into()
+ }
+}
+
+fn color_picker(label: &str, color: Color) -> Element<'_, Color> {
+ row![
+ text(label).width(64),
+ slider(0.0..=1.0, color.r, move |r| { Color { r, ..color } })
+ .step(0.01),
+ slider(0.0..=1.0, color.g, move |g| { Color { g, ..color } })
+ .step(0.01),
+ slider(0.0..=1.0, color.b, move |b| { Color { b, ..color } })
+ .step(0.01),
+ ]
+ .spacing(8)
+ .padding(8)
+ .align_items(Alignment::Center)
+ .into()
+}
diff --git a/examples/integration/Cargo.toml b/examples/integration/Cargo.toml
index 22914742..a4a961f8 100644
--- a/examples/integration/Cargo.toml
+++ b/examples/integration/Cargo.toml
@@ -6,19 +6,18 @@ edition = "2021"
publish = false
[dependencies]
-iced_winit = { path = "../../winit" }
-iced_wgpu = { path = "../../wgpu" }
-iced_widget = { path = "../../widget" }
-iced_renderer = { path = "../../renderer", features = ["wgpu"] }
-env_logger = "0.10"
+iced_winit.workspace = true
+iced_wgpu.workspace = true
+iced_widget.workspace = true
+
+[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
+tracing-subscriber = "0.3"
[target.'cfg(target_arch = "wasm32")'.dependencies]
-console_error_panic_hook = "0.1.7"
-console_log = "0.2.0"
-log = "0.4"
+iced_wgpu.workspace = true
+iced_wgpu.features = ["webgl"]
+
+console_error_panic_hook = "0.1"
+console_log = "1.0"
wasm-bindgen = "0.2"
web-sys = { version = "0.3", features = ["Element", "HtmlCanvasElement", "Window", "Document"] }
-# This dependency a little bit quirky, it is deep in the tree and without `js` feature it
-# refuses to work with `wasm32-unknown-unknown target`. Unfortunately, we need this patch
-# to make it work
-getrandom = { version = "0.2", features = ["js"] }
diff --git a/examples/integration/README.md b/examples/integration/README.md
index ece9ba1e..996cdc17 100644
--- a/examples/integration/README.md
+++ b/examples/integration/README.md
@@ -5,9 +5,7 @@ A demonstration of how to integrate Iced in an existing [`wgpu`] application.
The __[`main`]__ file contains all the code of the example.
<div align="center">
- <a href="https://gfycat.com/nicemediocrekodiakbear">
- <img src="https://thumbs.gfycat.com/NiceMediocreKodiakbear-small.gif">
- </a>
+ <img src="https://iced.rs/examples/integration.gif">
</div>
You can run it with `cargo run`:
diff --git a/examples/integration/src/main.rs b/examples/integration/src/main.rs
index e011a411..7945bd20 100644
--- a/examples/integration/src/main.rs
+++ b/examples/integration/src/main.rs
@@ -29,7 +29,7 @@ use winit::platform::web::WindowBuilderExtWebSys;
pub fn main() -> Result<(), Box<dyn std::error::Error>> {
#[cfg(target_arch = "wasm32")]
let canvas_element = {
- console_log::init_with_level(log::Level::Debug)?;
+ console_log::init().expect("Initialize logger");
std::panic::set_hook(Box::new(console_error_panic_hook::hook));
@@ -41,7 +41,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
};
#[cfg(not(target_arch = "wasm32"))]
- env_logger::init();
+ tracing_subscriber::fmt::init();
// Initialize winit
let event_loop = EventLoop::new();
@@ -82,7 +82,6 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
futures::futures::executor::block_on(async {
let adapter = wgpu::util::initialize_adapter_from_env_or_default(
&instance,
- backend,
Some(&surface),
)
.await
diff --git a/examples/lazy/Cargo.toml b/examples/lazy/Cargo.toml
index e03e89a9..4ccb9584 100644
--- a/examples/lazy/Cargo.toml
+++ b/examples/lazy/Cargo.toml
@@ -6,4 +6,5 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["debug", "lazy"] }
+iced.workspace = true
+iced.features = ["debug", "lazy"]
diff --git a/examples/loading_spinners/Cargo.toml b/examples/loading_spinners/Cargo.toml
index ee9a48aa..a32da386 100644
--- a/examples/loading_spinners/Cargo.toml
+++ b/examples/loading_spinners/Cargo.toml
@@ -6,6 +6,8 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["advanced", "canvas"] }
-lyon_algorithms = "1"
-once_cell = "1"
+iced.workspace = true
+iced.features = ["advanced", "canvas"]
+
+lyon_algorithms = "1.0"
+once_cell.workspace = true \ No newline at end of file
diff --git a/examples/loading_spinners/README.md b/examples/loading_spinners/README.md
index 3573c6f6..75b88804 100644
--- a/examples/loading_spinners/README.md
+++ b/examples/loading_spinners/README.md
@@ -2,12 +2,6 @@
Example implementation of animated indeterminate loading spinners.
-<div align="center">
- <a href="https://gfycat.com/importantdevotedhammerheadbird">
- <img src="https://thumbs.gfycat.com/ImportantDevotedHammerheadbird-small.gif">
- </a>
-</div>
-
You can run it with `cargo run`:
```
cargo run --package loading_spinners
diff --git a/examples/modal/Cargo.toml b/examples/modal/Cargo.toml
index 3ac61e6a..009d9653 100644
--- a/examples/modal/Cargo.toml
+++ b/examples/modal/Cargo.toml
@@ -6,4 +6,5 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["advanced"] }
+iced.workspace = true
+iced.features = ["advanced"]
diff --git a/examples/modal/src/main.rs b/examples/modal/src/main.rs
index aa9107d0..c050d3cc 100644
--- a/examples/modal/src/main.rs
+++ b/examples/modal/src/main.rs
@@ -1,12 +1,14 @@
+use iced::event::{self, Event};
use iced::executor;
use iced::keyboard;
-use iced::subscription::{self, Subscription};
use iced::theme;
use iced::widget::{
self, button, column, container, horizontal_space, pick_list, row, text,
text_input,
};
-use iced::{Alignment, Application, Command, Element, Event, Length, Settings};
+use iced::{
+ Alignment, Application, Command, Element, Length, Settings, Subscription,
+};
use modal::Modal;
use std::fmt;
@@ -49,7 +51,7 @@ impl Application for App {
}
fn subscription(&self) -> Subscription<Self::Message> {
- subscription::events().map(Message::Event)
+ event::listen().map(Message::Event)
}
fn update(&mut self, message: Message) -> Command<Message> {
diff --git a/examples/multitouch/Cargo.toml b/examples/multitouch/Cargo.toml
index 867312f8..e0d14f58 100644
--- a/examples/multitouch/Cargo.toml
+++ b/examples/multitouch/Cargo.toml
@@ -6,7 +6,8 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["canvas", "tokio", "debug"] }
-tokio = { version = "1.0", features = ["sync"] }
-env_logger = "0.10"
+iced.workspace = true
+iced.features = ["debug", "canvas", "tokio"]
+
+tracing-subscriber = "0.3"
voronator = "0.2"
diff --git a/examples/multitouch/src/main.rs b/examples/multitouch/src/main.rs
index 2830b78d..ba8df7aa 100644
--- a/examples/multitouch/src/main.rs
+++ b/examples/multitouch/src/main.rs
@@ -13,7 +13,7 @@ use iced::{
use std::collections::HashMap;
pub fn main() -> iced::Result {
- env_logger::builder().format_timestamp(None).init();
+ tracing_subscriber::fmt::init();
Multitouch::run(Settings {
antialiasing: true,
diff --git a/examples/pane_grid/Cargo.toml b/examples/pane_grid/Cargo.toml
index 4c0bf072..095ecd10 100644
--- a/examples/pane_grid/Cargo.toml
+++ b/examples/pane_grid/Cargo.toml
@@ -6,4 +6,5 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["debug", "lazy"] }
+iced.workspace = true
+iced.features = ["debug", "lazy"]
diff --git a/examples/pane_grid/README.md b/examples/pane_grid/README.md
index a4cfcb7d..65357b23 100644
--- a/examples/pane_grid/README.md
+++ b/examples/pane_grid/README.md
@@ -15,9 +15,7 @@ This example showcases the `PaneGrid` widget, which features:
The __[`main`]__ file contains all the code of the example.
<div align="center">
- <a href="https://gfycat.com/frailfreshairedaleterrier">
- <img src="https://thumbs.gfycat.com/FrailFreshAiredaleterrier-small.gif">
- </a>
+ <img src="https://iced.rs/examples/pane_grid.gif">
</div>
You can run it with `cargo run`:
diff --git a/examples/pane_grid/src/main.rs b/examples/pane_grid/src/main.rs
index 04896e20..af87e2c0 100644
--- a/examples/pane_grid/src/main.rs
+++ b/examples/pane_grid/src/main.rs
@@ -1,8 +1,6 @@
use iced::alignment::{self, Alignment};
-use iced::event::{self, Event};
use iced::executor;
use iced::keyboard;
-use iced::subscription;
use iced::theme::{self, Theme};
use iced::widget::pane_grid::{self, PaneGrid};
use iced::widget::{
@@ -146,18 +144,12 @@ impl Application for Example {
}
fn subscription(&self) -> Subscription<Message> {
- subscription::events_with(|event, status| {
- if let event::Status::Captured = status {
+ keyboard::on_key_press(|key_code, modifiers| {
+ if !modifiers.command() {
return None;
}
- match event {
- Event::Keyboard(keyboard::Event::KeyPressed {
- modifiers,
- key_code,
- }) if modifiers.command() => handle_hotkey(key_code),
- _ => None,
- }
+ handle_hotkey(key_code)
})
}
diff --git a/examples/pick_list/Cargo.toml b/examples/pick_list/Cargo.toml
index 4aa4603a..030558e7 100644
--- a/examples/pick_list/Cargo.toml
+++ b/examples/pick_list/Cargo.toml
@@ -6,4 +6,5 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["debug"] }
+iced.workspace = true
+iced.features = ["debug"]
diff --git a/examples/pokedex/Cargo.toml b/examples/pokedex/Cargo.toml
index e99fc0c3..bf7e1e35 100644
--- a/examples/pokedex/Cargo.toml
+++ b/examples/pokedex/Cargo.toml
@@ -6,7 +6,9 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["image", "debug", "tokio"] }
+iced.workspace = true
+iced.features = ["image", "debug", "tokio"]
+
serde_json = "1.0"
[dependencies.serde]
@@ -19,5 +21,8 @@ default-features = false
features = ["json", "rustls-tls"]
[dependencies.rand]
-version = "0.7"
-features = ["wasm-bindgen"]
+version = "0.8"
+
+[dependencies.getrandom]
+version = "0.2"
+features = ["js"]
diff --git a/examples/pokedex/README.md b/examples/pokedex/README.md
index 50720f57..8e8562ac 100644
--- a/examples/pokedex/README.md
+++ b/examples/pokedex/README.md
@@ -4,9 +4,7 @@ An application that loads a random Pokédex entry using the [PokéAPI].
All the example code can be found in the __[`main`](src/main.rs)__ file.
<div align="center">
- <a href="https://gfycat.com/aggressivedarkelephantseal-rust-gui">
- <img src="https://thumbs.gfycat.com/AggressiveDarkElephantseal-small.gif" height="400px">
- </a>
+ <img src="https://iced.rs/examples/pokedex.gif">
</div>
You can run it on native platforms with `cargo run`:
diff --git a/examples/pokedex/src/main.rs b/examples/pokedex/src/main.rs
index 4482814c..8b71a269 100644
--- a/examples/pokedex/src/main.rs
+++ b/examples/pokedex/src/main.rs
@@ -153,7 +153,7 @@ impl Pokemon {
let id = {
let mut rng = rand::rngs::OsRng;
- rng.gen_range(0, Pokemon::TOTAL)
+ rng.gen_range(0..Pokemon::TOTAL)
};
let fetch_entry = async {
diff --git a/examples/progress_bar/Cargo.toml b/examples/progress_bar/Cargo.toml
index 383a9bdd..6624ae15 100644
--- a/examples/progress_bar/Cargo.toml
+++ b/examples/progress_bar/Cargo.toml
@@ -6,4 +6,4 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../.." }
+iced.workspace = true
diff --git a/examples/progress_bar/README.md b/examples/progress_bar/README.md
index 1e927b3c..1268ac6b 100644
--- a/examples/progress_bar/README.md
+++ b/examples/progress_bar/README.md
@@ -5,9 +5,7 @@ A simple progress bar that can be filled by using a slider.
The __[`main`]__ file contains all the code of the example.
<div align="center">
- <a href="https://gfycat.com/importantdevotedhammerheadbird">
- <img src="https://thumbs.gfycat.com/ImportantDevotedHammerheadbird-small.gif">
- </a>
+ <img src="https://iced.rs/examples/pokedex.gif">
</div>
You can run it with `cargo run`:
diff --git a/examples/qr_code/Cargo.toml b/examples/qr_code/Cargo.toml
index 2f164df6..8f33ea8c 100644
--- a/examples/qr_code/Cargo.toml
+++ b/examples/qr_code/Cargo.toml
@@ -6,4 +6,5 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["qr_code"] }
+iced.workspace = true
+iced.features = ["qr_code"]
diff --git a/examples/qr_code/README.md b/examples/qr_code/README.md
index 2dd89c26..0d1abaa7 100644
--- a/examples/qr_code/README.md
+++ b/examples/qr_code/README.md
@@ -5,9 +5,7 @@ A basic QR code generator that showcases the `QRCode` widget.
The __[`main`]__ file contains all the code of the example.
<div align="center">
- <a href="https://gfycat.com/heavyexhaustedaracari">
- <img src="https://thumbs.gfycat.com/HeavyExhaustedAracari-size_restricted.gif">
- </a>
+ <img src="https://iced.rs/examples/qr_code.gif">
</div>
You can run it with `cargo run`:
diff --git a/examples/screenshot/Cargo.toml b/examples/screenshot/Cargo.toml
index b79300b7..dcd77439 100644
--- a/examples/screenshot/Cargo.toml
+++ b/examples/screenshot/Cargo.toml
@@ -6,6 +6,8 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["debug", "image", "advanced"] }
-image = { version = "0.24.6", features = ["png"]}
-env_logger = "0.10.0"
+iced.workspace = true
+iced.features = ["debug", "image", "advanced"]
+
+image = { workspace = true, features = ["png"]}
+tracing-subscriber = "0.3" \ No newline at end of file
diff --git a/examples/screenshot/src/main.rs b/examples/screenshot/src/main.rs
index 83824535..68c9d031 100644
--- a/examples/screenshot/src/main.rs
+++ b/examples/screenshot/src/main.rs
@@ -4,16 +4,15 @@ use iced::theme::{Button, Container};
use iced::widget::{button, column, container, image, row, text, text_input};
use iced::window::screenshot::{self, Screenshot};
use iced::{
- event, executor, keyboard, subscription, Alignment, Application, Command,
- ContentFit, Element, Event, Length, Rectangle, Renderer, Subscription,
- Theme,
+ event, executor, keyboard, Alignment, Application, Command, ContentFit,
+ Element, Event, Length, Rectangle, Renderer, Subscription, Theme,
};
use ::image as img;
use ::image::ColorType;
fn main() -> iced::Result {
- env_logger::builder().format_timestamp(None).init();
+ tracing_subscriber::fmt::init();
Example::run(iced::Settings::default())
}
@@ -254,7 +253,7 @@ impl Application for Example {
}
fn subscription(&self) -> Subscription<Self::Message> {
- subscription::events_with(|event, status| {
+ event::listen_with(|event, status| {
if let event::Status::Captured = status {
return None;
}
diff --git a/examples/scrollable/Cargo.toml b/examples/scrollable/Cargo.toml
index e6411e26..f8c735c0 100644
--- a/examples/scrollable/Cargo.toml
+++ b/examples/scrollable/Cargo.toml
@@ -6,5 +6,7 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["debug"] }
-once_cell = "1.16.0"
+iced.workspace = true
+iced.features = ["debug"]
+
+once_cell.workspace = true
diff --git a/examples/sierpinski_triangle/Cargo.toml b/examples/sierpinski_triangle/Cargo.toml
index 39d45f64..600a9e06 100644
--- a/examples/sierpinski_triangle/Cargo.toml
+++ b/examples/sierpinski_triangle/Cargo.toml
@@ -6,5 +6,7 @@ edition = "2018"
publish = false
[dependencies]
-iced = { path = "../..", features = ["canvas", "debug"] }
-rand = "0.8.4"
+iced.workspace = true
+iced.features = ["debug", "canvas"]
+
+rand = "0.8"
diff --git a/examples/sierpinski_triangle/README.md b/examples/sierpinski_triangle/README.md
index 9fd18257..8b7676d1 100644
--- a/examples/sierpinski_triangle/README.md
+++ b/examples/sierpinski_triangle/README.md
@@ -5,9 +5,7 @@ A simple [Sierpiński triangle](https://en.wikipedia.org/wiki/Sierpi%C5%84ski_tr
Left-click add fixed point, right-click remove fixed point.
<div align="center">
- <a href="https://gfycat.com/flippantrectangularechidna">
- <img src="https://thumbs.gfycat.com/FlippantRectangularEchidna-size_restricted.gif">
- </a>
+ <img src="https://iced.rs/examples/sierpinski_triangle.gif">
</div>
You can run with cargo:
diff --git a/examples/slider/Cargo.toml b/examples/slider/Cargo.toml
index 112d7cff..fad8916e 100644
--- a/examples/slider/Cargo.toml
+++ b/examples/slider/Cargo.toml
@@ -6,4 +6,4 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../.." }
+iced.workspace = true
diff --git a/examples/solar_system/Cargo.toml b/examples/solar_system/Cargo.toml
index 1a98a87e..ca64da14 100644
--- a/examples/solar_system/Cargo.toml
+++ b/examples/solar_system/Cargo.toml
@@ -6,6 +6,8 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["canvas", "tokio", "debug"] }
-env_logger = "0.10.0"
+iced.workspace = true
+iced.features = ["debug", "canvas", "tokio"]
+
rand = "0.8.3"
+tracing-subscriber = "0.3"
diff --git a/examples/solar_system/README.md b/examples/solar_system/README.md
index acfbc466..81ffd3a5 100644
--- a/examples/solar_system/README.md
+++ b/examples/solar_system/README.md
@@ -5,9 +5,7 @@ An animated solar system drawn using the `Canvas` widget and showcasing how to c
The __[`main`]__ file contains all the code of the example.
<div align="center">
- <a href="https://gfycat.com/selfassuredaromaticdunnart">
- <img src="https://thumbs.gfycat.com/SelfassuredAromaticDunnart-small.gif">
- </a>
+ <img src="https://iced.rs/examples/solar_system.gif">
</div>
You can run it with `cargo run`:
diff --git a/examples/solar_system/src/main.rs b/examples/solar_system/src/main.rs
index 58d06206..8fa8946e 100644
--- a/examples/solar_system/src/main.rs
+++ b/examples/solar_system/src/main.rs
@@ -23,7 +23,7 @@ use iced::{
use std::time::Instant;
pub fn main() -> iced::Result {
- env_logger::builder().format_timestamp(None).init();
+ tracing_subscriber::fmt::init();
SolarSystem::run(Settings {
antialiasing: true,
diff --git a/examples/stopwatch/Cargo.toml b/examples/stopwatch/Cargo.toml
index f623feb9..6b1419f6 100644
--- a/examples/stopwatch/Cargo.toml
+++ b/examples/stopwatch/Cargo.toml
@@ -6,4 +6,5 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["smol"] }
+iced.workspace = true
+iced.features = ["smol"]
diff --git a/examples/stopwatch/README.md b/examples/stopwatch/README.md
index 4cf4582e..1cf370bd 100644
--- a/examples/stopwatch/README.md
+++ b/examples/stopwatch/README.md
@@ -5,9 +5,7 @@ A watch with start/stop and reset buttons showcasing how to listen to time.
The __[`main`]__ file contains all the code of the example.
<div align="center">
- <a href="https://gfycat.com/granularenviousgoitered-rust-gui">
- <img src="https://thumbs.gfycat.com/GranularEnviousGoitered-small.gif">
- </a>
+ <img src="https://iced.rs/examples/stopwatch.gif">
</div>
You can run it with `cargo run`:
diff --git a/examples/stopwatch/src/main.rs b/examples/stopwatch/src/main.rs
index 842ba3d4..0b0f0607 100644
--- a/examples/stopwatch/src/main.rs
+++ b/examples/stopwatch/src/main.rs
@@ -1,5 +1,6 @@
use iced::alignment;
use iced::executor;
+use iced::keyboard;
use iced::theme::{self, Theme};
use iced::time;
use iced::widget::{button, column, container, row, text};
@@ -77,12 +78,25 @@ impl Application for Stopwatch {
}
fn subscription(&self) -> Subscription<Message> {
- match self.state {
+ let tick = match self.state {
State::Idle => Subscription::none(),
State::Ticking { .. } => {
time::every(Duration::from_millis(10)).map(Message::Tick)
}
+ };
+
+ fn handle_hotkey(
+ key_code: keyboard::KeyCode,
+ _modifiers: keyboard::Modifiers,
+ ) -> Option<Message> {
+ match key_code {
+ keyboard::KeyCode::Space => Some(Message::Toggle),
+ keyboard::KeyCode::R => Some(Message::Reset),
+ _ => None,
+ }
}
+
+ Subscription::batch(vec![tick, keyboard::on_key_press(handle_hotkey)])
}
fn view(&self) -> Element<Message> {
diff --git a/examples/styling/Cargo.toml b/examples/styling/Cargo.toml
index f771708c..c8a90258 100644
--- a/examples/styling/Cargo.toml
+++ b/examples/styling/Cargo.toml
@@ -6,4 +6,4 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../.." }
+iced.workspace = true
diff --git a/examples/styling/README.md b/examples/styling/README.md
index 6c198a54..fd12300d 100644
--- a/examples/styling/README.md
+++ b/examples/styling/README.md
@@ -4,9 +4,7 @@ An example showcasing custom styling with a light and dark theme.
All the example code is located in the __[`main`](src/main.rs)__ file.
<div align="center">
- <a href="https://user-images.githubusercontent.com/518289/71867993-acff4300-310c-11ea-85a3-d01d8f884346.gif">
- <img src="https://user-images.githubusercontent.com/518289/71867993-acff4300-310c-11ea-85a3-d01d8f884346.gif" height="400px">
- </a>
+ <img src="https://iced.rs/examples/styling.gif">
</div>
You can run it with `cargo run`:
diff --git a/examples/styling/src/main.rs b/examples/styling/src/main.rs
index f8a4c80a..51538ec2 100644
--- a/examples/styling/src/main.rs
+++ b/examples/styling/src/main.rs
@@ -108,6 +108,7 @@ impl Sandbox for Styling {
column!["Scroll me!", vertical_space(800), "You did it!"]
.width(Length::Fill),
)
+ .width(Length::Fill)
.height(100);
let checkbox = checkbox(
diff --git a/examples/svg/Cargo.toml b/examples/svg/Cargo.toml
index f5a6eaa2..78208fb0 100644
--- a/examples/svg/Cargo.toml
+++ b/examples/svg/Cargo.toml
@@ -6,4 +6,5 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["svg"] }
+iced.workspace = true
+iced.features = ["svg"]
diff --git a/examples/system_information/Cargo.toml b/examples/system_information/Cargo.toml
index 7d1e4b94..41903122 100644
--- a/examples/system_information/Cargo.toml
+++ b/examples/system_information/Cargo.toml
@@ -6,5 +6,7 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["system"] }
-bytesize = { version = "1.1.0" }
+iced.workspace = true
+iced.features = ["system"]
+
+bytesize = "1.1"
diff --git a/examples/toast/Cargo.toml b/examples/toast/Cargo.toml
index f703572c..113313e2 100644
--- a/examples/toast/Cargo.toml
+++ b/examples/toast/Cargo.toml
@@ -6,4 +6,5 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["advanced"] }
+iced.workspace = true
+iced.features = ["advanced"]
diff --git a/examples/toast/src/main.rs b/examples/toast/src/main.rs
index 50fa885a..8570a38e 100644
--- a/examples/toast/src/main.rs
+++ b/examples/toast/src/main.rs
@@ -1,10 +1,12 @@
+use iced::event::{self, Event};
use iced::executor;
use iced::keyboard;
-use iced::subscription::{self, Subscription};
use iced::widget::{
self, button, column, container, pick_list, row, slider, text, text_input,
};
-use iced::{Alignment, Application, Command, Element, Event, Length, Settings};
+use iced::{
+ Alignment, Application, Command, Element, Length, Settings, Subscription,
+};
use toast::{Status, Toast};
@@ -57,7 +59,7 @@ impl Application for App {
}
fn subscription(&self) -> Subscription<Self::Message> {
- subscription::events().map(Message::Event)
+ event::listen().map(Message::Event)
}
fn update(&mut self, message: Message) -> Command<Message> {
diff --git a/examples/todos/Cargo.toml b/examples/todos/Cargo.toml
index 7292f665..3c62bfbc 100644
--- a/examples/todos/Cargo.toml
+++ b/examples/todos/Cargo.toml
@@ -6,21 +6,26 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["async-std", "debug"] }
-uuid = { version = "1.0", features = ["v4", "fast-rng", "serde"] }
+iced.workspace = true
+iced.features = ["async-std", "debug"]
+
+once_cell.workspace = true
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
-once_cell = "1.0"
-tracing-subscriber = "0.3"
+uuid = { version = "1.0", features = ["v4", "fast-rng", "serde"] }
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
-async-std = "1.0"
+async-std.workspace = true
directories-next = "2.0"
+tracing-subscriber = "0.3"
[target.'cfg(target_arch = "wasm32")'.dependencies]
+iced.workspace = true
+iced.features = ["debug", "webgl"]
+
uuid = { version = "1.0", features = ["js"] }
-web-sys = { version = "0.3", features = ["Window", "Storage"] }
-wasm-timer = "0.2"
+web-sys = { workspace = true, features = ["Window", "Storage"] }
+wasm-timer.workspace = true
[package.metadata.deb]
assets = [
diff --git a/examples/todos/README.md b/examples/todos/README.md
index 9c2598b9..5e42f166 100644
--- a/examples/todos/README.md
+++ b/examples/todos/README.md
@@ -5,8 +5,8 @@ A todos tracker inspired by [TodoMVC]. It showcases dynamic layout, text input,
All the example code is located in the __[`main`]__ file.
<div align="center">
- <a href="https://gfycat.com/littlesanehalicore">
- <img src="https://thumbs.gfycat.com/LittleSaneHalicore-small.gif" height="400px">
+ <a href="https://iced.rs/examples/todos.mp4">
+ <img src="https://iced.rs/examples/todos.gif">
</a>
</div>
@@ -14,7 +14,14 @@ You can run the native version with `cargo run`:
```
cargo run --package todos
```
-We have not yet implemented a `LocalStorage` version of the auto-save feature. Therefore, it does not work on web _yet_!
+
+The web version can be run with [`trunk`]:
+
+```
+cd examples/todos
+trunk serve
+```
[`main`]: src/main.rs
[TodoMVC]: http://todomvc.com/
+[`trunk`]: https://trunkrs.dev/
diff --git a/examples/todos/src/main.rs b/examples/todos/src/main.rs
index 1dd8a307..5d8936df 100644
--- a/examples/todos/src/main.rs
+++ b/examples/todos/src/main.rs
@@ -1,8 +1,6 @@
use iced::alignment::{self, Alignment};
-use iced::event::{self, Event};
use iced::font::{self, Font};
-use iced::keyboard::{self, KeyCode, Modifiers};
-use iced::subscription;
+use iced::keyboard;
use iced::theme::{self, Theme};
use iced::widget::{
self, button, checkbox, column, container, keyed_column, row, scrollable,
@@ -55,7 +53,7 @@ enum Message {
FilterChanged(Filter),
TaskMessage(usize, TaskMessage),
TabPressed { shift: bool },
- ToggleFullscreen(window::Mode),
+ ChangeWindowMode(window::Mode),
}
impl Application for Todos {
@@ -166,7 +164,7 @@ impl Application for Todos {
widget::focus_next()
}
}
- Message::ToggleFullscreen(mode) => {
+ Message::ChangeWindowMode(mode) => {
window::change_mode(mode)
}
_ => Command::none(),
@@ -267,33 +265,19 @@ impl Application for Todos {
}
fn subscription(&self) -> Subscription<Message> {
- subscription::events_with(|event, status| match (event, status) {
- (
- Event::Keyboard(keyboard::Event::KeyPressed {
- key_code: keyboard::KeyCode::Tab,
- modifiers,
- ..
+ keyboard::on_key_press(|key_code, modifiers| {
+ match (key_code, modifiers) {
+ (keyboard::KeyCode::Tab, _) => Some(Message::TabPressed {
+ shift: modifiers.shift(),
}),
- event::Status::Ignored,
- ) => Some(Message::TabPressed {
- shift: modifiers.shift(),
- }),
- (
- Event::Keyboard(keyboard::Event::KeyPressed {
- key_code,
- modifiers: Modifiers::SHIFT,
- }),
- event::Status::Ignored,
- ) => match key_code {
- KeyCode::Up => {
- Some(Message::ToggleFullscreen(window::Mode::Fullscreen))
+ (keyboard::KeyCode::Up, keyboard::Modifiers::SHIFT) => {
+ Some(Message::ChangeWindowMode(window::Mode::Fullscreen))
}
- KeyCode::Down => {
- Some(Message::ToggleFullscreen(window::Mode::Windowed))
+ (keyboard::KeyCode::Down, keyboard::Modifiers::SHIFT) => {
+ Some(Message::ChangeWindowMode(window::Mode::Windowed))
}
_ => None,
- },
- _ => None,
+ }
})
}
}
diff --git a/examples/tooltip/Cargo.toml b/examples/tooltip/Cargo.toml
index 25840fb4..57bb0dcb 100644
--- a/examples/tooltip/Cargo.toml
+++ b/examples/tooltip/Cargo.toml
@@ -6,4 +6,5 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["debug"] }
+iced.workspace = true
+iced.features = ["debug"]
diff --git a/examples/tour/Cargo.toml b/examples/tour/Cargo.toml
index 48471f2d..9e984ad1 100644
--- a/examples/tour/Cargo.toml
+++ b/examples/tour/Cargo.toml
@@ -6,5 +6,15 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["image", "debug"] }
-env_logger = "0.10.0"
+iced.workspace = true
+iced.features = ["image", "debug"]
+
+[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
+tracing-subscriber = "0.3"
+
+[target.'cfg(target_arch = "wasm32")'.dependencies]
+iced.workspace = true
+iced.features = ["image", "debug", "webgl"]
+
+console_error_panic_hook = "0.1"
+console_log = "1.0"
diff --git a/examples/tour/README.md b/examples/tour/README.md
index 731e7e66..1c01236b 100644
--- a/examples/tour/README.md
+++ b/examples/tour/README.md
@@ -5,8 +5,8 @@ A simple UI tour that can run both on native platforms and the web! It showcases
The __[`main`]__ file contains all the code of the example! All the cross-platform GUI is defined in terms of __state__, __messages__, __update logic__ and __view logic__.
<div align="center">
- <a href="https://gfycat.com/politeadorableiberianmole">
- <img src="https://thumbs.gfycat.com/PoliteAdorableIberianmole-small.gif">
+ <a href="https://iced.rs/examples/tour.mp4">
+ <img src="https://iced.rs/examples/tour.gif">
</a>
</div>
diff --git a/examples/tour/src/main.rs b/examples/tour/src/main.rs
index 10de2ae1..3e3a8ad7 100644
--- a/examples/tour/src/main.rs
+++ b/examples/tour/src/main.rs
@@ -8,7 +8,14 @@ use iced::widget::{Button, Column, Container, Slider};
use iced::{Color, Element, Font, Length, Pixels, Renderer, Sandbox, Settings};
pub fn main() -> iced::Result {
- env_logger::init();
+ #[cfg(target_arch = "wasm32")]
+ {
+ console_log::init().expect("Initialize logger");
+ std::panic::set_hook(Box::new(console_error_panic_hook::hook));
+ }
+
+ #[cfg(not(target_arch = "wasm32"))]
+ tracing_subscriber::fmt::init();
Tour::run(Settings::default())
}
diff --git a/examples/url_handler/Cargo.toml b/examples/url_handler/Cargo.toml
index 4dcff92d..7bb9914b 100644
--- a/examples/url_handler/Cargo.toml
+++ b/examples/url_handler/Cargo.toml
@@ -6,4 +6,4 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../.." }
+iced.workspace = true
diff --git a/examples/url_handler/src/main.rs b/examples/url_handler/src/main.rs
index f63fa06a..bf570123 100644
--- a/examples/url_handler/src/main.rs
+++ b/examples/url_handler/src/main.rs
@@ -1,6 +1,5 @@
-use iced::event::{Event, MacOS, PlatformSpecific};
+use iced::event::{self, Event};
use iced::executor;
-use iced::subscription;
use iced::widget::{container, text};
use iced::{
Application, Command, Element, Length, Settings, Subscription, Theme,
@@ -37,9 +36,11 @@ impl Application for App {
fn update(&mut self, message: Message) -> Command<Message> {
match message {
Message::EventOccurred(event) => {
- if let Event::PlatformSpecific(PlatformSpecific::MacOS(
- MacOS::ReceivedUrl(url),
- )) = event
+ if let Event::PlatformSpecific(
+ event::PlatformSpecific::MacOS(event::MacOS::ReceivedUrl(
+ url,
+ )),
+ ) = event
{
self.url = Some(url);
}
@@ -50,7 +51,7 @@ impl Application for App {
}
fn subscription(&self) -> Subscription<Message> {
- subscription::events().map(Message::EventOccurred)
+ event::listen().map(Message::EventOccurred)
}
fn view(&self) -> Element<Message> {
diff --git a/examples/visible_bounds/Cargo.toml b/examples/visible_bounds/Cargo.toml
index cfa56dd2..37594b84 100644
--- a/examples/visible_bounds/Cargo.toml
+++ b/examples/visible_bounds/Cargo.toml
@@ -6,5 +6,7 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["debug"] }
-once_cell = "1"
+iced.workspace = true
+iced.features = ["debug"]
+
+once_cell.workspace = true
diff --git a/examples/visible_bounds/src/main.rs b/examples/visible_bounds/src/main.rs
index 8b684514..42dfc24c 100644
--- a/examples/visible_bounds/src/main.rs
+++ b/examples/visible_bounds/src/main.rs
@@ -1,14 +1,14 @@
+use iced::event::{self, Event};
use iced::executor;
use iced::mouse;
-use iced::subscription::{self, Subscription};
use iced::theme::{self, Theme};
use iced::widget::{
column, container, horizontal_space, row, scrollable, text, vertical_space,
};
use iced::window;
use iced::{
- Alignment, Application, Color, Command, Element, Event, Font, Length,
- Point, Rectangle, Settings,
+ Alignment, Application, Color, Command, Element, Font, Length, Point,
+ Rectangle, Settings, Subscription,
};
pub fn main() -> iced::Result {
@@ -163,7 +163,7 @@ impl Application for Example {
}
fn subscription(&self) -> Subscription<Message> {
- subscription::events_with(|event, _| match event {
+ event::listen_with(|event, _| match event {
Event::Mouse(mouse::Event::CursorMoved { position }) => {
Some(Message::MouseMoved(position))
}
diff --git a/examples/websocket/Cargo.toml b/examples/websocket/Cargo.toml
index 12af9658..2756e8e0 100644
--- a/examples/websocket/Cargo.toml
+++ b/examples/websocket/Cargo.toml
@@ -6,16 +6,16 @@ edition = "2021"
publish = false
[dependencies]
-iced = { path = "../..", features = ["tokio", "debug"] }
-once_cell = "1.15"
+iced.workspace = true
+iced.features = ["debug", "tokio"]
+
+once_cell.workspace = true
+warp = "0.3"
[dependencies.async-tungstenite]
version = "0.23"
features = ["tokio-rustls-webpki-roots"]
[dependencies.tokio]
-version = "1"
+workspace = true
features = ["time"]
-
-[dependencies.warp]
-version = "0.3"
diff --git a/futures/Cargo.toml b/futures/Cargo.toml
index 044827c2..69a915e4 100644
--- a/futures/Cargo.toml
+++ b/futures/Cargo.toml
@@ -1,47 +1,40 @@
[package]
name = "iced_futures"
-version = "0.7.0"
-authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
-edition = "2021"
-description = "Commands, subscriptions, and runtimes for Iced"
-license = "MIT"
-repository = "https://github.com/iced-rs/iced"
-documentation = "https://docs.rs/iced_futures"
-keywords = ["gui", "ui", "graphics", "interface", "futures"]
-categories = ["gui"]
+description = "Commands, subscriptions, and future executors for iced"
+version.workspace = true
+edition.workspace = true
+authors.workspace = true
+license.workspace = true
+repository.workspace = true
+homepage.workspace = true
+categories.workspace = true
+keywords.workspace = true
+
+[package.metadata.docs.rs]
+rustdoc-args = ["--cfg", "docsrs"]
+all-features = true
[features]
thread-pool = ["futures/thread-pool"]
[dependencies]
-log = "0.4"
-
-[dependencies.iced_core]
-version = "0.10"
-path = "../core"
+iced_core.workspace = true
-[dependencies.futures]
-version = "0.3"
+futures.workspace = true
+log.workspace = true
-[target.'cfg(not(target_arch = "wasm32"))'.dependencies.tokio]
-package = "tokio"
-version = "1.0"
-optional = true
-features = ["rt", "rt-multi-thread", "time"]
+[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
+async-std.workspace = true
+async-std.optional = true
+async-std.features = ["unstable"]
-[target.'cfg(not(target_arch = "wasm32"))'.dependencies.async-std]
-version = "1.0"
-optional = true
-features = ["unstable"]
+smol.workspace = true
+smol.optional = true
-[target.'cfg(not(target_arch = "wasm32"))'.dependencies.smol]
-version = "1.2"
-optional = true
+tokio.workspace = true
+tokio.optional = true
+tokio.features = ["rt", "rt-multi-thread", "time"]
[target.'cfg(target_arch = "wasm32")'.dependencies]
-wasm-bindgen-futures = "0.4"
-wasm-timer = "0.2"
-
-[package.metadata.docs.rs]
-rustdoc-args = ["--cfg", "docsrs"]
-all-features = true
+wasm-bindgen-futures.workspace = true
+wasm-timer.workspace = true
diff --git a/futures/src/event.rs b/futures/src/event.rs
new file mode 100644
index 00000000..214d2d40
--- /dev/null
+++ b/futures/src/event.rs
@@ -0,0 +1,59 @@
+//! Listen to runtime events.
+use crate::core::event::{self, Event};
+use crate::core::window;
+use crate::subscription::{self, Subscription};
+use crate::MaybeSend;
+
+/// Returns a [`Subscription`] to all the ignored runtime events.
+///
+/// This subscription will notify your application of any [`Event`] that was
+/// not captured by any widget.
+pub fn listen() -> Subscription<Event> {
+ listen_with(|event, status| match status {
+ event::Status::Ignored => Some(event),
+ event::Status::Captured => None,
+ })
+}
+
+/// Creates a [`Subscription`] that listens and filters all the runtime events
+/// with the provided function, producing messages accordingly.
+///
+/// This subscription will call the provided function for every [`Event`]
+/// handled by the runtime. If the function:
+///
+/// - Returns `None`, the [`Event`] will be discarded.
+/// - Returns `Some` message, the `Message` will be produced.
+pub fn listen_with<Message>(
+ f: fn(Event, event::Status) -> Option<Message>,
+) -> Subscription<Message>
+where
+ Message: 'static + MaybeSend,
+{
+ #[derive(Hash)]
+ struct EventsWith;
+
+ subscription::filter_map(
+ (EventsWith, f),
+ move |event, status| match event {
+ Event::Window(window::Event::RedrawRequested(_)) => None,
+ _ => f(event, status),
+ },
+ )
+}
+
+/// Creates a [`Subscription`] that produces a message for every runtime event,
+/// including the redraw request events.
+///
+/// **Warning:** This [`Subscription`], if unfiltered, may produce messages in
+/// an infinite loop.
+pub fn listen_raw<Message>(
+ f: fn(Event, event::Status) -> Option<Message>,
+) -> Subscription<Message>
+where
+ Message: 'static + MaybeSend,
+{
+ #[derive(Hash)]
+ struct RawEvents;
+
+ subscription::filter_map((RawEvents, f), f)
+}
diff --git a/futures/src/keyboard.rs b/futures/src/keyboard.rs
new file mode 100644
index 00000000..af68e1f2
--- /dev/null
+++ b/futures/src/keyboard.rs
@@ -0,0 +1,61 @@
+//! Listen to keyboard events.
+use crate::core;
+use crate::core::keyboard::{Event, KeyCode, Modifiers};
+use crate::subscription::{self, Subscription};
+use crate::MaybeSend;
+
+/// Listens to keyboard key presses and calls the given function
+/// map them into actual messages.
+///
+/// If the function returns `None`, the key press will be simply
+/// ignored.
+pub fn on_key_press<Message>(
+ f: fn(KeyCode, Modifiers) -> Option<Message>,
+) -> Subscription<Message>
+where
+ Message: MaybeSend + 'static,
+{
+ #[derive(Hash)]
+ struct OnKeyPress;
+
+ subscription::filter_map((OnKeyPress, f), move |event, status| {
+ match (event, status) {
+ (
+ core::Event::Keyboard(Event::KeyPressed {
+ key_code,
+ modifiers,
+ }),
+ core::event::Status::Ignored,
+ ) => f(key_code, modifiers),
+ _ => None,
+ }
+ })
+}
+
+/// Listens to keyboard key releases and calls the given function
+/// map them into actual messages.
+///
+/// If the function returns `None`, the key release will be simply
+/// ignored.
+pub fn on_key_release<Message>(
+ f: fn(KeyCode, Modifiers) -> Option<Message>,
+) -> Subscription<Message>
+where
+ Message: MaybeSend + 'static,
+{
+ #[derive(Hash)]
+ struct OnKeyRelease;
+
+ subscription::filter_map((OnKeyRelease, f), move |event, status| {
+ match (event, status) {
+ (
+ core::Event::Keyboard(Event::KeyReleased {
+ key_code,
+ modifiers,
+ }),
+ core::event::Status::Ignored,
+ ) => f(key_code, modifiers),
+ _ => None,
+ }
+ })
+}
diff --git a/futures/src/lib.rs b/futures/src/lib.rs
index 34d81e1e..abc46176 100644
--- a/futures/src/lib.rs
+++ b/futures/src/lib.rs
@@ -4,6 +4,7 @@
#![doc(
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
)]
+#![forbid(unsafe_code, rust_2018_idioms)]
#![deny(
missing_debug_implementations,
missing_docs,
@@ -12,9 +13,9 @@
clippy::from_over_into,
clippy::needless_borrow,
clippy::new_without_default,
- clippy::useless_conversion
+ clippy::useless_conversion,
+ rustdoc::broken_intra_doc_links
)]
-#![forbid(unsafe_code, rust_2018_idioms)]
#![allow(clippy::inherent_to_string, clippy::type_complexity)]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
pub use futures;
@@ -24,7 +25,9 @@ mod maybe_send;
mod runtime;
pub mod backend;
+pub mod event;
pub mod executor;
+pub mod keyboard;
pub mod subscription;
pub use executor::Executor;
diff --git a/futures/src/runtime.rs b/futures/src/runtime.rs
index 2241a494..16111b36 100644
--- a/futures/src/runtime.rs
+++ b/futures/src/runtime.rs
@@ -9,9 +9,9 @@ use std::marker::PhantomData;
/// A batteries-included runtime of commands and subscriptions.
///
/// If you have an [`Executor`], a [`Runtime`] can be leveraged to run any
-/// [`Command`] or [`Subscription`] and get notified of the results!
+/// `Command` or [`Subscription`] and get notified of the results!
///
-/// [`Command`]: crate::Command
+/// [`Subscription`]: crate::Subscription
#[derive(Debug)]
pub struct Runtime<Executor, Sender, Message> {
executor: Executor,
@@ -75,6 +75,7 @@ where
/// [`Tracker::update`] to learn more about this!
///
/// [`Tracker::update`]: subscription::Tracker::update
+ /// [`Subscription`]: crate::Subscription
pub fn track(
&mut self,
recipes: impl IntoIterator<
diff --git a/futures/src/subscription.rs b/futures/src/subscription.rs
index 8f78ce3a..d40125e3 100644
--- a/futures/src/subscription.rs
+++ b/futures/src/subscription.rs
@@ -4,7 +4,6 @@ mod tracker;
pub use tracker::Tracker;
use crate::core::event::{self, Event};
-use crate::core::window;
use crate::core::Hasher;
use crate::futures::{Future, Stream};
use crate::{BoxStream, MaybeSend};
@@ -20,16 +19,14 @@ pub type EventStream = BoxStream<(Event, event::Status)>;
/// A request to listen to external events.
///
-/// Besides performing async actions on demand with [`Command`], most
+/// Besides performing async actions on demand with `Command`, most
/// applications also need to listen to external events passively.
///
-/// A [`Subscription`] is normally provided to some runtime, like a [`Command`],
+/// A [`Subscription`] is normally provided to some runtime, like a `Command`,
/// and it will generate events as long as the user keeps requesting it.
///
/// For instance, you can use a [`Subscription`] to listen to a WebSocket
/// connection, keyboard presses, mouse events, time ticks, etc.
-///
-/// [`Command`]: crate::Command
#[must_use = "`Subscription` must be returned to runtime to take effect"]
pub struct Subscription<Message> {
recipes: Vec<Box<dyn Recipe<Output = Message>>>,
@@ -215,77 +212,6 @@ where
}
}
-/// Returns a [`Subscription`] to all the ignored runtime events.
-///
-/// This subscription will notify your application of any [`Event`] that was
-/// not captured by any widget.
-pub fn events() -> Subscription<Event> {
- events_with(|event, status| match status {
- event::Status::Ignored => Some(event),
- event::Status::Captured => None,
- })
-}
-
-/// Returns a [`Subscription`] that filters all the runtime events with the
-/// provided function, producing messages accordingly.
-///
-/// This subscription will call the provided function for every [`Event`]
-/// handled by the runtime. If the function:
-///
-/// - Returns `None`, the [`Event`] will be discarded.
-/// - Returns `Some` message, the `Message` will be produced.
-pub fn events_with<Message>(
- f: fn(Event, event::Status) -> Option<Message>,
-) -> Subscription<Message>
-where
- Message: 'static + MaybeSend,
-{
- #[derive(Hash)]
- struct EventsWith;
-
- Subscription::from_recipe(Runner {
- id: (EventsWith, f),
- spawn: move |events| {
- use futures::future;
- use futures::stream::StreamExt;
-
- events.filter_map(move |(event, status)| {
- future::ready(match event {
- Event::Window(window::Event::RedrawRequested(_)) => None,
- _ => f(event, status),
- })
- })
- },
- })
-}
-
-/// Returns a [`Subscription`] that produces a message for every runtime event,
-/// including the redraw request events.
-///
-/// **Warning:** This [`Subscription`], if unfiltered, may produce messages in
-/// an infinite loop.
-pub fn raw_events<Message>(
- f: fn(Event, event::Status) -> Option<Message>,
-) -> Subscription<Message>
-where
- Message: 'static + MaybeSend,
-{
- #[derive(Hash)]
- struct RawEvents;
-
- Subscription::from_recipe(Runner {
- id: (RawEvents, f),
- spawn: move |events| {
- use futures::future;
- use futures::stream::StreamExt;
-
- events.filter_map(move |(event, status)| {
- future::ready(f(event, status))
- })
- },
- })
-}
-
/// Returns a [`Subscription`] that will call the given function to create and
/// asynchronously run the given [`Stream`].
pub fn run<S, Message>(builder: fn() -> S) -> Subscription<Message>
@@ -338,6 +264,25 @@ where
)
}
+pub(crate) fn filter_map<I, F, Message>(id: I, f: F) -> Subscription<Message>
+where
+ I: Hash + 'static,
+ F: Fn(Event, event::Status) -> Option<Message> + MaybeSend + 'static,
+ Message: 'static + MaybeSend,
+{
+ Subscription::from_recipe(Runner {
+ id,
+ spawn: |events| {
+ use futures::future;
+ use futures::stream::StreamExt;
+
+ events.filter_map(move |(event, status)| {
+ future::ready(f(event, status))
+ })
+ },
+ })
+}
+
/// Creates a [`Subscription`] that publishes the events sent from a [`Future`]
/// to an [`mpsc::Sender`] with the given bounds.
///
diff --git a/futures/src/subscription/tracker.rs b/futures/src/subscription/tracker.rs
index ae71cd25..3a83da09 100644
--- a/futures/src/subscription/tracker.rs
+++ b/futures/src/subscription/tracker.rs
@@ -14,6 +14,8 @@ use std::hash::Hasher as _;
/// If you have an application that continuously returns a [`Subscription`],
/// you can use a [`Tracker`] to keep track of the different recipes and keep
/// its executions alive.
+///
+/// [`Subscription`]: crate::Subscription
#[derive(Debug, Default)]
pub struct Tracker {
subscriptions: HashMap<u64, Execution>,
@@ -51,6 +53,7 @@ impl Tracker {
/// the [`Tracker`] changes.
///
/// [`Recipe`]: crate::subscription::Recipe
+ /// [`Subscription`]: crate::Subscription
pub fn update<Message, Receiver>(
&mut self,
recipes: impl Iterator<Item = Box<dyn Recipe<Output = Message>>>,
diff --git a/graphics/Cargo.toml b/graphics/Cargo.toml
index 6fc6ab00..ff698649 100644
--- a/graphics/Cargo.toml
+++ b/graphics/Cargo.toml
@@ -1,14 +1,18 @@
[package]
name = "iced_graphics"
-version = "0.9.0"
-authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
-edition = "2021"
-description = "A bunch of backend-agnostic types that can be leveraged to build a renderer for Iced"
-license = "MIT"
-repository = "https://github.com/iced-rs/iced"
-documentation = "https://docs.rs/iced_graphics"
-keywords = ["gui", "ui", "graphics", "interface", "widgets"]
-categories = ["gui"]
+description = "A bunch of backend-agnostic types that can be leveraged to build a renderer for iced"
+version.workspace = true
+edition.workspace = true
+authors.workspace = true
+license.workspace = true
+repository.workspace = true
+homepage.workspace = true
+categories.workspace = true
+keywords.workspace = true
+
+[package.metadata.docs.rs]
+rustdoc-args = ["--cfg", "docsrs"]
+all-features = true
[features]
geometry = ["lyon_path"]
@@ -17,43 +21,29 @@ image = ["dep:image", "kamadak-exif"]
web-colors = []
[dependencies]
-glam = "0.24"
-half = "2.2.1"
-log = "0.4"
-raw-window-handle = "0.5"
-thiserror = "1.0"
-bitflags = "1.2"
-cosmic-text = "0.9"
-rustc-hash = "1.1"
-
-[dependencies.bytemuck]
-version = "1.4"
-features = ["derive"]
-
-[dependencies.iced_core]
-version = "0.10"
-path = "../core"
-
-[dependencies.twox-hash]
-version = "1.6"
-default-features = false
-
-[target.'cfg(not(target_arch = "wasm32"))'.dependencies.twox-hash]
-version = "1.6.1"
-features = ["std"]
-
-[dependencies.image]
-version = "0.24"
-optional = true
-
-[dependencies.kamadak-exif]
-version = "0.5"
-optional = true
-
-[dependencies.lyon_path]
-version = "1"
-optional = true
+iced_core.workspace = true
-[package.metadata.docs.rs]
-rustdoc-args = ["--cfg", "docsrs"]
-all-features = true
+bitflags.workspace = true
+bytemuck.workspace = true
+glam.workspace = true
+half.workspace = true
+log.workspace = true
+raw-window-handle.workspace = true
+thiserror.workspace = true
+cosmic-text.workspace = true
+rustc-hash.workspace = true
+
+lyon_path.workspace = true
+lyon_path.optional = true
+
+image.workspace = true
+image.optional = true
+
+kamadak-exif.workspace = true
+kamadak-exif.optional = true
+
+twox-hash.workspace = true
+
+[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
+twox-hash.workspace = true
+twox-hash.features = ["std"]
diff --git a/graphics/src/compositor.rs b/graphics/src/compositor.rs
index f7b86045..7173ffa7 100644
--- a/graphics/src/compositor.rs
+++ b/graphics/src/compositor.rs
@@ -63,7 +63,7 @@ pub trait Compositor: Sized {
/// Screenshots the current [`Renderer`] primitives to an offscreen texture, and returns the bytes of
/// the texture ordered as `RGBA` in the sRGB color space.
///
- /// [`Renderer`]: Self::Renderer;
+ /// [`Renderer`]: Self::Renderer
fn screenshot<T: AsRef<str>>(
&mut self,
renderer: &mut Self::Renderer,
diff --git a/graphics/src/geometry.rs b/graphics/src/geometry.rs
index 7cd3dd3a..d7d6a0aa 100644
--- a/graphics/src/geometry.rs
+++ b/graphics/src/geometry.rs
@@ -14,11 +14,11 @@ pub use text::Text;
pub use crate::gradient::{self, Gradient};
-/// A renderer capable of drawing some [`Geometry`].
+/// A renderer capable of drawing some [`Self::Geometry`].
pub trait Renderer: crate::core::Renderer {
/// The kind of geometry this renderer can draw.
type Geometry;
- /// Draws the given layers of [`Geometry`].
+ /// Draws the given layers of [`Self::Geometry`].
fn draw(&mut self, layers: Vec<Self::Geometry>);
}
diff --git a/graphics/src/geometry/fill.rs b/graphics/src/geometry/fill.rs
index b773c99b..670fbc12 100644
--- a/graphics/src/geometry/fill.rs
+++ b/graphics/src/geometry/fill.rs
@@ -1,4 +1,6 @@
-//! Fill [crate::widget::canvas::Geometry] with a certain style.
+//! Fill [`Geometry`] with a certain style.
+//!
+//! [`Geometry`]: super::Renderer::Geometry
pub use crate::geometry::Style;
use crate::core::Color;
diff --git a/graphics/src/geometry/stroke.rs b/graphics/src/geometry/stroke.rs
index 69a76e1c..aff49ab3 100644
--- a/graphics/src/geometry/stroke.rs
+++ b/graphics/src/geometry/stroke.rs
@@ -1,4 +1,6 @@
-//! Create lines from a [crate::widget::canvas::Path] and assigns them various attributes/styles.
+//! Create lines from a [`Path`] and assigns them various attributes/styles.
+//!
+//! [`Path`]: super::Path
pub use crate::geometry::Style;
use iced_core::Color;
diff --git a/graphics/src/gradient.rs b/graphics/src/gradient.rs
index 4db565d8..b274ec86 100644
--- a/graphics/src/gradient.rs
+++ b/graphics/src/gradient.rs
@@ -1,8 +1,6 @@
-//! A gradient that can be used as a [`Fill`] for some geometry.
+//! A gradient that can be used as a fill for some geometry.
//!
//! For a gradient that you can use as a background variant for a widget, see [`Gradient`].
-//!
-//! [`Gradient`]: crate::core::Gradient;
use crate::color;
use crate::core::gradient::ColorStop;
use crate::core::{self, Color, Point, Rectangle};
@@ -36,10 +34,7 @@ impl Gradient {
}
}
-/// A linear gradient that can be used in the style of [`Fill`] or [`Stroke`].
-///
-/// [`Fill`]: crate::geometry::Fill;
-/// [`Stroke`]: crate::geometry::Stroke;
+/// A linear gradient.
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Linear {
/// The absolute starting position of the gradient.
@@ -53,7 +48,7 @@ pub struct Linear {
}
impl Linear {
- /// Creates a new [`Builder`].
+ /// Creates a new [`Linear`] builder.
pub fn new(start: Point, end: Point) -> Self {
Self {
start,
diff --git a/graphics/src/lib.rs b/graphics/src/lib.rs
index 902eb5b0..01a358ca 100644
--- a/graphics/src/lib.rs
+++ b/graphics/src/lib.rs
@@ -7,6 +7,7 @@
#![doc(
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
)]
+#![forbid(rust_2018_idioms)]
#![deny(
missing_debug_implementations,
//missing_docs,
@@ -16,9 +17,9 @@
clippy::from_over_into,
clippy::needless_borrow,
clippy::new_without_default,
- clippy::useless_conversion
+ clippy::useless_conversion,
+ rustdoc::broken_intra_doc_links
)]
-#![forbid(rust_2018_idioms)]
#![allow(clippy::inherent_to_string, clippy::type_complexity)]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
mod antialiasing;
diff --git a/graphics/src/mesh.rs b/graphics/src/mesh.rs
index cfb5a60f..041986cf 100644
--- a/graphics/src/mesh.rs
+++ b/graphics/src/mesh.rs
@@ -41,7 +41,7 @@ impl Damage for Mesh {
}
}
-/// A set of [`Vertex2D`] and indices representing a list of triangles.
+/// A set of vertices and indices representing a list of triangles.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Indexed<T> {
/// The vertices of the mesh
diff --git a/graphics/src/text/cache.rs b/graphics/src/text/cache.rs
index 9e4fbf65..577c4687 100644
--- a/graphics/src/text/cache.rs
+++ b/graphics/src/text/cache.rs
@@ -43,7 +43,10 @@ impl Cache {
}
if let hash_map::Entry::Vacant(entry) = self.entries.entry(hash) {
- let metrics = cosmic_text::Metrics::new(key.size, key.line_height);
+ let metrics = cosmic_text::Metrics::new(
+ key.size,
+ key.line_height.max(f32::MIN_POSITIVE),
+ );
let mut buffer = cosmic_text::Buffer::new(font_system, metrics);
buffer.set_size(
diff --git a/renderer/Cargo.toml b/renderer/Cargo.toml
index 89326d73..56e17209 100644
--- a/renderer/Cargo.toml
+++ b/renderer/Cargo.toml
@@ -1,14 +1,14 @@
[package]
name = "iced_renderer"
-version = "0.1.0"
-authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
-edition = "2021"
-description = "The official renderer for Iced"
-license = "MIT"
-repository = "https://github.com/iced-rs/iced"
-documentation = "https://docs.rs/iced_renderer"
-keywords = ["gui", "ui", "graphics", "interface", "widgets"]
-categories = ["gui"]
+description = "The official renderer for iced"
+version.workspace = true
+edition.workspace = true
+authors.workspace = true
+license.workspace = true
+repository.workspace = true
+homepage.workspace = true
+categories.workspace = true
+keywords.workspace = true
[features]
wgpu = ["iced_wgpu"]
@@ -17,21 +17,15 @@ svg = ["iced_tiny_skia/svg", "iced_wgpu?/svg"]
geometry = ["iced_graphics/geometry", "iced_tiny_skia/geometry", "iced_wgpu?/geometry"]
tracing = ["iced_wgpu?/tracing"]
web-colors = ["iced_wgpu?/web-colors"]
+webgl = ["iced_wgpu?/webgl"]
[dependencies]
-raw-window-handle = "0.5"
-thiserror = "1"
-log = "0.4"
+iced_graphics.workspace = true
+iced_tiny_skia.workspace = true
-[dependencies.iced_graphics]
-version = "0.9"
-path = "../graphics"
+iced_wgpu.workspace = true
+iced_wgpu.optional = true
-[dependencies.iced_tiny_skia]
-version = "0.1"
-path = "../tiny_skia"
-
-[dependencies.iced_wgpu]
-version = "0.11"
-path = "../wgpu"
-optional = true
+log.workspace = true
+raw-window-handle.workspace = true
+thiserror.workspace = true
diff --git a/renderer/src/geometry.rs b/renderer/src/geometry.rs
index 04b5d9e6..1ecb0a43 100644
--- a/renderer/src/geometry.rs
+++ b/renderer/src/geometry.rs
@@ -96,13 +96,11 @@ impl Frame {
/// resulting glyphs will not be rotated or scaled properly.
///
/// Additionally, all text will be rendered on top of all the layers of
- /// a [`Canvas`]. Therefore, it is currently only meant to be used for
+ /// a `Canvas`. Therefore, it is currently only meant to be used for
/// overlays, which is the most common use case.
///
/// Support for vectorial text is planned, and should address all these
/// limitations.
- ///
- /// [`Canvas`]: crate::widget::Canvas
pub fn fill_text(&mut self, text: impl Into<Text>) {
delegate!(self, frame, frame.fill_text(text));
}
@@ -168,12 +166,18 @@ impl Frame {
delegate!(self, frame, frame.rotate(angle));
}
- /// Applies a scaling to the current transform of the [`Frame`].
+ /// Applies a uniform scaling to the current transform of the [`Frame`].
#[inline]
- pub fn scale(&mut self, scale: f32) {
+ pub fn scale(&mut self, scale: impl Into<f32>) {
delegate!(self, frame, frame.scale(scale));
}
+ /// Applies a non-uniform scaling to the current transform of the [`Frame`].
+ #[inline]
+ pub fn scale_nonuniform(&mut self, scale: impl Into<Vector>) {
+ delegate!(self, frame, frame.scale_nonuniform(scale));
+ }
+
pub fn into_geometry(self) -> Geometry {
match self {
Self::TinySkia(frame) => Geometry::TinySkia(frame.into_primitive()),
diff --git a/renderer/src/lib.rs b/renderer/src/lib.rs
index 2b282a0b..8bdf231d 100644
--- a/renderer/src/lib.rs
+++ b/renderer/src/lib.rs
@@ -1,3 +1,16 @@
+#![forbid(rust_2018_idioms)]
+#![deny(
+ unsafe_code,
+ unused_results,
+ clippy::extra_unused_lifetimes,
+ clippy::from_over_into,
+ clippy::needless_borrow,
+ clippy::new_without_default,
+ clippy::useless_conversion,
+ rustdoc::broken_intra_doc_links
+)]
+#![allow(clippy::inherent_to_string, clippy::type_complexity)]
+#![cfg_attr(docsrs, feature(doc_auto_cfg))]
pub mod compositor;
#[cfg(feature = "geometry")]
diff --git a/renderer/src/settings.rs b/renderer/src/settings.rs
index 08f2099e..432eb8a0 100644
--- a/renderer/src/settings.rs
+++ b/renderer/src/settings.rs
@@ -1,9 +1,7 @@
use crate::core::{Font, Pixels};
use crate::graphics::Antialiasing;
-/// The settings of a [`Backend`].
-///
-/// [`Backend`]: crate::Backend
+/// The settings of a Backend.
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Settings {
/// The default [`Font`] to use.
diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml
index 9fbe4be7..d19aedd3 100644
--- a/runtime/Cargo.toml
+++ b/runtime/Cargo.toml
@@ -1,23 +1,21 @@
[package]
name = "iced_runtime"
-version = "0.1.1"
-authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
-edition = "2021"
-description = "A renderer-agnostic runtime for Iced"
-license = "MIT"
-repository = "https://github.com/iced-rs/iced"
+description = "A renderer-agnostic runtime for iced"
+version.workspace = true
+edition.workspace = true
+authors.workspace = true
+license.workspace = true
+repository.workspace = true
+homepage.workspace = true
+categories.workspace = true
+keywords.workspace = true
[features]
debug = []
[dependencies]
-thiserror = "1"
+iced_core.workspace = true
+iced_futures.workspace = true
+iced_futures.features = ["thread-pool"]
-[dependencies.iced_core]
-version = "0.10"
-path = "../core"
-
-[dependencies.iced_futures]
-version = "0.7"
-path = "../futures"
-features = ["thread-pool"]
+thiserror.workspace = true
diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs
index 59c70ff7..c3261cca 100644
--- a/runtime/src/lib.rs
+++ b/runtime/src/lib.rs
@@ -2,35 +2,13 @@
//!
//! ![The native path of the Iced ecosystem](https://github.com/iced-rs/iced/raw/improvement/update-ecosystem-and-roadmap/docs/graphs/native.png)
//!
-//! `iced_native` takes [`iced_core`] and builds a native runtime on top of it,
-//! featuring:
-//!
-//! - A custom layout engine, greatly inspired by [`druid`]
-//! - Event handling for all the built-in widgets
-//! - A renderer-agnostic API
-//!
-//! To achieve this, it introduces a couple of reusable interfaces:
-//!
-//! - A [`Widget`] trait, which is used to implement new widgets: from layout
-//! requirements to event and drawing logic.
-//! - A bunch of `Renderer` traits, meant to keep the crate renderer-agnostic.
-//!
-//! # Usage
-//! The strategy to use this crate depends on your particular use case. If you
-//! want to:
-//! - Implement a custom shell or integrate it in your own system, check out the
-//! [`UserInterface`] type.
-//! - Build a new renderer, see the [renderer] module.
-//! - Build a custom widget, start at the [`Widget`] trait.
+//! `iced_runtime` takes [`iced_core`] and builds a native runtime on top of it.
//!
//! [`iced_core`]: https://github.com/iced-rs/iced/tree/0.10/core
-//! [`iced_winit`]: https://github.com/iced-rs/iced/tree/0.10/winit
-//! [`druid`]: https://github.com/xi-editor/druid
-//! [`raw-window-handle`]: https://github.com/rust-windowing/raw-window-handle
-//! [renderer]: crate::renderer
#![doc(
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
)]
+#![forbid(unsafe_code, rust_2018_idioms)]
#![deny(
missing_debug_implementations,
missing_docs,
@@ -39,9 +17,9 @@
clippy::from_over_into,
clippy::needless_borrow,
clippy::new_without_default,
- clippy::useless_conversion
+ clippy::useless_conversion,
+ rustdoc::broken_intra_doc_links
)]
-#![forbid(unsafe_code, rust_2018_idioms)]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
pub mod clipboard;
pub mod command;
diff --git a/runtime/src/overlay/nested.rs b/runtime/src/overlay/nested.rs
index b729f769..21b6f7c1 100644
--- a/runtime/src/overlay/nested.rs
+++ b/runtime/src/overlay/nested.rs
@@ -6,7 +6,7 @@ use crate::core::renderer;
use crate::core::widget;
use crate::core::{Clipboard, Event, Layout, Point, Rectangle, Shell, Size};
-/// An [`Overlay`] container that displays nested overlays
+/// An overlay container that displays nested overlays
#[allow(missing_debug_implementations)]
pub struct Nested<'a, Message, Renderer> {
overlay: overlay::Element<'a, Message, Renderer>,
@@ -27,6 +27,8 @@ where
}
/// Returns the layout [`Node`] of the [`Nested`] overlay.
+ ///
+ /// [`Node`]: layout::Node
pub fn layout(
&mut self,
renderer: &Renderer,
diff --git a/runtime/src/program/state.rs b/runtime/src/program/state.rs
index 35df6078..9aa2d550 100644
--- a/runtime/src/program/state.rs
+++ b/runtime/src/program/state.rs
@@ -175,7 +175,7 @@ where
(uncaptured_events, command)
}
- /// Applies [`widget::Operation`]s to the [`State`]
+ /// Applies [`Operation`]s to the [`State`]
pub fn operate(
&mut self,
renderer: &mut P::Renderer,
diff --git a/runtime/src/user_interface.rs b/runtime/src/user_interface.rs
index b684fbde..dae9e0ac 100644
--- a/runtime/src/user_interface.rs
+++ b/runtime/src/user_interface.rs
@@ -361,7 +361,7 @@ where
/// It returns the current [`mouse::Interaction`]. You should update the
/// icon of the mouse cursor accordingly in your system.
///
- /// [`Renderer`]: crate::Renderer
+ /// [`Renderer`]: crate::core::Renderer
///
/// # Example
/// We can finally draw our [counter](index.html#usage) by
@@ -624,7 +624,7 @@ pub enum State {
/// The [`UserInterface`] is up-to-date and can be reused without
/// rebuilding.
Updated {
- /// The [`Instant`] when a redraw should be performed.
+ /// The [`window::RedrawRequest`] when a redraw should be performed.
redraw_request: Option<window::RedrawRequest>,
},
}
diff --git a/runtime/src/window.rs b/runtime/src/window.rs
index 5219fbfd..41816967 100644
--- a/runtime/src/window.rs
+++ b/runtime/src/window.rs
@@ -10,7 +10,8 @@ use crate::command::{self, Command};
use crate::core::time::Instant;
use crate::core::window::{Event, Icon, Level, Mode, UserAttention};
use crate::core::Size;
-use crate::futures::subscription::{self, Subscription};
+use crate::futures::event;
+use crate::futures::Subscription;
/// Subscribes to the frames of the window of the running application.
///
@@ -21,7 +22,7 @@ use crate::futures::subscription::{self, Subscription};
/// In any case, this [`Subscription`] is useful to smoothly draw application-driven
/// animations without missing any frames.
pub fn frames() -> Subscription<Instant> {
- subscription::raw_events(|event, _status| match event {
+ event::listen_raw(|event, _status| match event {
iced_core::Event::Window(Event::RedrawRequested(at)) => Some(at),
_ => None,
})
diff --git a/src/lib.rs b/src/lib.rs
index 36f48ba2..3cbe716a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -20,9 +20,9 @@
//! Check out the [repository] and the [examples] for more details!
//!
//! [Cross-platform support]: https://github.com/iced-rs/iced/blob/master/docs/images/todos_desktop.jpg?raw=true
-//! [text inputs]: https://gfycat.com/alertcalmcrow-rust-gui
-//! [scrollables]: https://gfycat.com/perkybaggybaboon-rust-gui
-//! [Debug overlay with performance metrics]: https://gfycat.com/incredibledarlingbee
+//! [text inputs]: https://iced.rs/examples/text_input.mp4
+//! [scrollables]: https://iced.rs/examples/scrollable.mp4
+//! [Debug overlay with performance metrics]: https://iced.rs/examples/debug.mp4
//! [Modular ecosystem]: https://github.com/iced-rs/iced/blob/master/ECOSYSTEM.md
//! [renderer-agnostic native runtime]: https://github.com/iced-rs/iced/tree/0.10/runtime
//! [`wgpu`]: https://github.com/gfx-rs/wgpu-rs
@@ -151,6 +151,7 @@
#![doc(
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
)]
+#![forbid(rust_2018_idioms, unsafe_code)]
#![deny(
missing_debug_implementations,
missing_docs,
@@ -159,9 +160,9 @@
clippy::from_over_into,
clippy::needless_borrow,
clippy::new_without_default,
- clippy::useless_conversion
+ clippy::useless_conversion,
+ rustdoc::broken_intra_doc_links
)]
-#![forbid(rust_2018_idioms, unsafe_code)]
#![allow(clippy::inherent_to_string, clippy::type_complexity)]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
use iced_widget::graphics;
@@ -187,7 +188,6 @@ pub mod advanced;
pub use style::theme;
pub use crate::core::alignment;
-pub use crate::core::event;
pub use crate::core::gradient;
pub use crate::core::{
color, Alignment, Background, BorderRadius, Color, ContentFit, Degrees,
@@ -223,9 +223,16 @@ pub mod font {
pub use crate::runtime::font::*;
}
+pub mod event {
+ //! Handle events of a user interface.
+ pub use crate::core::event::{Event, MacOS, PlatformSpecific, Status};
+ pub use iced_futures::event::{listen, listen_raw, listen_with};
+}
+
pub mod keyboard {
//! Listen and react to keyboard events.
pub use crate::core::keyboard::{Event, KeyCode, Modifiers};
+ pub use iced_futures::keyboard::{on_key_press, on_key_release};
}
pub mod mouse {
@@ -238,7 +245,7 @@ pub mod mouse {
pub mod subscription {
//! Listen to external events in your application.
pub use iced_futures::subscription::{
- channel, events, events_with, run, run_with_id, unfold, Subscription,
+ channel, run, run_with_id, unfold, Subscription,
};
}
@@ -252,11 +259,11 @@ pub mod system {
pub mod overlay {
//! Display interactive elements on top of other widgets.
- /// A generic [`Overlay`].
+ /// A generic overlay.
///
- /// This is an alias of an `iced_native` element with a default `Renderer`.
+ /// This is an alias of an [`overlay::Element`] with a default `Renderer`.
///
- /// [`Overlay`]: iced_native::Overlay
+ /// [`overlay::Element`]: crate::core::overlay::Element
pub type Element<'a, Message, Renderer = crate::Renderer> =
crate::core::overlay::Element<'a, Message, Renderer>;
diff --git a/src/settings.rs b/src/settings.rs
index 794f89fd..d9778d7e 100644
--- a/src/settings.rs
+++ b/src/settings.rs
@@ -23,7 +23,7 @@ pub struct Settings<Flags> {
/// The default [`Font`] to be used.
///
- /// By default, it uses [`Font::SansSerif`].
+ /// By default, it uses [`Family::SansSerif`](crate::font::Family::SansSerif).
pub default_font: Font,
/// The text size that will be used by default.
diff --git a/src/window/icon.rs b/src/window/icon.rs
index 0fe010ca..ef71c228 100644
--- a/src/window/icon.rs
+++ b/src/window/icon.rs
@@ -10,10 +10,10 @@ use std::path::Path;
/// Creates an icon from an image file.
///
-/// This will return an error in case the file is missing at run-time. You may prefer [`Self::from_file_data`] instead.
+/// This will return an error in case the file is missing at run-time. You may prefer [`from_file_data`] instead.
#[cfg(feature = "image")]
pub fn from_file<P: AsRef<Path>>(icon_path: P) -> Result<Icon, Error> {
- let icon = image_rs::io::Reader::open(icon_path)?.decode()?.to_rgba8();
+ let icon = image::io::Reader::open(icon_path)?.decode()?.to_rgba8();
Ok(icon::from_rgba(icon.to_vec(), icon.width(), icon.height())?)
}
@@ -25,9 +25,10 @@ pub fn from_file<P: AsRef<Path>>(icon_path: P) -> Result<Icon, Error> {
#[cfg(feature = "image")]
pub fn from_file_data(
data: &[u8],
- explicit_format: Option<image_rs::ImageFormat>,
+ explicit_format: Option<image::ImageFormat>,
) -> Result<Icon, Error> {
- let mut icon = image_rs::io::Reader::new(std::io::Cursor::new(data));
+ let mut icon = image::io::Reader::new(std::io::Cursor::new(data));
+
let icon_with_format = match explicit_format {
Some(format) => {
icon.set_format(format);
@@ -59,5 +60,5 @@ pub enum Error {
/// The `image` crate reported an error.
#[cfg(feature = "image")]
#[error("Unable to create icon from a file: {0}")]
- ImageError(#[from] image_rs::error::ImageError),
+ ImageError(#[from] image::error::ImageError),
}
diff --git a/style/Cargo.toml b/style/Cargo.toml
index 689cf978..3f00e787 100644
--- a/style/Cargo.toml
+++ b/style/Cargo.toml
@@ -1,22 +1,18 @@
[package]
name = "iced_style"
-version = "0.9.0"
-authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
-edition = "2021"
description = "The default set of styles of Iced"
-license = "MIT"
-repository = "https://github.com/iced-rs/iced"
-documentation = "https://docs.rs/iced_style"
-keywords = ["gui", "ui", "graphics", "interface", "widgets"]
-categories = ["gui"]
+version.workspace = true
+edition.workspace = true
+authors.workspace = true
+license.workspace = true
+repository.workspace = true
+homepage.workspace = true
+categories.workspace = true
+keywords.workspace = true
-[dependencies.iced_core]
-version = "0.10"
-path = "../core"
-features = ["palette"]
+[dependencies]
+iced_core.workspace = true
+iced_core.features = ["palette"]
-[dependencies.palette]
-version = "0.7"
-
-[dependencies.once_cell]
-version = "1.15"
+palette.workspace = true
+once_cell.workspace = true
diff --git a/style/src/lib.rs b/style/src/lib.rs
index 286ff9db..0c555ed8 100644
--- a/style/src/lib.rs
+++ b/style/src/lib.rs
@@ -7,16 +7,18 @@
#![doc(
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
)]
+#![forbid(unsafe_code, rust_2018_idioms)]
#![deny(
unused_results,
clippy::extra_unused_lifetimes,
clippy::from_over_into,
clippy::needless_borrow,
clippy::new_without_default,
- clippy::useless_conversion
+ clippy::useless_conversion,
+ missing_docs,
+ unused_results,
+ rustdoc::broken_intra_doc_links
)]
-#![deny(missing_docs, unused_results)]
-#![forbid(unsafe_code, rust_2018_idioms)]
#![allow(clippy::inherent_to_string, clippy::type_complexity)]
pub use iced_core as core;
diff --git a/style/src/theme.rs b/style/src/theme.rs
index 64497181..893d7202 100644
--- a/style/src/theme.rs
+++ b/style/src/theme.rs
@@ -1,8 +1,7 @@
//! Use the built-in theme and styles.
pub mod palette;
-use self::palette::Extended;
-pub use self::palette::Palette;
+pub use palette::Palette;
use crate::application;
use crate::button;
@@ -40,7 +39,16 @@ pub enum Theme {
impl Theme {
/// Creates a new custom [`Theme`] from the given [`Palette`].
pub fn custom(palette: Palette) -> Self {
- Self::Custom(Box::new(Custom::new(palette)))
+ Self::custom_with_fn(palette, palette::Extended::generate)
+ }
+
+ /// Creates a new custom [`Theme`] from the given [`Palette`], with
+ /// a custom generator of a [`palette::Extended`].
+ pub fn custom_with_fn(
+ palette: Palette,
+ generate: impl FnOnce(Palette) -> palette::Extended,
+ ) -> Self {
+ Self::Custom(Box::new(Custom::with_fn(palette, generate)))
}
/// Returns the [`Palette`] of the [`Theme`].
@@ -66,15 +74,24 @@ impl Theme {
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Custom {
palette: Palette,
- extended: Extended,
+ extended: palette::Extended,
}
impl Custom {
/// Creates a [`Custom`] theme from the given [`Palette`].
pub fn new(palette: Palette) -> Self {
+ Self::with_fn(palette, palette::Extended::generate)
+ }
+
+ /// Creates a [`Custom`] theme from the given [`Palette`] with
+ /// a custom generator of a [`palette::Extended`].
+ pub fn with_fn(
+ palette: Palette,
+ generate: impl FnOnce(Palette) -> palette::Extended,
+ ) -> Self {
Self {
palette,
- extended: Extended::generate(palette),
+ extended: generate(palette),
}
}
}
diff --git a/tiny_skia/Cargo.toml b/tiny_skia/Cargo.toml
index 9aa63a4f..15a6928a 100644
--- a/tiny_skia/Cargo.toml
+++ b/tiny_skia/Cargo.toml
@@ -1,14 +1,14 @@
[package]
name = "iced_tiny_skia"
-version = "0.1.0"
-authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
-edition = "2021"
-description = "A software renderer for Iced"
-license = "MIT"
-repository = "https://github.com/iced-rs/iced"
-documentation = "https://docs.rs/iced_tiny_skia"
-keywords = ["gui", "ui", "graphics", "interface", "widgets"]
-categories = ["gui"]
+description = "A software renderer for iced on top of tiny-skia"
+version.workspace = true
+edition.workspace = true
+authors.workspace = true
+license.workspace = true
+repository.workspace = true
+homepage.workspace = true
+categories.workspace = true
+keywords.workspace = true
[features]
image = ["iced_graphics/image"]
@@ -16,27 +16,21 @@ svg = ["resvg"]
geometry = ["iced_graphics/geometry"]
[dependencies]
-raw-window-handle = "0.5"
-softbuffer = "0.2"
-tiny-skia = "0.10"
-cosmic-text = "0.9"
-bytemuck = "1"
-rustc-hash = "1.1"
-kurbo = "0.9"
-log = "0.4"
+iced_graphics.workspace = true
-[dependencies.iced_graphics]
-version = "0.9"
-path = "../graphics"
+bytemuck.workspace = true
+cosmic-text.workspace = true
+kurbo.workspace = true
+log.workspace = true
+raw-window-handle.workspace = true
+rustc-hash.workspace = true
+softbuffer.workspace = true
+tiny-skia.workspace = true
+twox-hash.workspace = true
-[dependencies.twox-hash]
-version = "1.6"
-default-features = false
+resvg.workspace = true
+resvg.optional = true
-[target.'cfg(not(target_arch = "wasm32"))'.dependencies.twox-hash]
-version = "1.6.1"
-features = ["std"]
-
-[dependencies.resvg]
-version = "0.35"
-optional = true
+[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
+twox-hash.workspace = true
+twox-hash.features = ["std"]
diff --git a/tiny_skia/src/geometry.rs b/tiny_skia/src/geometry.rs
index 0fae7364..047bc0ff 100644
--- a/tiny_skia/src/geometry.rs
+++ b/tiny_skia/src/geometry.rs
@@ -154,8 +154,16 @@ impl Frame {
.pre_concat(tiny_skia::Transform::from_rotate(angle.to_degrees()));
}
- pub fn scale(&mut self, scale: f32) {
- self.transform = self.transform.pre_scale(scale, scale);
+ pub fn scale(&mut self, scale: impl Into<f32>) {
+ let scale = scale.into();
+
+ self.scale_nonuniform(Vector { x: scale, y: scale });
+ }
+
+ pub fn scale_nonuniform(&mut self, scale: impl Into<Vector>) {
+ let scale = scale.into();
+
+ self.transform = self.transform.pre_scale(scale.x, scale.y);
}
pub fn into_primitive(self) -> Primitive {
@@ -295,7 +303,7 @@ pub fn into_fill_rule(rule: fill::Rule) -> tiny_skia::FillRule {
}
}
-pub fn into_stroke(stroke: &Stroke) -> tiny_skia::Stroke {
+pub fn into_stroke(stroke: &Stroke<'_>) -> tiny_skia::Stroke {
tiny_skia::Stroke {
width: stroke.width,
line_cap: match stroke.line_cap {
diff --git a/tiny_skia/src/lib.rs b/tiny_skia/src/lib.rs
index 15de6ce2..e48468e9 100644
--- a/tiny_skia/src/lib.rs
+++ b/tiny_skia/src/lib.rs
@@ -1,3 +1,16 @@
+#![forbid(rust_2018_idioms)]
+#![deny(
+ unsafe_code,
+ unused_results,
+ clippy::extra_unused_lifetimes,
+ clippy::from_over_into,
+ clippy::needless_borrow,
+ clippy::new_without_default,
+ clippy::useless_conversion,
+ rustdoc::broken_intra_doc_links
+)]
+#![allow(clippy::inherent_to_string, clippy::type_complexity)]
+#![cfg_attr(docsrs, feature(doc_auto_cfg))]
pub mod window;
mod backend;
diff --git a/tiny_skia/src/raster.rs b/tiny_skia/src/raster.rs
index dedb127c..d13b1167 100644
--- a/tiny_skia/src/raster.rs
+++ b/tiny_skia/src/raster.rs
@@ -85,14 +85,14 @@ impl Cache {
);
}
- entry.insert(Some(Entry {
+ let _ = entry.insert(Some(Entry {
width: image.width(),
height: image.height(),
pixels: buffer,
}));
}
- self.hits.insert(id);
+ let _ = self.hits.insert(id);
self.entries.get(&id).unwrap().as_ref().map(|entry| {
tiny_skia::PixmapRef::from_bytes(
bytemuck::cast_slice(&entry.pixels),
diff --git a/tiny_skia/src/text.rs b/tiny_skia/src/text.rs
index 820e7bd8..cb3ef54c 100644
--- a/tiny_skia/src/text.rs
+++ b/tiny_skia/src/text.rs
@@ -267,10 +267,10 @@ impl GlyphCache {
}
}
- entry.insert((buffer, image.placement));
+ let _ = entry.insert((buffer, image.placement));
}
- self.recently_used.insert(key);
+ let _ = self.recently_used.insert(key);
self.entries.get(&key).map(|(buffer, placement)| {
(bytemuck::cast_slice(buffer.as_slice()), *placement)
diff --git a/tiny_skia/src/vector.rs b/tiny_skia/src/vector.rs
index 433ca0f5..490b9f69 100644
--- a/tiny_skia/src/vector.rs
+++ b/tiny_skia/src/vector.rs
@@ -92,10 +92,10 @@ impl Cache {
}
};
- entry.insert(svg);
+ let _ = entry.insert(svg);
}
- self.tree_hits.insert(id);
+ let _ = self.tree_hits.insert(id);
self.trees.get(&id).unwrap().as_ref()
}
@@ -178,10 +178,10 @@ impl Cache {
}
}
- self.rasters.insert(key, image);
+ let _ = self.rasters.insert(key, image);
}
- self.raster_hits.insert(key);
+ let _ = self.raster_hits.insert(key);
self.rasters.get(&key).map(tiny_skia::Pixmap::as_ref)
}
diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs
index a996fffc..828e522f 100644
--- a/tiny_skia/src/window/compositor.rs
+++ b/tiny_skia/src/window/compositor.rs
@@ -46,6 +46,7 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
width: u32,
height: u32,
) -> Surface {
+ #[allow(unsafe_code)]
let window =
unsafe { softbuffer::GraphicsContext::new(window, window) }
.expect("Create softbuffer for window");
diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml
index 09740f54..a460c127 100644
--- a/wgpu/Cargo.toml
+++ b/wgpu/Cargo.toml
@@ -1,54 +1,45 @@
[package]
name = "iced_wgpu"
-version = "0.11.1"
-authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
-edition = "2021"
-description = "A wgpu renderer for Iced"
-license = "MIT AND OFL-1.1"
-repository = "https://github.com/iced-rs/iced"
+description = "A renderer for iced on top of wgpu"
+version.workspace = true
+edition.workspace = true
+authors.workspace = true
+license.workspace = true
+repository.workspace = true
+homepage.workspace = true
+categories.workspace = true
+keywords.workspace = true
+
+[package.metadata.docs.rs]
+rustdoc-args = ["--cfg", "docsrs"]
+all-features = true
[features]
geometry = ["iced_graphics/geometry", "lyon"]
image = ["iced_graphics/image"]
svg = ["resvg"]
web-colors = ["iced_graphics/web-colors"]
+webgl = ["wgpu/webgl"]
[dependencies]
-wgpu = "0.16"
-glyphon = "0.3"
-raw-window-handle = "0.5"
-guillotiere = "0.6"
-futures = "0.3"
-bitflags = "1.2"
-once_cell = "1.0"
-log = "0.4"
-
-[target.'cfg(target_arch = "wasm32")'.dependencies]
-wgpu = { version = "0.16", features = ["webgl"] }
-
-[dependencies.bytemuck]
-version = "1.9"
-features = ["derive"]
-
-[dependencies.iced_graphics]
-version = "0.9"
-path = "../graphics"
-
-[dependencies.glam]
-version = "0.24"
-
-[dependencies.lyon]
-version = "1.0"
-optional = true
-
-[dependencies.resvg]
-version = "0.35"
-optional = true
-
-[dependencies.tracing]
-version = "0.1.6"
-optional = true
-
-[package.metadata.docs.rs]
-rustdoc-args = ["--cfg", "docsrs"]
-all-features = true
+iced_graphics.workspace = true
+
+bitflags.workspace = true
+bytemuck.workspace = true
+futures.workspace = true
+glam.workspace = true
+glyphon.workspace = true
+guillotiere.workspace = true
+log.workspace = true
+once_cell.workspace = true
+raw-window-handle.workspace = true
+wgpu.workspace = true
+
+lyon.workspace = true
+lyon.optional = true
+
+resvg.workspace = true
+resvg.optional = true
+
+tracing.workspace = true
+tracing.optional = true
diff --git a/wgpu/src/geometry.rs b/wgpu/src/geometry.rs
index e421e0b0..63a59c05 100644
--- a/wgpu/src/geometry.rs
+++ b/wgpu/src/geometry.rs
@@ -310,13 +310,11 @@ impl Frame {
/// resulting glyphs will not be rotated or scaled properly.
///
/// Additionally, all text will be rendered on top of all the layers of
- /// a [`Canvas`]. Therefore, it is currently only meant to be used for
+ /// a `Canvas`. Therefore, it is currently only meant to be used for
/// overlays, which is the most common use case.
///
/// Support for vectorial text is planned, and should address all these
/// limitations.
- ///
- /// [`Canvas`]: crate::widget::Canvas
pub fn fill_text(&mut self, text: impl Into<Text>) {
let text = text.into();
@@ -444,11 +442,21 @@ impl Frame {
self.transforms.current.is_identity = false;
}
- /// Applies a scaling to the current transform of the [`Frame`].
+ /// Applies a uniform scaling to the current transform of the [`Frame`].
+ #[inline]
+ pub fn scale(&mut self, scale: impl Into<f32>) {
+ let scale = scale.into();
+
+ self.scale_nonuniform(Vector { x: scale, y: scale });
+ }
+
+ /// Applies a non-uniform scaling to the current transform of the [`Frame`].
#[inline]
- pub fn scale(&mut self, scale: f32) {
+ pub fn scale_nonuniform(&mut self, scale: impl Into<Vector>) {
+ let scale = scale.into();
+
self.transforms.current.raw =
- self.transforms.current.raw.pre_scale(scale, scale);
+ self.transforms.current.raw.pre_scale(scale.x, scale.y);
self.transforms.current.is_identity = false;
}
diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs
index cd457072..2f483751 100644
--- a/wgpu/src/lib.rs
+++ b/wgpu/src/lib.rs
@@ -20,6 +20,7 @@
#![doc(
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
)]
+#![forbid(rust_2018_idioms)]
#![deny(
missing_debug_implementations,
//missing_docs,
@@ -29,9 +30,9 @@
clippy::from_over_into,
clippy::needless_borrow,
clippy::new_without_default,
- clippy::useless_conversion
+ clippy::useless_conversion,
+ rustdoc::broken_intra_doc_links
)]
-#![forbid(rust_2018_idioms)]
#![allow(clippy::inherent_to_string, clippy::type_complexity)]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
pub mod layer;
diff --git a/wgpu/src/quad/gradient.rs b/wgpu/src/quad/gradient.rs
index 6db37252..a8e83d01 100644
--- a/wgpu/src/quad/gradient.rs
+++ b/wgpu/src/quad/gradient.rs
@@ -1,3 +1,4 @@
+use crate::graphics::color;
use crate::graphics::gradient;
use crate::quad::{self, Quad};
use crate::Buffer;
@@ -78,7 +79,23 @@ impl Pipeline {
device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("iced_wgpu.quad.gradient.shader"),
source: wgpu::ShaderSource::Wgsl(std::borrow::Cow::Borrowed(
- include_str!("../shader/quad.wgsl"),
+ if color::GAMMA_CORRECTION {
+ concat!(
+ include_str!("../shader/quad.wgsl"),
+ "\n",
+ include_str!("../shader/quad/gradient.wgsl"),
+ "\n",
+ include_str!("../shader/color/oklab.wgsl")
+ )
+ } else {
+ concat!(
+ include_str!("../shader/quad.wgsl"),
+ "\n",
+ include_str!("../shader/quad/gradient.wgsl"),
+ "\n",
+ include_str!("../shader/color/linear_rgb.wgsl")
+ )
+ },
)),
});
diff --git a/wgpu/src/quad/solid.rs b/wgpu/src/quad/solid.rs
index f8f1e3a5..9bc6b466 100644
--- a/wgpu/src/quad/solid.rs
+++ b/wgpu/src/quad/solid.rs
@@ -72,7 +72,11 @@ impl Pipeline {
device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("iced_wgpu.quad.solid.shader"),
source: wgpu::ShaderSource::Wgsl(std::borrow::Cow::Borrowed(
- include_str!("../shader/quad.wgsl"),
+ concat!(
+ include_str!("../shader/quad.wgsl"),
+ "\n",
+ include_str!("../shader/quad/solid.wgsl"),
+ ),
)),
});
diff --git a/wgpu/src/shader/color/linear_rgb.wgsl b/wgpu/src/shader/color/linear_rgb.wgsl
new file mode 100644
index 00000000..a5cf45d4
--- /dev/null
+++ b/wgpu/src/shader/color/linear_rgb.wgsl
@@ -0,0 +1,3 @@
+fn interpolate_color(from_: vec4<f32>, to_: vec4<f32>, factor: f32) -> vec4<f32> {
+ return mix(from_, to_, factor);
+}
diff --git a/wgpu/src/shader/color/oklab.wgsl b/wgpu/src/shader/color/oklab.wgsl
new file mode 100644
index 00000000..0dc37ba6
--- /dev/null
+++ b/wgpu/src/shader/color/oklab.wgsl
@@ -0,0 +1,26 @@
+const to_lms = mat3x4<f32>(
+ vec4<f32>(0.4121656120, 0.2118591070, 0.0883097947, 0.0),
+ vec4<f32>(0.5362752080, 0.6807189584, 0.2818474174, 0.0),
+ vec4<f32>(0.0514575653, 0.1074065790, 0.6302613616, 0.0),
+);
+
+const to_rgb = mat3x4<f32>(
+ vec4<f32>( 4.0767245293, -3.3072168827, 0.2307590544, 0.0),
+ vec4<f32>(-1.2681437731, 2.6093323231, -0.3411344290, 0.0),
+ vec4<f32>(-0.0041119885, -0.7034763098, 1.7068625689, 0.0),
+);
+
+fn interpolate_color(from_: vec4<f32>, to_: vec4<f32>, factor: f32) -> vec4<f32> {
+ // To Oklab
+ let lms_a = pow(from_ * to_lms, vec3<f32>(1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0));
+ let lms_b = pow(to_ * to_lms, vec3<f32>(1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0));
+ let mixed = mix(lms_a, lms_b, factor);
+
+ // Back to linear RGB
+ var color = to_rgb * (mixed * mixed * mixed);
+
+ // Alpha interpolation
+ color.a = mix(from_.a, to_.a, factor);
+
+ return color;
+}
diff --git a/wgpu/src/shader/quad.wgsl b/wgpu/src/shader/quad.wgsl
index fb402158..f919cfe2 100644
--- a/wgpu/src/shader/quad.wgsl
+++ b/wgpu/src/shader/quad.wgsl
@@ -37,309 +37,3 @@ fn select_border_radius(radi: vec4<f32>, position: vec2<f32>, center: vec2<f32>)
rx = select(rx, ry, position.y > center.y);
return rx;
}
-
-fn unpack_u32(color: vec2<u32>) -> vec4<f32> {
- let rg: vec2<f32> = unpack2x16float(color.x);
- let ba: vec2<f32> = unpack2x16float(color.y);
-
- return vec4<f32>(rg.y, rg.x, ba.y, ba.x);
-}
-
-struct SolidVertexInput {
- @location(0) v_pos: vec2<f32>,
- @location(1) color: vec4<f32>,
- @location(2) pos: vec2<f32>,
- @location(3) scale: vec2<f32>,
- @location(4) border_color: vec4<f32>,
- @location(5) border_radius: vec4<f32>,
- @location(6) border_width: f32,
-}
-
-struct SolidVertexOutput {
- @builtin(position) position: vec4<f32>,
- @location(0) color: vec4<f32>,
- @location(1) border_color: vec4<f32>,
- @location(2) pos: vec2<f32>,
- @location(3) scale: vec2<f32>,
- @location(4) border_radius: vec4<f32>,
- @location(5) border_width: f32,
-}
-
-@vertex
-fn solid_vs_main(input: SolidVertexInput) -> SolidVertexOutput {
- var out: SolidVertexOutput;
-
- var pos: vec2<f32> = input.pos * globals.scale;
- var scale: vec2<f32> = input.scale * globals.scale;
-
- var min_border_radius = min(input.scale.x, input.scale.y) * 0.5;
- var border_radius: vec4<f32> = vec4<f32>(
- min(input.border_radius.x, min_border_radius),
- min(input.border_radius.y, min_border_radius),
- min(input.border_radius.z, min_border_radius),
- min(input.border_radius.w, min_border_radius)
- );
-
- var transform: mat4x4<f32> = mat4x4<f32>(
- vec4<f32>(scale.x + 1.0, 0.0, 0.0, 0.0),
- vec4<f32>(0.0, scale.y + 1.0, 0.0, 0.0),
- vec4<f32>(0.0, 0.0, 1.0, 0.0),
- vec4<f32>(pos - vec2<f32>(0.5, 0.5), 0.0, 1.0)
- );
-
- out.position = globals.transform * transform * vec4<f32>(input.v_pos, 0.0, 1.0);
- out.color = input.color;
- out.border_color = input.border_color;
- out.pos = pos;
- out.scale = scale;
- out.border_radius = border_radius * globals.scale;
- out.border_width = input.border_width * globals.scale;
-
- return out;
-}
-
-@fragment
-fn solid_fs_main(
- input: SolidVertexOutput
-) -> @location(0) vec4<f32> {
- var mixed_color: vec4<f32> = input.color;
-
- var border_radius = select_border_radius(
- input.border_radius,
- input.position.xy,
- (input.pos + input.scale * 0.5).xy
- );
-
- if (input.border_width > 0.0) {
- var internal_border: f32 = max(border_radius - input.border_width, 0.0);
-
- var internal_distance: f32 = distance_alg(
- input.position.xy,
- input.pos + vec2<f32>(input.border_width, input.border_width),
- input.scale - vec2<f32>(input.border_width * 2.0, input.border_width * 2.0),
- internal_border
- );
-
- var border_mix: f32 = smoothstep(
- max(internal_border - 0.5, 0.0),
- internal_border + 0.5,
- internal_distance
- );
-
- mixed_color = mix(input.color, input.border_color, vec4<f32>(border_mix, border_mix, border_mix, border_mix));
- }
-
- var dist: f32 = distance_alg(
- vec2<f32>(input.position.x, input.position.y),
- input.pos,
- input.scale,
- border_radius
- );
-
- var radius_alpha: f32 = 1.0 - smoothstep(
- max(border_radius - 0.5, 0.0),
- border_radius + 0.5,
- dist
- );
-
- return vec4<f32>(mixed_color.x, mixed_color.y, mixed_color.z, mixed_color.w * radius_alpha);
-}
-
-struct GradientVertexInput {
- @location(0) v_pos: vec2<f32>,
- @location(1) colors_1: vec4<u32>,
- @location(2) colors_2: vec4<u32>,
- @location(3) colors_3: vec4<u32>,
- @location(4) colors_4: vec4<u32>,
- @location(5) offsets: vec4<u32>,
- @location(6) direction: vec4<f32>,
- @location(7) position_and_scale: vec4<f32>,
- @location(8) border_color: vec4<f32>,
- @location(9) border_radius: vec4<f32>,
- @location(10) border_width: f32,
-}
-
-struct GradientVertexOutput {
- @builtin(position) position: vec4<f32>,
- @location(1) colors_1: vec4<u32>,
- @location(2) colors_2: vec4<u32>,
- @location(3) colors_3: vec4<u32>,
- @location(4) colors_4: vec4<u32>,
- @location(5) offsets: vec4<u32>,
- @location(6) direction: vec4<f32>,
- @location(7) position_and_scale: vec4<f32>,
- @location(8) border_color: vec4<f32>,
- @location(9) border_radius: vec4<f32>,
- @location(10) border_width: f32,
-}
-
-@vertex
-fn gradient_vs_main(input: GradientVertexInput) -> GradientVertexOutput {
- var out: GradientVertexOutput;
-
- var pos: vec2<f32> = input.position_and_scale.xy * globals.scale;
- var scale: vec2<f32> = input.position_and_scale.zw * globals.scale;
-
- var min_border_radius = min(input.position_and_scale.z, input.position_and_scale.w) * 0.5;
- var border_radius: vec4<f32> = vec4<f32>(
- min(input.border_radius.x, min_border_radius),
- min(input.border_radius.y, min_border_radius),
- min(input.border_radius.z, min_border_radius),
- min(input.border_radius.w, min_border_radius)
- );
-
- var transform: mat4x4<f32> = mat4x4<f32>(
- vec4<f32>(scale.x + 1.0, 0.0, 0.0, 0.0),
- vec4<f32>(0.0, scale.y + 1.0, 0.0, 0.0),
- vec4<f32>(0.0, 0.0, 1.0, 0.0),
- vec4<f32>(pos - vec2<f32>(0.5, 0.5), 0.0, 1.0)
- );
-
- out.position = globals.transform * transform * vec4<f32>(input.v_pos, 0.0, 1.0);
- out.colors_1 = input.colors_1;
- out.colors_2 = input.colors_2;
- out.colors_3 = input.colors_3;
- out.colors_4 = input.colors_4;
- out.offsets = input.offsets;
- out.direction = input.direction * globals.scale;
- out.position_and_scale = vec4<f32>(pos, scale);
- out.border_color = input.border_color;
- out.border_radius = border_radius * globals.scale;
- out.border_width = input.border_width * globals.scale;
-
- return out;
-}
-
-fn random(coords: vec2<f32>) -> f32 {
- return fract(sin(dot(coords, vec2(12.9898,78.233))) * 43758.5453);
-}
-
-/// Returns the current interpolated color with a max 8-stop gradient
-fn gradient(
- raw_position: vec2<f32>,
- direction: vec4<f32>,
- colors: array<vec4<f32>, 8>,
- offsets: array<f32, 8>,
- last_index: i32
-) -> vec4<f32> {
- let start = direction.xy;
- let end = direction.zw;
-
- let v1 = end - start;
- let v2 = raw_position - start;
- let unit = normalize(v1);
- let coord_offset = dot(unit, v2) / length(v1);
-
- //need to store these as a var to use dynamic indexing in a loop
- //this is already added to wgsl spec but not in wgpu yet
- var colors_arr = colors;
- var offsets_arr = offsets;
-
- var color: vec4<f32>;
-
- let noise_granularity: f32 = 0.3/255.0;
-
- for (var i: i32 = 0; i < last_index; i++) {
- let curr_offset = offsets_arr[i];
- let next_offset = offsets_arr[i+1];
-
- if (coord_offset <= offsets_arr[0]) {
- color = colors_arr[0];
- }
-
- if (curr_offset <= coord_offset && coord_offset <= next_offset) {
- color = mix(colors_arr[i], colors_arr[i+1], smoothstep(
- curr_offset,
- next_offset,
- coord_offset,
- ));
- }
-
- if (coord_offset >= offsets_arr[last_index]) {
- color = colors_arr[last_index];
- }
- }
-
- return color + mix(-noise_granularity, noise_granularity, random(raw_position));
-}
-
-@fragment
-fn gradient_fs_main(input: GradientVertexOutput) -> @location(0) vec4<f32> {
- let colors = array<vec4<f32>, 8>(
- unpack_u32(input.colors_1.xy),
- unpack_u32(input.colors_1.zw),
- unpack_u32(input.colors_2.xy),
- unpack_u32(input.colors_2.zw),
- unpack_u32(input.colors_3.xy),
- unpack_u32(input.colors_3.zw),
- unpack_u32(input.colors_4.xy),
- unpack_u32(input.colors_4.zw),
- );
-
- let offsets_1: vec4<f32> = unpack_u32(input.offsets.xy);
- let offsets_2: vec4<f32> = unpack_u32(input.offsets.zw);
-
- var offsets = array<f32, 8>(
- offsets_1.x,
- offsets_1.y,
- offsets_1.z,
- offsets_1.w,
- offsets_2.x,
- offsets_2.y,
- offsets_2.z,
- offsets_2.w,
- );
-
- //TODO could just pass this in to the shader but is probably more performant to just check it here
- var last_index = 7;
- for (var i: i32 = 0; i <= 7; i++) {
- if (offsets[i] > 1.0) {
- last_index = i - 1;
- break;
- }
- }
-
- var mixed_color: vec4<f32> = gradient(input.position.xy, input.direction, colors, offsets, last_index);
-
- let pos = input.position_and_scale.xy;
- let scale = input.position_and_scale.zw;
-
- var border_radius = select_border_radius(
- input.border_radius,
- input.position.xy,
- (pos + scale * 0.5).xy
- );
-
- if (input.border_width > 0.0) {
- var internal_border: f32 = max(border_radius - input.border_width, 0.0);
-
- var internal_distance: f32 = distance_alg(
- input.position.xy,
- pos + vec2<f32>(input.border_width, input.border_width),
- scale - vec2<f32>(input.border_width * 2.0, input.border_width * 2.0),
- internal_border
- );
-
- var border_mix: f32 = smoothstep(
- max(internal_border - 0.5, 0.0),
- internal_border + 0.5,
- internal_distance
- );
-
- mixed_color = mix(mixed_color, input.border_color, vec4<f32>(border_mix, border_mix, border_mix, border_mix));
- }
-
- var dist: f32 = distance_alg(
- input.position.xy,
- pos,
- scale,
- border_radius
- );
-
- var radius_alpha: f32 = 1.0 - smoothstep(
- max(border_radius - 0.5, 0.0),
- border_radius + 0.5,
- dist);
-
- return vec4<f32>(mixed_color.x, mixed_color.y, mixed_color.z, mixed_color.w * radius_alpha);
-}
diff --git a/wgpu/src/shader/quad/gradient.wgsl b/wgpu/src/shader/quad/gradient.wgsl
new file mode 100644
index 00000000..0754e97f
--- /dev/null
+++ b/wgpu/src/shader/quad/gradient.wgsl
@@ -0,0 +1,205 @@
+struct GradientVertexInput {
+ @location(0) v_pos: vec2<f32>,
+ @location(1) @interpolate(flat) colors_1: vec4<u32>,
+ @location(2) @interpolate(flat) colors_2: vec4<u32>,
+ @location(3) @interpolate(flat) colors_3: vec4<u32>,
+ @location(4) @interpolate(flat) colors_4: vec4<u32>,
+ @location(5) @interpolate(flat) offsets: vec4<u32>,
+ @location(6) direction: vec4<f32>,
+ @location(7) position_and_scale: vec4<f32>,
+ @location(8) border_color: vec4<f32>,
+ @location(9) border_radius: vec4<f32>,
+ @location(10) border_width: f32,
+}
+
+struct GradientVertexOutput {
+ @builtin(position) position: vec4<f32>,
+ @location(1) @interpolate(flat) colors_1: vec4<u32>,
+ @location(2) @interpolate(flat) colors_2: vec4<u32>,
+ @location(3) @interpolate(flat) colors_3: vec4<u32>,
+ @location(4) @interpolate(flat) colors_4: vec4<u32>,
+ @location(5) @interpolate(flat) offsets: vec4<u32>,
+ @location(6) direction: vec4<f32>,
+ @location(7) position_and_scale: vec4<f32>,
+ @location(8) border_color: vec4<f32>,
+ @location(9) border_radius: vec4<f32>,
+ @location(10) border_width: f32,
+}
+
+@vertex
+fn gradient_vs_main(input: GradientVertexInput) -> GradientVertexOutput {
+ var out: GradientVertexOutput;
+
+ var pos: vec2<f32> = input.position_and_scale.xy * globals.scale;
+ var scale: vec2<f32> = input.position_and_scale.zw * globals.scale;
+
+ var min_border_radius = min(input.position_and_scale.z, input.position_and_scale.w) * 0.5;
+ var border_radius: vec4<f32> = vec4<f32>(
+ min(input.border_radius.x, min_border_radius),
+ min(input.border_radius.y, min_border_radius),
+ min(input.border_radius.z, min_border_radius),
+ min(input.border_radius.w, min_border_radius)
+ );
+
+ var transform: mat4x4<f32> = mat4x4<f32>(
+ vec4<f32>(scale.x + 1.0, 0.0, 0.0, 0.0),
+ vec4<f32>(0.0, scale.y + 1.0, 0.0, 0.0),
+ vec4<f32>(0.0, 0.0, 1.0, 0.0),
+ vec4<f32>(pos - vec2<f32>(0.5, 0.5), 0.0, 1.0)
+ );
+
+ out.position = globals.transform * transform * vec4<f32>(input.v_pos, 0.0, 1.0);
+ out.colors_1 = input.colors_1;
+ out.colors_2 = input.colors_2;
+ out.colors_3 = input.colors_3;
+ out.colors_4 = input.colors_4;
+ out.offsets = input.offsets;
+ out.direction = input.direction * globals.scale;
+ out.position_and_scale = vec4<f32>(pos, scale);
+ out.border_color = input.border_color;
+ out.border_radius = border_radius * globals.scale;
+ out.border_width = input.border_width * globals.scale;
+
+ return out;
+}
+
+fn random(coords: vec2<f32>) -> f32 {
+ return fract(sin(dot(coords, vec2(12.9898,78.233))) * 43758.5453);
+}
+
+/// Returns the current interpolated color with a max 8-stop gradient
+fn gradient(
+ raw_position: vec2<f32>,
+ direction: vec4<f32>,
+ colors: array<vec4<f32>, 8>,
+ offsets: array<f32, 8>,
+ last_index: i32
+) -> vec4<f32> {
+ let start = direction.xy;
+ let end = direction.zw;
+
+ let v1 = end - start;
+ let v2 = raw_position - start;
+ let unit = normalize(v1);
+ let coord_offset = dot(unit, v2) / length(v1);
+
+ //need to store these as a var to use dynamic indexing in a loop
+ //this is already added to wgsl spec but not in wgpu yet
+ var colors_arr = colors;
+ var offsets_arr = offsets;
+
+ var color: vec4<f32>;
+
+ let noise_granularity: f32 = 0.3/255.0;
+
+ for (var i: i32 = 0; i < last_index; i++) {
+ let curr_offset = offsets_arr[i];
+ let next_offset = offsets_arr[i+1];
+
+ if (coord_offset <= offsets_arr[0]) {
+ color = colors_arr[0];
+ }
+
+ if (curr_offset <= coord_offset && coord_offset <= next_offset) {
+ let from_ = colors_arr[i];
+ let to_ = colors_arr[i+1];
+ let factor = smoothstep(curr_offset, next_offset, coord_offset);
+
+ color = interpolate_color(from_, to_, factor);
+ }
+
+ if (coord_offset >= offsets_arr[last_index]) {
+ color = colors_arr[last_index];
+ }
+ }
+
+ return color + mix(-noise_granularity, noise_granularity, random(raw_position));
+}
+
+@fragment
+fn gradient_fs_main(input: GradientVertexOutput) -> @location(0) vec4<f32> {
+ let colors = array<vec4<f32>, 8>(
+ unpack_u32(input.colors_1.xy),
+ unpack_u32(input.colors_1.zw),
+ unpack_u32(input.colors_2.xy),
+ unpack_u32(input.colors_2.zw),
+ unpack_u32(input.colors_3.xy),
+ unpack_u32(input.colors_3.zw),
+ unpack_u32(input.colors_4.xy),
+ unpack_u32(input.colors_4.zw),
+ );
+
+ let offsets_1: vec4<f32> = unpack_u32(input.offsets.xy);
+ let offsets_2: vec4<f32> = unpack_u32(input.offsets.zw);
+
+ var offsets = array<f32, 8>(
+ offsets_1.x,
+ offsets_1.y,
+ offsets_1.z,
+ offsets_1.w,
+ offsets_2.x,
+ offsets_2.y,
+ offsets_2.z,
+ offsets_2.w,
+ );
+
+ //TODO could just pass this in to the shader but is probably more performant to just check it here
+ var last_index = 7;
+ for (var i: i32 = 0; i <= 7; i++) {
+ if (offsets[i] > 1.0) {
+ last_index = i - 1;
+ break;
+ }
+ }
+
+ var mixed_color: vec4<f32> = gradient(input.position.xy, input.direction, colors, offsets, last_index);
+
+ let pos = input.position_and_scale.xy;
+ let scale = input.position_and_scale.zw;
+
+ var border_radius = select_border_radius(
+ input.border_radius,
+ input.position.xy,
+ (pos + scale * 0.5).xy
+ );
+
+ if (input.border_width > 0.0) {
+ var internal_border: f32 = max(border_radius - input.border_width, 0.0);
+
+ var internal_distance: f32 = distance_alg(
+ input.position.xy,
+ pos + vec2<f32>(input.border_width, input.border_width),
+ scale - vec2<f32>(input.border_width * 2.0, input.border_width * 2.0),
+ internal_border
+ );
+
+ var border_mix: f32 = smoothstep(
+ max(internal_border - 0.5, 0.0),
+ internal_border + 0.5,
+ internal_distance
+ );
+
+ mixed_color = mix(mixed_color, input.border_color, vec4<f32>(border_mix, border_mix, border_mix, border_mix));
+ }
+
+ var dist: f32 = distance_alg(
+ input.position.xy,
+ pos,
+ scale,
+ border_radius
+ );
+
+ var radius_alpha: f32 = 1.0 - smoothstep(
+ max(border_radius - 0.5, 0.0),
+ border_radius + 0.5,
+ dist);
+
+ return vec4<f32>(mixed_color.x, mixed_color.y, mixed_color.z, mixed_color.w * radius_alpha);
+}
+
+fn unpack_u32(color: vec2<u32>) -> vec4<f32> {
+ let rg: vec2<f32> = unpack2x16float(color.x);
+ let ba: vec2<f32> = unpack2x16float(color.y);
+
+ return vec4<f32>(rg.y, rg.x, ba.y, ba.x);
+}
diff --git a/wgpu/src/shader/quad/solid.wgsl b/wgpu/src/shader/quad/solid.wgsl
new file mode 100644
index 00000000..ebd6d877
--- /dev/null
+++ b/wgpu/src/shader/quad/solid.wgsl
@@ -0,0 +1,99 @@
+struct SolidVertexInput {
+ @location(0) v_pos: vec2<f32>,
+ @location(1) color: vec4<f32>,
+ @location(2) pos: vec2<f32>,
+ @location(3) scale: vec2<f32>,
+ @location(4) border_color: vec4<f32>,
+ @location(5) border_radius: vec4<f32>,
+ @location(6) border_width: f32,
+}
+
+struct SolidVertexOutput {
+ @builtin(position) position: vec4<f32>,
+ @location(0) color: vec4<f32>,
+ @location(1) border_color: vec4<f32>,
+ @location(2) pos: vec2<f32>,
+ @location(3) scale: vec2<f32>,
+ @location(4) border_radius: vec4<f32>,
+ @location(5) border_width: f32,
+}
+
+@vertex
+fn solid_vs_main(input: SolidVertexInput) -> SolidVertexOutput {
+ var out: SolidVertexOutput;
+
+ var pos: vec2<f32> = input.pos * globals.scale;
+ var scale: vec2<f32> = input.scale * globals.scale;
+
+ var min_border_radius = min(input.scale.x, input.scale.y) * 0.5;
+ var border_radius: vec4<f32> = vec4<f32>(
+ min(input.border_radius.x, min_border_radius),
+ min(input.border_radius.y, min_border_radius),
+ min(input.border_radius.z, min_border_radius),
+ min(input.border_radius.w, min_border_radius)
+ );
+
+ var transform: mat4x4<f32> = mat4x4<f32>(
+ vec4<f32>(scale.x + 1.0, 0.0, 0.0, 0.0),
+ vec4<f32>(0.0, scale.y + 1.0, 0.0, 0.0),
+ vec4<f32>(0.0, 0.0, 1.0, 0.0),
+ vec4<f32>(pos - vec2<f32>(0.5, 0.5), 0.0, 1.0)
+ );
+
+ out.position = globals.transform * transform * vec4<f32>(input.v_pos, 0.0, 1.0);
+ out.color = input.color;
+ out.border_color = input.border_color;
+ out.pos = pos;
+ out.scale = scale;
+ out.border_radius = border_radius * globals.scale;
+ out.border_width = input.border_width * globals.scale;
+
+ return out;
+}
+
+@fragment
+fn solid_fs_main(
+ input: SolidVertexOutput
+) -> @location(0) vec4<f32> {
+ var mixed_color: vec4<f32> = input.color;
+
+ var border_radius = select_border_radius(
+ input.border_radius,
+ input.position.xy,
+ (input.pos + input.scale * 0.5).xy
+ );
+
+ if (input.border_width > 0.0) {
+ var internal_border: f32 = max(border_radius - input.border_width, 0.0);
+
+ var internal_distance: f32 = distance_alg(
+ input.position.xy,
+ input.pos + vec2<f32>(input.border_width, input.border_width),
+ input.scale - vec2<f32>(input.border_width * 2.0, input.border_width * 2.0),
+ internal_border
+ );
+
+ var border_mix: f32 = smoothstep(
+ max(internal_border - 0.5, 0.0),
+ internal_border + 0.5,
+ internal_distance
+ );
+
+ mixed_color = mix(input.color, input.border_color, vec4<f32>(border_mix, border_mix, border_mix, border_mix));
+ }
+
+ var dist: f32 = distance_alg(
+ vec2<f32>(input.position.x, input.position.y),
+ input.pos,
+ input.scale,
+ border_radius
+ );
+
+ var radius_alpha: f32 = 1.0 - smoothstep(
+ max(border_radius - 0.5, 0.0),
+ border_radius + 0.5,
+ dist
+ );
+
+ return vec4<f32>(mixed_color.x, mixed_color.y, mixed_color.z, mixed_color.w * radius_alpha);
+}
diff --git a/wgpu/src/shader/triangle.wgsl b/wgpu/src/shader/triangle.wgsl
index 9f512d14..e4c19344 100644
--- a/wgpu/src/shader/triangle.wgsl
+++ b/wgpu/src/shader/triangle.wgsl
@@ -3,163 +3,3 @@ struct Globals {
}
@group(0) @binding(0) var<uniform> globals: Globals;
-
-fn unpack_u32(color: vec2<u32>) -> vec4<f32> {
- let rg: vec2<f32> = unpack2x16float(color.x);
- let ba: vec2<f32> = unpack2x16float(color.y);
-
- return vec4<f32>(rg.y, rg.x, ba.y, ba.x);
-}
-
-struct SolidVertexInput {
- @location(0) position: vec2<f32>,
- @location(1) color: vec4<f32>,
-}
-
-struct SolidVertexOutput {
- @builtin(position) position: vec4<f32>,
- @location(0) color: vec4<f32>,
-}
-
-@vertex
-fn solid_vs_main(input: SolidVertexInput) -> SolidVertexOutput {
- var out: SolidVertexOutput;
-
- out.color = input.color;
- out.position = globals.transform * vec4<f32>(input.position, 0.0, 1.0);
-
- return out;
-}
-
-@fragment
-fn solid_fs_main(input: SolidVertexOutput) -> @location(0) vec4<f32> {
- return input.color;
-}
-
-struct GradientVertexInput {
- @location(0) v_pos: vec2<f32>,
- @location(1) colors_1: vec4<u32>,
- @location(2) colors_2: vec4<u32>,
- @location(3) colors_3: vec4<u32>,
- @location(4) colors_4: vec4<u32>,
- @location(5) offsets: vec4<u32>,
- @location(6) direction: vec4<f32>,
-}
-
-struct GradientVertexOutput {
- @builtin(position) position: vec4<f32>,
- @location(0) raw_position: vec2<f32>,
- @location(1) colors_1: vec4<u32>,
- @location(2) colors_2: vec4<u32>,
- @location(3) colors_3: vec4<u32>,
- @location(4) colors_4: vec4<u32>,
- @location(5) offsets: vec4<u32>,
- @location(6) direction: vec4<f32>,
-}
-
-@vertex
-fn gradient_vs_main(input: GradientVertexInput) -> GradientVertexOutput {
- var output: GradientVertexOutput;
-
- output.position = globals.transform * vec4<f32>(input.v_pos, 0.0, 1.0);
- output.raw_position = input.v_pos;
- output.colors_1 = input.colors_1;
- output.colors_2 = input.colors_2;
- output.colors_3 = input.colors_3;
- output.colors_4 = input.colors_4;
- output.offsets = input.offsets;
- output.direction = input.direction;
-
- return output;
-}
-
-fn random(coords: vec2<f32>) -> f32 {
- return fract(sin(dot(coords, vec2(12.9898,78.233))) * 43758.5453);
-}
-
-/// Returns the current interpolated color with a max 8-stop gradient
-fn gradient(
- raw_position: vec2<f32>,
- direction: vec4<f32>,
- colors: array<vec4<f32>, 8>,
- offsets: array<f32, 8>,
- last_index: i32
-) -> vec4<f32> {
- let start = direction.xy;
- let end = direction.zw;
-
- let v1 = end - start;
- let v2 = raw_position - start;
- let unit = normalize(v1);
- let coord_offset = dot(unit, v2) / length(v1);
-
- //need to store these as a var to use dynamic indexing in a loop
- //this is already added to wgsl spec but not in wgpu yet
- var colors_arr = colors;
- var offsets_arr = offsets;
-
- var color: vec4<f32>;
-
- let noise_granularity: f32 = 0.3/255.0;
-
- for (var i: i32 = 0; i < last_index; i++) {
- let curr_offset = offsets_arr[i];
- let next_offset = offsets_arr[i+1];
-
- if (coord_offset <= offsets_arr[0]) {
- color = colors_arr[0];
- }
-
- if (curr_offset <= coord_offset && coord_offset <= next_offset) {
- color = mix(colors_arr[i], colors_arr[i+1], smoothstep(
- curr_offset,
- next_offset,
- coord_offset,
- ));
- }
-
- if (coord_offset >= offsets_arr[last_index]) {
- color = colors_arr[last_index];
- }
- }
-
- return color + mix(-noise_granularity, noise_granularity, random(raw_position));
-}
-
-@fragment
-fn gradient_fs_main(input: GradientVertexOutput) -> @location(0) vec4<f32> {
- let colors = array<vec4<f32>, 8>(
- unpack_u32(input.colors_1.xy),
- unpack_u32(input.colors_1.zw),
- unpack_u32(input.colors_2.xy),
- unpack_u32(input.colors_2.zw),
- unpack_u32(input.colors_3.xy),
- unpack_u32(input.colors_3.zw),
- unpack_u32(input.colors_4.xy),
- unpack_u32(input.colors_4.zw),
- );
-
- let offsets_1: vec4<f32> = unpack_u32(input.offsets.xy);
- let offsets_2: vec4<f32> = unpack_u32(input.offsets.zw);
-
- var offsets = array<f32, 8>(
- offsets_1.x,
- offsets_1.y,
- offsets_1.z,
- offsets_1.w,
- offsets_2.x,
- offsets_2.y,
- offsets_2.z,
- offsets_2.w,
- );
-
- var last_index = 7;
- for (var i: i32 = 0; i <= 7; i++) {
- if (offsets[i] >= 1.0) {
- last_index = i;
- break;
- }
- }
-
- return gradient(input.raw_position, input.direction, colors, offsets, last_index);
-}
diff --git a/wgpu/src/shader/triangle/gradient.wgsl b/wgpu/src/shader/triangle/gradient.wgsl
new file mode 100644
index 00000000..1a8ae3b5
--- /dev/null
+++ b/wgpu/src/shader/triangle/gradient.wgsl
@@ -0,0 +1,134 @@
+struct GradientVertexInput {
+ @location(0) v_pos: vec2<f32>,
+ @location(1) @interpolate(flat) colors_1: vec4<u32>,
+ @location(2) @interpolate(flat) colors_2: vec4<u32>,
+ @location(3) @interpolate(flat) colors_3: vec4<u32>,
+ @location(4) @interpolate(flat) colors_4: vec4<u32>,
+ @location(5) @interpolate(flat) offsets: vec4<u32>,
+ @location(6) direction: vec4<f32>,
+}
+
+struct GradientVertexOutput {
+ @builtin(position) position: vec4<f32>,
+ @location(0) raw_position: vec2<f32>,
+ @location(1) @interpolate(flat) colors_1: vec4<u32>,
+ @location(2) @interpolate(flat) colors_2: vec4<u32>,
+ @location(3) @interpolate(flat) colors_3: vec4<u32>,
+ @location(4) @interpolate(flat) colors_4: vec4<u32>,
+ @location(5) @interpolate(flat) offsets: vec4<u32>,
+ @location(6) direction: vec4<f32>,
+}
+
+@vertex
+fn gradient_vs_main(input: GradientVertexInput) -> GradientVertexOutput {
+ var output: GradientVertexOutput;
+
+ output.position = globals.transform * vec4<f32>(input.v_pos, 0.0, 1.0);
+ output.raw_position = input.v_pos;
+ output.colors_1 = input.colors_1;
+ output.colors_2 = input.colors_2;
+ output.colors_3 = input.colors_3;
+ output.colors_4 = input.colors_4;
+ output.offsets = input.offsets;
+ output.direction = input.direction;
+
+ return output;
+}
+
+/// Returns the current interpolated color with a max 8-stop gradient
+fn gradient(
+ raw_position: vec2<f32>,
+ direction: vec4<f32>,
+ colors: array<vec4<f32>, 8>,
+ offsets: array<f32, 8>,
+ last_index: i32
+) -> vec4<f32> {
+ let start = direction.xy;
+ let end = direction.zw;
+
+ let v1 = end - start;
+ let v2 = raw_position - start;
+ let unit = normalize(v1);
+ let coord_offset = dot(unit, v2) / length(v1);
+
+ //need to store these as a var to use dynamic indexing in a loop
+ //this is already added to wgsl spec but not in wgpu yet
+ var colors_arr = colors;
+ var offsets_arr = offsets;
+
+ var color: vec4<f32>;
+
+ let noise_granularity: f32 = 0.3/255.0;
+
+ for (var i: i32 = 0; i < last_index; i++) {
+ let curr_offset = offsets_arr[i];
+ let next_offset = offsets_arr[i+1];
+
+ if (coord_offset <= offsets_arr[0]) {
+ color = colors_arr[0];
+ }
+
+ if (curr_offset <= coord_offset && coord_offset <= next_offset) {
+ let from_ = colors_arr[i];
+ let to_ = colors_arr[i+1];
+ let factor = smoothstep(curr_offset, next_offset, coord_offset);
+
+ color = interpolate_color(from_, to_, factor);
+ }
+
+ if (coord_offset >= offsets_arr[last_index]) {
+ color = colors_arr[last_index];
+ }
+ }
+
+ return color + mix(-noise_granularity, noise_granularity, random(raw_position));
+}
+
+@fragment
+fn gradient_fs_main(input: GradientVertexOutput) -> @location(0) vec4<f32> {
+ let colors = array<vec4<f32>, 8>(
+ unpack_u32(input.colors_1.xy),
+ unpack_u32(input.colors_1.zw),
+ unpack_u32(input.colors_2.xy),
+ unpack_u32(input.colors_2.zw),
+ unpack_u32(input.colors_3.xy),
+ unpack_u32(input.colors_3.zw),
+ unpack_u32(input.colors_4.xy),
+ unpack_u32(input.colors_4.zw),
+ );
+
+ let offsets_1: vec4<f32> = unpack_u32(input.offsets.xy);
+ let offsets_2: vec4<f32> = unpack_u32(input.offsets.zw);
+
+ var offsets = array<f32, 8>(
+ offsets_1.x,
+ offsets_1.y,
+ offsets_1.z,
+ offsets_1.w,
+ offsets_2.x,
+ offsets_2.y,
+ offsets_2.z,
+ offsets_2.w,
+ );
+
+ var last_index = 7;
+ for (var i: i32 = 0; i <= 7; i++) {
+ if (offsets[i] >= 1.0) {
+ last_index = i;
+ break;
+ }
+ }
+
+ return gradient(input.raw_position, input.direction, colors, offsets, last_index);
+}
+
+fn unpack_u32(color: vec2<u32>) -> vec4<f32> {
+ let rg: vec2<f32> = unpack2x16float(color.x);
+ let ba: vec2<f32> = unpack2x16float(color.y);
+
+ return vec4<f32>(rg.y, rg.x, ba.y, ba.x);
+}
+
+fn random(coords: vec2<f32>) -> f32 {
+ return fract(sin(dot(coords, vec2(12.9898,78.233))) * 43758.5453);
+}
diff --git a/wgpu/src/shader/triangle/solid.wgsl b/wgpu/src/shader/triangle/solid.wgsl
new file mode 100644
index 00000000..9ef81982
--- /dev/null
+++ b/wgpu/src/shader/triangle/solid.wgsl
@@ -0,0 +1,24 @@
+struct SolidVertexInput {
+ @location(0) position: vec2<f32>,
+ @location(1) color: vec4<f32>,
+}
+
+struct SolidVertexOutput {
+ @builtin(position) position: vec4<f32>,
+ @location(0) color: vec4<f32>,
+}
+
+@vertex
+fn solid_vs_main(input: SolidVertexInput) -> SolidVertexOutput {
+ var out: SolidVertexOutput;
+
+ out.color = input.color;
+ out.position = globals.transform * vec4<f32>(input.position, 0.0, 1.0);
+
+ return out;
+}
+
+@fragment
+fn solid_fs_main(input: SolidVertexOutput) -> @location(0) vec4<f32> {
+ return input.color;
+}
diff --git a/wgpu/src/triangle.rs b/wgpu/src/triangle.rs
index d8b23dfe..d430e607 100644
--- a/wgpu/src/triangle.rs
+++ b/wgpu/src/triangle.rs
@@ -487,8 +487,10 @@ mod solid {
device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("iced_wgpu.triangle.solid.shader"),
source: wgpu::ShaderSource::Wgsl(
- std::borrow::Cow::Borrowed(include_str!(
- "shader/triangle.wgsl"
+ std::borrow::Cow::Borrowed(concat!(
+ include_str!("shader/triangle.wgsl"),
+ "\n",
+ include_str!("shader/triangle/solid.wgsl"),
)),
),
});
@@ -537,6 +539,7 @@ mod solid {
}
mod gradient {
+ use crate::graphics::color;
use crate::graphics::mesh;
use crate::graphics::Antialiasing;
use crate::triangle;
@@ -633,9 +636,31 @@ mod gradient {
device.create_shader_module(wgpu::ShaderModuleDescriptor {
label: Some("iced_wgpu.triangle.gradient.shader"),
source: wgpu::ShaderSource::Wgsl(
- std::borrow::Cow::Borrowed(include_str!(
- "shader/triangle.wgsl"
- )),
+ std::borrow::Cow::Borrowed(
+ if color::GAMMA_CORRECTION {
+ concat!(
+ include_str!("shader/triangle.wgsl"),
+ "\n",
+ include_str!(
+ "shader/triangle/gradient.wgsl"
+ ),
+ "\n",
+ include_str!("shader/color/oklab.wgsl")
+ )
+ } else {
+ concat!(
+ include_str!("shader/triangle.wgsl"),
+ "\n",
+ include_str!(
+ "shader/triangle/gradient.wgsl"
+ ),
+ "\n",
+ include_str!(
+ "shader/color/linear_rgb.wgsl"
+ )
+ )
+ },
+ ),
),
});
diff --git a/wgpu/src/window/compositor.rs b/wgpu/src/window/compositor.rs
index 09e11fdc..a9521a15 100644
--- a/wgpu/src/window/compositor.rs
+++ b/wgpu/src/window/compositor.rs
@@ -6,8 +6,6 @@ use crate::graphics::compositor;
use crate::graphics::{Error, Viewport};
use crate::{Backend, Primitive, Renderer, Settings};
-use futures::stream::{self, StreamExt};
-
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
use std::marker::PhantomData;
@@ -95,14 +93,15 @@ impl<Theme> Compositor<Theme> {
let limits =
[wgpu::Limits::default(), wgpu::Limits::downlevel_defaults()];
- let limits = limits.into_iter().map(|limits| wgpu::Limits {
+ let mut limits = limits.into_iter().map(|limits| wgpu::Limits {
max_bind_groups: 2,
..limits
});
- let (device, queue) = stream::iter(limits)
- .filter_map(|limits| async {
- adapter.request_device(
+ let (device, queue) =
+ loop {
+ let limits = limits.next()?;
+ let device = adapter.request_device(
&wgpu::DeviceDescriptor {
label: Some(
"iced_wgpu::window::compositor device descriptor",
@@ -111,11 +110,12 @@ impl<Theme> Compositor<Theme> {
limits,
},
None,
- ).await.ok()
- })
- .boxed()
- .next()
- .await?;
+ ).await.ok();
+
+ if let Some(device) = device {
+ break Some(device);
+ }
+ }?;
Some(Compositor {
instance,
diff --git a/widget/Cargo.toml b/widget/Cargo.toml
index 128a7c38..6d62c181 100644
--- a/widget/Cargo.toml
+++ b/widget/Cargo.toml
@@ -1,14 +1,18 @@
[package]
name = "iced_widget"
-version = "0.1.3"
-authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
-edition = "2021"
-description = "The built-in widgets for Iced"
-license = "MIT"
-repository = "https://github.com/iced-rs/iced"
-documentation = "https://docs.rs/iced_widget"
-keywords = ["gui", "ui", "graphics", "interface", "widgets"]
-categories = ["gui"]
+description = "The built-in widgets for iced"
+version.workspace = true
+edition.workspace = true
+authors.workspace = true
+license.workspace = true
+repository.workspace = true
+homepage.workspace = true
+categories.workspace = true
+keywords.workspace = true
+
+[package.metadata.docs.rs]
+rustdoc-args = ["--cfg", "docsrs"]
+all-features = true
[features]
lazy = ["ouroboros"]
@@ -18,31 +22,16 @@ canvas = ["iced_renderer/geometry"]
qr_code = ["canvas", "qrcode"]
[dependencies]
-unicode-segmentation = "1.6"
-num-traits = "0.2"
-thiserror = "1"
-
-[dependencies.iced_runtime]
-version = "0.1"
-path = "../runtime"
+iced_renderer.workspace = true
+iced_runtime.workspace = true
+iced_style.workspace = true
-[dependencies.iced_renderer]
-version = "0.1"
-path = "../renderer"
+num-traits.workspace = true
+thiserror.workspace = true
+unicode-segmentation.workspace = true
-[dependencies.iced_style]
-version = "0.9"
-path = "../style"
+ouroboros.workspace = true
+ouroboros.optional = true
-[dependencies.ouroboros]
-version = "0.17"
-optional = true
-
-[dependencies.qrcode]
-version = "0.12"
-optional = true
-default-features = false
-
-[package.metadata.docs.rs]
-rustdoc-args = ["--cfg", "docsrs"]
-all-features = true
+qrcode.workspace = true
+qrcode.optional = true
diff --git a/widget/src/button.rs b/widget/src/button.rs
index 8ca4a542..4915bd49 100644
--- a/widget/src/button.rs
+++ b/widget/src/button.rs
@@ -119,9 +119,9 @@ where
/// Sets the style variant of this [`Button`].
pub fn style(
mut self,
- style: <Renderer::Theme as StyleSheet>::Style,
+ style: impl Into<<Renderer::Theme as StyleSheet>::Style>,
) -> Self {
- self.style = style;
+ self.style = style.into();
self
}
}
diff --git a/widget/src/canvas/event.rs b/widget/src/canvas/event.rs
index 4508c184..1288365f 100644
--- a/widget/src/canvas/event.rs
+++ b/widget/src/canvas/event.rs
@@ -7,7 +7,7 @@ pub use crate::core::event::Status;
/// A [`Canvas`] event.
///
-/// [`Canvas`]: crate::widget::Canvas
+/// [`Canvas`]: crate::Canvas
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Event {
/// A mouse event.
diff --git a/widget/src/canvas/program.rs b/widget/src/canvas/program.rs
index b3f6175e..2ac23061 100644
--- a/widget/src/canvas/program.rs
+++ b/widget/src/canvas/program.rs
@@ -8,7 +8,7 @@ use crate::graphics::geometry;
/// A [`Program`] can mutate internal state and produce messages for an
/// application.
///
-/// [`Canvas`]: crate::widget::Canvas
+/// [`Canvas`]: crate::Canvas
pub trait Program<Message, Renderer = crate::Renderer>
where
Renderer: geometry::Renderer,
@@ -26,7 +26,7 @@ where
///
/// By default, this method does and returns nothing.
///
- /// [`Canvas`]: crate::widget::Canvas
+ /// [`Canvas`]: crate::Canvas
fn update(
&self,
_state: &mut Self::State,
@@ -42,8 +42,9 @@ where
/// [`Geometry`] can be easily generated with a [`Frame`] or stored in a
/// [`Cache`].
///
- /// [`Frame`]: crate::widget::canvas::Frame
- /// [`Cache`]: crate::widget::canvas::Cache
+ /// [`Geometry`]: crate::canvas::Geometry
+ /// [`Frame`]: crate::canvas::Frame
+ /// [`Cache`]: crate::canvas::Cache
fn draw(
&self,
state: &Self::State,
@@ -58,7 +59,7 @@ where
/// The interaction returned will be in effect even if the cursor position
/// is out of bounds of the program's [`Canvas`].
///
- /// [`Canvas`]: crate::widget::Canvas
+ /// [`Canvas`]: crate::Canvas
fn mouse_interaction(
&self,
_state: &Self::State,
diff --git a/widget/src/checkbox.rs b/widget/src/checkbox.rs
index 2860d496..d7fdf339 100644
--- a/widget/src/checkbox.rs
+++ b/widget/src/checkbox.rs
@@ -121,7 +121,7 @@ where
self
}
- /// Sets the text [`LineHeight`] of the [`Checkbox`].
+ /// Sets the text [`text::LineHeight`] of the [`Checkbox`].
pub fn text_line_height(
mut self,
line_height: impl Into<text::LineHeight>,
@@ -136,9 +136,9 @@ where
self
}
- /// Sets the [`Font`] of the text of the [`Checkbox`].
+ /// Sets the [`Renderer::Font`] of the text of the [`Checkbox`].
///
- /// [`Font`]: crate::text::Renderer::Font
+ /// [`Renderer::Font`]: crate::core::text::Renderer
pub fn font(mut self, font: impl Into<Renderer::Font>) -> Self {
self.font = Some(font.into());
self
diff --git a/widget/src/combo_box.rs b/widget/src/combo_box.rs
index 650954ef..d6915281 100644
--- a/widget/src/combo_box.rs
+++ b/widget/src/combo_box.rs
@@ -20,7 +20,7 @@ use std::time::Instant;
///
/// This widget is composed by a [`TextInput`] that can be filled with the text
/// to search for corresponding values from the list of options that are displayed
-/// as a [`Menu`].
+/// as a Menu.
#[allow(missing_debug_implementations)]
pub struct ComboBox<'a, T, Message, Renderer = crate::Renderer>
where
@@ -131,14 +131,16 @@ where
self
}
- /// Sets the [`Font`] of the [`ComboBox`].
+ /// Sets the [`Renderer::Font`] of the [`ComboBox`].
+ ///
+ /// [`Renderer::Font`]: text::Renderer
pub fn font(mut self, font: Renderer::Font) -> Self {
self.text_input = self.text_input.font(font);
self.font = Some(font);
self
}
- /// Sets the [`Icon`] of the [`ComboBox`].
+ /// Sets the [`text_input::Icon`] of the [`ComboBox`].
pub fn icon(mut self, icon: text_input::Icon<Renderer::Font>) -> Self {
self.text_input = self.text_input.icon(icon);
self
diff --git a/widget/src/helpers.rs b/widget/src/helpers.rs
index c885d724..3c9c2b29 100644
--- a/widget/src/helpers.rs
+++ b/widget/src/helpers.rs
@@ -26,7 +26,7 @@ use std::ops::RangeInclusive;
/// Creates a [`Column`] with the given children.
///
-/// [`Column`]: widget::Column
+/// [`Column`]: crate::Column
#[macro_export]
macro_rules! column {
() => (
@@ -39,7 +39,7 @@ macro_rules! column {
/// Creates a [`Row`] with the given children.
///
-/// [`Row`]: widget::Row
+/// [`Row`]: crate::Row
#[macro_export]
macro_rules! row {
() => (
@@ -52,7 +52,7 @@ macro_rules! row {
/// Creates a new [`Container`] with the provided content.
///
-/// [`Container`]: widget::Container
+/// [`Container`]: crate::Container
pub fn container<'a, Message, Renderer>(
content: impl Into<Element<'a, Message, Renderer>>,
) -> Container<'a, Message, Renderer>
@@ -82,7 +82,7 @@ where
/// Creates a new [`Row`] with the given children.
///
-/// [`Row`]: widget::Row
+/// [`Row`]: crate::Row
pub fn row<Message, Renderer>(
children: Vec<Element<'_, Message, Renderer>>,
) -> Row<'_, Message, Renderer> {
@@ -91,7 +91,7 @@ pub fn row<Message, Renderer>(
/// Creates a new [`Scrollable`] with the provided content.
///
-/// [`Scrollable`]: widget::Scrollable
+/// [`Scrollable`]: crate::Scrollable
pub fn scrollable<'a, Message, Renderer>(
content: impl Into<Element<'a, Message, Renderer>>,
) -> Scrollable<'a, Message, Renderer>
@@ -104,7 +104,7 @@ where
/// Creates a new [`Button`] with the provided content.
///
-/// [`Button`]: widget::Button
+/// [`Button`]: crate::Button
pub fn button<'a, Message, Renderer>(
content: impl Into<Element<'a, Message, Renderer>>,
) -> Button<'a, Message, Renderer>
@@ -118,8 +118,8 @@ where
/// Creates a new [`Tooltip`] with the provided content, tooltip text, and [`tooltip::Position`].
///
-/// [`Tooltip`]: widget::Tooltip
-/// [`tooltip::Position`]: widget::tooltip::Position
+/// [`Tooltip`]: crate::Tooltip
+/// [`tooltip::Position`]: crate::tooltip::Position
pub fn tooltip<'a, Message, Renderer>(
content: impl Into<Element<'a, Message, Renderer>>,
tooltip: impl ToString,
@@ -134,7 +134,7 @@ where
/// Creates a new [`Text`] widget with the provided content.
///
-/// [`Text`]: widget::Text
+/// [`Text`]: core::widget::Text
pub fn text<'a, Renderer>(text: impl ToString) -> Text<'a, Renderer>
where
Renderer: core::text::Renderer,
@@ -145,7 +145,7 @@ where
/// Creates a new [`Checkbox`].
///
-/// [`Checkbox`]: widget::Checkbox
+/// [`Checkbox`]: crate::Checkbox
pub fn checkbox<'a, Message, Renderer>(
label: impl Into<String>,
is_checked: bool,
@@ -160,7 +160,7 @@ where
/// Creates a new [`Radio`].
///
-/// [`Radio`]: widget::Radio
+/// [`Radio`]: crate::Radio
pub fn radio<Message, Renderer, V>(
label: impl Into<String>,
value: V,
@@ -178,7 +178,7 @@ where
/// Creates a new [`Toggler`].
///
-/// [`Toggler`]: widget::Toggler
+/// [`Toggler`]: crate::Toggler
pub fn toggler<'a, Message, Renderer>(
label: impl Into<Option<String>>,
is_checked: bool,
@@ -193,7 +193,7 @@ where
/// Creates a new [`TextInput`].
///
-/// [`TextInput`]: widget::TextInput
+/// [`TextInput`]: crate::TextInput
pub fn text_input<'a, Message, Renderer>(
placeholder: &str,
value: &str,
@@ -208,7 +208,7 @@ where
/// Creates a new [`Slider`].
///
-/// [`Slider`]: widget::Slider
+/// [`Slider`]: crate::Slider
pub fn slider<'a, T, Message, Renderer>(
range: std::ops::RangeInclusive<T>,
value: T,
@@ -225,7 +225,7 @@ where
/// Creates a new [`VerticalSlider`].
///
-/// [`VerticalSlider`]: widget::VerticalSlider
+/// [`VerticalSlider`]: crate::VerticalSlider
pub fn vertical_slider<'a, T, Message, Renderer>(
range: std::ops::RangeInclusive<T>,
value: T,
@@ -242,7 +242,7 @@ where
/// Creates a new [`PickList`].
///
-/// [`PickList`]: widget::PickList
+/// [`PickList`]: crate::PickList
pub fn pick_list<'a, Message, Renderer, T>(
options: impl Into<Cow<'a, [T]>>,
selected: Option<T>,
@@ -264,7 +264,7 @@ where
/// Creates a new [`ComboBox`].
///
-/// [`ComboBox`]: widget::ComboBox
+/// [`ComboBox`]: crate::ComboBox
pub fn combo_box<'a, T, Message, Renderer>(
state: &'a combo_box::State<T>,
placeholder: &str,
@@ -281,21 +281,21 @@ where
/// Creates a new horizontal [`Space`] with the given [`Length`].
///
-/// [`Space`]: widget::Space
+/// [`Space`]: crate::Space
pub fn horizontal_space(width: impl Into<Length>) -> Space {
Space::with_width(width)
}
/// Creates a new vertical [`Space`] with the given [`Length`].
///
-/// [`Space`]: widget::Space
+/// [`Space`]: crate::Space
pub fn vertical_space(height: impl Into<Length>) -> Space {
Space::with_height(height)
}
/// Creates a horizontal [`Rule`] with the given height.
///
-/// [`Rule`]: widget::Rule
+/// [`Rule`]: crate::Rule
pub fn horizontal_rule<Renderer>(height: impl Into<Pixels>) -> Rule<Renderer>
where
Renderer: core::Renderer,
@@ -306,7 +306,7 @@ where
/// Creates a vertical [`Rule`] with the given width.
///
-/// [`Rule`]: widget::Rule
+/// [`Rule`]: crate::Rule
pub fn vertical_rule<Renderer>(width: impl Into<Pixels>) -> Rule<Renderer>
where
Renderer: core::Renderer,
@@ -321,7 +321,7 @@ where
/// * an inclusive range of possible values, and
/// * the current value of the [`ProgressBar`].
///
-/// [`ProgressBar`]: widget::ProgressBar
+/// [`ProgressBar`]: crate::ProgressBar
pub fn progress_bar<Renderer>(
range: RangeInclusive<f32>,
value: f32,
@@ -335,7 +335,7 @@ where
/// Creates a new [`Image`].
///
-/// [`Image`]: widget::Image
+/// [`Image`]: crate::Image
#[cfg(feature = "image")]
pub fn image<Handle>(handle: impl Into<Handle>) -> crate::Image<Handle> {
crate::Image::new(handle.into())
@@ -343,8 +343,8 @@ pub fn image<Handle>(handle: impl Into<Handle>) -> crate::Image<Handle> {
/// Creates a new [`Svg`] widget from the given [`Handle`].
///
-/// [`Svg`]: widget::Svg
-/// [`Handle`]: widget::svg::Handle
+/// [`Svg`]: crate::Svg
+/// [`Handle`]: crate::svg::Handle
#[cfg(feature = "svg")]
pub fn svg<Renderer>(
handle: impl Into<core::svg::Handle>,
@@ -357,6 +357,8 @@ where
}
/// Creates a new [`Canvas`].
+///
+/// [`Canvas`]: crate::Canvas
#[cfg(feature = "canvas")]
pub fn canvas<P, Message, Renderer>(
program: P,
diff --git a/widget/src/lib.rs b/widget/src/lib.rs
index 707fec04..7e204171 100644
--- a/widget/src/lib.rs
+++ b/widget/src/lib.rs
@@ -2,6 +2,7 @@
#![doc(
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
)]
+#![forbid(unsafe_code, rust_2018_idioms)]
#![deny(
missing_debug_implementations,
missing_docs,
@@ -10,9 +11,9 @@
clippy::from_over_into,
clippy::needless_borrow,
clippy::new_without_default,
- clippy::useless_conversion
+ clippy::useless_conversion,
+ rustdoc::broken_intra_doc_links
)]
-#![forbid(unsafe_code, rust_2018_idioms)]
#![allow(clippy::inherent_to_string, clippy::type_complexity)]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
pub use iced_renderer as renderer;
diff --git a/widget/src/overlay/menu.rs b/widget/src/overlay/menu.rs
index 5a2e1bf0..b293f9fa 100644
--- a/widget/src/overlay/menu.rs
+++ b/widget/src/overlay/menu.rs
@@ -89,7 +89,7 @@ where
self
}
- /// Sets the text [`LineHeight`] of the [`Menu`].
+ /// Sets the text [`text::LineHeight`] of the [`Menu`].
pub fn text_line_height(
mut self,
line_height: impl Into<text::LineHeight>,
diff --git a/widget/src/pane_grid.rs b/widget/src/pane_grid.rs
index 6e2b39a4..f868a648 100644
--- a/widget/src/pane_grid.rs
+++ b/widget/src/pane_grid.rs
@@ -1,6 +1,6 @@
//! Let your users split regions of your application and organize layout dynamically.
//!
-//! [![Pane grid - Iced](https://thumbs.gfycat.com/MixedFlatJellyfish-small.gif)](https://gfycat.com/mixedflatjellyfish)
+//! ![Pane grid - Iced](https://iced.rs/examples/pane_grid.gif)
//!
//! # Example
//! The [`pane_grid` example] showcases how to use a [`PaneGrid`] with resizing,
@@ -49,7 +49,7 @@ use crate::core::{
/// A collection of panes distributed using either vertical or horizontal splits
/// to completely fill the space available.
///
-/// [![Pane grid - Iced](https://thumbs.gfycat.com/FrailFreshAiredaleterrier-small.gif)](https://gfycat.com/frailfreshairedaleterrier)
+/// ![Pane grid - Iced](https://iced.rs/examples/pane_grid.gif)
///
/// This distribution of space is common in tiling window managers (like
/// [`awesome`](https://awesomewm.org/), [`i3`](https://i3wm.org/), or even
diff --git a/widget/src/pane_grid/configuration.rs b/widget/src/pane_grid/configuration.rs
index ddbc3bc2..b8aa2c7d 100644
--- a/widget/src/pane_grid/configuration.rs
+++ b/widget/src/pane_grid/configuration.rs
@@ -2,7 +2,7 @@ use crate::pane_grid::Axis;
/// The arrangement of a [`PaneGrid`].
///
-/// [`PaneGrid`]: crate::widget::PaneGrid
+/// [`PaneGrid`]: super::PaneGrid
#[derive(Debug, Clone)]
pub enum Configuration<T> {
/// A split of the available space.
@@ -21,6 +21,6 @@ pub enum Configuration<T> {
},
/// A [`Pane`].
///
- /// [`Pane`]: crate::widget::pane_grid::Pane
+ /// [`Pane`]: super::Pane
Pane(T),
}
diff --git a/widget/src/pane_grid/content.rs b/widget/src/pane_grid/content.rs
index 5dbc5496..826ea663 100644
--- a/widget/src/pane_grid/content.rs
+++ b/widget/src/pane_grid/content.rs
@@ -10,7 +10,7 @@ use crate::pane_grid::{Draggable, TitleBar};
/// The content of a [`Pane`].
///
-/// [`Pane`]: crate::widget::pane_grid::Pane
+/// [`Pane`]: super::Pane
#[allow(missing_debug_implementations)]
pub struct Content<'a, Message, Renderer = crate::Renderer>
where
@@ -87,7 +87,7 @@ where
/// Draws the [`Content`] with the provided [`Renderer`] and [`Layout`].
///
- /// [`Renderer`]: crate::Renderer
+ /// [`Renderer`]: crate::core::Renderer
pub fn draw(
&self,
tree: &Tree,
diff --git a/widget/src/pane_grid/node.rs b/widget/src/pane_grid/node.rs
index 6de5920f..3c707f15 100644
--- a/widget/src/pane_grid/node.rs
+++ b/widget/src/pane_grid/node.rs
@@ -5,7 +5,7 @@ use std::collections::BTreeMap;
/// A layout node of a [`PaneGrid`].
///
-/// [`PaneGrid`]: crate::widget::PaneGrid
+/// [`PaneGrid`]: super::PaneGrid
#[derive(Debug, Clone)]
pub enum Node {
/// The region of this [`Node`] is split into two.
diff --git a/widget/src/pane_grid/pane.rs b/widget/src/pane_grid/pane.rs
index d6fbab83..cabf55c1 100644
--- a/widget/src/pane_grid/pane.rs
+++ b/widget/src/pane_grid/pane.rs
@@ -1,5 +1,5 @@
/// A rectangular region in a [`PaneGrid`] used to display widgets.
///
-/// [`PaneGrid`]: crate::widget::PaneGrid
+/// [`PaneGrid`]: super::PaneGrid
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Pane(pub(super) usize);
diff --git a/widget/src/pane_grid/split.rs b/widget/src/pane_grid/split.rs
index 8132272a..ce021978 100644
--- a/widget/src/pane_grid/split.rs
+++ b/widget/src/pane_grid/split.rs
@@ -1,5 +1,5 @@
/// A divider that splits a region in a [`PaneGrid`] into two different panes.
///
-/// [`PaneGrid`]: crate::widget::PaneGrid
+/// [`PaneGrid`]: super::PaneGrid
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Split(pub(super) usize);
diff --git a/widget/src/pane_grid/state.rs b/widget/src/pane_grid/state.rs
index 6fd15890..28a52cf0 100644
--- a/widget/src/pane_grid/state.rs
+++ b/widget/src/pane_grid/state.rs
@@ -1,6 +1,6 @@
//! The state of a [`PaneGrid`].
//!
-//! [`PaneGrid`]: crate::widget::PaneGrid
+//! [`PaneGrid`]: super::PaneGrid
use crate::core::{Point, Size};
use crate::pane_grid::{
Axis, Configuration, Direction, Edge, Node, Pane, Region, Split, Target,
@@ -18,23 +18,23 @@ use std::collections::HashMap;
/// provided to the view function of [`PaneGrid::new`] for displaying each
/// [`Pane`].
///
-/// [`PaneGrid`]: crate::widget::PaneGrid
-/// [`PaneGrid::new`]: crate::widget::PaneGrid::new
+/// [`PaneGrid`]: super::PaneGrid
+/// [`PaneGrid::new`]: super::PaneGrid::new
#[derive(Debug, Clone)]
pub struct State<T> {
/// The panes of the [`PaneGrid`].
///
- /// [`PaneGrid`]: crate::widget::PaneGrid
+ /// [`PaneGrid`]: super::PaneGrid
pub panes: HashMap<Pane, T>,
/// The internal state of the [`PaneGrid`].
///
- /// [`PaneGrid`]: crate::widget::PaneGrid
+ /// [`PaneGrid`]: super::PaneGrid
pub internal: Internal,
/// The maximized [`Pane`] of the [`PaneGrid`].
///
- /// [`PaneGrid`]: crate::widget::PaneGrid
+ /// [`PaneGrid`]: super::PaneGrid
pub(super) maximized: Option<Pane>,
}
@@ -236,6 +236,8 @@ impl<T> State<T> {
}
/// Move [`Pane`] to an [`Edge`] of the [`PaneGrid`].
+ ///
+ /// [`PaneGrid`]: super::PaneGrid
pub fn move_to_edge(&mut self, pane: &Pane, edge: Edge) {
match edge {
Edge::Top => {
@@ -269,8 +271,8 @@ impl<T> State<T> {
/// If you want to swap panes on drag and drop in your [`PaneGrid`], you
/// will need to call this method when handling a [`DragEvent`].
///
- /// [`PaneGrid`]: crate::widget::PaneGrid
- /// [`DragEvent`]: crate::widget::pane_grid::DragEvent
+ /// [`PaneGrid`]: super::PaneGrid
+ /// [`DragEvent`]: super::DragEvent
pub fn swap(&mut self, a: &Pane, b: &Pane) {
self.internal.layout.update(&|node| match node {
Node::Split { .. } => {}
@@ -292,8 +294,8 @@ impl<T> State<T> {
/// If you want to enable resize interactions in your [`PaneGrid`], you will
/// need to call this method when handling a [`ResizeEvent`].
///
- /// [`PaneGrid`]: crate::widget::PaneGrid
- /// [`ResizeEvent`]: crate::widget::pane_grid::ResizeEvent
+ /// [`PaneGrid`]: super::PaneGrid
+ /// [`ResizeEvent`]: super::ResizeEvent
pub fn resize(&mut self, split: &Split, ratio: f32) {
let _ = self.internal.layout.resize(split, ratio);
}
@@ -315,7 +317,7 @@ impl<T> State<T> {
/// Maximize the given [`Pane`]. Only this pane will be rendered by the
/// [`PaneGrid`] until [`Self::restore()`] is called.
///
- /// [`PaneGrid`]: crate::widget::PaneGrid
+ /// [`PaneGrid`]: super::PaneGrid
pub fn maximize(&mut self, pane: &Pane) {
self.maximized = Some(*pane);
}
@@ -323,14 +325,14 @@ impl<T> State<T> {
/// Restore the currently maximized [`Pane`] to it's normal size. All panes
/// will be rendered by the [`PaneGrid`].
///
- /// [`PaneGrid`]: crate::widget::PaneGrid
+ /// [`PaneGrid`]: super::PaneGrid
pub fn restore(&mut self) {
let _ = self.maximized.take();
}
/// Returns the maximized [`Pane`] of the [`PaneGrid`].
///
- /// [`PaneGrid`]: crate::widget::PaneGrid
+ /// [`PaneGrid`]: super::PaneGrid
pub fn maximized(&self) -> Option<Pane> {
self.maximized
}
@@ -338,7 +340,7 @@ impl<T> State<T> {
/// The internal state of a [`PaneGrid`].
///
-/// [`PaneGrid`]: crate::widget::PaneGrid
+/// [`PaneGrid`]: super::PaneGrid
#[derive(Debug, Clone)]
pub struct Internal {
layout: Node,
@@ -349,7 +351,7 @@ impl Internal {
/// Initializes the [`Internal`] state of a [`PaneGrid`] from a
/// [`Configuration`].
///
- /// [`PaneGrid`]: crate::widget::PaneGrid
+ /// [`PaneGrid`]: super::PaneGrid
pub fn from_configuration<T>(
panes: &mut HashMap<Pane, T>,
content: Configuration<T>,
@@ -394,16 +396,16 @@ impl Internal {
/// The current action of a [`PaneGrid`].
///
-/// [`PaneGrid`]: crate::widget::PaneGrid
+/// [`PaneGrid`]: super::PaneGrid
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Action {
/// The [`PaneGrid`] is idle.
///
- /// [`PaneGrid`]: crate::widget::PaneGrid
+ /// [`PaneGrid`]: super::PaneGrid
Idle,
/// A [`Pane`] in the [`PaneGrid`] is being dragged.
///
- /// [`PaneGrid`]: crate::widget::PaneGrid
+ /// [`PaneGrid`]: super::PaneGrid
Dragging {
/// The [`Pane`] being dragged.
pane: Pane,
@@ -412,7 +414,7 @@ pub enum Action {
},
/// A [`Split`] in the [`PaneGrid`] is being dragged.
///
- /// [`PaneGrid`]: crate::widget::PaneGrid
+ /// [`PaneGrid`]: super::PaneGrid
Resizing {
/// The [`Split`] being dragged.
split: Split,
diff --git a/widget/src/pane_grid/title_bar.rs b/widget/src/pane_grid/title_bar.rs
index 8a4523e8..5ae7a6a0 100644
--- a/widget/src/pane_grid/title_bar.rs
+++ b/widget/src/pane_grid/title_bar.rs
@@ -11,7 +11,7 @@ use crate::core::{
/// The title bar of a [`Pane`].
///
-/// [`Pane`]: crate::widget::pane_grid::Pane
+/// [`Pane`]: super::Pane
#[allow(missing_debug_implementations)]
pub struct TitleBar<'a, Message, Renderer = crate::Renderer>
where
@@ -75,7 +75,7 @@ where
/// [`TitleBar`] is hovered.
///
/// [`controls`]: Self::controls
- /// [`Pane`]: crate::widget::pane_grid::Pane
+ /// [`Pane`]: super::Pane
pub fn always_show_controls(mut self) -> Self {
self.always_show_controls = true;
self
@@ -114,7 +114,7 @@ where
/// Draws the [`TitleBar`] with the provided [`Renderer`] and [`Layout`].
///
- /// [`Renderer`]: crate::Renderer
+ /// [`Renderer`]: crate::core::Renderer
pub fn draw(
&self,
tree: &Tree,
diff --git a/widget/src/pick_list.rs b/widget/src/pick_list.rs
index 8feb1788..056a5e65 100644
--- a/widget/src/pick_list.rs
+++ b/widget/src/pick_list.rs
@@ -105,7 +105,7 @@ where
self
}
- /// Sets the text [`LineHeight`] of the [`PickList`].
+ /// Sets the text [`text::LineHeight`] of the [`PickList`].
pub fn text_line_height(
mut self,
line_height: impl Into<text::LineHeight>,
diff --git a/widget/src/qr_code.rs b/widget/src/qr_code.rs
index d176021d..1dc4da7f 100644
--- a/widget/src/qr_code.rs
+++ b/widget/src/qr_code.rs
@@ -87,7 +87,7 @@ impl<'a, Message, Theme> Widget<Message, Renderer<Theme>> for QRCode<'a> {
let geometry =
self.state.cache.draw(renderer, bounds.size(), |frame| {
// Scale units to cell size
- frame.scale(f32::from(self.cell_size));
+ frame.scale(self.cell_size);
// Draw background
frame.fill_rectangle(
diff --git a/widget/src/radio.rs b/widget/src/radio.rs
index a85dad63..57acc033 100644
--- a/widget/src/radio.rs
+++ b/widget/src/radio.rs
@@ -156,7 +156,7 @@ where
self
}
- /// Sets the text [`LineHeight`] of the [`Radio`] button.
+ /// Sets the text [`text::LineHeight`] of the [`Radio`] button.
pub fn text_line_height(
mut self,
line_height: impl Into<text::LineHeight>,
diff --git a/widget/src/scrollable.rs b/widget/src/scrollable.rs
index 5decfd9d..def28821 100644
--- a/widget/src/scrollable.rs
+++ b/widget/src/scrollable.rs
@@ -1151,6 +1151,16 @@ impl Viewport {
RelativeOffset { x, y }
}
+
+ /// Returns the bounds of the current [`Viewport`].
+ pub fn bounds(&self) -> Rectangle {
+ self.bounds
+ }
+
+ /// Returns the content bounds of the current [`Viewport`].
+ pub fn content_bounds(&self) -> Rectangle {
+ self.content_bounds
+ }
}
impl State {
diff --git a/widget/src/slider.rs b/widget/src/slider.rs
index a9727aa3..2c4a2913 100644
--- a/widget/src/slider.rs
+++ b/widget/src/slider.rs
@@ -137,8 +137,8 @@ where
}
/// Sets the step size of the [`Slider`].
- pub fn step(mut self, step: T) -> Self {
- self.step = step;
+ pub fn step(mut self, step: impl Into<T>) -> Self {
+ self.step = step.into();
self
}
}
diff --git a/widget/src/text_input.rs b/widget/src/text_input.rs
index aa35b5e4..bfd196fd 100644
--- a/widget/src/text_input.rs
+++ b/widget/src/text_input.rs
@@ -182,7 +182,7 @@ where
self
}
- /// Sets the [`LineHeight`] of the [`TextInput`].
+ /// Sets the [`text::LineHeight`] of the [`TextInput`].
pub fn line_height(
mut self,
line_height: impl Into<text::LineHeight>,
diff --git a/widget/src/text_input/value.rs b/widget/src/text_input/value.rs
index cf4da562..d1b056c8 100644
--- a/widget/src/text_input/value.rs
+++ b/widget/src/text_input/value.rs
@@ -2,7 +2,7 @@ use unicode_segmentation::UnicodeSegmentation;
/// The value of a [`TextInput`].
///
-/// [`TextInput`]: crate::widget::TextInput
+/// [`TextInput`]: super::TextInput
// TODO: Reduce allocations, cache results (?)
#[derive(Debug, Clone)]
pub struct Value {
diff --git a/widget/src/toggler.rs b/widget/src/toggler.rs
index acb9b25d..2440317f 100644
--- a/widget/src/toggler.rs
+++ b/widget/src/toggler.rs
@@ -109,7 +109,7 @@ where
self
}
- /// Sets the text [`LineHeight`] of the [`Toggler`].
+ /// Sets the text [`text::LineHeight`] of the [`Toggler`].
pub fn text_line_height(
mut self,
line_height: impl Into<text::LineHeight>,
@@ -136,9 +136,9 @@ where
self
}
- /// Sets the [`Font`] of the text of the [`Toggler`]
+ /// Sets the [`Renderer::Font`] of the text of the [`Toggler`]
///
- /// [`Font`]: crate::text::Renderer::Font
+ /// [`Renderer::Font`]: crate::core::text::Renderer
pub fn font(mut self, font: impl Into<Renderer::Font>) -> Self {
self.font = Some(font.into());
self
diff --git a/winit/Cargo.toml b/winit/Cargo.toml
index 67216147..674a66d3 100644
--- a/winit/Cargo.toml
+++ b/winit/Cargo.toml
@@ -1,19 +1,17 @@
[package]
name = "iced_winit"
-version = "0.10.0"
-authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]
-edition = "2021"
-description = "A winit runtime for Iced"
-license = "MIT"
-repository = "https://github.com/iced-rs/iced"
-documentation = "https://docs.rs/iced_winit"
-keywords = ["gui", "ui", "graphics", "interface", "widgets"]
-categories = ["gui"]
+description = "A runtime for iced on top of winit"
+version.workspace = true
+edition.workspace = true
+authors.workspace = true
+license.workspace = true
+repository.workspace = true
+homepage.workspace = true
+categories.workspace = true
+keywords.workspace = true
[features]
default = ["x11", "wayland", "wayland-dlopen", "wayland-csd-adwaita"]
-trace = ["tracing", "tracing-core", "tracing-subscriber"]
-chrome-trace = ["trace", "tracing-chrome"]
debug = ["iced_runtime/debug"]
system = ["sysinfo"]
application = []
@@ -23,54 +21,23 @@ wayland-dlopen = ["winit/wayland-dlopen"]
wayland-csd-adwaita = ["winit/wayland-csd-adwaita"]
[dependencies]
-window_clipboard = "0.3"
-log = "0.4"
-thiserror = "1.0"
-raw-window-handle = "0.5"
-
-[dependencies.winit]
-version = "0.28"
-git = "https://github.com/iced-rs/winit.git"
-rev = "c52db2045d0a2f1b8d9923870de1d4ab1994146e"
-default-features = false
-
-[dependencies.iced_runtime]
-version = "0.1"
-path = "../runtime"
-
-[dependencies.iced_graphics]
-version = "0.9"
-path = "../graphics"
-
-[dependencies.iced_style]
-version = "0.9"
-path = "../style"
-
-[dependencies.tracing]
-version = "0.1.37"
-optional = true
-features = ["std"]
-
-[dependencies.tracing-core]
-version = "0.1.30"
-optional = true
-
-[dependencies.tracing-subscriber]
-version = "0.3.16"
-optional = true
-features = ["registry"]
-
-[dependencies.tracing-chrome]
-version = "0.7.0"
-optional = true
-
-[target.'cfg(target_os = "windows")'.dependencies.winapi]
-version = "0.3.6"
-
-[target.'cfg(target_arch = "wasm32")'.dependencies.web-sys]
-version = "0.3"
-features = ["Document", "Window"]
-
-[dependencies.sysinfo]
-version = "0.28"
-optional = true
+iced_graphics.workspace = true
+iced_runtime.workspace = true
+iced_style.workspace = true
+
+log.workspace = true
+raw-window-handle.workspace = true
+thiserror.workspace = true
+tracing.workspace = true
+window_clipboard.workspace = true
+winit.workspace = true
+
+sysinfo.workspace = true
+sysinfo.optional = true
+
+[target.'cfg(target_os = "windows")'.dependencies]
+winapi.workspace = true
+
+[target.'cfg(target_arch = "wasm32")'.dependencies]
+web-sys.workspace = true
+web-sys.features = ["Document", "Window"]
diff --git a/winit/src/application/state.rs b/winit/src/application/state.rs
index 967f43f2..e655529a 100644
--- a/winit/src/application/state.rs
+++ b/winit/src/application/state.rs
@@ -184,9 +184,7 @@ where
/// window.
///
/// Normally an [`Application`] should be synchronized with its [`State`]
- /// and window after calling [`Application::update`].
- ///
- /// [`Application::update`]: crate::Program::update
+ /// and window after calling [`crate::application::update`].
pub fn synchronize(&mut self, application: &A, window: &Window) {
// Update window title
let new_title = application.title();
diff --git a/winit/src/conversion.rs b/winit/src/conversion.rs
index b2398e62..3ecd044c 100644
--- a/winit/src/conversion.rs
+++ b/winit/src/conversion.rs
@@ -521,7 +521,7 @@ pub fn user_attention(
}
}
-/// Converts some [`Icon`] into it's `winit` counterpart.
+/// Converts some [`window::Icon`] into it's `winit` counterpart.
///
/// Returns `None` if there is an error during the conversion.
pub fn icon(icon: window::Icon) -> Option<winit::window::Icon> {
diff --git a/winit/src/lib.rs b/winit/src/lib.rs
index 1a87ca11..9852a182 100644
--- a/winit/src/lib.rs
+++ b/winit/src/lib.rs
@@ -17,6 +17,7 @@
#![doc(
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
)]
+#![forbid(rust_2018_idioms)]
#![deny(
missing_debug_implementations,
missing_docs,
@@ -26,9 +27,9 @@
clippy::needless_borrow,
clippy::new_without_default,
clippy::useless_conversion,
- unsafe_code
+ unsafe_code,
+ rustdoc::broken_intra_doc_links
)]
-#![forbid(rust_2018_idioms)]
#![allow(clippy::inherent_to_string, clippy::type_complexity)]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
pub use iced_graphics as graphics;