├── .cargo └── config.toml ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── BUG-REPORT.yml │ └── config.yml ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── audit.yml │ ├── build.yml │ ├── check.yml │ ├── document.yml │ ├── format.yml │ ├── lint.yml │ └── test.yml ├── .gitignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Cargo.lock ├── Cargo.toml ├── Cross.toml ├── DEPENDENCIES.md ├── LICENSE ├── README.md ├── ROADMAP.md ├── beacon ├── Cargo.toml └── src │ ├── client.rs │ ├── error.rs │ ├── lib.rs │ ├── span.rs │ └── stream.rs ├── benches ├── ipsum.txt └── wgpu.rs ├── clippy.toml ├── core ├── Cargo.toml ├── README.md └── src │ ├── alignment.rs │ ├── angle.rs │ ├── animation.rs │ ├── background.rs │ ├── border.rs │ ├── clipboard.rs │ ├── color.rs │ ├── content_fit.rs │ ├── element.rs │ ├── event.rs │ ├── font.rs │ ├── gradient.rs │ ├── hasher.rs │ ├── image.rs │ ├── input_method.rs │ ├── keyboard.rs │ ├── keyboard │ ├── event.rs │ ├── key.rs │ ├── location.rs │ └── modifiers.rs │ ├── layout.rs │ ├── layout │ ├── DRUID_LICENSE │ ├── flex.rs │ ├── limits.rs │ └── node.rs │ ├── length.rs │ ├── lib.rs │ ├── mouse.rs │ ├── mouse │ ├── button.rs │ ├── click.rs │ ├── cursor.rs │ ├── event.rs │ └── interaction.rs │ ├── overlay.rs │ ├── overlay │ ├── element.rs │ └── group.rs │ ├── padding.rs │ ├── pixels.rs │ ├── point.rs │ ├── rectangle.rs │ ├── renderer.rs │ ├── renderer │ └── null.rs │ ├── rotation.rs │ ├── settings.rs │ ├── shadow.rs │ ├── shell.rs │ ├── size.rs │ ├── svg.rs │ ├── text.rs │ ├── text │ ├── editor.rs │ ├── highlighter.rs │ └── paragraph.rs │ ├── theme.rs │ ├── theme │ └── palette.rs │ ├── time.rs │ ├── touch.rs │ ├── transformation.rs │ ├── vector.rs │ ├── widget.rs │ ├── widget │ ├── id.rs │ ├── operation.rs │ ├── operation │ │ ├── focusable.rs │ │ ├── scrollable.rs │ │ └── text_input.rs │ ├── text.rs │ └── tree.rs │ ├── window.rs │ └── window │ ├── direction.rs │ ├── event.rs │ ├── icon.rs │ ├── id.rs │ ├── level.rs │ ├── mode.rs │ ├── position.rs │ ├── redraw_request.rs │ ├── screenshot.rs │ ├── settings.rs │ ├── settings │ ├── linux.rs │ ├── macos.rs │ ├── other.rs │ ├── wasm.rs │ └── windows.rs │ └── user_attention.rs ├── debug ├── Cargo.toml └── src │ └── lib.rs ├── devtools ├── Cargo.toml └── src │ ├── comet.rs │ ├── executor.rs │ ├── lib.rs │ └── time_machine.rs ├── docs ├── graphs │ ├── ecosystem.png │ ├── foundations.png │ ├── iced.png │ └── native.png ├── images │ ├── checkbox.png │ ├── radio.png │ ├── text.png │ ├── text_input.png │ └── todos_desktop.jpg ├── logo-no-shadow.svg ├── logo.svg ├── redirect.html └── release_summary.py ├── examples ├── README.md ├── arc │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── bezier_tool │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── changelog │ ├── Cargo.toml │ └── src │ │ ├── changelog.rs │ │ ├── icon.rs │ │ └── main.rs ├── checkbox │ ├── Cargo.toml │ ├── README.md │ ├── fonts │ │ └── icons.ttf │ └── src │ │ └── main.rs ├── clock │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── color_palette │ ├── Cargo.toml │ ├── README.md │ ├── screenshot.png │ └── src │ │ └── main.rs ├── combo_box │ ├── Cargo.toml │ ├── README.md │ ├── combobox.gif │ └── src │ │ └── main.rs ├── counter │ ├── Cargo.toml │ ├── README.md │ ├── index.html │ └── src │ │ └── main.rs ├── custom_quad │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── custom_shader │ ├── Cargo.toml │ ├── src │ │ ├── main.rs │ │ ├── scene.rs │ │ ├── scene │ │ │ ├── camera.rs │ │ │ ├── pipeline.rs │ │ │ └── pipeline │ │ │ │ ├── buffer.rs │ │ │ │ ├── cube.rs │ │ │ │ ├── uniforms.rs │ │ │ │ └── vertex.rs │ │ └── shaders │ │ │ ├── cubes.wgsl │ │ │ └── depth.wgsl │ └── textures │ │ ├── ice_cube_normal_map.png │ │ └── skybox │ │ ├── neg_x.jpg │ │ ├── neg_y.jpg │ │ ├── neg_z.jpg │ │ ├── pos_x.jpg │ │ ├── pos_y.jpg │ │ └── pos_z.jpg ├── custom_widget │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── download_progress │ ├── Cargo.toml │ ├── README.md │ ├── index.html │ └── src │ │ ├── download.rs │ │ └── main.rs ├── editor │ ├── Cargo.toml │ ├── fonts │ │ └── icons.ttf │ └── src │ │ └── main.rs ├── events │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── exit │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── ferris │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── gallery │ ├── Cargo.toml │ └── src │ │ ├── civitai.rs │ │ └── main.rs ├── game_of_life │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── main.rs │ │ └── preset.rs ├── geometry │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── gradient │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── integration │ ├── .gitignore │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── controls.rs │ │ ├── main.rs │ │ ├── scene.rs │ │ └── shader │ │ ├── frag.wgsl │ │ └── vert.wgsl ├── layout │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── lazy │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── loading_spinners │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── circular.rs │ │ ├── easing.rs │ │ ├── linear.rs │ │ └── main.rs ├── loupe │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── markdown │ ├── Cargo.toml │ ├── build.rs │ ├── fonts │ │ ├── markdown-icons.toml │ │ └── markdown-icons.ttf │ ├── overview.md │ └── src │ │ ├── icon.rs │ │ └── main.rs ├── modal │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── multi_window │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── multitouch │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── pane_grid │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── pick_list │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── pokedex │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── progress_bar │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── qr_code │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── screenshot │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── scrollable │ ├── Cargo.toml │ ├── README.md │ ├── screenshot.png │ └── src │ │ └── main.rs ├── sierpinski_triangle │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── slider │ ├── Cargo.toml │ ├── README.md │ ├── sliders.gif │ └── src │ │ └── main.rs ├── solar_system │ ├── Cargo.toml │ ├── README.md │ ├── assets │ │ ├── earth.png │ │ ├── moon.png │ │ └── sun.png │ └── src │ │ └── main.rs ├── stopwatch │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── styling │ ├── Cargo.toml │ ├── README.md │ ├── snapshots │ │ ├── catppuccin_frappé-tiny-skia.sha256 │ │ ├── catppuccin_latte-tiny-skia.sha256 │ │ ├── catppuccin_macchiato-tiny-skia.sha256 │ │ ├── catppuccin_mocha-tiny-skia.sha256 │ │ ├── dark-tiny-skia.sha256 │ │ ├── dracula-tiny-skia.sha256 │ │ ├── ferra-tiny-skia.sha256 │ │ ├── gruvbox_dark-tiny-skia.sha256 │ │ ├── gruvbox_light-tiny-skia.sha256 │ │ ├── kanagawa_dragon-tiny-skia.sha256 │ │ ├── kanagawa_lotus-tiny-skia.sha256 │ │ ├── kanagawa_wave-tiny-skia.sha256 │ │ ├── light-tiny-skia.sha256 │ │ ├── moonfly-tiny-skia.sha256 │ │ ├── nightfly-tiny-skia.sha256 │ │ ├── nord-tiny-skia.sha256 │ │ ├── oxocarbon-tiny-skia.sha256 │ │ ├── solarized_dark-tiny-skia.sha256 │ │ ├── solarized_light-tiny-skia.sha256 │ │ ├── tokyo_night-tiny-skia.sha256 │ │ ├── tokyo_night_light-tiny-skia.sha256 │ │ └── tokyo_night_storm-tiny-skia.sha256 │ └── src │ │ └── main.rs ├── svg │ ├── Cargo.toml │ ├── README.md │ ├── resources │ │ └── tiger.svg │ └── src │ │ └── main.rs ├── system_information │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── the_matrix │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── toast │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── todos │ ├── Cargo.toml │ ├── README.md │ ├── fonts │ │ └── icons.ttf │ ├── iced-todos.desktop │ ├── index.html │ ├── snapshots │ │ ├── creates_a_new_task-tiny-skia.sha256 │ │ └── creates_a_new_task-wgpu.sha256 │ └── src │ │ └── main.rs ├── tooltip │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── tour │ ├── Cargo.toml │ ├── README.md │ ├── images │ │ └── ferris.png │ ├── index.html │ └── src │ │ └── main.rs ├── url_handler │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── vectorial_text │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── visible_bounds │ ├── Cargo.toml │ └── src │ │ └── main.rs └── websocket │ ├── Cargo.toml │ ├── README.md │ └── src │ ├── echo.rs │ ├── echo │ └── server.rs │ └── main.rs ├── futures ├── Cargo.toml └── src │ ├── backend.rs │ ├── backend │ ├── default.rs │ ├── native.rs │ ├── native │ │ ├── smol.rs │ │ ├── thread_pool.rs │ │ └── tokio.rs │ ├── null.rs │ ├── wasm.rs │ └── wasm │ │ └── wasm_bindgen.rs │ ├── event.rs │ ├── executor.rs │ ├── keyboard.rs │ ├── lib.rs │ ├── maybe.rs │ ├── runtime.rs │ ├── stream.rs │ ├── subscription.rs │ └── subscription │ └── tracker.rs ├── graphics ├── Cargo.toml ├── fonts │ ├── FiraSans-Regular.ttf │ └── Iced-Icons.ttf └── src │ ├── antialiasing.rs │ ├── cache.rs │ ├── color.rs │ ├── compositor.rs │ ├── damage.rs │ ├── error.rs │ ├── geometry.rs │ ├── geometry │ ├── cache.rs │ ├── fill.rs │ ├── frame.rs │ ├── path.rs │ ├── path │ │ ├── arc.rs │ │ └── builder.rs │ ├── stroke.rs │ ├── style.rs │ └── text.rs │ ├── gradient.rs │ ├── image.rs │ ├── image │ └── storage.rs │ ├── layer.rs │ ├── lib.rs │ ├── mesh.rs │ ├── settings.rs │ ├── text.rs │ ├── text │ ├── cache.rs │ ├── editor.rs │ └── paragraph.rs │ └── viewport.rs ├── highlighter ├── Cargo.toml └── src │ └── lib.rs ├── program ├── Cargo.toml └── src │ └── lib.rs ├── renderer ├── Cargo.toml └── src │ ├── fallback.rs │ └── lib.rs ├── runtime ├── Cargo.toml ├── README.md └── src │ ├── clipboard.rs │ ├── font.rs │ ├── keyboard.rs │ ├── lib.rs │ ├── overlay.rs │ ├── overlay │ └── nested.rs │ ├── system.rs │ ├── task.rs │ ├── user_interface.rs │ └── window.rs ├── rustfmt.toml ├── src ├── advanced.rs ├── application.rs ├── application │ └── timed.rs ├── daemon.rs ├── error.rs ├── lib.rs ├── time.rs ├── touch.rs ├── window.rs └── window │ └── icon.rs ├── test ├── Cargo.toml └── src │ ├── lib.rs │ └── selector.rs ├── tiny_skia ├── Cargo.toml └── src │ ├── engine.rs │ ├── geometry.rs │ ├── layer.rs │ ├── lib.rs │ ├── primitive.rs │ ├── raster.rs │ ├── settings.rs │ ├── text.rs │ ├── vector.rs │ ├── window.rs │ └── window │ └── compositor.rs ├── wgpu ├── Cargo.toml ├── README.md └── src │ ├── buffer.rs │ ├── color.rs │ ├── engine.rs │ ├── geometry.rs │ ├── image │ ├── atlas.rs │ ├── atlas │ │ ├── allocation.rs │ │ ├── allocator.rs │ │ ├── entry.rs │ │ └── layer.rs │ ├── cache.rs │ ├── mod.rs │ ├── null.rs │ ├── raster.rs │ └── vector.rs │ ├── layer.rs │ ├── lib.rs │ ├── primitive.rs │ ├── quad.rs │ ├── quad │ ├── gradient.rs │ └── solid.rs │ ├── settings.rs │ ├── shader │ ├── blit.wgsl │ ├── color.wgsl │ ├── color │ │ ├── linear_rgb.wgsl │ │ └── oklab.wgsl │ ├── image.wgsl │ ├── quad.wgsl │ ├── quad │ │ ├── gradient.wgsl │ │ └── solid.wgsl │ ├── triangle.wgsl │ ├── triangle │ │ ├── gradient.wgsl │ │ └── solid.wgsl │ └── vertex.wgsl │ ├── text.rs │ ├── triangle.rs │ ├── triangle │ └── msaa.rs │ ├── window.rs │ └── window │ └── compositor.rs ├── widget ├── Cargo.toml ├── assets │ └── iced-logo.svg └── src │ ├── action.rs │ ├── button.rs │ ├── canvas.rs │ ├── canvas │ └── program.rs │ ├── checkbox.rs │ ├── column.rs │ ├── combo_box.rs │ ├── container.rs │ ├── float.rs │ ├── grid.rs │ ├── helpers.rs │ ├── image.rs │ ├── image │ └── viewer.rs │ ├── keyed.rs │ ├── keyed │ └── column.rs │ ├── lazy.rs │ ├── lazy │ ├── cache.rs │ ├── component.rs │ ├── helpers.rs │ └── responsive.rs │ ├── lib.rs │ ├── markdown.rs │ ├── mouse_area.rs │ ├── overlay.rs │ ├── overlay │ └── menu.rs │ ├── pane_grid.rs │ ├── pane_grid │ ├── axis.rs │ ├── configuration.rs │ ├── content.rs │ ├── controls.rs │ ├── direction.rs │ ├── draggable.rs │ ├── node.rs │ ├── pane.rs │ ├── split.rs │ ├── state.rs │ └── title_bar.rs │ ├── pick_list.rs │ ├── pin.rs │ ├── pop.rs │ ├── progress_bar.rs │ ├── qr_code.rs │ ├── radio.rs │ ├── row.rs │ ├── rule.rs │ ├── scrollable.rs │ ├── shader.rs │ ├── shader │ └── program.rs │ ├── slider.rs │ ├── space.rs │ ├── stack.rs │ ├── svg.rs │ ├── text.rs │ ├── text │ └── rich.rs │ ├── text_editor.rs │ ├── text_input.rs │ ├── text_input │ ├── cursor.rs │ ├── editor.rs │ └── value.rs │ ├── themer.rs │ ├── toggler.rs │ ├── tooltip.rs │ └── vertical_slider.rs └── winit ├── Cargo.toml ├── README.md └── src ├── clipboard.rs ├── conversion.rs ├── error.rs ├── lib.rs ├── proxy.rs ├── system.rs ├── window.rs └── window └── state.rs /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [alias] 2 | lint = "clippy --workspace --benches --all-features --no-deps -- -D warnings" 3 | lint-fix = "clippy --fix --allow-dirty --workspace --benches --all-features --no-deps -- -D warnings" 4 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: hecrj 2 | ko_fi: hecrj_ 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: I have a question 4 | url: https://discourse.iced.rs/c/learn/6 5 | about: Ask and learn from others in the Discourse forum. 6 | - name: I want to request a feature or start a discussion 7 | url: https://discourse.iced.rs/c/request-feedback/7 8 | about: Share your idea and gather feedback in the Discourse forum. 9 | - name: I want to chat with other users of the library 10 | url: https://discord.com/invite/3xZJ65GAhd 11 | about: Join the Discord server and get involved with the community! 12 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | The core team is busy and does not have time to mentor nor babysit new contributors. If a member of the core team thinks that reviewing and understanding your work will take more time and effort than writing it from scratch by themselves, your contribution will be dismissed. It is your responsibility to communicate and figure out how to reduce the likelihood of this! 2 | 3 | Read the contributing guidelines for more details: https://github.com/iced-rs/iced/blob/master/CONTRIBUTING.md 4 | -------------------------------------------------------------------------------- /.github/workflows/audit.yml: -------------------------------------------------------------------------------- 1 | name: Audit 2 | on: 3 | push: {} 4 | pull_request: {} 5 | schedule: 6 | - cron: '0 0 * * *' 7 | jobs: 8 | vulnerabilities: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: hecrj/setup-rust-action@v2 12 | - name: Install cargo-audit 13 | run: cargo install cargo-audit 14 | - uses: actions/checkout@master 15 | - name: Resolve dependencies 16 | run: cargo update 17 | - name: Audit vulnerabilities 18 | run: cargo audit 19 | 20 | # artifacts: 21 | # runs-on: ubuntu-latest 22 | # steps: 23 | # - uses: hecrj/setup-rust-action@v2 24 | # - name: Install cargo-outdated 25 | # run: cargo install cargo-outdated 26 | # - uses: actions/checkout@master 27 | # - name: Delete `web-sys` dependency from `integration` example 28 | # run: sed -i '$d' examples/integration/Cargo.toml 29 | # - name: Find outdated dependencies 30 | # run: cargo outdated --workspace --exit-code 1 --ignore raw-window-handle 31 | -------------------------------------------------------------------------------- /.github/workflows/check.yml: -------------------------------------------------------------------------------- 1 | name: Check 2 | on: [push, pull_request] 3 | jobs: 4 | wasm: 5 | runs-on: ubuntu-latest 6 | env: 7 | RUSTFLAGS: --cfg=web_sys_unstable_apis 8 | steps: 9 | - uses: hecrj/setup-rust-action@v2 10 | with: 11 | rust-version: stable 12 | targets: wasm32-unknown-unknown 13 | - uses: actions/checkout@master 14 | - name: Run checks 15 | run: cargo check --package iced --target wasm32-unknown-unknown 16 | - name: Check compilation of `tour` example 17 | run: cargo build --package tour --target wasm32-unknown-unknown 18 | - name: Check compilation of `todos` example 19 | run: cargo build --package todos --target wasm32-unknown-unknown 20 | 21 | widget: 22 | runs-on: ubuntu-latest 23 | steps: 24 | - uses: hecrj/setup-rust-action@v2 25 | - uses: actions/checkout@master 26 | - name: Check standalone `iced_widget` crate 27 | run: cargo check --package iced_widget --features image,svg,canvas 28 | -------------------------------------------------------------------------------- /.github/workflows/document.yml: -------------------------------------------------------------------------------- 1 | name: Document 2 | on: [push, pull_request] 3 | jobs: 4 | all: 5 | runs-on: ubuntu-latest 6 | concurrency: 7 | group: ${{ github.workflow }}-${{ github.ref }} 8 | steps: 9 | - uses: hecrj/setup-rust-action@v2 10 | with: 11 | rust-version: nightly 12 | - uses: actions/checkout@v2 13 | - name: Generate documentation 14 | run: | 15 | RUSTDOCFLAGS="--cfg docsrs" \ 16 | cargo doc --no-deps --all-features \ 17 | -p futures-core \ 18 | -p iced_beacon \ 19 | -p iced_core \ 20 | -p iced_debug \ 21 | -p iced_devtools \ 22 | -p iced_futures \ 23 | -p iced_graphics \ 24 | -p iced_highlighter \ 25 | -p iced_renderer \ 26 | -p iced_runtime \ 27 | -p iced_tiny_skia \ 28 | -p iced_wgpu \ 29 | -p iced_widget \ 30 | -p iced_winit \ 31 | -p iced 32 | - name: Write CNAME file 33 | run: echo 'docs.iced.rs' > ./target/doc/CNAME 34 | - name: Copy redirect file as index.html 35 | run: cp docs/redirect.html target/doc/index.html 36 | - name: Publish documentation 37 | if: github.ref == 'refs/heads/master' 38 | uses: peaceiris/actions-gh-pages@v3 39 | with: 40 | deploy_key: ${{ secrets.DOCS_DEPLOY_KEY }} 41 | external_repository: iced-rs/docs 42 | publish_dir: ./target/doc 43 | -------------------------------------------------------------------------------- /.github/workflows/format.yml: -------------------------------------------------------------------------------- 1 | name: Format 2 | on: [push, pull_request] 3 | jobs: 4 | all: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: hecrj/setup-rust-action@v2 8 | with: 9 | components: rustfmt 10 | - uses: actions/checkout@master 11 | - name: Check format 12 | run: cargo fmt --all -- --check --verbose 13 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | on: [push, pull_request] 3 | jobs: 4 | all: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: hecrj/setup-rust-action@v2 8 | with: 9 | components: clippy 10 | - uses: actions/checkout@master 11 | - name: Install dependencies 12 | run: | 13 | export DEBIAN_FRONTED=noninteractive 14 | sudo apt-get -qq update 15 | sudo apt-get install -y libxkbcommon-dev libgtk-3-dev 16 | - name: Check lints 17 | run: cargo lint 18 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | on: [push, pull_request] 3 | jobs: 4 | all: 5 | runs-on: ${{ matrix.os }} 6 | env: 7 | RUSTFLAGS: --deny warnings 8 | ICED_TEST_BACKEND: tiny-skia 9 | strategy: 10 | matrix: 11 | os: [ubuntu-latest, windows-latest, macOS-latest] 12 | rust: [stable, beta, "1.85"] 13 | steps: 14 | - uses: hecrj/setup-rust-action@v2 15 | with: 16 | rust-version: ${{ matrix.rust }} 17 | - uses: actions/checkout@master 18 | - name: Install dependencies 19 | if: matrix.os == 'ubuntu-latest' 20 | run: | 21 | export DEBIAN_FRONTED=noninteractive 22 | sudo apt-get -qq update 23 | sudo apt-get install -y libxkbcommon-dev libgtk-3-dev 24 | - name: Run tests 25 | run: | 26 | cargo test --verbose --workspace -- --ignored 27 | cargo test --verbose --workspace --all-features -- --ignored 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | pkg/ 3 | **/*.rs.bk 4 | dist/ 5 | traces/ 6 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thank you for considering contributing to Iced! Take a look at [the roadmap] to get an idea of the current state of the library. 4 | 5 | The core team is busy and does not have time to mentor nor babysit new contributors. If a member of the core team thinks that reviewing and understanding your work will take more time and effort than writing it from scratch by themselves, your contribution will be dismissed. It is your responsibility to communicate and figure out how to reduce the likelihood of this! 6 | 7 | The general advice for new contributors is to share your ideas with the community. You can share your ideas and gather feedback in [our Discourse forum]. This is a very important step. It helps to coordinate work, get on the same page, and start building trust. Remember that [Code is the Easy Part] and also [The Hard Parts of Open Source]! 8 | 9 | Once you have started a channel of communication, you must wait until someone from the core team chimes in. If the core team is busy, this can take a long time (maybe months!). Your idea may need a bunch of iteration, or it may turn into something completely different, or it may be completely discarded! You will have to be patient and humble. Remember that open-source is a gift. 10 | 11 | Besides directly writing code, there are many other different ways you can contribute. To name a few: 12 | 13 | - Writing tutorials or blog posts 14 | - Improving the documentation 15 | - Submitting bug reports and use cases 16 | - Sharing, discussing, researching and exploring new ideas or crates 17 | 18 | [the roadmap]: ROADMAP.md 19 | [our Discourse forum]: https://discourse.iced.rs/ 20 | [Code is the Easy Part]: https://youtu.be/DSjbTC-hvqQ?t=1138 21 | [The Hard Parts of Open Source]: https://www.youtube.com/watch?v=o_4EX4dPppA 22 | -------------------------------------------------------------------------------- /Cross.toml: -------------------------------------------------------------------------------- 1 | [target.aarch64-unknown-linux-gnu] 2 | image = "ghcr.io/iced-rs/aarch64:latest" 3 | xargo = false 4 | 5 | [target.armv7-unknown-linux-gnueabihf] 6 | image = "ghcr.io/iced-rs/armv7:latest" 7 | xargo = false 8 | -------------------------------------------------------------------------------- /DEPENDENCIES.md: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | 3 | Iced requires some system dependencies to work, and not 4 | all operating systems come with them installed. 5 | 6 | You can follow the provided instructions for your system to 7 | get them, if your system isn't here, add it! 8 | 9 | ## NixOS 10 | 11 | You can add this `shell.nix` to your project and use it by running `nix-shell`: 12 | 13 | ```nix 14 | { pkgs ? import {} }: 15 | 16 | pkgs.mkShell rec { 17 | buildInputs = with pkgs; [ 18 | expat 19 | fontconfig 20 | freetype 21 | freetype.dev 22 | libGL 23 | pkg-config 24 | xorg.libX11 25 | xorg.libXcursor 26 | xorg.libXi 27 | xorg.libXrandr 28 | wayland 29 | libxkbcommon 30 | ]; 31 | 32 | LD_LIBRARY_PATH = 33 | builtins.foldl' (a: b: "${a}:${b}/lib") "${pkgs.vulkan-loader}/lib" buildInputs; 34 | } 35 | ``` 36 | 37 | Alternatively, you can use this `flake.nix` to create a dev shell, activated by `nix develop`: 38 | 39 | ```nix 40 | { 41 | inputs = { 42 | nixpkgs.url = "nixpkgs/nixos-unstable"; 43 | flake-utils.url = "github:numtide/flake-utils"; 44 | }; 45 | 46 | outputs = { 47 | nixpkgs, 48 | flake-utils, 49 | ... 50 | }: 51 | flake-utils.lib.eachDefaultSystem ( 52 | system: let 53 | pkgs = import nixpkgs { 54 | inherit system; 55 | }; 56 | 57 | buildInputs = with pkgs; [ 58 | expat 59 | fontconfig 60 | freetype 61 | freetype.dev 62 | libGL 63 | pkg-config 64 | xorg.libX11 65 | xorg.libXcursor 66 | xorg.libXi 67 | xorg.libXrandr 68 | wayland 69 | libxkbcommon 70 | ]; 71 | in { 72 | devShells.default = pkgs.mkShell { 73 | inherit buildInputs; 74 | 75 | LD_LIBRARY_PATH = 76 | builtins.foldl' (a: b: "${a}:${b}/lib") "${pkgs.vulkan-loader}/lib" buildInputs; 77 | }; 78 | } 79 | ); 80 | } 81 | ``` 82 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2019 Héctor Ramón, Iced contributors 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so, 8 | subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /ROADMAP.md: -------------------------------------------------------------------------------- 1 | # Roadmap 2 | We have [a detailed graphical roadmap now](https://whimsical.com/roadmap-iced-7vhq6R35Lp3TmYH4WeYwLM)! 3 | -------------------------------------------------------------------------------- /beacon/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "iced_beacon" 3 | description = "A client/server protocol to monitor and supervise iced applications" 4 | version.workspace = true 5 | edition.workspace = true 6 | authors.workspace = true 7 | license.workspace = true 8 | repository.workspace = true 9 | homepage.workspace = true 10 | categories.workspace = true 11 | keywords.workspace = true 12 | 13 | [dependencies] 14 | iced_core.workspace = true 15 | iced_core.features = ["serde"] 16 | 17 | bincode.workspace = true 18 | futures.workspace = true 19 | log.workspace = true 20 | thiserror.workspace = true 21 | 22 | tokio.workspace = true 23 | tokio.features = ["rt", "rt-multi-thread", "net", "sync", "time", "io-util", "macros"] 24 | 25 | serde.workspace = true 26 | serde.features = ["derive"] 27 | 28 | semver.workspace = true 29 | semver.features = ["serde"] 30 | -------------------------------------------------------------------------------- /beacon/src/error.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | 3 | #[derive(Debug, thiserror::Error)] 4 | pub enum Error { 5 | #[error("input/output operation failed: {0}")] 6 | IOFailed(#[from] io::Error), 7 | #[error("decoding failed: {0}")] 8 | DecodingFailed(#[from] Box), 9 | } 10 | -------------------------------------------------------------------------------- /beacon/src/stream.rs: -------------------------------------------------------------------------------- 1 | use futures::Future; 2 | use futures::channel::mpsc; 3 | use futures::stream::{self, Stream, StreamExt}; 4 | 5 | pub fn channel(f: impl Fn(mpsc::Sender) -> F) -> impl Stream 6 | where 7 | F: Future, 8 | { 9 | let (sender, receiver) = mpsc::channel(1); 10 | 11 | stream::select( 12 | receiver, 13 | stream::once(f(sender)).filter_map(|_| async { None }), 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /clippy.toml: -------------------------------------------------------------------------------- 1 | too-many-arguments-threshold = 20 2 | enum-variant-name-threshold = 10 3 | -------------------------------------------------------------------------------- /core/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "iced_core" 3 | description = "The essential ideas of iced" 4 | version.workspace = true 5 | edition.workspace = true 6 | authors.workspace = true 7 | license.workspace = true 8 | repository.workspace = true 9 | homepage.workspace = true 10 | categories.workspace = true 11 | keywords.workspace = true 12 | 13 | [lints] 14 | workspace = true 15 | 16 | [features] 17 | auto-detect-theme = ["dep:dark-light"] 18 | advanced = [] 19 | crisp = [] 20 | 21 | [dependencies] 22 | bitflags.workspace = true 23 | bytes.workspace = true 24 | glam.workspace = true 25 | lilt.workspace = true 26 | log.workspace = true 27 | num-traits.workspace = true 28 | rustc-hash.workspace = true 29 | smol_str.workspace = true 30 | thiserror.workspace = true 31 | web-time.workspace = true 32 | 33 | dark-light.workspace = true 34 | dark-light.optional = true 35 | 36 | serde.workspace = true 37 | serde.optional = true 38 | serde.features = ["derive"] 39 | -------------------------------------------------------------------------------- /core/README.md: -------------------------------------------------------------------------------- 1 | # `iced_core` 2 | [![Documentation](https://docs.rs/iced_core/badge.svg)][documentation] 3 | [![Crates.io](https://img.shields.io/crates/v/iced_core.svg)](https://crates.io/crates/iced_core) 4 | [![License](https://img.shields.io/crates/l/iced_core.svg)](https://github.com/iced-rs/iced/blob/master/LICENSE) 5 | [![Discord Server](https://img.shields.io/discord/628993209984614400?label=&labelColor=6A7EC2&logo=discord&logoColor=ffffff&color=7389D8)](https://discord.gg/3xZJ65GAhd) 6 | 7 | `iced_core` holds basic reusable types of the public API. For instance, basic data types like `Point`, `Rectangle`, `Length`, etc. 8 | 9 | This crate is meant to be a starting point for an Iced runtime. 10 | 11 |

12 | The foundations 13 |

14 | 15 | [documentation]: https://docs.rs/iced_core 16 | -------------------------------------------------------------------------------- /core/src/background.rs: -------------------------------------------------------------------------------- 1 | use crate::Color; 2 | use crate::gradient::{self, Gradient}; 3 | 4 | /// The background of some element. 5 | #[derive(Debug, Clone, Copy, PartialEq)] 6 | pub enum Background { 7 | /// A solid color. 8 | Color(Color), 9 | /// Linearly interpolate between several colors. 10 | Gradient(Gradient), 11 | // TODO: Add image variant 12 | } 13 | 14 | impl Background { 15 | /// Scales the alpha channel of the [`Background`] by the given 16 | /// factor. 17 | pub fn scale_alpha(self, factor: f32) -> Self { 18 | match self { 19 | Self::Color(color) => Self::Color(color.scale_alpha(factor)), 20 | Self::Gradient(gradient) => { 21 | Self::Gradient(gradient.scale_alpha(factor)) 22 | } 23 | } 24 | } 25 | } 26 | 27 | impl From for Background { 28 | fn from(color: Color) -> Self { 29 | Background::Color(color) 30 | } 31 | } 32 | 33 | impl From for Background { 34 | fn from(gradient: Gradient) -> Self { 35 | Background::Gradient(gradient) 36 | } 37 | } 38 | 39 | impl From for Background { 40 | fn from(gradient: gradient::Linear) -> Self { 41 | Background::Gradient(Gradient::Linear(gradient)) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /core/src/clipboard.rs: -------------------------------------------------------------------------------- 1 | //! Access the clipboard. 2 | 3 | /// A buffer for short-term storage and transfer within and between 4 | /// applications. 5 | pub trait Clipboard { 6 | /// Reads the current content of the [`Clipboard`] as text. 7 | fn read(&self, kind: Kind) -> Option; 8 | 9 | /// Writes the given text contents to the [`Clipboard`]. 10 | fn write(&mut self, kind: Kind, contents: String); 11 | } 12 | 13 | /// The kind of [`Clipboard`]. 14 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 15 | pub enum Kind { 16 | /// The standard clipboard. 17 | Standard, 18 | /// The primary clipboard. 19 | /// 20 | /// Normally only present in X11 and Wayland. 21 | Primary, 22 | } 23 | 24 | /// A null implementation of the [`Clipboard`] trait. 25 | #[derive(Debug, Clone, Copy)] 26 | pub struct Null; 27 | 28 | impl Clipboard for Null { 29 | fn read(&self, _kind: Kind) -> Option { 30 | None 31 | } 32 | 33 | fn write(&mut self, _kind: Kind, _contents: String) {} 34 | } 35 | -------------------------------------------------------------------------------- /core/src/event.rs: -------------------------------------------------------------------------------- 1 | //! Handle events of a user interface. 2 | use crate::input_method; 3 | use crate::keyboard; 4 | use crate::mouse; 5 | use crate::touch; 6 | use crate::window; 7 | 8 | /// A user interface event. 9 | /// 10 | /// _**Note:** This type is largely incomplete! If you need to track 11 | /// additional events, feel free to [open an issue] and share your use case!_ 12 | /// 13 | /// [open an issue]: https://github.com/iced-rs/iced/issues 14 | #[derive(Debug, Clone, PartialEq)] 15 | pub enum Event { 16 | /// A keyboard event 17 | Keyboard(keyboard::Event), 18 | 19 | /// A mouse event 20 | Mouse(mouse::Event), 21 | 22 | /// A window event 23 | Window(window::Event), 24 | 25 | /// A touch event 26 | Touch(touch::Event), 27 | 28 | /// An input method event 29 | InputMethod(input_method::Event), 30 | } 31 | 32 | /// The status of an [`Event`] after being processed. 33 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 34 | pub enum Status { 35 | /// The [`Event`] was **NOT** handled by any widget. 36 | Ignored, 37 | 38 | /// The [`Event`] was handled and processed by a widget. 39 | Captured, 40 | } 41 | 42 | impl Status { 43 | /// Merges two [`Status`] into one. 44 | /// 45 | /// `Captured` takes precedence over `Ignored`: 46 | /// 47 | /// ``` 48 | /// use iced_core::event::Status; 49 | /// 50 | /// assert_eq!(Status::Ignored.merge(Status::Ignored), Status::Ignored); 51 | /// assert_eq!(Status::Ignored.merge(Status::Captured), Status::Captured); 52 | /// assert_eq!(Status::Captured.merge(Status::Ignored), Status::Captured); 53 | /// assert_eq!(Status::Captured.merge(Status::Captured), Status::Captured); 54 | /// ``` 55 | pub fn merge(self, b: Self) -> Self { 56 | match self { 57 | Status::Ignored => b, 58 | Status::Captured => Status::Captured, 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /core/src/hasher.rs: -------------------------------------------------------------------------------- 1 | /// The hasher used to compare layouts. 2 | #[allow(missing_debug_implementations)] // Doesn't really make sense to have debug on the hasher state anyways. 3 | #[derive(Default)] 4 | pub struct Hasher(rustc_hash::FxHasher); 5 | 6 | impl core::hash::Hasher for Hasher { 7 | fn write(&mut self, bytes: &[u8]) { 8 | self.0.write(bytes); 9 | } 10 | 11 | fn finish(&self) -> u64 { 12 | self.0.finish() 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /core/src/keyboard.rs: -------------------------------------------------------------------------------- 1 | //! Listen to keyboard events. 2 | pub mod key; 3 | 4 | mod event; 5 | mod location; 6 | mod modifiers; 7 | 8 | pub use event::Event; 9 | pub use key::Key; 10 | pub use location::Location; 11 | pub use modifiers::Modifiers; 12 | -------------------------------------------------------------------------------- /core/src/keyboard/event.rs: -------------------------------------------------------------------------------- 1 | use crate::SmolStr; 2 | use crate::keyboard::key; 3 | use crate::keyboard::{Key, Location, Modifiers}; 4 | 5 | /// A keyboard event. 6 | /// 7 | /// _**Note:** This type is largely incomplete! If you need to track 8 | /// additional events, feel free to [open an issue] and share your use case!_ 9 | /// 10 | /// [open an issue]: https://github.com/iced-rs/iced/issues 11 | #[derive(Debug, Clone, PartialEq, Eq)] 12 | pub enum Event { 13 | /// A keyboard key was pressed. 14 | KeyPressed { 15 | /// The key pressed. 16 | key: Key, 17 | 18 | /// The key pressed with all keyboard modifiers applied, except Ctrl. 19 | modified_key: Key, 20 | 21 | /// The physical key pressed. 22 | physical_key: key::Physical, 23 | 24 | /// The location of the key. 25 | location: Location, 26 | 27 | /// The state of the modifier keys. 28 | modifiers: Modifiers, 29 | 30 | /// The text produced by the key press, if any. 31 | text: Option, 32 | }, 33 | 34 | /// A keyboard key was released. 35 | KeyReleased { 36 | /// The key released. 37 | key: Key, 38 | 39 | /// The key released with all keyboard modifiers applied, except Ctrl. 40 | modified_key: Key, 41 | 42 | /// The physical key released. 43 | physical_key: key::Physical, 44 | 45 | /// The location of the key. 46 | location: Location, 47 | 48 | /// The state of the modifier keys. 49 | modifiers: Modifiers, 50 | }, 51 | 52 | /// The keyboard modifiers have changed. 53 | ModifiersChanged(Modifiers), 54 | } 55 | -------------------------------------------------------------------------------- /core/src/keyboard/location.rs: -------------------------------------------------------------------------------- 1 | /// The location of a key on the keyboard. 2 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 3 | pub enum Location { 4 | /// The standard group of keys on the keyboard. 5 | Standard, 6 | /// The left side of the keyboard. 7 | Left, 8 | /// The right side of the keyboard. 9 | Right, 10 | /// The numpad of the keyboard. 11 | Numpad, 12 | } 13 | -------------------------------------------------------------------------------- /core/src/mouse.rs: -------------------------------------------------------------------------------- 1 | //! Handle mouse events. 2 | pub mod click; 3 | 4 | mod button; 5 | mod cursor; 6 | mod event; 7 | mod interaction; 8 | 9 | pub use button::Button; 10 | pub use click::Click; 11 | pub use cursor::Cursor; 12 | pub use event::{Event, ScrollDelta}; 13 | pub use interaction::Interaction; 14 | -------------------------------------------------------------------------------- /core/src/mouse/button.rs: -------------------------------------------------------------------------------- 1 | /// The button of a mouse. 2 | #[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)] 3 | pub enum Button { 4 | /// The left mouse button. 5 | Left, 6 | 7 | /// The right mouse button. 8 | Right, 9 | 10 | /// The middle (wheel) button. 11 | Middle, 12 | 13 | /// The back mouse button. 14 | Back, 15 | 16 | /// The forward mouse button. 17 | Forward, 18 | 19 | /// Some other button. 20 | Other(u16), 21 | } 22 | -------------------------------------------------------------------------------- /core/src/mouse/event.rs: -------------------------------------------------------------------------------- 1 | use crate::Point; 2 | 3 | use super::Button; 4 | 5 | /// A mouse event. 6 | /// 7 | /// _**Note:** This type is largely incomplete! If you need to track 8 | /// additional events, feel free to [open an issue] and share your use case!_ 9 | /// 10 | /// [open an issue]: https://github.com/iced-rs/iced/issues 11 | #[derive(Debug, Clone, Copy, PartialEq)] 12 | pub enum Event { 13 | /// The mouse cursor entered the window. 14 | CursorEntered, 15 | 16 | /// The mouse cursor left the window. 17 | CursorLeft, 18 | 19 | /// The mouse cursor was moved 20 | CursorMoved { 21 | /// The new position of the mouse cursor 22 | position: Point, 23 | }, 24 | 25 | /// A mouse button was pressed. 26 | ButtonPressed(Button), 27 | 28 | /// A mouse button was released. 29 | ButtonReleased(Button), 30 | 31 | /// The mouse wheel was scrolled. 32 | WheelScrolled { 33 | /// The scroll movement. 34 | delta: ScrollDelta, 35 | }, 36 | } 37 | 38 | /// A scroll movement. 39 | #[derive(Debug, Clone, Copy, PartialEq)] 40 | pub enum ScrollDelta { 41 | /// A line-based scroll movement 42 | Lines { 43 | /// The number of horizontal lines scrolled 44 | x: f32, 45 | 46 | /// The number of vertical lines scrolled 47 | y: f32, 48 | }, 49 | /// A pixel-based scroll movement 50 | Pixels { 51 | /// The number of horizontal pixels scrolled 52 | x: f32, 53 | /// The number of vertical pixels scrolled 54 | y: f32, 55 | }, 56 | } 57 | -------------------------------------------------------------------------------- /core/src/mouse/interaction.rs: -------------------------------------------------------------------------------- 1 | /// The interaction of a mouse cursor. 2 | #[derive(Debug, Eq, PartialEq, Clone, Copy, PartialOrd, Ord, Default)] 3 | #[allow(missing_docs)] 4 | pub enum Interaction { 5 | #[default] 6 | None, 7 | Idle, 8 | Pointer, 9 | Grab, 10 | Text, 11 | Crosshair, 12 | Working, 13 | Grabbing, 14 | ResizingHorizontally, 15 | ResizingVertically, 16 | ResizingDiagonallyUp, 17 | ResizingDiagonallyDown, 18 | NotAllowed, 19 | ZoomIn, 20 | ZoomOut, 21 | Cell, 22 | Move, 23 | Copy, 24 | Help, 25 | } 26 | -------------------------------------------------------------------------------- /core/src/settings.rs: -------------------------------------------------------------------------------- 1 | //! Configure your application. 2 | use crate::{Font, Pixels}; 3 | 4 | use std::borrow::Cow; 5 | 6 | /// The settings of an iced program. 7 | #[derive(Debug, Clone)] 8 | pub struct Settings { 9 | /// The identifier of the application. 10 | /// 11 | /// If provided, this identifier may be used to identify the application or 12 | /// communicate with it through the windowing system. 13 | pub id: Option, 14 | 15 | /// The fonts to load on boot. 16 | pub fonts: Vec>, 17 | 18 | /// The default [`Font`] to be used. 19 | /// 20 | /// By default, it uses [`Family::SansSerif`](crate::font::Family::SansSerif). 21 | pub default_font: Font, 22 | 23 | /// The text size that will be used by default. 24 | /// 25 | /// The default value is `16.0`. 26 | pub default_text_size: Pixels, 27 | 28 | /// If set to true, the renderer will try to perform antialiasing for some 29 | /// primitives. 30 | /// 31 | /// Enabling it can produce a smoother result in some widgets, like the 32 | /// `canvas` widget, at a performance cost. 33 | /// 34 | /// By default, it is enabled. 35 | pub antialiasing: bool, 36 | } 37 | 38 | impl Default for Settings { 39 | fn default() -> Self { 40 | Self { 41 | id: None, 42 | fonts: Vec::new(), 43 | default_font: Font::default(), 44 | default_text_size: Pixels(16.0), 45 | antialiasing: true, 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /core/src/shadow.rs: -------------------------------------------------------------------------------- 1 | use crate::{Color, Vector}; 2 | 3 | /// A shadow. 4 | #[derive(Debug, Clone, Copy, PartialEq, Default)] 5 | pub struct Shadow { 6 | /// The color of the shadow. 7 | pub color: Color, 8 | 9 | /// The offset of the shadow. 10 | pub offset: Vector, 11 | 12 | /// The blur radius of the shadow. 13 | pub blur_radius: f32, 14 | } 15 | -------------------------------------------------------------------------------- /core/src/time.rs: -------------------------------------------------------------------------------- 1 | //! Keep track of time, both in native and web platforms! 2 | 3 | pub use web_time::Duration; 4 | pub use web_time::Instant; 5 | pub use web_time::SystemTime; 6 | 7 | /// Creates a [`Duration`] representing the given amount of milliseconds. 8 | pub fn milliseconds(milliseconds: u64) -> Duration { 9 | Duration::from_millis(milliseconds) 10 | } 11 | 12 | /// Creates a [`Duration`] representing the given amount of seconds. 13 | pub fn seconds(seconds: u64) -> Duration { 14 | Duration::from_secs(seconds) 15 | } 16 | 17 | /// Creates a [`Duration`] representing the given amount of minutes. 18 | pub fn minutes(minutes: u64) -> Duration { 19 | seconds(minutes * 60) 20 | } 21 | 22 | /// Creates a [`Duration`] representing the given amount of hours. 23 | pub fn hours(hours: u64) -> Duration { 24 | minutes(hours * 60) 25 | } 26 | 27 | /// Creates a [`Duration`] representing the given amount of days. 28 | pub fn days(days: u64) -> Duration { 29 | hours(days * 24) 30 | } 31 | -------------------------------------------------------------------------------- /core/src/touch.rs: -------------------------------------------------------------------------------- 1 | //! Build touch events. 2 | use crate::Point; 3 | 4 | /// A touch interaction. 5 | #[derive(Debug, Clone, Copy, PartialEq)] 6 | #[allow(missing_docs)] 7 | pub enum Event { 8 | /// A touch interaction was started. 9 | FingerPressed { id: Finger, position: Point }, 10 | 11 | /// An on-going touch interaction was moved. 12 | FingerMoved { id: Finger, position: Point }, 13 | 14 | /// A touch interaction was ended. 15 | FingerLifted { id: Finger, position: Point }, 16 | 17 | /// A touch interaction was canceled. 18 | FingerLost { id: Finger, position: Point }, 19 | } 20 | 21 | /// A unique identifier representing a finger on a touch interaction. 22 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 23 | pub struct Finger(pub u64); 24 | -------------------------------------------------------------------------------- /core/src/vector.rs: -------------------------------------------------------------------------------- 1 | /// A 2D vector. 2 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 3 | pub struct Vector { 4 | /// The X component of the [`Vector`] 5 | pub x: T, 6 | 7 | /// The Y component of the [`Vector`] 8 | pub y: T, 9 | } 10 | 11 | impl Vector { 12 | /// Creates a new [`Vector`] with the given components. 13 | pub const fn new(x: T, y: T) -> Self { 14 | Self { x, y } 15 | } 16 | } 17 | 18 | impl Vector { 19 | /// The zero [`Vector`]. 20 | pub const ZERO: Self = Self::new(0.0, 0.0); 21 | } 22 | 23 | impl std::ops::Neg for Vector 24 | where 25 | T: std::ops::Neg, 26 | { 27 | type Output = Self; 28 | 29 | fn neg(self) -> Self::Output { 30 | Self::new(-self.x, -self.y) 31 | } 32 | } 33 | 34 | impl std::ops::Add for Vector 35 | where 36 | T: std::ops::Add, 37 | { 38 | type Output = Self; 39 | 40 | fn add(self, b: Self) -> Self { 41 | Self::new(self.x + b.x, self.y + b.y) 42 | } 43 | } 44 | 45 | impl std::ops::Sub for Vector 46 | where 47 | T: std::ops::Sub, 48 | { 49 | type Output = Self; 50 | 51 | fn sub(self, b: Self) -> Self { 52 | Self::new(self.x - b.x, self.y - b.y) 53 | } 54 | } 55 | 56 | impl std::ops::Mul for Vector 57 | where 58 | T: std::ops::Mul + Copy, 59 | { 60 | type Output = Self; 61 | 62 | fn mul(self, scale: T) -> Self { 63 | Self::new(self.x * scale, self.y * scale) 64 | } 65 | } 66 | 67 | impl Default for Vector 68 | where 69 | T: Default, 70 | { 71 | fn default() -> Self { 72 | Self { 73 | x: T::default(), 74 | y: T::default(), 75 | } 76 | } 77 | } 78 | 79 | impl From<[T; 2]> for Vector { 80 | fn from([x, y]: [T; 2]) -> Self { 81 | Self::new(x, y) 82 | } 83 | } 84 | 85 | impl From> for [T; 2] 86 | where 87 | T: Copy, 88 | { 89 | fn from(other: Vector) -> Self { 90 | [other.x, other.y] 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /core/src/widget/id.rs: -------------------------------------------------------------------------------- 1 | use std::borrow; 2 | use std::sync::atomic::{self, AtomicUsize}; 3 | 4 | static NEXT_ID: AtomicUsize = AtomicUsize::new(0); 5 | 6 | /// The identifier of a generic widget. 7 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] 8 | pub struct Id(Internal); 9 | 10 | impl Id { 11 | /// Creates a custom [`Id`]. 12 | pub fn new(id: impl Into>) -> Self { 13 | Self(Internal::Custom(id.into())) 14 | } 15 | 16 | /// Creates a unique [`Id`]. 17 | /// 18 | /// This function produces a different [`Id`] every time it is called. 19 | pub fn unique() -> Self { 20 | let id = NEXT_ID.fetch_add(1, atomic::Ordering::Relaxed); 21 | 22 | Self(Internal::Unique(id)) 23 | } 24 | } 25 | 26 | impl From<&'static str> for Id { 27 | fn from(value: &'static str) -> Self { 28 | Self::new(value) 29 | } 30 | } 31 | 32 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] 33 | enum Internal { 34 | Unique(usize), 35 | Custom(borrow::Cow<'static, str>), 36 | } 37 | 38 | #[cfg(test)] 39 | mod tests { 40 | use super::Id; 41 | 42 | #[test] 43 | fn unique_generates_different_ids() { 44 | let a = Id::unique(); 45 | let b = Id::unique(); 46 | 47 | assert_ne!(a, b); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /core/src/window.rs: -------------------------------------------------------------------------------- 1 | //! Build window-based GUI applications. 2 | pub mod icon; 3 | pub mod screenshot; 4 | pub mod settings; 5 | 6 | mod direction; 7 | mod event; 8 | mod id; 9 | mod level; 10 | mod mode; 11 | mod position; 12 | mod redraw_request; 13 | mod user_attention; 14 | 15 | pub use direction::Direction; 16 | pub use event::Event; 17 | pub use icon::Icon; 18 | pub use id::Id; 19 | pub use level::Level; 20 | pub use mode::Mode; 21 | pub use position::Position; 22 | pub use redraw_request::RedrawRequest; 23 | pub use screenshot::Screenshot; 24 | pub use settings::Settings; 25 | pub use user_attention::UserAttention; 26 | -------------------------------------------------------------------------------- /core/src/window/direction.rs: -------------------------------------------------------------------------------- 1 | /// The cardinal directions relative to the center of a window. 2 | #[derive(Debug, Clone, Copy)] 3 | pub enum Direction { 4 | /// Points to the top edge of a window. 5 | North, 6 | 7 | /// Points to the bottom edge of a window. 8 | South, 9 | 10 | /// Points to the right edge of a window. 11 | East, 12 | 13 | /// Points to the left edge of a window. 14 | West, 15 | 16 | /// Points to the top-right corner of a window. 17 | NorthEast, 18 | 19 | /// Points to the top-left corner of a window. 20 | NorthWest, 21 | 22 | /// Points to the bottom-right corner of a window. 23 | SouthEast, 24 | 25 | /// Points to the bottom-left corner of a window. 26 | SouthWest, 27 | } 28 | -------------------------------------------------------------------------------- /core/src/window/id.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | use std::hash::Hash; 3 | use std::sync::atomic::{self, AtomicU64}; 4 | 5 | /// The id of the window. 6 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] 7 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 8 | pub struct Id(u64); 9 | 10 | static COUNT: AtomicU64 = AtomicU64::new(1); 11 | 12 | impl Id { 13 | /// Creates a new unique window [`Id`]. 14 | pub fn unique() -> Id { 15 | Id(COUNT.fetch_add(1, atomic::Ordering::Relaxed)) 16 | } 17 | } 18 | 19 | impl fmt::Display for Id { 20 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 21 | self.0.fmt(f) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /core/src/window/level.rs: -------------------------------------------------------------------------------- 1 | /// A window level groups windows with respect to their z-position. 2 | /// 3 | /// The relative ordering between windows in different window levels is fixed. 4 | /// The z-order of a window within the same window level may change dynamically 5 | /// on user interaction. 6 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] 7 | pub enum Level { 8 | /// The default behavior. 9 | #[default] 10 | Normal, 11 | 12 | /// The window will always be below normal windows. 13 | /// 14 | /// This is useful for a widget-based app. 15 | AlwaysOnBottom, 16 | 17 | /// The window will always be on top of normal windows. 18 | AlwaysOnTop, 19 | } 20 | -------------------------------------------------------------------------------- /core/src/window/mode.rs: -------------------------------------------------------------------------------- 1 | /// The mode of a window-based application. 2 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 3 | pub enum Mode { 4 | /// The application appears in its own window. 5 | Windowed, 6 | 7 | /// The application takes the whole screen of its current monitor. 8 | Fullscreen, 9 | 10 | /// The application is hidden 11 | Hidden, 12 | } 13 | -------------------------------------------------------------------------------- /core/src/window/position.rs: -------------------------------------------------------------------------------- 1 | use crate::{Point, Size}; 2 | 3 | /// The position of a window in a given screen. 4 | #[derive(Debug, Clone, Copy, PartialEq)] 5 | pub enum Position { 6 | /// The platform-specific default position for a new window. 7 | Default, 8 | /// The window is completely centered on the screen. 9 | Centered, 10 | /// The window is positioned with specific coordinates: `(X, Y)`. 11 | /// 12 | /// When the decorations of the window are enabled, Windows 10 will add some 13 | /// invisible padding to the window. This padding gets included in the 14 | /// position. So if you have decorations enabled and want the window to be 15 | /// at (0, 0) you would have to set the position to 16 | /// `(PADDING_X, PADDING_Y)`. 17 | Specific(Point), 18 | /// Like [`Specific`], but the window is positioned with the specific coordinates returned by the function. 19 | /// 20 | /// The function receives the window size and the monitor's resolution as input. 21 | /// 22 | /// [`Specific`]: Self::Specific 23 | SpecificWith(fn(Size, Size) -> Point), 24 | } 25 | 26 | impl Default for Position { 27 | fn default() -> Self { 28 | Self::Default 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /core/src/window/redraw_request.rs: -------------------------------------------------------------------------------- 1 | use crate::time::Instant; 2 | 3 | /// A request to redraw a window. 4 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] 5 | pub enum RedrawRequest { 6 | /// Redraw the next frame. 7 | NextFrame, 8 | 9 | /// Redraw at the given time. 10 | At(Instant), 11 | 12 | /// No redraw is needed. 13 | Wait, 14 | } 15 | 16 | impl From for RedrawRequest { 17 | fn from(time: Instant) -> Self { 18 | Self::At(time) 19 | } 20 | } 21 | 22 | #[cfg(test)] 23 | mod tests { 24 | use super::*; 25 | use crate::time::Duration; 26 | 27 | #[test] 28 | fn ordering() { 29 | let now = Instant::now(); 30 | let later = now + Duration::from_millis(10); 31 | 32 | assert_eq!(RedrawRequest::NextFrame, RedrawRequest::NextFrame); 33 | assert_eq!(RedrawRequest::At(now), RedrawRequest::At(now)); 34 | 35 | assert!(RedrawRequest::NextFrame < RedrawRequest::At(now)); 36 | assert!(RedrawRequest::At(now) > RedrawRequest::NextFrame); 37 | assert!(RedrawRequest::At(now) < RedrawRequest::At(later)); 38 | assert!(RedrawRequest::At(later) > RedrawRequest::At(now)); 39 | 40 | assert!(RedrawRequest::NextFrame <= RedrawRequest::NextFrame); 41 | assert!(RedrawRequest::NextFrame <= RedrawRequest::At(now)); 42 | assert!(RedrawRequest::At(now) >= RedrawRequest::NextFrame); 43 | assert!(RedrawRequest::At(now) <= RedrawRequest::At(now)); 44 | assert!(RedrawRequest::At(now) <= RedrawRequest::At(later)); 45 | assert!(RedrawRequest::At(later) >= RedrawRequest::At(now)); 46 | 47 | assert!(RedrawRequest::Wait > RedrawRequest::NextFrame); 48 | assert!(RedrawRequest::Wait > RedrawRequest::At(later)); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /core/src/window/settings/linux.rs: -------------------------------------------------------------------------------- 1 | //! Platform specific settings for Linux. 2 | 3 | /// The platform specific window settings of an application. 4 | #[derive(Debug, Clone, PartialEq, Eq, Default)] 5 | pub struct PlatformSpecific { 6 | /// Sets the application id of the window. 7 | /// 8 | /// As a best practice, it is suggested to select an application id that match 9 | /// the basename of the application’s .desktop file. 10 | pub application_id: String, 11 | 12 | /// Whether bypass the window manager mapping for x11 windows 13 | /// 14 | /// This flag is particularly useful for creating UI elements that need precise 15 | /// positioning and immediate display without window manager interference. 16 | pub override_redirect: bool, 17 | } 18 | -------------------------------------------------------------------------------- /core/src/window/settings/macos.rs: -------------------------------------------------------------------------------- 1 | //! Platform specific settings for macOS. 2 | 3 | /// The platform specific window settings of an application. 4 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] 5 | pub struct PlatformSpecific { 6 | /// Hides the window title. 7 | pub title_hidden: bool, 8 | /// Makes the titlebar transparent and allows the content to appear behind it. 9 | pub titlebar_transparent: bool, 10 | /// Makes the window content appear behind the titlebar. 11 | pub fullsize_content_view: bool, 12 | } 13 | -------------------------------------------------------------------------------- /core/src/window/settings/other.rs: -------------------------------------------------------------------------------- 1 | /// The platform specific window settings of an application. 2 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] 3 | pub struct PlatformSpecific; 4 | -------------------------------------------------------------------------------- /core/src/window/settings/wasm.rs: -------------------------------------------------------------------------------- 1 | //! Platform specific settings for WebAssembly. 2 | 3 | /// The platform specific window settings of an application. 4 | #[derive(Debug, Clone, PartialEq, Eq)] 5 | pub struct PlatformSpecific { 6 | /// The identifier of a DOM element that will be replaced with the 7 | /// application. 8 | /// 9 | /// If set to `None`, the application will be appended to the HTML body. 10 | /// 11 | /// By default, it is set to `"iced"`. 12 | pub target: Option, 13 | } 14 | 15 | impl Default for PlatformSpecific { 16 | fn default() -> Self { 17 | Self { 18 | target: Some(String::from("iced")), 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /core/src/window/settings/windows.rs: -------------------------------------------------------------------------------- 1 | //! Platform specific settings for Windows. 2 | 3 | /// The platform specific window settings of an application. 4 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 5 | pub struct PlatformSpecific { 6 | /// Drag and drop support 7 | pub drag_and_drop: bool, 8 | 9 | /// Whether show or hide the window icon in the taskbar. 10 | pub skip_taskbar: bool, 11 | 12 | /// Shows or hides the background drop shadow for undecorated windows. 13 | /// 14 | /// The shadow is hidden by default. 15 | /// Enabling the shadow causes a thin 1px line to appear on the top of the window. 16 | pub undecorated_shadow: bool, 17 | } 18 | 19 | impl Default for PlatformSpecific { 20 | fn default() -> Self { 21 | Self { 22 | drag_and_drop: true, 23 | skip_taskbar: false, 24 | undecorated_shadow: false, 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /core/src/window/user_attention.rs: -------------------------------------------------------------------------------- 1 | /// The type of user attention to request. 2 | /// 3 | /// ## Platform-specific 4 | /// 5 | /// - **X11:** Sets the WM's `XUrgencyHint`. No distinction between [`Critical`] and [`Informational`]. 6 | /// 7 | /// [`Critical`]: Self::Critical 8 | /// [`Informational`]: Self::Informational 9 | #[derive(Debug, Clone, Copy)] 10 | pub enum UserAttention { 11 | /// ## Platform-specific 12 | /// 13 | /// - **macOS:** Bounces the dock icon until the application is in focus. 14 | /// - **Windows:** Flashes both the window and the taskbar button until the application is in focus. 15 | Critical, 16 | /// ## Platform-specific 17 | /// 18 | /// - **macOS:** Bounces the dock icon once. 19 | /// - **Windows:** Flashes the taskbar button until the application is in focus. 20 | Informational, 21 | } 22 | -------------------------------------------------------------------------------- /debug/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "iced_debug" 3 | description = "A pluggable API for debugging iced applications" 4 | version.workspace = true 5 | edition.workspace = true 6 | authors.workspace = true 7 | license.workspace = true 8 | repository.workspace = true 9 | homepage.workspace = true 10 | categories.workspace = true 11 | keywords.workspace = true 12 | 13 | [features] 14 | enable = ["dep:iced_beacon"] 15 | 16 | [dependencies] 17 | iced_core.workspace = true 18 | iced_futures.workspace = true 19 | log.workspace = true 20 | 21 | [target.'cfg(not(target_arch = "wasm32"))'.dependencies] 22 | iced_beacon.workspace = true 23 | iced_beacon.optional = true 24 | -------------------------------------------------------------------------------- /devtools/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "iced_devtools" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | repository.workspace = true 8 | homepage.workspace = true 9 | categories.workspace = true 10 | keywords.workspace = true 11 | rust-version.workspace = true 12 | 13 | [lints] 14 | workspace = true 15 | 16 | [features] 17 | time-travel = ["iced_program/time-travel"] 18 | 19 | [dependencies] 20 | iced_debug.workspace = true 21 | iced_program.workspace = true 22 | iced_widget.workspace = true 23 | 24 | log.workspace = true 25 | -------------------------------------------------------------------------------- /devtools/src/executor.rs: -------------------------------------------------------------------------------- 1 | use crate::futures::futures::channel::mpsc; 2 | use crate::futures::futures::channel::oneshot; 3 | use crate::futures::futures::stream::{self, StreamExt}; 4 | use crate::runtime::Task; 5 | 6 | use std::thread; 7 | 8 | pub fn spawn_blocking( 9 | f: impl FnOnce(mpsc::Sender) + Send + 'static, 10 | ) -> Task 11 | where 12 | T: Send + 'static, 13 | { 14 | let (sender, receiver) = mpsc::channel(1); 15 | 16 | let _ = thread::spawn(move || { 17 | f(sender); 18 | }); 19 | 20 | Task::stream(receiver) 21 | } 22 | 23 | pub fn try_spawn_blocking( 24 | f: impl FnOnce(mpsc::Sender) -> Result<(), E> + Send + 'static, 25 | ) -> Task> 26 | where 27 | T: Send + 'static, 28 | E: Send + 'static, 29 | { 30 | let (sender, receiver) = mpsc::channel(1); 31 | let (error_sender, error_receiver) = oneshot::channel(); 32 | 33 | let _ = thread::spawn(move || { 34 | if let Err(error) = f(sender) { 35 | let _ = error_sender.send(Err(error)); 36 | } 37 | }); 38 | 39 | Task::stream(stream::select( 40 | receiver.map(Ok), 41 | stream::once(error_receiver).filter_map(async |result| result.ok()), 42 | )) 43 | } 44 | -------------------------------------------------------------------------------- /docs/graphs/ecosystem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/docs/graphs/ecosystem.png -------------------------------------------------------------------------------- /docs/graphs/foundations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/docs/graphs/foundations.png -------------------------------------------------------------------------------- /docs/graphs/iced.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/docs/graphs/iced.png -------------------------------------------------------------------------------- /docs/graphs/native.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/docs/graphs/native.png -------------------------------------------------------------------------------- /docs/images/checkbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/docs/images/checkbox.png -------------------------------------------------------------------------------- /docs/images/radio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/docs/images/radio.png -------------------------------------------------------------------------------- /docs/images/text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/docs/images/text.png -------------------------------------------------------------------------------- /docs/images/text_input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/docs/images/text_input.png -------------------------------------------------------------------------------- /docs/images/todos_desktop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/docs/images/todos_desktop.jpg -------------------------------------------------------------------------------- /docs/logo-no-shadow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /docs/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /docs/redirect.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Redirecting... 8 | 9 | 10 | 11 |

If you are not redirected automatically, follow this link.

12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/arc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "arc" 3 | version = "0.1.0" 4 | authors = ["ThatsNoMoon "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["canvas", "tokio", "debug"] 11 | -------------------------------------------------------------------------------- /examples/arc/README.md: -------------------------------------------------------------------------------- 1 | ## Arc 2 | 3 | An application that uses the `Canvas` widget to draw a rotating arc. 4 | 5 | This is a simple demo for https://github.com/iced-rs/iced/pull/1358. 6 | 7 | The __[`main`]__ file contains all the code of the example. 8 | 9 | You can run it with `cargo run`: 10 | ``` 11 | cargo run --package arc 12 | ``` 13 | 14 | [`main`]: src/main.rs 15 | -------------------------------------------------------------------------------- /examples/bezier_tool/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bezier_tool" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["canvas", "debug"] 11 | -------------------------------------------------------------------------------- /examples/bezier_tool/README.md: -------------------------------------------------------------------------------- 1 | ## Bézier tool 2 | 3 | A Paint-like tool for drawing Bézier curves using the `Canvas` widget. 4 | 5 | The __[`main`]__ file contains all the code of the example. 6 | 7 |
8 | 9 |
10 | 11 | You can run it with `cargo run`: 12 | ``` 13 | cargo run --package bezier_tool 14 | ``` 15 | 16 | [`main`]: src/main.rs 17 | -------------------------------------------------------------------------------- /examples/changelog/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "changelog" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [lints.clippy] 9 | large_enum_variant = "allow" 10 | 11 | [dependencies] 12 | iced.workspace = true 13 | iced.features = ["tokio", "markdown", "highlighter", "debug"] 14 | 15 | log.workspace = true 16 | thiserror.workspace = true 17 | tokio.features = ["fs", "process"] 18 | tokio.workspace = true 19 | 20 | serde = "1" 21 | webbrowser = "1" 22 | tracing-subscriber = "0.3" 23 | 24 | [dependencies.reqwest] 25 | version = "0.12" 26 | features = ["json"] 27 | -------------------------------------------------------------------------------- /examples/changelog/src/icon.rs: -------------------------------------------------------------------------------- 1 | use iced::widget::{text, Text}; 2 | use iced::Font; 3 | 4 | pub const FONT_BYTES: &[u8] = include_bytes!("../fonts/changelog-icons.ttf"); 5 | 6 | const FONT: Font = Font::with_name("changelog-icons"); 7 | 8 | pub fn copy() -> Text<'static> { 9 | text('\u{e800}').font(FONT) 10 | } 11 | -------------------------------------------------------------------------------- /examples/checkbox/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "checkbox" 3 | version = "0.1.0" 4 | authors = ["Casper Rogild Storm"] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | -------------------------------------------------------------------------------- /examples/checkbox/README.md: -------------------------------------------------------------------------------- 1 | ## Checkbox 2 | 3 | A box that can be checked. 4 | 5 | The __[`main`]__ file contains all the code of the example. 6 | 7 | You can run it with `cargo run`: 8 | ``` 9 | cargo run --package checkbox 10 | ``` 11 | 12 | [`main`]: src/main.rs 13 | -------------------------------------------------------------------------------- /examples/checkbox/fonts/icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/examples/checkbox/fonts/icons.ttf -------------------------------------------------------------------------------- /examples/clock/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "clock" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["canvas", "tokio", "debug"] 11 | chrono = "0.4" 12 | tracing-subscriber = "0.3" 13 | -------------------------------------------------------------------------------- /examples/clock/README.md: -------------------------------------------------------------------------------- 1 | ## Clock 2 | 3 | An application that uses the `Canvas` widget to draw a clock and its hands to display the current time. 4 | 5 | The __[`main`]__ file contains all the code of the example. 6 | 7 |
8 | 9 |
10 | 11 | You can run it with `cargo run`: 12 | ``` 13 | cargo run --package clock 14 | ``` 15 | 16 | [`main`]: src/main.rs 17 | -------------------------------------------------------------------------------- /examples/color_palette/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "color_palette" 3 | version = "0.1.0" 4 | authors = ["Clark Moody "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["canvas"] 11 | 12 | palette = "0.7" 13 | -------------------------------------------------------------------------------- /examples/color_palette/README.md: -------------------------------------------------------------------------------- 1 | ## Color palette 2 | 3 | A color palette generator, based on a user-defined root color. 4 | 5 |
6 | 7 |
8 | 9 | You can run it with `cargo run`: 10 | 11 | ``` 12 | cargo run --package color_palette 13 | ``` 14 | -------------------------------------------------------------------------------- /examples/color_palette/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/examples/color_palette/screenshot.png -------------------------------------------------------------------------------- /examples/combo_box/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "combo_box" 3 | version = "0.1.0" 4 | authors = ["Joao Freitas "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["debug"] 11 | -------------------------------------------------------------------------------- /examples/combo_box/README.md: -------------------------------------------------------------------------------- 1 | ## Combo-Box 2 | 3 | A dropdown list of searchable and selectable options. 4 | 5 | It displays and positions an overlay based on the window position of the widget. 6 | 7 | The __[`main`]__ file contains all the code of the example. 8 | 9 |
10 | 11 |
12 | 13 | You can run it with `cargo run`: 14 | ``` 15 | cargo run --package combo_box 16 | ``` 17 | 18 | [`main`]: src/main.rs 19 | -------------------------------------------------------------------------------- /examples/combo_box/combobox.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/examples/combo_box/combobox.gif -------------------------------------------------------------------------------- /examples/counter/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "counter" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | 11 | [target.'cfg(target_arch = "wasm32")'.dependencies] 12 | iced.workspace = true 13 | iced.features = ["webgl", "fira-sans"] 14 | 15 | [dev-dependencies] 16 | iced_test.workspace = true 17 | -------------------------------------------------------------------------------- /examples/counter/README.md: -------------------------------------------------------------------------------- 1 | ## Counter 2 | 3 | The classic counter example explained in the [`README`](../../README.md). 4 | 5 | The __[`main`]__ file contains all the code of the example. 6 | 7 |
8 | 9 |
10 | 11 | You can run it with `cargo run`: 12 | ``` 13 | cargo run --package counter 14 | ``` 15 | 16 | The web version can be run with [`trunk`]: 17 | 18 | ``` 19 | cd examples/counter 20 | trunk serve 21 | ``` 22 | 23 | [`main`]: src/main.rs 24 | [`trunk`]: https://trunkrs.dev/ 25 | -------------------------------------------------------------------------------- /examples/counter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Counter - Iced 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/counter/src/main.rs: -------------------------------------------------------------------------------- 1 | use iced::Center; 2 | use iced::widget::{Column, button, column, text}; 3 | 4 | pub fn main() -> iced::Result { 5 | iced::run(Counter::update, Counter::view) 6 | } 7 | 8 | #[derive(Default)] 9 | struct Counter { 10 | value: i64, 11 | } 12 | 13 | #[derive(Debug, Clone, Copy)] 14 | enum Message { 15 | Increment, 16 | Decrement, 17 | } 18 | 19 | impl Counter { 20 | fn update(&mut self, message: Message) { 21 | match message { 22 | Message::Increment => { 23 | self.value += 1; 24 | } 25 | Message::Decrement => { 26 | self.value -= 1; 27 | } 28 | } 29 | } 30 | 31 | fn view(&self) -> Column { 32 | column![ 33 | button("Increment").on_press(Message::Increment), 34 | text(self.value).size(50), 35 | button("Decrement").on_press(Message::Decrement) 36 | ] 37 | .padding(20) 38 | .align_x(Center) 39 | } 40 | } 41 | 42 | #[cfg(test)] 43 | mod tests { 44 | use super::*; 45 | use iced_test::{Error, simulator}; 46 | 47 | #[test] 48 | fn it_counts() -> Result<(), Error> { 49 | let mut counter = Counter { value: 0 }; 50 | let mut ui = simulator(counter.view()); 51 | 52 | let _ = ui.click("Increment")?; 53 | let _ = ui.click("Increment")?; 54 | let _ = ui.click("Decrement")?; 55 | 56 | for message in ui.into_messages() { 57 | counter.update(message); 58 | } 59 | 60 | assert_eq!(counter.value, 1); 61 | 62 | let mut ui = simulator(counter.view()); 63 | assert!(ui.find("1").is_ok(), "Counter should display 1!"); 64 | 65 | Ok(()) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /examples/custom_quad/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "custom_quad" 3 | version = "0.1.0" 4 | authors = ["Robert Krahn"] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["advanced"] 11 | -------------------------------------------------------------------------------- /examples/custom_shader/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "custom_shader" 3 | version = "0.1.0" 4 | authors = ["Bingus "] 5 | edition = "2024" 6 | 7 | [dependencies] 8 | iced.workspace = true 9 | iced.features = ["debug", "image", "advanced"] 10 | 11 | image.workspace = true 12 | bytemuck.workspace = true 13 | 14 | glam.workspace = true 15 | glam.features = ["bytemuck"] 16 | 17 | rand = "0.8.5" 18 | -------------------------------------------------------------------------------- /examples/custom_shader/src/scene/camera.rs: -------------------------------------------------------------------------------- 1 | use glam::{mat4, vec3, vec4}; 2 | use iced::Rectangle; 3 | 4 | #[derive(Copy, Clone)] 5 | pub struct Camera { 6 | eye: glam::Vec3, 7 | target: glam::Vec3, 8 | up: glam::Vec3, 9 | fov_y: f32, 10 | near: f32, 11 | far: f32, 12 | } 13 | 14 | impl Default for Camera { 15 | fn default() -> Self { 16 | Self { 17 | eye: vec3(0.0, 2.0, 3.0), 18 | target: glam::Vec3::ZERO, 19 | up: glam::Vec3::Y, 20 | fov_y: 45.0, 21 | near: 0.1, 22 | far: 100.0, 23 | } 24 | } 25 | } 26 | 27 | pub const OPENGL_TO_WGPU_MATRIX: glam::Mat4 = mat4( 28 | vec4(1.0, 0.0, 0.0, 0.0), 29 | vec4(0.0, 1.0, 0.0, 0.0), 30 | vec4(0.0, 0.0, 0.5, 0.0), 31 | vec4(0.0, 0.0, 0.5, 1.0), 32 | ); 33 | 34 | impl Camera { 35 | pub fn build_view_proj_matrix(&self, bounds: Rectangle) -> glam::Mat4 { 36 | //TODO looks distorted without padding; base on surface texture size instead? 37 | let aspect_ratio = bounds.width / (bounds.height + 150.0); 38 | 39 | let view = glam::Mat4::look_at_rh(self.eye, self.target, self.up); 40 | let proj = glam::Mat4::perspective_rh( 41 | self.fov_y, 42 | aspect_ratio, 43 | self.near, 44 | self.far, 45 | ); 46 | 47 | OPENGL_TO_WGPU_MATRIX * proj * view 48 | } 49 | 50 | pub fn position(&self) -> glam::Vec4 { 51 | glam::Vec4::from((self.eye, 0.0)) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /examples/custom_shader/src/scene/pipeline/buffer.rs: -------------------------------------------------------------------------------- 1 | use crate::wgpu; 2 | 3 | // A custom buffer container for dynamic resizing. 4 | pub struct Buffer { 5 | pub raw: wgpu::Buffer, 6 | label: &'static str, 7 | size: u64, 8 | usage: wgpu::BufferUsages, 9 | } 10 | 11 | impl Buffer { 12 | pub fn new( 13 | device: &wgpu::Device, 14 | label: &'static str, 15 | size: u64, 16 | usage: wgpu::BufferUsages, 17 | ) -> Self { 18 | Self { 19 | raw: device.create_buffer(&wgpu::BufferDescriptor { 20 | label: Some(label), 21 | size, 22 | usage, 23 | mapped_at_creation: false, 24 | }), 25 | label, 26 | size, 27 | usage, 28 | } 29 | } 30 | 31 | pub fn resize(&mut self, device: &wgpu::Device, new_size: u64) { 32 | if new_size > self.size { 33 | self.raw = device.create_buffer(&wgpu::BufferDescriptor { 34 | label: Some(self.label), 35 | size: new_size, 36 | usage: self.usage, 37 | mapped_at_creation: false, 38 | }); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /examples/custom_shader/src/scene/pipeline/uniforms.rs: -------------------------------------------------------------------------------- 1 | use crate::scene::Camera; 2 | 3 | use iced::{Color, Rectangle}; 4 | 5 | #[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)] 6 | #[repr(C)] 7 | pub struct Uniforms { 8 | camera_proj: glam::Mat4, 9 | camera_pos: glam::Vec4, 10 | light_color: glam::Vec4, 11 | } 12 | 13 | impl Uniforms { 14 | pub fn new(camera: &Camera, bounds: Rectangle, light_color: Color) -> Self { 15 | let camera_proj = camera.build_view_proj_matrix(bounds); 16 | 17 | Self { 18 | camera_proj, 19 | camera_pos: camera.position(), 20 | light_color: glam::Vec4::from(light_color.into_linear()), 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/custom_shader/src/scene/pipeline/vertex.rs: -------------------------------------------------------------------------------- 1 | use crate::wgpu; 2 | 3 | #[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] 4 | #[repr(C)] 5 | pub struct Vertex { 6 | pub pos: glam::Vec3, 7 | pub normal: glam::Vec3, 8 | pub tangent: glam::Vec3, 9 | pub uv: glam::Vec2, 10 | } 11 | 12 | impl Vertex { 13 | const ATTRIBS: [wgpu::VertexAttribute; 4] = wgpu::vertex_attr_array![ 14 | //position 15 | 0 => Float32x3, 16 | //normal 17 | 1 => Float32x3, 18 | //tangent 19 | 2 => Float32x3, 20 | //uv 21 | 3 => Float32x2, 22 | ]; 23 | 24 | pub fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { 25 | wgpu::VertexBufferLayout { 26 | array_stride: std::mem::size_of::() as wgpu::BufferAddress, 27 | step_mode: wgpu::VertexStepMode::Vertex, 28 | attributes: &Self::ATTRIBS, 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /examples/custom_shader/src/shaders/depth.wgsl: -------------------------------------------------------------------------------- 1 | var positions: array, 6> = array, 6>( 2 | vec2(-1.0, 1.0), 3 | vec2(-1.0, -1.0), 4 | vec2(1.0, -1.0), 5 | vec2(-1.0, 1.0), 6 | vec2(1.0, 1.0), 7 | vec2(1.0, -1.0) 8 | ); 9 | 10 | var uvs: array, 6> = array, 6>( 11 | vec2(0.0, 0.0), 12 | vec2(0.0, 1.0), 13 | vec2(1.0, 1.0), 14 | vec2(0.0, 0.0), 15 | vec2(1.0, 0.0), 16 | vec2(1.0, 1.0) 17 | ); 18 | 19 | @group(0) @binding(0) var depth_sampler: sampler; 20 | @group(0) @binding(1) var depth_texture: texture_2d; 21 | 22 | struct Output { 23 | @builtin(position) position: vec4, 24 | @location(0) uv: vec2, 25 | } 26 | 27 | @vertex 28 | fn vs_main(@builtin(vertex_index) v_index: u32) -> Output { 29 | var out: Output; 30 | 31 | out.position = vec4(positions[v_index], 0.0, 1.0); 32 | out.uv = uvs[v_index]; 33 | 34 | return out; 35 | } 36 | 37 | @fragment 38 | fn fs_main(input: Output) -> @location(0) vec4 { 39 | let depth = textureSample(depth_texture, depth_sampler, input.uv).r; 40 | 41 | if (depth > .9999) { 42 | discard; 43 | } 44 | 45 | let c = 1.0 - depth; 46 | 47 | return vec4(c, c, c, 1.0); 48 | } 49 | -------------------------------------------------------------------------------- /examples/custom_shader/textures/ice_cube_normal_map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/examples/custom_shader/textures/ice_cube_normal_map.png -------------------------------------------------------------------------------- /examples/custom_shader/textures/skybox/neg_x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/examples/custom_shader/textures/skybox/neg_x.jpg -------------------------------------------------------------------------------- /examples/custom_shader/textures/skybox/neg_y.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/examples/custom_shader/textures/skybox/neg_y.jpg -------------------------------------------------------------------------------- /examples/custom_shader/textures/skybox/neg_z.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/examples/custom_shader/textures/skybox/neg_z.jpg -------------------------------------------------------------------------------- /examples/custom_shader/textures/skybox/pos_x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/examples/custom_shader/textures/skybox/pos_x.jpg -------------------------------------------------------------------------------- /examples/custom_shader/textures/skybox/pos_y.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/examples/custom_shader/textures/skybox/pos_y.jpg -------------------------------------------------------------------------------- /examples/custom_shader/textures/skybox/pos_z.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/examples/custom_shader/textures/skybox/pos_z.jpg -------------------------------------------------------------------------------- /examples/custom_widget/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "custom_widget" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["advanced"] 11 | -------------------------------------------------------------------------------- /examples/custom_widget/README.md: -------------------------------------------------------------------------------- 1 | ## Custom widget 2 | 3 | A demonstration of how to build a custom widget that draws a circle. 4 | 5 | The __[`main`]__ file contains all the code of the example. 6 | 7 |
8 | 9 |
10 | 11 | You can run it with `cargo run`: 12 | ``` 13 | cargo run --package custom_widget 14 | ``` 15 | 16 | [`main`]: src/main.rs 17 | -------------------------------------------------------------------------------- /examples/download_progress/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "download_progress" 3 | version = "0.1.0" 4 | authors = ["Songtronix ", "Folyd "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["tokio", "sipper"] 11 | 12 | [dependencies.reqwest] 13 | version = "0.12" 14 | features = ["stream"] 15 | -------------------------------------------------------------------------------- /examples/download_progress/README.md: -------------------------------------------------------------------------------- 1 | ## Download progress 2 | 3 | A basic application that asynchronously downloads multiple dummy files of 100 MB and tracks the download progress. 4 | 5 | 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. 6 | 7 |
8 | 9 |
10 | 11 | You can run it with `cargo run`: 12 | 13 | ``` 14 | cargo run --package download_progress 15 | ``` 16 | -------------------------------------------------------------------------------- /examples/download_progress/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Download_Progress - Iced 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/download_progress/src/download.rs: -------------------------------------------------------------------------------- 1 | use iced::futures::StreamExt; 2 | use iced::task::{Straw, sipper}; 3 | 4 | use std::sync::Arc; 5 | 6 | pub fn download(url: impl AsRef) -> impl Straw<(), Progress, Error> { 7 | sipper(async move |mut progress| { 8 | let response = reqwest::get(url.as_ref()).await?; 9 | let total = response.content_length().ok_or(Error::NoContentLength)?; 10 | 11 | let _ = progress.send(Progress { percent: 0.0 }).await; 12 | 13 | let mut byte_stream = response.bytes_stream(); 14 | let mut downloaded = 0; 15 | 16 | while let Some(next_bytes) = byte_stream.next().await { 17 | let bytes = next_bytes?; 18 | downloaded += bytes.len(); 19 | 20 | let _ = progress 21 | .send(Progress { 22 | percent: 100.0 * downloaded as f32 / total as f32, 23 | }) 24 | .await; 25 | } 26 | 27 | Ok(()) 28 | }) 29 | } 30 | 31 | #[derive(Debug, Clone)] 32 | pub struct Progress { 33 | pub percent: f32, 34 | } 35 | 36 | #[derive(Debug, Clone)] 37 | pub enum Error { 38 | RequestFailed(Arc), 39 | NoContentLength, 40 | } 41 | 42 | impl From for Error { 43 | fn from(error: reqwest::Error) -> Self { 44 | Error::RequestFailed(Arc::new(error)) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /examples/editor/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "editor" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["highlighter", "tokio", "debug"] 11 | 12 | tokio.workspace = true 13 | tokio.features = ["fs"] 14 | 15 | rfd = "0.13" 16 | -------------------------------------------------------------------------------- /examples/editor/fonts/icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/examples/editor/fonts/icons.ttf -------------------------------------------------------------------------------- /examples/events/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "events" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["debug"] 11 | -------------------------------------------------------------------------------- /examples/events/README.md: -------------------------------------------------------------------------------- 1 | ## Events 2 | 3 | A log of native events displayed using a conditional `Subscription`. 4 | 5 | The __[`main`]__ file contains all the code of the example. 6 | 7 | You can run it with `cargo run`: 8 | ``` 9 | cargo run --package events 10 | ``` 11 | 12 | [`main`]: src/main.rs 13 | -------------------------------------------------------------------------------- /examples/exit/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "exit" 3 | version = "0.1.0" 4 | edition = "2024" 5 | publish = false 6 | 7 | [dependencies] 8 | iced.workspace = true 9 | -------------------------------------------------------------------------------- /examples/exit/README.md: -------------------------------------------------------------------------------- 1 | ## Exit 2 | 3 | How to exit an application based on user input. 4 | 5 | The __[`main`]__ file contains all the code of the example. 6 | 7 | You can run it with `cargo run`: 8 | ``` 9 | cargo run --package exit 10 | ``` 11 | 12 | [`main`]: src/main.rs 13 | -------------------------------------------------------------------------------- /examples/exit/src/main.rs: -------------------------------------------------------------------------------- 1 | use iced::widget::{button, center, column}; 2 | use iced::window; 3 | use iced::{Center, Element, Task}; 4 | 5 | pub fn main() -> iced::Result { 6 | iced::run(Exit::update, Exit::view) 7 | } 8 | 9 | #[derive(Default)] 10 | struct Exit { 11 | show_confirm: bool, 12 | } 13 | 14 | #[derive(Debug, Clone, Copy)] 15 | enum Message { 16 | Confirm, 17 | Exit, 18 | } 19 | 20 | impl Exit { 21 | fn update(&mut self, message: Message) -> Task { 22 | match message { 23 | Message::Confirm => window::get_latest().and_then(window::close), 24 | Message::Exit => { 25 | self.show_confirm = true; 26 | 27 | Task::none() 28 | } 29 | } 30 | } 31 | 32 | fn view(&self) -> Element { 33 | let content = if self.show_confirm { 34 | column![ 35 | "Are you sure you want to exit?", 36 | button("Yes, exit now") 37 | .padding([10, 20]) 38 | .on_press(Message::Confirm), 39 | ] 40 | } else { 41 | column![ 42 | "Click the button to exit", 43 | button("Exit").padding([10, 20]).on_press(Message::Exit), 44 | ] 45 | } 46 | .spacing(10) 47 | .align_x(Center); 48 | 49 | center(content).padding(20).into() 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /examples/ferris/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ferris" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["image", "tokio", "debug"] 11 | -------------------------------------------------------------------------------- /examples/gallery/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "gallery" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["tokio", "sipper", "image", "debug"] 11 | 12 | reqwest.version = "0.12" 13 | reqwest.features = ["json"] 14 | 15 | serde.version = "1.0" 16 | serde.features = ["derive"] 17 | 18 | bytes.workspace = true 19 | image.workspace = true 20 | sipper.workspace = true 21 | tokio.workspace = true 22 | 23 | blurhash = "0.2.3" 24 | 25 | [lints] 26 | workspace = true 27 | -------------------------------------------------------------------------------- /examples/game_of_life/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "game_of_life" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["debug", "canvas", "tokio"] 11 | 12 | itertools = "0.12" 13 | rustc-hash.workspace = true 14 | tokio = { workspace = true, features = ["sync"] } 15 | tracing-subscriber = "0.3" 16 | -------------------------------------------------------------------------------- /examples/game_of_life/README.md: -------------------------------------------------------------------------------- 1 | ## Game of Life 2 | 3 | An interactive version of the [Game of Life], invented by [John Horton Conway]. 4 | 5 | It runs a simulation in a background thread while allowing interaction with a `Canvas` that displays an infinite grid with zooming, panning, and drawing support. 6 | 7 | The __[`main`]__ file contains the relevant code of the example. 8 | 9 |
10 | 11 |
12 | 13 | You can run it with `cargo run`: 14 | ``` 15 | cargo run --package game_of_life 16 | ``` 17 | 18 | [`main`]: src/main.rs 19 | [Game of Life]: https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life 20 | [John Horton Conway]: https://en.wikipedia.org/wiki/John_Horton_Conway 21 | -------------------------------------------------------------------------------- /examples/geometry/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "geometry" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["advanced"] 11 | -------------------------------------------------------------------------------- /examples/geometry/README.md: -------------------------------------------------------------------------------- 1 | ## Geometry 2 | 3 | A custom widget showcasing how to draw geometry with the `Mesh2D` primitive in [`iced_wgpu`](../../wgpu). 4 | 5 | The __[`main`]__ file contains all the code of the example. 6 | 7 |
8 | 9 |
10 | 11 | You can run it with `cargo run`: 12 | ``` 13 | cargo run --package geometry 14 | ``` 15 | 16 | [`main`]: src/main.rs 17 | -------------------------------------------------------------------------------- /examples/gradient/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "gradient" 3 | version = "0.1.0" 4 | edition = "2024" 5 | publish = false 6 | 7 | [dependencies] 8 | iced.workspace = true 9 | iced.features = ["debug"] 10 | 11 | tracing-subscriber = "0.3" 12 | -------------------------------------------------------------------------------- /examples/integration/.gitignore: -------------------------------------------------------------------------------- 1 | *.wasm 2 | *.js 3 | -------------------------------------------------------------------------------- /examples/integration/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "integration" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced_winit.workspace = true 10 | iced_wgpu.workspace = true 11 | 12 | iced_widget.workspace = true 13 | iced_widget.features = ["wgpu"] 14 | 15 | futures.workspace = true 16 | futures.features = ["thread-pool"] 17 | 18 | [target.'cfg(not(target_arch = "wasm32"))'.dependencies] 19 | tracing-subscriber = "0.3" 20 | 21 | [target.'cfg(target_arch = "wasm32")'.dependencies] 22 | iced_wgpu.workspace = true 23 | iced_wgpu.features = ["webgl"] 24 | 25 | console_error_panic_hook = "0.1" 26 | console_log = "1.0" 27 | wasm-bindgen = "0.2" 28 | web-sys = { version = "0.3", features = ["Element", "HtmlCanvasElement", "Window", "Document"] } 29 | -------------------------------------------------------------------------------- /examples/integration/README.md: -------------------------------------------------------------------------------- 1 | ## `wgpu` integration 2 | 3 | A demonstration of how to integrate Iced in an existing [`wgpu`] application. 4 | 5 | The __[`main`]__ file contains all the code of the example. 6 | 7 |
8 | 9 |
10 | 11 | You can run it with `cargo run`: 12 | ``` 13 | cargo run --package integration 14 | ``` 15 | 16 | [`main`]: src/main.rs 17 | [`wgpu`]: https://github.com/gfx-rs/wgpu 18 | -------------------------------------------------------------------------------- /examples/integration/src/shader/frag.wgsl: -------------------------------------------------------------------------------- 1 | @fragment 2 | fn main() -> @location(0) vec4 { 3 | return vec4(1.0, 0.0, 0.0, 1.0); 4 | } 5 | -------------------------------------------------------------------------------- /examples/integration/src/shader/vert.wgsl: -------------------------------------------------------------------------------- 1 | @vertex 2 | fn main(@builtin(vertex_index) in_vertex_index: u32) -> @builtin(position) vec4 { 3 | let x = f32(1 - i32(in_vertex_index)) * 0.5; 4 | let y = f32(1 - i32(in_vertex_index & 1u) * 2) * 0.5; 5 | return vec4(x, y, 0.0, 1.0); 6 | } 7 | -------------------------------------------------------------------------------- /examples/layout/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "layout" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced = { path = "../..", features = ["canvas"] } 10 | -------------------------------------------------------------------------------- /examples/lazy/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "lazy" 3 | version = "0.1.0" 4 | authors = ["Nick Senger "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["debug", "lazy"] 11 | -------------------------------------------------------------------------------- /examples/loading_spinners/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "loading_spinners" 3 | version = "0.1.0" 4 | authors = ["Nick Senger "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["advanced", "canvas"] 11 | 12 | lyon_algorithms = "1.0" 13 | -------------------------------------------------------------------------------- /examples/loading_spinners/README.md: -------------------------------------------------------------------------------- 1 | ## Loading Spinners 2 | 3 | Example implementation of animated indeterminate loading spinners. 4 | 5 | You can run it with `cargo run`: 6 | ``` 7 | cargo run --package loading_spinners 8 | ``` 9 | -------------------------------------------------------------------------------- /examples/loupe/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "loupe" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["advanced", "debug"] -------------------------------------------------------------------------------- /examples/markdown/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "markdown" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["markdown", "highlighter", "image", "tokio", "debug"] 11 | 12 | reqwest.version = "0.12" 13 | reqwest.features = ["json"] 14 | 15 | image.workspace = true 16 | tokio.workspace = true 17 | 18 | open = "5.3" 19 | 20 | # Disabled to keep amount of build dependencies low 21 | # This can be re-enabled on demand 22 | # [build-dependencies] 23 | # iced_fontello = "0.13" 24 | -------------------------------------------------------------------------------- /examples/markdown/build.rs: -------------------------------------------------------------------------------- 1 | pub fn main() { 2 | // println!("cargo::rerun-if-changed=fonts/markdown-icons.toml"); 3 | // iced_fontello::build("fonts/markdown-icons.toml") 4 | // .expect("Build icons font"); 5 | } 6 | -------------------------------------------------------------------------------- /examples/markdown/fonts/markdown-icons.toml: -------------------------------------------------------------------------------- 1 | module = "icon" 2 | 3 | [glyphs] 4 | copy = "fontawesome-docs" 5 | -------------------------------------------------------------------------------- /examples/markdown/fonts/markdown-icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/examples/markdown/fonts/markdown-icons.ttf -------------------------------------------------------------------------------- /examples/markdown/src/icon.rs: -------------------------------------------------------------------------------- 1 | // Generated automatically by iced_fontello at build time. 2 | // Do not edit manually. Source: ../fonts/markdown-icons.toml 3 | // dcd2f0c969d603e2ee9237a4b70fa86b1a6e84d86f4689046d8fdd10440b06b9 4 | use iced::Font; 5 | use iced::widget::{Text, text}; 6 | 7 | pub const FONT: &[u8] = include_bytes!("../fonts/markdown-icons.ttf"); 8 | 9 | pub fn copy<'a>() -> Text<'a> { 10 | icon("\u{F0C5}") 11 | } 12 | 13 | fn icon(codepoint: &str) -> Text<'_> { 14 | text(codepoint).font(Font::with_name("markdown-icons")) 15 | } 16 | -------------------------------------------------------------------------------- /examples/modal/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "modal" 3 | version = "0.1.0" 4 | authors = ["tarkah "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["advanced"] 11 | -------------------------------------------------------------------------------- /examples/multi_window/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "multi_window" 3 | version = "0.1.0" 4 | authors = ["Bingus "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced = { path = "../..", features = ["debug"] } 10 | -------------------------------------------------------------------------------- /examples/multitouch/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "multitouch" 3 | version = "0.1.0" 4 | authors = ["Artur Sapek "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["debug", "canvas", "tokio"] 11 | 12 | tracing-subscriber = "0.3" 13 | voronator = "0.2" 14 | -------------------------------------------------------------------------------- /examples/pane_grid/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pane_grid" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["debug", "lazy"] 11 | -------------------------------------------------------------------------------- /examples/pane_grid/README.md: -------------------------------------------------------------------------------- 1 | ## Pane grid 2 | 3 | A grid of panes that can be split, resized, and reorganized. 4 | 5 | This example showcases the `PaneGrid` widget, which features: 6 | 7 | * Vertical and horizontal splits 8 | * Tracking of the last active pane 9 | * Mouse-based resizing 10 | * Drag and drop to reorganize panes 11 | * Hotkey support 12 | * Configurable modifier keys 13 | * API to perform actions programmatically (`split`, `swap`, `resize`, etc.) 14 | 15 | The __[`main`]__ file contains all the code of the example. 16 | 17 |
18 | 19 |
20 | 21 | You can run it with `cargo run`: 22 | ``` 23 | cargo run --package pane_grid 24 | ``` 25 | 26 | [`main`]: src/main.rs 27 | -------------------------------------------------------------------------------- /examples/pick_list/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pick_list" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["debug"] 11 | -------------------------------------------------------------------------------- /examples/pick_list/README.md: -------------------------------------------------------------------------------- 1 | ## Pick-list 2 | 3 | A dropdown list of selectable options. 4 | 5 | It displays and positions an overlay based on the window position of the widget. 6 | 7 | The __[`main`]__ file contains all the code of the example. 8 | 9 |
10 | 11 |
12 | 13 | You can run it with `cargo run`: 14 | ``` 15 | cargo run --package pick_list 16 | ``` 17 | 18 | [`main`]: src/main.rs 19 | -------------------------------------------------------------------------------- /examples/pokedex/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pokedex" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["image", "debug", "tokio"] 11 | 12 | serde_json = "1.0" 13 | 14 | [dependencies.serde] 15 | version = "1.0" 16 | features = ["derive"] 17 | 18 | [dependencies.reqwest] 19 | version = "0.12" 20 | features = ["json"] 21 | 22 | [dependencies.rand] 23 | version = "0.8" 24 | 25 | [dependencies.getrandom] 26 | version = "0.2" 27 | features = ["js"] 28 | -------------------------------------------------------------------------------- /examples/pokedex/README.md: -------------------------------------------------------------------------------- 1 | # Pokédex 2 | An application that loads a random Pokédex entry using the [PokéAPI]. 3 | 4 | All the example code can be found in the __[`main`](src/main.rs)__ file. 5 | 6 |
7 | 8 |
9 | 10 | You can run it on native platforms with `cargo run`: 11 | ``` 12 | cargo run --package pokedex 13 | ``` 14 | 15 | [PokéAPI]: https://pokeapi.co/ 16 | -------------------------------------------------------------------------------- /examples/progress_bar/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "progress_bar" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | -------------------------------------------------------------------------------- /examples/progress_bar/README.md: -------------------------------------------------------------------------------- 1 | ## Progress bar 2 | 3 | A simple progress bar that can be filled by using a slider. 4 | 5 | The __[`main`]__ file contains all the code of the example. 6 | 7 |
8 | 9 |
10 | 11 | You can run it with `cargo run`: 12 | ``` 13 | cargo run --package progress_bar 14 | ``` 15 | 16 | [`main`]: src/main.rs 17 | -------------------------------------------------------------------------------- /examples/progress_bar/src/main.rs: -------------------------------------------------------------------------------- 1 | use iced::Element; 2 | use iced::widget::{ 3 | center, center_x, checkbox, column, progress_bar, row, slider, 4 | vertical_slider, 5 | }; 6 | 7 | pub fn main() -> iced::Result { 8 | iced::run(Progress::update, Progress::view) 9 | } 10 | 11 | #[derive(Default)] 12 | struct Progress { 13 | value: f32, 14 | is_vertical: bool, 15 | } 16 | 17 | #[derive(Debug, Clone, Copy)] 18 | enum Message { 19 | SliderChanged(f32), 20 | ToggleVertical(bool), 21 | } 22 | 23 | impl Progress { 24 | fn update(&mut self, message: Message) { 25 | match message { 26 | Message::SliderChanged(x) => self.value = x, 27 | Message::ToggleVertical(is_vertical) => { 28 | self.is_vertical = is_vertical 29 | } 30 | } 31 | } 32 | 33 | fn view(&self) -> Element { 34 | let bar = progress_bar(0.0..=100.0, self.value); 35 | 36 | column![ 37 | if self.is_vertical { 38 | center( 39 | row![ 40 | bar.vertical(), 41 | vertical_slider( 42 | 0.0..=100.0, 43 | self.value, 44 | Message::SliderChanged 45 | ) 46 | .step(0.01) 47 | ] 48 | .spacing(20), 49 | ) 50 | } else { 51 | center( 52 | column![ 53 | bar, 54 | slider(0.0..=100.0, self.value, Message::SliderChanged) 55 | .step(0.01) 56 | ] 57 | .spacing(20), 58 | ) 59 | }, 60 | center_x( 61 | checkbox("Vertical", self.is_vertical) 62 | .on_toggle(Message::ToggleVertical) 63 | ), 64 | ] 65 | .spacing(20) 66 | .padding(20) 67 | .into() 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /examples/qr_code/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "qr_code" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["qr_code"] 11 | -------------------------------------------------------------------------------- /examples/qr_code/README.md: -------------------------------------------------------------------------------- 1 | ## QR Code Generator 2 | 3 | A basic QR code generator that showcases the `QRCode` widget. 4 | 5 | The __[`main`]__ file contains all the code of the example. 6 | 7 |
8 | 9 |
10 | 11 | You can run it with `cargo run`: 12 | ``` 13 | cargo run --package qr_code 14 | ``` 15 | 16 | [`main`]: src/main.rs 17 | -------------------------------------------------------------------------------- /examples/screenshot/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "screenshot" 3 | version = "0.1.0" 4 | authors = ["Bingus "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["debug", "image", "advanced", "tokio"] 11 | 12 | image.workspace = true 13 | image.features = ["png"] 14 | 15 | tokio.workspace = true 16 | 17 | tracing-subscriber = "0.3" -------------------------------------------------------------------------------- /examples/scrollable/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "scrollable" 3 | version = "0.1.0" 4 | authors = ["Clark Moody "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["debug"] 11 | -------------------------------------------------------------------------------- /examples/scrollable/README.md: -------------------------------------------------------------------------------- 1 | # Scrollable 2 | An example showcasing the various size and style options for the Scrollable. 3 | 4 | All the example code is located in the __[`main`](src/main.rs)__ file. 5 | 6 |
7 | 8 | 9 | 10 |
11 | 12 | You can run it with `cargo run`: 13 | ``` 14 | cargo run --package scrollable 15 | ``` 16 | -------------------------------------------------------------------------------- /examples/scrollable/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/examples/scrollable/screenshot.png -------------------------------------------------------------------------------- /examples/sierpinski_triangle/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sierpinski_triangle" 3 | version = "0.1.0" 4 | authors = ["xkenmon "] 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["debug", "canvas"] 11 | 12 | rand = "0.8" 13 | -------------------------------------------------------------------------------- /examples/sierpinski_triangle/README.md: -------------------------------------------------------------------------------- 1 | ## Sierpinski Triangle Emulator 2 | 3 | A simple [Sierpiński triangle](https://en.wikipedia.org/wiki/Sierpi%C5%84ski_triangle) Emulator, use canvas and slider. 4 | 5 | Left-click add fixed point, right-click remove fixed point. 6 | 7 |
8 | 9 |
10 | 11 | You can run with cargo: 12 | ``` 13 | cargo run --package sierpinski_triangle 14 | ``` -------------------------------------------------------------------------------- /examples/slider/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "slider" 3 | version = "0.1.0" 4 | authors = ["Casper Rogild Storm"] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["svg"] 11 | -------------------------------------------------------------------------------- /examples/slider/README.md: -------------------------------------------------------------------------------- 1 | ## Slider 2 | 3 | A `Slider` is a bar and a handle that selects a single value from a range of values. 4 | There exists both `Slider` and `VerticalSlider` depending on which orientation you need. 5 | 6 |
7 | 8 |
9 | 10 | You can run it with `cargo run`: 11 | 12 | ``` 13 | cargo run --package slider 14 | ``` 15 | -------------------------------------------------------------------------------- /examples/slider/sliders.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/examples/slider/sliders.gif -------------------------------------------------------------------------------- /examples/slider/src/main.rs: -------------------------------------------------------------------------------- 1 | use iced::widget::{column, container, iced, slider, text, vertical_slider}; 2 | use iced::{Center, Element, Fill}; 3 | 4 | pub fn main() -> iced::Result { 5 | iced::run(Slider::update, Slider::view) 6 | } 7 | 8 | #[derive(Debug, Clone)] 9 | pub enum Message { 10 | SliderChanged(u8), 11 | } 12 | 13 | pub struct Slider { 14 | value: u8, 15 | } 16 | 17 | impl Slider { 18 | fn new() -> Self { 19 | Slider { value: 50 } 20 | } 21 | 22 | fn update(&mut self, message: Message) { 23 | match message { 24 | Message::SliderChanged(value) => { 25 | self.value = value; 26 | } 27 | } 28 | } 29 | 30 | fn view(&self) -> Element { 31 | let h_slider = container( 32 | slider(1..=100, self.value, Message::SliderChanged) 33 | .default(50) 34 | .shift_step(5), 35 | ) 36 | .width(250); 37 | 38 | let v_slider = container( 39 | vertical_slider(1..=100, self.value, Message::SliderChanged) 40 | .default(50) 41 | .shift_step(5), 42 | ) 43 | .height(200); 44 | 45 | let text = text(self.value); 46 | 47 | column![v_slider, h_slider, text, iced(self.value as f32),] 48 | .width(Fill) 49 | .align_x(Center) 50 | .spacing(20) 51 | .padding(20) 52 | .into() 53 | } 54 | } 55 | 56 | impl Default for Slider { 57 | fn default() -> Self { 58 | Self::new() 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /examples/solar_system/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "solar_system" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["debug", "canvas", "image", "tokio"] 11 | 12 | rand = "0.8.3" 13 | tracing-subscriber = "0.3" 14 | -------------------------------------------------------------------------------- /examples/solar_system/README.md: -------------------------------------------------------------------------------- 1 | ## Solar system 2 | 3 | An animated solar system drawn using the `Canvas` widget and showcasing how to compose different transforms. 4 | 5 | The __[`main`]__ file contains all the code of the example. 6 | 7 |
8 | 9 |
10 | 11 | You can run it with `cargo run`: 12 | ``` 13 | cargo run --package solar_system 14 | ``` 15 | 16 | [`main`]: src/main.rs 17 | -------------------------------------------------------------------------------- /examples/solar_system/assets/earth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/examples/solar_system/assets/earth.png -------------------------------------------------------------------------------- /examples/solar_system/assets/moon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/examples/solar_system/assets/moon.png -------------------------------------------------------------------------------- /examples/solar_system/assets/sun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/examples/solar_system/assets/sun.png -------------------------------------------------------------------------------- /examples/stopwatch/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stopwatch" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["smol"] 11 | -------------------------------------------------------------------------------- /examples/stopwatch/README.md: -------------------------------------------------------------------------------- 1 | ## Stopwatch 2 | 3 | A watch with start/stop and reset buttons showcasing how to listen to time. 4 | 5 | The __[`main`]__ file contains all the code of the example. 6 | 7 |
8 | 9 |
10 | 11 | You can run it with `cargo run`: 12 | ``` 13 | cargo run --package stopwatch 14 | ``` 15 | 16 | [`main`]: src/main.rs 17 | -------------------------------------------------------------------------------- /examples/styling/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "styling" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | 11 | [dev-dependencies] 12 | iced_test.workspace = true 13 | rayon = "1" 14 | -------------------------------------------------------------------------------- /examples/styling/README.md: -------------------------------------------------------------------------------- 1 | # Styling 2 | An example showcasing custom styling with a light and dark theme. 3 | 4 | All the example code is located in the __[`main`](src/main.rs)__ file. 5 | 6 |
7 | 8 |
9 | 10 | You can run it with `cargo run`: 11 | ``` 12 | cargo run --package styling 13 | ``` 14 | -------------------------------------------------------------------------------- /examples/styling/snapshots/catppuccin_frappé-tiny-skia.sha256: -------------------------------------------------------------------------------- 1 | 12ba47a34ed415825a23f8ef377a2d52950d2f8614a66bf46c0ec28d0cf15c85 -------------------------------------------------------------------------------- /examples/styling/snapshots/catppuccin_latte-tiny-skia.sha256: -------------------------------------------------------------------------------- 1 | fa00d7e0ff95b366945d409712d7fe4ce44fff22425236cb56b8b96a88815ee6 -------------------------------------------------------------------------------- /examples/styling/snapshots/catppuccin_macchiato-tiny-skia.sha256: -------------------------------------------------------------------------------- 1 | 4e594cfec775d51f7f836646c59bf4a2de07252721d66ddddea69c17e9112bae -------------------------------------------------------------------------------- /examples/styling/snapshots/catppuccin_mocha-tiny-skia.sha256: -------------------------------------------------------------------------------- 1 | 2ab665b51387c61086ae0199c29e291105bfe4583bd4c4daa652e30917f10bd6 -------------------------------------------------------------------------------- /examples/styling/snapshots/dark-tiny-skia.sha256: -------------------------------------------------------------------------------- 1 | 61c9ee377b33ffa800f512877e45ad5f41fbac36f5d3f06d1b62d6af6ee9d7b2 -------------------------------------------------------------------------------- /examples/styling/snapshots/dracula-tiny-skia.sha256: -------------------------------------------------------------------------------- 1 | 75f2fb12c9090a256708515de01a25e78905f71e134b7cda79f4fe44b2434052 -------------------------------------------------------------------------------- /examples/styling/snapshots/ferra-tiny-skia.sha256: -------------------------------------------------------------------------------- 1 | b4a1b42d2e21b2a493605745e6beb8e1f28cbeb01b73336e1e8d9061249a8311 -------------------------------------------------------------------------------- /examples/styling/snapshots/gruvbox_dark-tiny-skia.sha256: -------------------------------------------------------------------------------- 1 | eb52921b3ee23e1814268701c935d0dff387e7eb741c50443f75a7ab902b5e44 -------------------------------------------------------------------------------- /examples/styling/snapshots/gruvbox_light-tiny-skia.sha256: -------------------------------------------------------------------------------- 1 | bf6c4cbd6eeed0167d28509e37292f5ce26ed1d58bb156bedb861d0619a1945b -------------------------------------------------------------------------------- /examples/styling/snapshots/kanagawa_dragon-tiny-skia.sha256: -------------------------------------------------------------------------------- 1 | 83726a4175900a9ef159b80925f2fa985b4ea87bff78d8bb01918fb6c40d6175 -------------------------------------------------------------------------------- /examples/styling/snapshots/kanagawa_lotus-tiny-skia.sha256: -------------------------------------------------------------------------------- 1 | 54c8d44afbdd644f324cf40e744b3d7871263e44de2d9a91f6c10470c38ac3c6 -------------------------------------------------------------------------------- /examples/styling/snapshots/kanagawa_wave-tiny-skia.sha256: -------------------------------------------------------------------------------- 1 | 5713843396e2efcfc7cc8abd00343d5d66ce8b8a195212a9b75dbfeec8edf7a7 -------------------------------------------------------------------------------- /examples/styling/snapshots/light-tiny-skia.sha256: -------------------------------------------------------------------------------- 1 | f1b20ab79f8242776d9eb1ad9cff7090435aa416811c48a7c22c69b09cd8e70f -------------------------------------------------------------------------------- /examples/styling/snapshots/moonfly-tiny-skia.sha256: -------------------------------------------------------------------------------- 1 | 2c4be9dc1340b65cad6d15d5318017412eba1247a016379b83db379dde0214af -------------------------------------------------------------------------------- /examples/styling/snapshots/nightfly-tiny-skia.sha256: -------------------------------------------------------------------------------- 1 | 2d5d6b9613ccb6a2f23142baf704288037808e7a60ee05bdc73490d8c8780064 -------------------------------------------------------------------------------- /examples/styling/snapshots/nord-tiny-skia.sha256: -------------------------------------------------------------------------------- 1 | 512b8dfd4687a609d202436e75ecf1a5553acc2157000e77e31c1578941b033c -------------------------------------------------------------------------------- /examples/styling/snapshots/oxocarbon-tiny-skia.sha256: -------------------------------------------------------------------------------- 1 | 4b3b7a2dc65307a3551227f1c5d2bb49da15d29e320ccaa160e3d9fca44c1037 -------------------------------------------------------------------------------- /examples/styling/snapshots/solarized_dark-tiny-skia.sha256: -------------------------------------------------------------------------------- 1 | 15aa476c65304bde23e3648ceb424d6394f525f6c1d3e49ee1150376b6fd3068 -------------------------------------------------------------------------------- /examples/styling/snapshots/solarized_light-tiny-skia.sha256: -------------------------------------------------------------------------------- 1 | 04fcb0da640c6e7c1d86c95c74570c9f9d8f56056c9802eef332187f52c003ca -------------------------------------------------------------------------------- /examples/styling/snapshots/tokyo_night-tiny-skia.sha256: -------------------------------------------------------------------------------- 1 | 26e9660da3caa88e5a995739c986b142487f1449c1a5dc555abf7bc7cbca2345 -------------------------------------------------------------------------------- /examples/styling/snapshots/tokyo_night_light-tiny-skia.sha256: -------------------------------------------------------------------------------- 1 | 8d846a765ff96506ad4f26a672976cb1bfa997d4b09c5ecabf273d5e22ae0a3a -------------------------------------------------------------------------------- /examples/styling/snapshots/tokyo_night_storm-tiny-skia.sha256: -------------------------------------------------------------------------------- 1 | 0ecd51994f6eb37f111dc1b21cad72bb705499eb83156e9dc3ae2221ec392a42 -------------------------------------------------------------------------------- /examples/svg/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "svg" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["svg"] 11 | -------------------------------------------------------------------------------- /examples/svg/README.md: -------------------------------------------------------------------------------- 1 | ## SVG 2 | 3 | An application that renders the [Ghostscript Tiger] by leveraging the `Svg` widget. 4 | 5 | The __[`main`]__ file contains all the code of the example. 6 | 7 |
8 | 9 |
10 | 11 | You can run it with `cargo run`: 12 | ``` 13 | cargo run --package svg 14 | ``` 15 | 16 | [`main`]: src/main.rs 17 | [Ghostscript Tiger]: https://commons.wikimedia.org/wiki/File:Ghostscript_Tiger.svg 18 | -------------------------------------------------------------------------------- /examples/svg/src/main.rs: -------------------------------------------------------------------------------- 1 | use iced::widget::{center, center_x, checkbox, column, svg}; 2 | use iced::{Element, Fill, color}; 3 | 4 | pub fn main() -> iced::Result { 5 | iced::run(Tiger::update, Tiger::view) 6 | } 7 | 8 | #[derive(Debug, Default)] 9 | struct Tiger { 10 | apply_color_filter: bool, 11 | } 12 | 13 | #[derive(Debug, Clone, Copy)] 14 | pub enum Message { 15 | ToggleColorFilter(bool), 16 | } 17 | 18 | impl Tiger { 19 | fn update(&mut self, message: Message) { 20 | match message { 21 | Message::ToggleColorFilter(apply_color_filter) => { 22 | self.apply_color_filter = apply_color_filter; 23 | } 24 | } 25 | } 26 | 27 | fn view(&self) -> Element { 28 | let handle = svg::Handle::from_path(format!( 29 | "{}/resources/tiger.svg", 30 | env!("CARGO_MANIFEST_DIR") 31 | )); 32 | 33 | let svg = 34 | svg(handle) 35 | .width(Fill) 36 | .height(Fill) 37 | .style(|_theme, _status| svg::Style { 38 | color: if self.apply_color_filter { 39 | Some(color!(0x0000ff)) 40 | } else { 41 | None 42 | }, 43 | }); 44 | 45 | let apply_color_filter = 46 | checkbox("Apply a color filter", self.apply_color_filter) 47 | .on_toggle(Message::ToggleColorFilter); 48 | 49 | center(column![svg, center_x(apply_color_filter)].spacing(20)) 50 | .padding(20) 51 | .into() 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /examples/system_information/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "system_information" 3 | version = "0.1.0" 4 | authors = ["Richard "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["system"] 11 | 12 | bytesize = "1.1" 13 | -------------------------------------------------------------------------------- /examples/the_matrix/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "the_matrix" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["canvas", "tokio", "debug"] 11 | 12 | rand = "0.8" 13 | tracing-subscriber = "0.3" 14 | -------------------------------------------------------------------------------- /examples/toast/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "toast" 3 | version = "0.1.0" 4 | authors = ["tarkah "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["advanced"] 11 | -------------------------------------------------------------------------------- /examples/todos/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "todos" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["tokio", "debug", "time-travel"] 11 | 12 | serde = { version = "1.0", features = ["derive"] } 13 | serde_json = "1.0" 14 | uuid = { version = "1.0", features = ["v4", "fast-rng", "serde"] } 15 | 16 | [target.'cfg(not(target_arch = "wasm32"))'.dependencies] 17 | tokio.workspace = true 18 | tokio.features = ["fs", "time"] 19 | directories = "6.0" 20 | tracing-subscriber = "0.3" 21 | 22 | [target.'cfg(target_arch = "wasm32")'.dependencies] 23 | iced.workspace = true 24 | iced.features = ["debug", "webgl", "fira-sans"] 25 | 26 | uuid = { version = "1.0", features = ["js"] } 27 | web-sys = { workspace = true, features = ["Window", "Storage"] } 28 | wasmtimer.workspace = true 29 | 30 | [dev-dependencies] 31 | iced_test.workspace = true 32 | 33 | [package.metadata.deb] 34 | assets = [ 35 | ["target/release-opt/todos", "usr/bin/iced-todos", "755"], 36 | ["iced-todos.desktop", "usr/share/applications/", "644"], 37 | ] 38 | -------------------------------------------------------------------------------- /examples/todos/README.md: -------------------------------------------------------------------------------- 1 | ## Todos 2 | 3 | A todos tracker inspired by [TodoMVC]. It showcases dynamic layout, text input, checkboxes, scrollables, icons, and async actions! It automatically saves your tasks in the background, even if you did not finish typing them. 4 | 5 | All the example code is located in the __[`main`]__ file. 6 | 7 |
8 | 9 | 10 | 11 |
12 | 13 | You can run the native version with `cargo run`: 14 | ``` 15 | cargo run --package todos 16 | ``` 17 | 18 | The web version can be run with [`trunk`]: 19 | 20 | ``` 21 | cd examples/todos 22 | trunk serve 23 | ``` 24 | 25 | [`main`]: src/main.rs 26 | [TodoMVC]: http://todomvc.com/ 27 | [`trunk`]: https://trunkrs.dev/ 28 | -------------------------------------------------------------------------------- /examples/todos/fonts/icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/examples/todos/fonts/icons.ttf -------------------------------------------------------------------------------- /examples/todos/iced-todos.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=Todos - Iced 3 | Exec=iced-todos 4 | Type=Application 5 | -------------------------------------------------------------------------------- /examples/todos/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Todos - Iced 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/todos/snapshots/creates_a_new_task-tiny-skia.sha256: -------------------------------------------------------------------------------- 1 | 0e355b080ad33905145e9f70a3b29e2481197c8fc8f42491acd5358238ebbd5f -------------------------------------------------------------------------------- /examples/todos/snapshots/creates_a_new_task-wgpu.sha256: -------------------------------------------------------------------------------- 1 | 804a1bb6d49e3b3158463202960447d9e7820b967280f41dd0c34c00d3edf2c3 -------------------------------------------------------------------------------- /examples/tooltip/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tooltip" 3 | version = "0.1.0" 4 | authors = ["Yusuf Bera Ertan "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["debug"] 11 | -------------------------------------------------------------------------------- /examples/tooltip/README.md: -------------------------------------------------------------------------------- 1 | ## Tooltip 2 | 3 | A tooltip. 4 | 5 | It displays and positions a widget on another based on cursor position. 6 | 7 | The __[`main`]__ file contains all the code of the example. 8 | 9 | You can run it with `cargo run`: 10 | ``` 11 | cargo run --package tooltip 12 | ``` 13 | 14 | [`main`]: src/main.rs 15 | -------------------------------------------------------------------------------- /examples/tooltip/src/main.rs: -------------------------------------------------------------------------------- 1 | use iced::Element; 2 | use iced::widget::tooltip::Position; 3 | use iced::widget::{button, center, container, tooltip}; 4 | 5 | pub fn main() -> iced::Result { 6 | iced::run(Tooltip::update, Tooltip::view) 7 | } 8 | 9 | #[derive(Default)] 10 | struct Tooltip { 11 | position: Position, 12 | } 13 | 14 | #[derive(Debug, Clone)] 15 | enum Message { 16 | ChangePosition, 17 | } 18 | 19 | impl Tooltip { 20 | fn update(&mut self, message: Message) { 21 | match message { 22 | Message::ChangePosition => { 23 | let position = match &self.position { 24 | Position::Top => Position::Bottom, 25 | Position::Bottom => Position::Left, 26 | Position::Left => Position::Right, 27 | Position::Right => Position::FollowCursor, 28 | Position::FollowCursor => Position::Top, 29 | }; 30 | 31 | self.position = position; 32 | } 33 | } 34 | } 35 | 36 | fn view(&self) -> Element { 37 | let tooltip = tooltip( 38 | button("Press to change position") 39 | .on_press(Message::ChangePosition), 40 | position_to_text(self.position), 41 | self.position, 42 | ) 43 | .gap(10) 44 | .style(container::rounded_box); 45 | 46 | center(tooltip).into() 47 | } 48 | } 49 | 50 | fn position_to_text<'a>(position: Position) -> &'a str { 51 | match position { 52 | Position::FollowCursor => "Follow Cursor", 53 | Position::Top => "Top", 54 | Position::Bottom => "Bottom", 55 | Position::Left => "Left", 56 | Position::Right => "Right", 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /examples/tour/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tour" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["image", "debug"] 11 | 12 | [target.'cfg(not(target_arch = "wasm32"))'.dependencies] 13 | tracing-subscriber = "0.3" 14 | open = "5" 15 | 16 | [target.'cfg(target_arch = "wasm32")'.dependencies] 17 | iced.workspace = true 18 | iced.features = ["image", "debug", "webgl", "fira-sans"] 19 | 20 | console_error_panic_hook = "0.1" 21 | console_log = "1.0" 22 | -------------------------------------------------------------------------------- /examples/tour/README.md: -------------------------------------------------------------------------------- 1 | ## Tour 2 | 3 | A simple UI tour that can run both on native platforms and the web! It showcases different widgets that can be built using Iced. 4 | 5 | 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__. 6 | 7 |
8 | 9 | 10 | 11 |
12 | 13 | [`main`]: src/main.rs 14 | [`iced_winit`]: ../../winit 15 | [`iced_native`]: ../../native 16 | [`iced_wgpu`]: ../../wgpu 17 | [`iced_web`]: https://github.com/iced-rs/iced_web 18 | [`winit`]: https://github.com/rust-windowing/winit 19 | [`wgpu`]: https://github.com/gfx-rs/wgpu-rs 20 | 21 | You can run the native version with `cargo run`: 22 | ``` 23 | cargo run --package tour 24 | ``` 25 | 26 | The web version can be run with [`trunk`]: 27 | 28 | ``` 29 | cd examples/tour 30 | trunk serve 31 | ``` 32 | 33 | [`trunk`]: https://trunkrs.dev/ 34 | -------------------------------------------------------------------------------- /examples/tour/images/ferris.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/examples/tour/images/ferris.png -------------------------------------------------------------------------------- /examples/tour/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Tour - Iced 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/url_handler/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "url_handler" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | -------------------------------------------------------------------------------- /examples/url_handler/src/main.rs: -------------------------------------------------------------------------------- 1 | use iced::event; 2 | use iced::widget::{center, text}; 3 | use iced::{Element, Subscription}; 4 | 5 | pub fn main() -> iced::Result { 6 | iced::application(App::default, App::update, App::view) 7 | .subscription(App::subscription) 8 | .run() 9 | } 10 | 11 | #[derive(Debug, Default)] 12 | struct App { 13 | url: Option, 14 | } 15 | 16 | #[derive(Debug, Clone)] 17 | enum Message { 18 | UrlReceived(String), 19 | } 20 | 21 | impl App { 22 | fn update(&mut self, message: Message) { 23 | match message { 24 | Message::UrlReceived(url) => { 25 | self.url = Some(url); 26 | } 27 | } 28 | } 29 | 30 | fn subscription(&self) -> Subscription { 31 | event::listen_url().map(Message::UrlReceived) 32 | } 33 | 34 | fn view(&self) -> Element { 35 | let content = match &self.url { 36 | Some(url) => text(url), 37 | None => text("No URL received yet!"), 38 | }; 39 | 40 | center(content.size(48)).into() 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /examples/vectorial_text/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "vectorial_text" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced = { path = "../..", features = ["canvas", "debug"] } 10 | -------------------------------------------------------------------------------- /examples/visible_bounds/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "visible_bounds" 3 | version = "0.1.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["debug"] 11 | -------------------------------------------------------------------------------- /examples/websocket/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "websocket" 3 | version = "1.0.0" 4 | authors = ["Héctor Ramón Jiménez "] 5 | edition = "2024" 6 | publish = false 7 | 8 | [dependencies] 9 | iced.workspace = true 10 | iced.features = ["debug", "tokio", "sipper"] 11 | 12 | warp = "0.3" 13 | 14 | [dependencies.async-tungstenite] 15 | version = "0.25" 16 | features = ["tokio-rustls-webpki-roots"] 17 | 18 | [dependencies.tokio] 19 | workspace = true 20 | features = ["time"] 21 | -------------------------------------------------------------------------------- /examples/websocket/README.md: -------------------------------------------------------------------------------- 1 | ## Websocket 2 | 3 | A simple example that keeps a WebSocket connection open to an echo server. 4 | 5 | The example consists of 3 modules: 6 | - [`main`] contains the `Application` logic. 7 | - [`echo`] implements a WebSocket client for the [`echo::server`] with `async-tungstenite`. 8 | - [`echo::server`] implements a simple WebSocket echo server with `warp`. 9 | 10 | You can run it with `cargo run`: 11 | ``` 12 | cargo run --package websocket 13 | ``` 14 | 15 | [`main`]: src/main.rs 16 | [`echo`]: src/echo.rs 17 | [`echo::server`]: src/echo/server.rs 18 | -------------------------------------------------------------------------------- /futures/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "iced_futures" 3 | description = "Commands, subscriptions, and future executors for iced" 4 | version.workspace = true 5 | edition.workspace = true 6 | authors.workspace = true 7 | license.workspace = true 8 | repository.workspace = true 9 | homepage.workspace = true 10 | categories.workspace = true 11 | keywords.workspace = true 12 | 13 | [lints] 14 | workspace = true 15 | 16 | [package.metadata.docs.rs] 17 | rustdoc-args = ["--cfg", "docsrs"] 18 | all-features = true 19 | 20 | [features] 21 | thread-pool = ["futures/thread-pool"] 22 | 23 | [dependencies] 24 | iced_core.workspace = true 25 | 26 | futures.workspace = true 27 | futures.features = ["std", "async-await"] 28 | 29 | log.workspace = true 30 | rustc-hash.workspace = true 31 | 32 | [target.'cfg(not(target_arch = "wasm32"))'.dependencies] 33 | smol.workspace = true 34 | smol.optional = true 35 | 36 | tokio.workspace = true 37 | tokio.optional = true 38 | tokio.features = ["rt", "rt-multi-thread", "time"] 39 | 40 | [target.'cfg(target_arch = "wasm32")'.dependencies] 41 | wasm-bindgen-futures.workspace = true 42 | wasmtimer.workspace = true 43 | -------------------------------------------------------------------------------- /futures/src/backend.rs: -------------------------------------------------------------------------------- 1 | //! The underlying implementations of the `iced_futures` contract! 2 | pub mod null; 3 | 4 | #[cfg(not(target_arch = "wasm32"))] 5 | pub mod native; 6 | 7 | #[cfg(target_arch = "wasm32")] 8 | pub mod wasm; 9 | 10 | pub mod default; 11 | -------------------------------------------------------------------------------- /futures/src/backend/default.rs: -------------------------------------------------------------------------------- 1 | //! A default, cross-platform backend. 2 | //! 3 | //! - On native platforms, it will use: 4 | //! - `backend::native::tokio` when the `tokio` feature is enabled. 5 | //! - `backend::native::smol` when the `smol` feature is enabled. 6 | //! - `backend::native::thread_pool` when the `thread-pool` feature is enabled. 7 | //! - `backend::null` otherwise. 8 | //! 9 | //! - On Wasm, it will use `backend::wasm::wasm_bindgen`. 10 | #[cfg(not(target_arch = "wasm32"))] 11 | mod platform { 12 | #[cfg(feature = "tokio")] 13 | pub use crate::backend::native::tokio::*; 14 | 15 | #[cfg(all(feature = "smol", not(feature = "tokio"),))] 16 | pub use crate::backend::native::smol::*; 17 | 18 | #[cfg(all( 19 | feature = "thread-pool", 20 | not(any(feature = "tokio", feature = "smol")) 21 | ))] 22 | pub use crate::backend::native::thread_pool::*; 23 | 24 | #[cfg(not(any( 25 | feature = "tokio", 26 | feature = "smol", 27 | feature = "thread-pool" 28 | )))] 29 | pub use crate::backend::null::*; 30 | } 31 | 32 | #[cfg(target_arch = "wasm32")] 33 | mod platform { 34 | pub use crate::backend::wasm::wasm_bindgen::*; 35 | } 36 | 37 | pub use platform::*; 38 | -------------------------------------------------------------------------------- /futures/src/backend/native.rs: -------------------------------------------------------------------------------- 1 | //! Backends that are only available in native platforms: Windows, macOS, or Linux. 2 | #[cfg(feature = "tokio")] 3 | pub mod tokio; 4 | 5 | #[cfg(feature = "smol")] 6 | pub mod smol; 7 | 8 | #[cfg(feature = "thread-pool")] 9 | pub mod thread_pool; 10 | -------------------------------------------------------------------------------- /futures/src/backend/native/smol.rs: -------------------------------------------------------------------------------- 1 | //! A `smol` backend. 2 | 3 | /// A `smol` executor. 4 | #[derive(Debug)] 5 | pub struct Executor; 6 | 7 | impl crate::Executor for Executor { 8 | fn new() -> Result { 9 | Ok(Self) 10 | } 11 | 12 | fn spawn(&self, future: impl Future + Send + 'static) { 13 | smol::spawn(future).detach(); 14 | } 15 | 16 | fn block_on(&self, future: impl Future) -> T { 17 | smol::block_on(future) 18 | } 19 | } 20 | 21 | pub mod time { 22 | //! Listen and react to time. 23 | use crate::subscription::{self, Hasher, Subscription}; 24 | 25 | /// Returns a [`Subscription`] that produces messages at a set interval. 26 | /// 27 | /// The first message is produced after a `duration`, and then continues to 28 | /// produce more messages every `duration` after that. 29 | pub fn every( 30 | duration: std::time::Duration, 31 | ) -> Subscription { 32 | subscription::from_recipe(Every(duration)) 33 | } 34 | 35 | #[derive(Debug)] 36 | struct Every(std::time::Duration); 37 | 38 | impl subscription::Recipe for Every { 39 | type Output = std::time::Instant; 40 | 41 | fn hash(&self, state: &mut Hasher) { 42 | use std::hash::Hash; 43 | 44 | std::any::TypeId::of::().hash(state); 45 | self.0.hash(state); 46 | } 47 | 48 | fn stream( 49 | self: Box, 50 | _input: subscription::EventStream, 51 | ) -> futures::stream::BoxStream<'static, Self::Output> { 52 | use futures::stream::StreamExt; 53 | 54 | smol::Timer::interval(self.0).boxed() 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /futures/src/backend/native/thread_pool.rs: -------------------------------------------------------------------------------- 1 | //! A `ThreadPool` backend. 2 | 3 | /// A thread pool executor for futures. 4 | pub type Executor = futures::executor::ThreadPool; 5 | 6 | impl crate::Executor for Executor { 7 | fn new() -> Result { 8 | futures::executor::ThreadPool::new() 9 | } 10 | 11 | fn spawn(&self, future: impl Future + Send + 'static) { 12 | self.spawn_ok(future); 13 | } 14 | 15 | fn block_on(&self, future: impl Future) -> T { 16 | futures::executor::block_on(future) 17 | } 18 | } 19 | 20 | pub mod time { 21 | //! Listen and react to time. 22 | } 23 | -------------------------------------------------------------------------------- /futures/src/backend/null.rs: -------------------------------------------------------------------------------- 1 | //! A backend that does nothing! 2 | use crate::MaybeSend; 3 | 4 | /// An executor that drops all the futures, instead of spawning them. 5 | #[derive(Debug)] 6 | pub struct Executor; 7 | 8 | impl crate::Executor for Executor { 9 | fn new() -> Result { 10 | Ok(Self) 11 | } 12 | 13 | fn spawn(&self, _future: impl Future + MaybeSend + 'static) {} 14 | 15 | #[cfg(not(target_arch = "wasm32"))] 16 | fn block_on(&self, _future: impl Future) -> T { 17 | unimplemented!() 18 | } 19 | } 20 | 21 | pub mod time { 22 | //! Listen and react to time. 23 | } 24 | -------------------------------------------------------------------------------- /futures/src/backend/wasm.rs: -------------------------------------------------------------------------------- 1 | //! Backends that are only available on Wasm targets. 2 | pub mod wasm_bindgen; 3 | -------------------------------------------------------------------------------- /futures/src/backend/wasm/wasm_bindgen.rs: -------------------------------------------------------------------------------- 1 | //! A `wasm-bindgen-futures` backend. 2 | 3 | /// A `wasm-bindgen-futures` executor. 4 | #[derive(Debug)] 5 | pub struct Executor; 6 | 7 | impl crate::Executor for Executor { 8 | fn new() -> Result { 9 | Ok(Self) 10 | } 11 | 12 | fn spawn(&self, future: impl futures::Future + 'static) { 13 | wasm_bindgen_futures::spawn_local(future); 14 | } 15 | } 16 | 17 | pub mod time { 18 | //! Listen and react to time. 19 | use crate::subscription::Subscription; 20 | 21 | use wasmtimer::std::Instant; 22 | 23 | /// Returns a [`Subscription`] that produces messages at a set interval. 24 | /// 25 | /// The first message is produced after a `duration`, and then continues to 26 | /// produce more messages every `duration` after that. 27 | pub fn every(duration: std::time::Duration) -> Subscription { 28 | Subscription::run_with(duration, |duration| { 29 | use futures::stream::StreamExt; 30 | 31 | let mut interval = wasmtimer::tokio::interval(*duration); 32 | interval.set_missed_tick_behavior( 33 | wasmtimer::tokio::MissedTickBehavior::Skip, 34 | ); 35 | 36 | let stream = { 37 | futures::stream::unfold(interval, |mut interval| async move { 38 | Some((interval.tick().await, interval)) 39 | }) 40 | }; 41 | 42 | stream.boxed() 43 | }) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /futures/src/executor.rs: -------------------------------------------------------------------------------- 1 | //! Choose your preferred executor to power a runtime. 2 | use crate::MaybeSend; 3 | 4 | /// A type that can run futures. 5 | pub trait Executor: Sized { 6 | /// Creates a new [`Executor`]. 7 | fn new() -> Result 8 | where 9 | Self: Sized; 10 | 11 | /// Spawns a future in the [`Executor`]. 12 | fn spawn(&self, future: impl Future + MaybeSend + 'static); 13 | 14 | /// Runs a future to completion in the current thread within the [`Executor`]. 15 | #[cfg(not(target_arch = "wasm32"))] 16 | fn block_on(&self, future: impl Future) -> T; 17 | 18 | /// Runs the given closure inside the [`Executor`]. 19 | /// 20 | /// Some executors, like `tokio`, require some global state to be in place 21 | /// before creating futures. This method can be leveraged to set up this 22 | /// global state, call a function, restore the state, and obtain the result 23 | /// of the call. 24 | fn enter(&self, f: impl FnOnce() -> R) -> R { 25 | f() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /futures/src/keyboard.rs: -------------------------------------------------------------------------------- 1 | //! Listen to keyboard events. 2 | use crate::MaybeSend; 3 | use crate::core; 4 | use crate::core::event; 5 | use crate::core::keyboard::{Event, Key, Modifiers}; 6 | use crate::subscription::{self, Subscription}; 7 | 8 | /// Listens to keyboard key presses and calls the given function 9 | /// to map them into actual messages. 10 | /// 11 | /// If the function returns `None`, the key press will be simply 12 | /// ignored. 13 | pub fn on_key_press( 14 | f: fn(Key, Modifiers) -> Option, 15 | ) -> Subscription 16 | where 17 | Message: MaybeSend + 'static, 18 | { 19 | #[derive(Hash)] 20 | struct OnKeyPress; 21 | 22 | subscription::filter_map((OnKeyPress, f), move |event| match event { 23 | subscription::Event::Interaction { 24 | event: 25 | core::Event::Keyboard(Event::KeyPressed { key, modifiers, .. }), 26 | status: event::Status::Ignored, 27 | .. 28 | } => f(key, modifiers), 29 | _ => None, 30 | }) 31 | } 32 | 33 | /// Listens to keyboard key releases and calls the given function 34 | /// to map them into actual messages. 35 | /// 36 | /// If the function returns `None`, the key release will be simply 37 | /// ignored. 38 | pub fn on_key_release( 39 | f: fn(Key, Modifiers) -> Option, 40 | ) -> Subscription 41 | where 42 | Message: MaybeSend + 'static, 43 | { 44 | #[derive(Hash)] 45 | struct OnKeyRelease; 46 | 47 | subscription::filter_map((OnKeyRelease, f), move |event| match event { 48 | subscription::Event::Interaction { 49 | event: 50 | core::Event::Keyboard(Event::KeyReleased { key, modifiers, .. }), 51 | status: event::Status::Ignored, 52 | .. 53 | } => f(key, modifiers), 54 | _ => None, 55 | }) 56 | } 57 | -------------------------------------------------------------------------------- /futures/src/maybe.rs: -------------------------------------------------------------------------------- 1 | #[cfg(not(target_arch = "wasm32"))] 2 | mod platform { 3 | /// An extension trait that enforces `Send` only on native platforms. 4 | /// 5 | /// Useful for writing cross-platform async code! 6 | pub trait MaybeSend: Send {} 7 | 8 | impl MaybeSend for T where T: Send {} 9 | 10 | /// An extension trait that enforces `Sync` only on native platforms. 11 | /// 12 | /// Useful for writing cross-platform async code! 13 | pub trait MaybeSync: Sync {} 14 | 15 | impl MaybeSync for T where T: Sync {} 16 | } 17 | 18 | #[cfg(target_arch = "wasm32")] 19 | mod platform { 20 | /// An extension trait that enforces `Send` only on native platforms. 21 | /// 22 | /// Useful for writing cross-platform async code! 23 | pub trait MaybeSend {} 24 | 25 | impl MaybeSend for T {} 26 | 27 | /// An extension trait that enforces `Sync` only on native platforms. 28 | /// 29 | /// Useful for writing cross-platform async code! 30 | pub trait MaybeSync {} 31 | 32 | impl MaybeSync for T {} 33 | } 34 | 35 | pub use platform::{MaybeSend, MaybeSync}; 36 | -------------------------------------------------------------------------------- /futures/src/stream.rs: -------------------------------------------------------------------------------- 1 | //! Create asynchronous streams of data. 2 | use futures::channel::mpsc; 3 | use futures::stream::{self, Stream, StreamExt}; 4 | 5 | /// Creates a new [`Stream`] that produces the items sent from a [`Future`] 6 | /// to the [`mpsc::Sender`] provided to the closure. 7 | /// 8 | /// This is a more ergonomic [`stream::unfold`], which allows you to go 9 | /// from the "world of futures" to the "world of streams" by simply looping 10 | /// and publishing to an async channel from inside a [`Future`]. 11 | pub fn channel( 12 | size: usize, 13 | f: impl AsyncFnOnce(mpsc::Sender), 14 | ) -> impl Stream { 15 | let (sender, receiver) = mpsc::channel(size); 16 | 17 | let runner = stream::once(f(sender)).filter_map(|_| async { None }); 18 | 19 | stream::select(receiver, runner) 20 | } 21 | 22 | /// Creates a new [`Stream`] that produces the items sent from a [`Future`] 23 | /// that can fail to the [`mpsc::Sender`] provided to the closure. 24 | pub fn try_channel( 25 | size: usize, 26 | f: impl AsyncFnOnce(mpsc::Sender) -> Result<(), E>, 27 | ) -> impl Stream> { 28 | let (sender, receiver) = mpsc::channel(size); 29 | 30 | let runner = stream::once(f(sender)).filter_map(|result| async { 31 | match result { 32 | Ok(()) => None, 33 | Err(error) => Some(Err(error)), 34 | } 35 | }); 36 | 37 | stream::select(receiver.map(Ok), runner) 38 | } 39 | -------------------------------------------------------------------------------- /graphics/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "iced_graphics" 3 | description = "A bunch of backend-agnostic types that can be leveraged to build a renderer for iced" 4 | version.workspace = true 5 | edition.workspace = true 6 | authors.workspace = true 7 | license.workspace = true 8 | repository.workspace = true 9 | homepage.workspace = true 10 | categories.workspace = true 11 | keywords.workspace = true 12 | 13 | [lints] 14 | workspace = true 15 | 16 | [package.metadata.docs.rs] 17 | rustdoc-args = ["--cfg", "docsrs"] 18 | all-features = true 19 | 20 | [features] 21 | geometry = ["lyon_path"] 22 | image = ["dep:image", "kamadak-exif"] 23 | svg = [] 24 | web-colors = [] 25 | fira-sans = [] 26 | 27 | [dependencies] 28 | iced_core.workspace = true 29 | iced_futures.workspace = true 30 | 31 | bitflags.workspace = true 32 | bytemuck.workspace = true 33 | cosmic-text.workspace = true 34 | half.workspace = true 35 | log.workspace = true 36 | raw-window-handle.workspace = true 37 | rustc-hash.workspace = true 38 | thiserror.workspace = true 39 | unicode-segmentation.workspace = true 40 | 41 | image.workspace = true 42 | image.optional = true 43 | 44 | kamadak-exif.workspace = true 45 | kamadak-exif.optional = true 46 | 47 | lyon_path.workspace = true 48 | lyon_path.optional = true 49 | -------------------------------------------------------------------------------- /graphics/fonts/FiraSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/graphics/fonts/FiraSans-Regular.ttf -------------------------------------------------------------------------------- /graphics/fonts/Iced-Icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iced-rs/iced/7afbb89ebfd49aa86453d45f7d9c13a7c48b58f2/graphics/fonts/Iced-Icons.ttf -------------------------------------------------------------------------------- /graphics/src/antialiasing.rs: -------------------------------------------------------------------------------- 1 | /// An antialiasing strategy. 2 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 3 | pub enum Antialiasing { 4 | /// Multisample AA with 2 samples 5 | MSAAx2, 6 | /// Multisample AA with 4 samples 7 | MSAAx4, 8 | /// Multisample AA with 8 samples 9 | MSAAx8, 10 | /// Multisample AA with 16 samples 11 | MSAAx16, 12 | } 13 | 14 | impl Antialiasing { 15 | /// Returns the amount of samples of the [`Antialiasing`]. 16 | pub fn sample_count(self) -> u32 { 17 | match self { 18 | Antialiasing::MSAAx2 => 2, 19 | Antialiasing::MSAAx4 => 4, 20 | Antialiasing::MSAAx8 => 8, 21 | Antialiasing::MSAAx16 => 16, 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /graphics/src/color.rs: -------------------------------------------------------------------------------- 1 | //! Manage colors for shaders. 2 | use crate::core::Color; 3 | 4 | use bytemuck::{Pod, Zeroable}; 5 | 6 | /// A color packed as 4 floats representing RGBA channels. 7 | #[derive(Debug, Clone, Copy, PartialEq, Zeroable, Pod)] 8 | #[repr(C)] 9 | pub struct Packed([f32; 4]); 10 | 11 | impl Packed { 12 | /// Returns the internal components of the [`Packed`] color. 13 | pub fn components(self) -> [f32; 4] { 14 | self.0 15 | } 16 | } 17 | 18 | /// A flag that indicates whether the renderer should perform gamma correction. 19 | pub const GAMMA_CORRECTION: bool = internal::GAMMA_CORRECTION; 20 | 21 | /// Packs a [`Color`]. 22 | pub fn pack(color: impl Into) -> Packed { 23 | Packed(internal::pack(color.into())) 24 | } 25 | 26 | #[cfg(not(feature = "web-colors"))] 27 | mod internal { 28 | use crate::core::Color; 29 | 30 | pub const GAMMA_CORRECTION: bool = true; 31 | 32 | pub fn pack(color: Color) -> [f32; 4] { 33 | color.into_linear() 34 | } 35 | } 36 | 37 | #[cfg(feature = "web-colors")] 38 | mod internal { 39 | use crate::core::Color; 40 | 41 | pub const GAMMA_CORRECTION: bool = false; 42 | 43 | pub fn pack(color: Color) -> [f32; 4] { 44 | [color.r, color.g, color.b, color.a] 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /graphics/src/error.rs: -------------------------------------------------------------------------------- 1 | //! See what can go wrong when creating graphical backends. 2 | 3 | /// An error that occurred while creating an application's graphical context. 4 | #[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)] 5 | pub enum Error { 6 | /// The requested backend version is not supported. 7 | #[error("the requested backend version is not supported")] 8 | VersionNotSupported, 9 | 10 | /// Failed to find any pixel format that matches the criteria. 11 | #[error("failed to find any pixel format that matches the criteria")] 12 | NoAvailablePixelFormat, 13 | 14 | /// A suitable graphics adapter or device could not be found. 15 | #[error("a suitable graphics adapter or device could not be found")] 16 | GraphicsAdapterNotFound { 17 | /// The name of the backend where the error happened 18 | backend: &'static str, 19 | /// The reason why this backend could not be used 20 | reason: Reason, 21 | }, 22 | 23 | /// An error occurred in the context's internal backend 24 | #[error("an error occurred in the context's internal backend")] 25 | BackendError(String), 26 | 27 | /// Multiple errors occurred 28 | #[error("multiple errors occurred: {0:?}")] 29 | List(Vec), 30 | } 31 | 32 | /// The reason why a graphics adapter could not be found 33 | #[derive(Debug, Clone, PartialEq, Eq)] 34 | pub enum Reason { 35 | /// The backend did not match the preference 36 | DidNotMatch { 37 | /// The preferred backend 38 | preferred_backend: String, 39 | }, 40 | /// The request to create the backend failed 41 | RequestFailed(String), 42 | } 43 | -------------------------------------------------------------------------------- /graphics/src/geometry.rs: -------------------------------------------------------------------------------- 1 | //! Build and draw geometry. 2 | pub mod fill; 3 | pub mod frame; 4 | pub mod path; 5 | pub mod stroke; 6 | 7 | mod cache; 8 | mod style; 9 | mod text; 10 | 11 | pub use cache::Cache; 12 | pub use fill::Fill; 13 | pub use frame::Frame; 14 | pub use path::Path; 15 | pub use stroke::{LineCap, LineDash, LineJoin, Stroke}; 16 | pub use style::Style; 17 | pub use text::Text; 18 | 19 | pub use crate::core::{Image, Svg}; 20 | pub use crate::gradient::{self, Gradient}; 21 | 22 | use crate::cache::Cached; 23 | use crate::core::{self, Size}; 24 | 25 | /// A renderer capable of drawing some [`Self::Geometry`]. 26 | pub trait Renderer: core::Renderer { 27 | /// The kind of geometry this renderer can draw. 28 | type Geometry: Cached; 29 | 30 | /// The kind of [`Frame`] this renderer supports. 31 | type Frame: frame::Backend; 32 | 33 | /// Creates a new [`Self::Frame`]. 34 | fn new_frame(&self, size: Size) -> Self::Frame; 35 | 36 | /// Draws the given [`Self::Geometry`]. 37 | fn draw_geometry(&mut self, geometry: Self::Geometry); 38 | } 39 | 40 | #[cfg(debug_assertions)] 41 | impl Renderer for () { 42 | type Geometry = (); 43 | type Frame = (); 44 | 45 | fn new_frame(&self, _size: Size) -> Self::Frame {} 46 | 47 | fn draw_geometry(&mut self, _geometry: Self::Geometry) {} 48 | } 49 | -------------------------------------------------------------------------------- /graphics/src/geometry/fill.rs: -------------------------------------------------------------------------------- 1 | //! Fill [`Geometry`] with a certain style. 2 | //! 3 | //! [`Geometry`]: super::Renderer::Geometry 4 | pub use crate::geometry::Style; 5 | 6 | use crate::core::Color; 7 | use crate::gradient::{self, Gradient}; 8 | 9 | /// The style used to fill geometry. 10 | #[derive(Debug, Clone, Copy)] 11 | pub struct Fill { 12 | /// The color or gradient of the fill. 13 | /// 14 | /// By default, it is set to [`Style::Solid`] with [`Color::BLACK`]. 15 | pub style: Style, 16 | 17 | /// The fill rule defines how to determine what is inside and what is 18 | /// outside of a shape. 19 | /// 20 | /// See the [SVG specification][1] for more details. 21 | /// 22 | /// By default, it is set to `NonZero`. 23 | /// 24 | /// [1]: https://www.w3.org/TR/SVG/painting.html#FillRuleProperty 25 | pub rule: Rule, 26 | } 27 | 28 | impl Default for Fill { 29 | fn default() -> Self { 30 | Self { 31 | style: Style::Solid(Color::BLACK), 32 | rule: Rule::NonZero, 33 | } 34 | } 35 | } 36 | 37 | impl From for Fill { 38 | fn from(color: Color) -> Fill { 39 | Fill { 40 | style: Style::Solid(color), 41 | ..Fill::default() 42 | } 43 | } 44 | } 45 | 46 | impl From for Fill { 47 | fn from(gradient: Gradient) -> Self { 48 | Fill { 49 | style: Style::Gradient(gradient), 50 | ..Default::default() 51 | } 52 | } 53 | } 54 | 55 | impl From for Fill { 56 | fn from(gradient: gradient::Linear) -> Self { 57 | Fill { 58 | style: Style::Gradient(Gradient::Linear(gradient)), 59 | ..Default::default() 60 | } 61 | } 62 | } 63 | 64 | /// The fill rule defines how to determine what is inside and what is outside of 65 | /// a shape. 66 | /// 67 | /// See the [SVG specification][1]. 68 | /// 69 | /// [1]: https://www.w3.org/TR/SVG/painting.html#FillRuleProperty 70 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 71 | #[allow(missing_docs)] 72 | pub enum Rule { 73 | NonZero, 74 | EvenOdd, 75 | } 76 | -------------------------------------------------------------------------------- /graphics/src/geometry/path/arc.rs: -------------------------------------------------------------------------------- 1 | //! Build and draw curves. 2 | use iced_core::{Point, Radians, Vector}; 3 | 4 | /// A segment of a differentiable curve. 5 | #[derive(Debug, Clone, Copy)] 6 | pub struct Arc { 7 | /// The center of the arc. 8 | pub center: Point, 9 | /// The radius of the arc. 10 | pub radius: f32, 11 | /// The start of the segment's angle, clockwise rotation from positive x-axis. 12 | pub start_angle: Radians, 13 | /// The end of the segment's angle, clockwise rotation from positive x-axis. 14 | pub end_angle: Radians, 15 | } 16 | 17 | /// An elliptical [`Arc`]. 18 | #[derive(Debug, Clone, Copy)] 19 | pub struct Elliptical { 20 | /// The center of the arc. 21 | pub center: Point, 22 | /// The radii of the arc's ellipse. The horizontal and vertical half-dimensions of the ellipse will match the x and y values of the radii vector. 23 | pub radii: Vector, 24 | /// The clockwise rotation of the arc's ellipse. 25 | pub rotation: Radians, 26 | /// The start of the segment's angle, clockwise rotation from positive x-axis. 27 | pub start_angle: Radians, 28 | /// The end of the segment's angle, clockwise rotation from positive x-axis. 29 | pub end_angle: Radians, 30 | } 31 | 32 | impl From for Elliptical { 33 | fn from(arc: Arc) -> Elliptical { 34 | Elliptical { 35 | center: arc.center, 36 | radii: Vector::new(arc.radius, arc.radius), 37 | rotation: Radians(0.0), 38 | start_angle: arc.start_angle, 39 | end_angle: arc.end_angle, 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /graphics/src/geometry/style.rs: -------------------------------------------------------------------------------- 1 | use crate::core::Color; 2 | use crate::geometry::Gradient; 3 | 4 | /// The coloring style of some drawing. 5 | #[derive(Debug, Clone, Copy, PartialEq)] 6 | pub enum Style { 7 | /// A solid [`Color`]. 8 | Solid(Color), 9 | 10 | /// A [`Gradient`] color. 11 | Gradient(Gradient), 12 | } 13 | 14 | impl From for Style { 15 | fn from(color: Color) -> Self { 16 | Self::Solid(color) 17 | } 18 | } 19 | 20 | impl From for Style { 21 | fn from(gradient: Gradient) -> Self { 22 | Self::Gradient(gradient) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /graphics/src/image/storage.rs: -------------------------------------------------------------------------------- 1 | //! Store images. 2 | use iced_core::Size; 3 | 4 | use std::fmt::Debug; 5 | 6 | /// Stores cached image data for use in rendering 7 | pub trait Storage { 8 | /// The type of an [`Entry`] in the [`Storage`]. 9 | type Entry: Entry; 10 | 11 | /// State provided to upload or remove a [`Self::Entry`]. 12 | type State<'a>; 13 | 14 | /// Upload the image data of a [`Self::Entry`]. 15 | fn upload( 16 | &mut self, 17 | width: u32, 18 | height: u32, 19 | data: &[u8], 20 | state: &mut Self::State<'_>, 21 | ) -> Option; 22 | 23 | /// Remove a [`Self::Entry`] from the [`Storage`]. 24 | fn remove(&mut self, entry: &Self::Entry, state: &mut Self::State<'_>); 25 | } 26 | 27 | /// An entry in some [`Storage`], 28 | pub trait Entry: Debug { 29 | /// The [`Size`] of the [`Entry`]. 30 | fn size(&self) -> Size; 31 | } 32 | -------------------------------------------------------------------------------- /graphics/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! A bunch of backend-agnostic types that can be leveraged to build a renderer 2 | //! for [`iced`]. 3 | //! 4 | //! ![The native path of the Iced ecosystem](https://github.com/iced-rs/iced/blob/0525d76ff94e828b7b21634fa94a747022001c83/docs/graphs/native.png?raw=true) 5 | //! 6 | //! [`iced`]: https://github.com/iced-rs/iced 7 | #![doc( 8 | html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg" 9 | )] 10 | #![cfg_attr(docsrs, feature(doc_auto_cfg))] 11 | mod antialiasing; 12 | mod settings; 13 | mod viewport; 14 | 15 | pub mod cache; 16 | pub mod color; 17 | pub mod compositor; 18 | pub mod damage; 19 | pub mod error; 20 | pub mod gradient; 21 | pub mod image; 22 | pub mod layer; 23 | pub mod mesh; 24 | pub mod text; 25 | 26 | #[cfg(feature = "geometry")] 27 | pub mod geometry; 28 | 29 | pub use antialiasing::Antialiasing; 30 | pub use cache::Cache; 31 | pub use compositor::Compositor; 32 | pub use error::Error; 33 | pub use gradient::Gradient; 34 | pub use image::Image; 35 | pub use layer::Layer; 36 | pub use mesh::Mesh; 37 | pub use settings::Settings; 38 | pub use text::Text; 39 | pub use viewport::Viewport; 40 | 41 | pub use iced_core as core; 42 | pub use iced_futures as futures; 43 | -------------------------------------------------------------------------------- /graphics/src/settings.rs: -------------------------------------------------------------------------------- 1 | use crate::Antialiasing; 2 | use crate::core::{self, Font, Pixels}; 3 | 4 | /// The settings of a renderer. 5 | #[derive(Debug, Clone, Copy, PartialEq)] 6 | pub struct Settings { 7 | /// The default [`Font`] to use. 8 | pub default_font: Font, 9 | 10 | /// The default size of text. 11 | /// 12 | /// By default, it will be set to `16.0`. 13 | pub default_text_size: Pixels, 14 | 15 | /// The antialiasing strategy that will be used for triangle primitives. 16 | /// 17 | /// By default, it is `None`. 18 | pub antialiasing: Option, 19 | } 20 | 21 | impl Default for Settings { 22 | fn default() -> Settings { 23 | Settings { 24 | default_font: Font::default(), 25 | default_text_size: Pixels(16.0), 26 | antialiasing: None, 27 | } 28 | } 29 | } 30 | 31 | impl From for Settings { 32 | fn from(settings: core::Settings) -> Self { 33 | Self { 34 | default_font: if cfg!(all( 35 | target_arch = "wasm32", 36 | feature = "fira-sans" 37 | )) && settings.default_font == Font::default() 38 | { 39 | Font::with_name("Fira Sans") 40 | } else { 41 | settings.default_font 42 | }, 43 | default_text_size: settings.default_text_size, 44 | antialiasing: settings.antialiasing.then_some(Antialiasing::MSAAx4), 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /graphics/src/viewport.rs: -------------------------------------------------------------------------------- 1 | use crate::core::{Size, Transformation}; 2 | 3 | /// A viewing region for displaying computer graphics. 4 | #[derive(Debug, Clone)] 5 | pub struct Viewport { 6 | physical_size: Size, 7 | logical_size: Size, 8 | scale_factor: f64, 9 | projection: Transformation, 10 | } 11 | 12 | impl Viewport { 13 | /// Creates a new [`Viewport`] with the given physical dimensions and scale 14 | /// factor. 15 | pub fn with_physical_size(size: Size, scale_factor: f64) -> Viewport { 16 | Viewport { 17 | physical_size: size, 18 | logical_size: Size::new( 19 | (size.width as f64 / scale_factor) as f32, 20 | (size.height as f64 / scale_factor) as f32, 21 | ), 22 | scale_factor, 23 | projection: Transformation::orthographic(size.width, size.height), 24 | } 25 | } 26 | 27 | /// Returns the physical size of the [`Viewport`]. 28 | pub fn physical_size(&self) -> Size { 29 | self.physical_size 30 | } 31 | 32 | /// Returns the physical width of the [`Viewport`]. 33 | pub fn physical_width(&self) -> u32 { 34 | self.physical_size.width 35 | } 36 | 37 | /// Returns the physical height of the [`Viewport`]. 38 | pub fn physical_height(&self) -> u32 { 39 | self.physical_size.height 40 | } 41 | 42 | /// Returns the logical size of the [`Viewport`]. 43 | pub fn logical_size(&self) -> Size { 44 | self.logical_size 45 | } 46 | 47 | /// Returns the scale factor of the [`Viewport`]. 48 | pub fn scale_factor(&self) -> f64 { 49 | self.scale_factor 50 | } 51 | 52 | /// Returns the projection transformation of the [`Viewport`]. 53 | pub fn projection(&self) -> Transformation { 54 | self.projection 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /highlighter/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "iced_highlighter" 3 | description = "A syntax highlighter for iced" 4 | version.workspace = true 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | repository.workspace = true 9 | homepage.workspace = true 10 | categories.workspace = true 11 | keywords.workspace = true 12 | 13 | [lints] 14 | workspace = true 15 | 16 | [dependencies] 17 | iced_core.workspace = true 18 | 19 | syntect.workspace = true 20 | -------------------------------------------------------------------------------- /program/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "iced_program" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | repository.workspace = true 8 | homepage.workspace = true 9 | categories.workspace = true 10 | keywords.workspace = true 11 | rust-version.workspace = true 12 | 13 | [lints] 14 | workspace = true 15 | 16 | [features] 17 | time-travel = [] 18 | 19 | [dependencies] 20 | iced_graphics.workspace = true 21 | iced_runtime.workspace = true 22 | -------------------------------------------------------------------------------- /renderer/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "iced_renderer" 3 | description = "The official renderer for iced" 4 | version.workspace = true 5 | edition.workspace = true 6 | authors.workspace = true 7 | license.workspace = true 8 | repository.workspace = true 9 | homepage.workspace = true 10 | categories.workspace = true 11 | keywords.workspace = true 12 | 13 | [lints] 14 | workspace = true 15 | 16 | [features] 17 | wgpu = ["iced_wgpu"] 18 | tiny-skia = ["iced_tiny_skia"] 19 | image = ["iced_tiny_skia?/image", "iced_wgpu?/image"] 20 | svg = ["iced_tiny_skia?/svg", "iced_wgpu?/svg"] 21 | geometry = ["iced_graphics/geometry", "iced_tiny_skia?/geometry", "iced_wgpu?/geometry"] 22 | web-colors = ["iced_wgpu?/web-colors"] 23 | webgl = ["iced_wgpu?/webgl"] 24 | fira-sans = ["iced_graphics/fira-sans"] 25 | strict-assertions = ["iced_wgpu?/strict-assertions"] 26 | 27 | [dependencies] 28 | iced_graphics.workspace = true 29 | 30 | iced_tiny_skia.workspace = true 31 | iced_tiny_skia.optional = true 32 | 33 | iced_wgpu.workspace = true 34 | iced_wgpu.optional = true 35 | 36 | log.workspace = true 37 | thiserror.workspace = true 38 | -------------------------------------------------------------------------------- /renderer/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! The official renderer for iced. 2 | #![cfg_attr(docsrs, feature(doc_auto_cfg))] 3 | #[cfg(feature = "wgpu")] 4 | pub use iced_wgpu as wgpu; 5 | 6 | pub mod fallback; 7 | 8 | pub use iced_graphics as graphics; 9 | pub use iced_graphics::core; 10 | 11 | #[cfg(feature = "geometry")] 12 | pub use iced_graphics::geometry; 13 | 14 | /// The default graphics renderer for [`iced`]. 15 | /// 16 | /// [`iced`]: https://github.com/iced-rs/iced 17 | pub type Renderer = renderer::Renderer; 18 | 19 | /// The default graphics compositor for [`iced`]. 20 | /// 21 | /// [`iced`]: https://github.com/iced-rs/iced 22 | pub type Compositor = renderer::Compositor; 23 | 24 | #[cfg(all(feature = "wgpu", feature = "tiny-skia"))] 25 | mod renderer { 26 | pub type Renderer = crate::fallback::Renderer< 27 | iced_wgpu::Renderer, 28 | iced_tiny_skia::Renderer, 29 | >; 30 | 31 | pub type Compositor = crate::fallback::Compositor< 32 | iced_wgpu::window::Compositor, 33 | iced_tiny_skia::window::Compositor, 34 | >; 35 | } 36 | 37 | #[cfg(all(feature = "wgpu", not(feature = "tiny-skia")))] 38 | mod renderer { 39 | pub type Renderer = iced_wgpu::Renderer; 40 | pub type Compositor = iced_wgpu::window::Compositor; 41 | } 42 | 43 | #[cfg(all(not(feature = "wgpu"), feature = "tiny-skia"))] 44 | mod renderer { 45 | pub type Renderer = iced_tiny_skia::Renderer; 46 | pub type Compositor = iced_tiny_skia::window::Compositor; 47 | } 48 | 49 | #[cfg(not(any(feature = "wgpu", feature = "tiny-skia")))] 50 | mod renderer { 51 | #[cfg(not(debug_assertions))] 52 | compile_error!( 53 | "Cannot compile `iced_renderer` in release mode \ 54 | without a renderer feature enabled. \ 55 | Enable either the `wgpu` or `tiny-skia` feature, or both." 56 | ); 57 | 58 | pub type Renderer = (); 59 | pub type Compositor = (); 60 | } 61 | -------------------------------------------------------------------------------- /runtime/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "iced_runtime" 3 | description = "A renderer-agnostic runtime for iced" 4 | version.workspace = true 5 | edition.workspace = true 6 | authors.workspace = true 7 | license.workspace = true 8 | repository.workspace = true 9 | homepage.workspace = true 10 | categories.workspace = true 11 | keywords.workspace = true 12 | 13 | [lints] 14 | workspace = true 15 | 16 | [dependencies] 17 | bytes.workspace = true 18 | iced_core.workspace = true 19 | iced_debug.workspace = true 20 | 21 | iced_futures.workspace = true 22 | 23 | raw-window-handle.workspace = true 24 | thiserror.workspace = true 25 | 26 | sipper.workspace = true 27 | sipper.optional = true 28 | -------------------------------------------------------------------------------- /runtime/README.md: -------------------------------------------------------------------------------- 1 | # `iced_runtime` 2 | [![Documentation](https://docs.rs/iced_runtime/badge.svg)][documentation] 3 | [![Crates.io](https://img.shields.io/crates/v/iced_runtime.svg)](https://crates.io/crates/iced_runtime) 4 | [![License](https://img.shields.io/crates/l/iced_runtime.svg)](https://github.com/iced-rs/iced/blob/master/LICENSE) 5 | [![Discord Server](https://img.shields.io/discord/628993209984614400?label=&labelColor=6A7EC2&logo=discord&logoColor=ffffff&color=7389D8)](https://discord.gg/3xZJ65GAhd) 6 | 7 | `iced_runtime` takes [`iced_core`] and builds a runtime on top of it. 8 | 9 | [documentation]: https://docs.rs/iced_runtime 10 | [`iced_core`]: ../core 11 | [`iced_winit`]: ../winit 12 | [`druid`]: https://github.com/xi-editor/druid 13 | [`raw-window-handle`]: https://github.com/rust-windowing/raw-window-handle 14 | 15 | __Iced moves fast and the `master` branch can contain breaking changes!__ If 16 | you want to learn about a specific release, check out [the release list]. 17 | 18 | [the release list]: https://github.com/iced-rs/iced/releases 19 | -------------------------------------------------------------------------------- /runtime/src/clipboard.rs: -------------------------------------------------------------------------------- 1 | //! Access the clipboard. 2 | use crate::core::clipboard::Kind; 3 | use crate::futures::futures::channel::oneshot; 4 | use crate::task::{self, Task}; 5 | 6 | /// A clipboard action to be performed by some [`Task`]. 7 | /// 8 | /// [`Task`]: crate::Task 9 | #[derive(Debug)] 10 | pub enum Action { 11 | /// Read the clipboard and produce `T` with the result. 12 | Read { 13 | /// The clipboard target. 14 | target: Kind, 15 | /// The channel to send the read contents. 16 | channel: oneshot::Sender>, 17 | }, 18 | 19 | /// Write the given contents to the clipboard. 20 | Write { 21 | /// The clipboard target. 22 | target: Kind, 23 | /// The contents to be written. 24 | contents: String, 25 | }, 26 | } 27 | 28 | /// Read the current contents of the clipboard. 29 | pub fn read() -> Task> { 30 | task::oneshot(|channel| { 31 | crate::Action::Clipboard(Action::Read { 32 | target: Kind::Standard, 33 | channel, 34 | }) 35 | }) 36 | } 37 | 38 | /// Read the current contents of the primary clipboard. 39 | pub fn read_primary() -> Task> { 40 | task::oneshot(|channel| { 41 | crate::Action::Clipboard(Action::Read { 42 | target: Kind::Primary, 43 | channel, 44 | }) 45 | }) 46 | } 47 | 48 | /// Write the given contents to the clipboard. 49 | pub fn write(contents: String) -> Task { 50 | task::effect(crate::Action::Clipboard(Action::Write { 51 | target: Kind::Standard, 52 | contents, 53 | })) 54 | } 55 | 56 | /// Write the given contents to the primary clipboard. 57 | pub fn write_primary(contents: String) -> Task { 58 | task::effect(crate::Action::Clipboard(Action::Write { 59 | target: Kind::Primary, 60 | contents, 61 | })) 62 | } 63 | -------------------------------------------------------------------------------- /runtime/src/font.rs: -------------------------------------------------------------------------------- 1 | //! Load and use fonts. 2 | use crate::Action; 3 | use crate::task::{self, Task}; 4 | use std::borrow::Cow; 5 | 6 | /// An error while loading a font. 7 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 8 | pub enum Error {} 9 | 10 | /// Load a font from its bytes. 11 | pub fn load(bytes: impl Into>) -> Task> { 12 | task::oneshot(|channel| Action::LoadFont { 13 | bytes: bytes.into(), 14 | channel, 15 | }) 16 | } 17 | -------------------------------------------------------------------------------- /runtime/src/keyboard.rs: -------------------------------------------------------------------------------- 1 | //! Track keyboard events. 2 | pub use iced_core::keyboard::*; 3 | -------------------------------------------------------------------------------- /runtime/src/overlay.rs: -------------------------------------------------------------------------------- 1 | //! Overlays for user interfaces. 2 | mod nested; 3 | 4 | pub use nested::Nested; 5 | -------------------------------------------------------------------------------- /runtime/src/system.rs: -------------------------------------------------------------------------------- 1 | //! Access the native system. 2 | use crate::futures::futures::channel::oneshot; 3 | 4 | /// An operation to be performed on the system. 5 | #[derive(Debug)] 6 | pub enum Action { 7 | /// Query system information and produce `T` with the result. 8 | QueryInformation(oneshot::Sender), 9 | } 10 | 11 | /// Contains information about the system (e.g. system name, processor, memory, graphics adapter). 12 | #[derive(Clone, Debug)] 13 | pub struct Information { 14 | /// The operating system name 15 | pub system_name: Option, 16 | /// Operating system kernel version 17 | pub system_kernel: Option, 18 | /// Long operating system version 19 | /// 20 | /// Examples: 21 | /// - MacOS 10.15 Catalina 22 | /// - Windows 10 Pro 23 | /// - Ubuntu 20.04 LTS (Focal Fossa) 24 | pub system_version: Option, 25 | /// Short operating system version number 26 | pub system_short_version: Option, 27 | /// Detailed processor model information 28 | pub cpu_brand: String, 29 | /// The number of physical cores on the processor 30 | pub cpu_cores: Option, 31 | /// Total RAM size, in bytes 32 | pub memory_total: u64, 33 | /// Memory used by this process, in bytes 34 | pub memory_used: Option, 35 | /// Underlying graphics backend for rendering 36 | pub graphics_backend: String, 37 | /// Model information for the active graphics adapter 38 | pub graphics_adapter: String, 39 | } 40 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width=80 2 | edition="2024" 3 | -------------------------------------------------------------------------------- /src/advanced.rs: -------------------------------------------------------------------------------- 1 | //! Leverage advanced concepts like custom widgets. 2 | pub mod subscription { 3 | //! Write your own subscriptions. 4 | pub use crate::runtime::futures::subscription::{ 5 | Event, EventStream, Hasher, MacOS, PlatformSpecific, Recipe, 6 | from_recipe, into_recipes, 7 | }; 8 | } 9 | 10 | pub mod widget { 11 | //! Create custom widgets and operate on them. 12 | pub use crate::core::widget::*; 13 | pub use crate::runtime::task::widget as operate; 14 | } 15 | 16 | pub use crate::core::Shell; 17 | pub use crate::core::clipboard::{self, Clipboard}; 18 | pub use crate::core::image; 19 | pub use crate::core::layout::{self, Layout}; 20 | pub use crate::core::mouse; 21 | pub use crate::core::overlay::{self, Overlay}; 22 | pub use crate::core::renderer::{self, Renderer}; 23 | pub use crate::core::svg; 24 | pub use crate::core::text::{self, Text}; 25 | pub use crate::renderer::graphics; 26 | 27 | pub use widget::Widget; 28 | -------------------------------------------------------------------------------- /src/error.rs: -------------------------------------------------------------------------------- 1 | use crate::futures; 2 | use crate::graphics; 3 | use crate::shell; 4 | 5 | /// An error that occurred while running an application. 6 | #[derive(Debug, thiserror::Error)] 7 | pub enum Error { 8 | /// The futures executor could not be created. 9 | #[error("the futures executor could not be created")] 10 | ExecutorCreationFailed(futures::io::Error), 11 | 12 | /// The application window could not be created. 13 | #[error("the application window could not be created")] 14 | WindowCreationFailed(Box), 15 | 16 | /// The application graphics context could not be created. 17 | #[error("the application graphics context could not be created")] 18 | GraphicsCreationFailed(graphics::Error), 19 | } 20 | 21 | impl From for Error { 22 | fn from(error: shell::Error) -> Error { 23 | match error { 24 | shell::Error::ExecutorCreationFailed(error) => { 25 | Error::ExecutorCreationFailed(error) 26 | } 27 | shell::Error::WindowCreationFailed(error) => { 28 | Error::WindowCreationFailed(Box::new(error)) 29 | } 30 | shell::Error::GraphicsCreationFailed(error) => { 31 | Error::GraphicsCreationFailed(error) 32 | } 33 | } 34 | } 35 | } 36 | 37 | #[cfg(test)] 38 | mod tests { 39 | use super::*; 40 | 41 | #[test] 42 | fn assert_send_sync() { 43 | fn _assert() {} 44 | _assert::(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/time.rs: -------------------------------------------------------------------------------- 1 | //! Listen and react to time. 2 | pub use crate::core::time::*; 3 | 4 | #[allow(unused_imports)] 5 | #[cfg_attr( 6 | docsrs, 7 | doc(cfg(any( 8 | feature = "tokio", 9 | feature = "smol", 10 | target_arch = "wasm32" 11 | ))) 12 | )] 13 | pub use iced_futures::backend::default::time::*; 14 | -------------------------------------------------------------------------------- /src/touch.rs: -------------------------------------------------------------------------------- 1 | //! Listen and react to touch events. 2 | pub use crate::core::touch::{Event, Finger}; 3 | -------------------------------------------------------------------------------- /src/window.rs: -------------------------------------------------------------------------------- 1 | //! Configure the window of your application in native platforms. 2 | 3 | pub mod icon; 4 | 5 | pub use icon::Icon; 6 | 7 | pub use crate::core::window::*; 8 | pub use crate::runtime::window::*; 9 | -------------------------------------------------------------------------------- /test/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "iced_test" 3 | version.workspace = true 4 | authors.workspace = true 5 | edition.workspace = true 6 | license.workspace = true 7 | repository.workspace = true 8 | homepage.workspace = true 9 | categories.workspace = true 10 | keywords.workspace = true 11 | rust-version.workspace = true 12 | 13 | [lints] 14 | workspace = true 15 | 16 | [dependencies] 17 | iced_runtime.workspace = true 18 | 19 | iced_renderer.workspace = true 20 | iced_renderer.features = ["fira-sans"] 21 | 22 | png.workspace = true 23 | sha2.workspace = true 24 | thiserror.workspace = true 25 | -------------------------------------------------------------------------------- /test/src/selector.rs: -------------------------------------------------------------------------------- 1 | //! Select widgets of a user interface. 2 | use crate::core::text; 3 | use crate::core::widget; 4 | 5 | /// A selector describes a strategy to find a certain widget in a user interface. 6 | #[derive(Debug, Clone, PartialEq, Eq)] 7 | pub enum Selector { 8 | /// Find the widget with the given [`widget::Id`]. 9 | Id(widget::Id), 10 | /// Find the widget containing the given [`text::Fragment`]. 11 | Text(text::Fragment<'static>), 12 | } 13 | 14 | impl From for Selector { 15 | fn from(id: widget::Id) -> Self { 16 | Self::Id(id) 17 | } 18 | } 19 | 20 | impl From<&'static str> for Selector { 21 | fn from(text: &'static str) -> Self { 22 | Self::Text(text.into()) 23 | } 24 | } 25 | 26 | /// Creates a [`Selector`] that finds the widget with the given [`widget::Id`]. 27 | pub fn id(id: impl Into) -> Selector { 28 | Selector::Id(id.into()) 29 | } 30 | 31 | /// Creates a [`Selector`] that finds the widget containing the given text fragment. 32 | pub fn text(fragment: impl text::IntoFragment<'static>) -> Selector { 33 | Selector::Text(fragment.into_fragment()) 34 | } 35 | -------------------------------------------------------------------------------- /tiny_skia/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "iced_tiny_skia" 3 | description = "A software renderer for iced on top of tiny-skia" 4 | version.workspace = true 5 | edition.workspace = true 6 | authors.workspace = true 7 | license.workspace = true 8 | repository.workspace = true 9 | homepage.workspace = true 10 | categories.workspace = true 11 | keywords.workspace = true 12 | 13 | [lints] 14 | workspace = true 15 | 16 | [features] 17 | image = ["iced_graphics/image"] 18 | svg = ["iced_graphics/svg", "resvg"] 19 | geometry = ["iced_graphics/geometry"] 20 | 21 | [dependencies] 22 | iced_debug.workspace = true 23 | iced_graphics.workspace = true 24 | 25 | bytemuck.workspace = true 26 | cosmic-text.workspace = true 27 | kurbo.workspace = true 28 | log.workspace = true 29 | rustc-hash.workspace = true 30 | softbuffer.workspace = true 31 | tiny-skia.workspace = true 32 | 33 | resvg.workspace = true 34 | resvg.optional = true 35 | -------------------------------------------------------------------------------- /tiny_skia/src/primitive.rs: -------------------------------------------------------------------------------- 1 | use crate::core::Rectangle; 2 | 3 | #[derive(Debug, Clone, PartialEq)] 4 | pub enum Primitive { 5 | /// A path filled with some paint. 6 | Fill { 7 | /// The path to fill. 8 | path: tiny_skia::Path, 9 | /// The paint to use. 10 | paint: tiny_skia::Paint<'static>, 11 | /// The fill rule to follow. 12 | rule: tiny_skia::FillRule, 13 | }, 14 | /// A path stroked with some paint. 15 | Stroke { 16 | /// The path to stroke. 17 | path: tiny_skia::Path, 18 | /// The paint to use. 19 | paint: tiny_skia::Paint<'static>, 20 | /// The stroke settings. 21 | stroke: tiny_skia::Stroke, 22 | }, 23 | } 24 | 25 | impl Primitive { 26 | /// Returns the visible bounds of the [`Primitive`]. 27 | pub fn visible_bounds(&self) -> Rectangle { 28 | let bounds = match self { 29 | Primitive::Fill { path, .. } => path.bounds(), 30 | Primitive::Stroke { path, .. } => path.bounds(), 31 | }; 32 | 33 | Rectangle { 34 | x: bounds.x(), 35 | y: bounds.y(), 36 | width: bounds.width(), 37 | height: bounds.height(), 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tiny_skia/src/settings.rs: -------------------------------------------------------------------------------- 1 | use crate::core::{Font, Pixels}; 2 | use crate::graphics; 3 | 4 | /// The settings of a [`Compositor`]. 5 | /// 6 | /// [`Compositor`]: crate::window::Compositor 7 | #[derive(Debug, Clone, Copy, PartialEq)] 8 | pub struct Settings { 9 | /// The default [`Font`] to use. 10 | pub default_font: Font, 11 | 12 | /// The default size of text. 13 | /// 14 | /// By default, it will be set to `16.0`. 15 | pub default_text_size: Pixels, 16 | } 17 | 18 | impl Default for Settings { 19 | fn default() -> Settings { 20 | Settings { 21 | default_font: Font::default(), 22 | default_text_size: Pixels(16.0), 23 | } 24 | } 25 | } 26 | 27 | impl From for Settings { 28 | fn from(settings: graphics::Settings) -> Self { 29 | Self { 30 | default_font: settings.default_font, 31 | default_text_size: settings.default_text_size, 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tiny_skia/src/window.rs: -------------------------------------------------------------------------------- 1 | pub mod compositor; 2 | 3 | pub use compositor::{Compositor, Surface}; 4 | -------------------------------------------------------------------------------- /wgpu/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "iced_wgpu" 3 | description = "A renderer for iced on top of wgpu" 4 | version.workspace = true 5 | edition.workspace = true 6 | authors.workspace = true 7 | license.workspace = true 8 | repository.workspace = true 9 | homepage.workspace = true 10 | categories.workspace = true 11 | keywords.workspace = true 12 | 13 | [lints] 14 | workspace = true 15 | 16 | [package.metadata.docs.rs] 17 | rustdoc-args = ["--cfg", "docsrs"] 18 | all-features = true 19 | 20 | [features] 21 | geometry = ["iced_graphics/geometry", "lyon"] 22 | image = ["iced_graphics/image"] 23 | svg = ["iced_graphics/svg", "resvg/text"] 24 | web-colors = ["iced_graphics/web-colors"] 25 | webgl = ["wgpu/webgl"] 26 | strict-assertions = [] 27 | 28 | [dependencies] 29 | iced_debug.workspace = true 30 | iced_graphics.workspace = true 31 | 32 | bitflags.workspace = true 33 | bytemuck.workspace = true 34 | futures.workspace = true 35 | glam.workspace = true 36 | cryoglyph.workspace = true 37 | guillotiere.workspace = true 38 | log.workspace = true 39 | rustc-hash.workspace = true 40 | thiserror.workspace = true 41 | wgpu.workspace = true 42 | 43 | lyon.workspace = true 44 | lyon.optional = true 45 | 46 | resvg.workspace = true 47 | resvg.optional = true 48 | -------------------------------------------------------------------------------- /wgpu/README.md: -------------------------------------------------------------------------------- 1 | # `iced_wgpu` 2 | [![Documentation](https://docs.rs/iced_wgpu/badge.svg)][documentation] 3 | [![Crates.io](https://img.shields.io/crates/v/iced_wgpu.svg)](https://crates.io/crates/iced_wgpu) 4 | [![License](https://img.shields.io/crates/l/iced_wgpu.svg)](https://github.com/iced-rs/iced/blob/master/LICENSE) 5 | [![Discord Server](https://img.shields.io/discord/628993209984614400?label=&labelColor=6A7EC2&logo=discord&logoColor=ffffff&color=7389D8)](https://discord.gg/3xZJ65GAhd) 6 | 7 | `iced_wgpu` is a [`wgpu`] renderer for [`iced_runtime`]. For now, it is the default renderer of Iced on [native platforms]. 8 | 9 | [`wgpu`] supports most modern graphics backends: Vulkan, Metal, DX12, OpenGL, and WebGPU. 10 | 11 |

12 | The native target 13 |

14 | 15 | [documentation]: https://docs.rs/iced_wgpu 16 | [`iced_runtime`]: ../runtime 17 | [`wgpu`]: https://github.com/gfx-rs/wgpu 18 | [native platforms]: https://github.com/gfx-rs/wgpu#supported-platforms 19 | [WebGPU API]: https://gpuweb.github.io/gpuweb/ 20 | [`wgpu_glyph`]: https://github.com/hecrj/wgpu_glyph 21 | -------------------------------------------------------------------------------- /wgpu/src/image/atlas/allocation.rs: -------------------------------------------------------------------------------- 1 | use crate::core::Size; 2 | use crate::image::atlas::{self, allocator}; 3 | 4 | #[derive(Debug)] 5 | pub enum Allocation { 6 | Partial { 7 | layer: usize, 8 | region: allocator::Region, 9 | }, 10 | Full { 11 | layer: usize, 12 | }, 13 | } 14 | 15 | impl Allocation { 16 | pub fn position(&self) -> (u32, u32) { 17 | match self { 18 | Allocation::Partial { region, .. } => region.position(), 19 | Allocation::Full { .. } => (0, 0), 20 | } 21 | } 22 | 23 | pub fn size(&self) -> Size { 24 | match self { 25 | Allocation::Partial { region, .. } => region.size(), 26 | Allocation::Full { .. } => Size::new(atlas::SIZE, atlas::SIZE), 27 | } 28 | } 29 | 30 | pub fn layer(&self) -> usize { 31 | match self { 32 | Allocation::Partial { layer, .. } => *layer, 33 | Allocation::Full { layer } => *layer, 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /wgpu/src/image/atlas/allocator.rs: -------------------------------------------------------------------------------- 1 | use guillotiere::{AtlasAllocator, Size}; 2 | 3 | pub struct Allocator { 4 | raw: AtlasAllocator, 5 | allocations: usize, 6 | } 7 | 8 | impl Allocator { 9 | pub fn new(size: u32) -> Allocator { 10 | let raw = AtlasAllocator::new(Size::new(size as i32, size as i32)); 11 | 12 | Allocator { 13 | raw, 14 | allocations: 0, 15 | } 16 | } 17 | 18 | pub fn allocate(&mut self, width: u32, height: u32) -> Option { 19 | let allocation = 20 | self.raw.allocate(Size::new(width as i32, height as i32))?; 21 | 22 | self.allocations += 1; 23 | 24 | Some(Region { allocation }) 25 | } 26 | 27 | pub fn deallocate(&mut self, region: &Region) { 28 | self.raw.deallocate(region.allocation.id); 29 | 30 | self.allocations = self.allocations.saturating_sub(1); 31 | } 32 | 33 | pub fn is_empty(&self) -> bool { 34 | self.allocations == 0 35 | } 36 | 37 | pub fn allocations(&self) -> usize { 38 | self.allocations 39 | } 40 | } 41 | 42 | pub struct Region { 43 | allocation: guillotiere::Allocation, 44 | } 45 | 46 | impl Region { 47 | pub fn position(&self) -> (u32, u32) { 48 | let rectangle = &self.allocation.rectangle; 49 | 50 | (rectangle.min.x as u32, rectangle.min.y as u32) 51 | } 52 | 53 | pub fn size(&self) -> crate::core::Size { 54 | let size = self.allocation.rectangle.size(); 55 | 56 | crate::core::Size::new(size.width as u32, size.height as u32) 57 | } 58 | } 59 | 60 | impl std::fmt::Debug for Allocator { 61 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 62 | write!(f, "Allocator") 63 | } 64 | } 65 | 66 | impl std::fmt::Debug for Region { 67 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 68 | f.debug_struct("Region") 69 | .field("id", &self.allocation.id) 70 | .field("rectangle", &self.allocation.rectangle) 71 | .finish() 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /wgpu/src/image/atlas/entry.rs: -------------------------------------------------------------------------------- 1 | use crate::core::Size; 2 | use crate::image::atlas; 3 | 4 | #[derive(Debug)] 5 | pub enum Entry { 6 | Contiguous(atlas::Allocation), 7 | Fragmented { 8 | size: Size, 9 | fragments: Vec, 10 | }, 11 | } 12 | 13 | impl Entry { 14 | #[cfg(feature = "image")] 15 | pub fn size(&self) -> Size { 16 | match self { 17 | Entry::Contiguous(allocation) => allocation.size(), 18 | Entry::Fragmented { size, .. } => *size, 19 | } 20 | } 21 | } 22 | 23 | #[derive(Debug)] 24 | pub struct Fragment { 25 | pub position: (u32, u32), 26 | pub allocation: atlas::Allocation, 27 | } 28 | -------------------------------------------------------------------------------- /wgpu/src/image/atlas/layer.rs: -------------------------------------------------------------------------------- 1 | use crate::image::atlas::Allocator; 2 | 3 | #[derive(Debug)] 4 | pub enum Layer { 5 | Empty, 6 | Busy(Allocator), 7 | Full, 8 | } 9 | 10 | impl Layer { 11 | pub fn is_empty(&self) -> bool { 12 | matches!(self, Layer::Empty) 13 | } 14 | 15 | pub fn allocations(&self) -> usize { 16 | match self { 17 | Layer::Empty => 0, 18 | Layer::Busy(allocator) => allocator.allocations(), 19 | Layer::Full => 1, 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /wgpu/src/image/null.rs: -------------------------------------------------------------------------------- 1 | pub use crate::graphics::Image; 2 | 3 | #[derive(Debug, Default)] 4 | pub struct Batch; 5 | 6 | impl Batch { 7 | pub fn push(&mut self, _image: Image) {} 8 | 9 | pub fn clear(&mut self) {} 10 | 11 | pub fn is_empty(&self) -> bool { 12 | true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /wgpu/src/shader/blit.wgsl: -------------------------------------------------------------------------------- 1 | var uvs: array, 6> = array, 6>( 2 | vec2(0.0, 0.0), 3 | vec2(1.0, 0.0), 4 | vec2(1.0, 1.0), 5 | vec2(0.0, 0.0), 6 | vec2(0.0, 1.0), 7 | vec2(1.0, 1.0) 8 | ); 9 | 10 | @group(0) @binding(0) var u_sampler: sampler; 11 | @group(0) @binding(1) var u_ratio: vec4; 12 | @group(1) @binding(0) var u_texture: texture_2d; 13 | 14 | struct VertexInput { 15 | @builtin(vertex_index) vertex_index: u32, 16 | } 17 | 18 | struct VertexOutput { 19 | @builtin(position) position: vec4, 20 | @location(0) uv: vec2, 21 | } 22 | 23 | @vertex 24 | fn vs_main(input: VertexInput) -> VertexOutput { 25 | let uv = uvs[input.vertex_index]; 26 | 27 | var out: VertexOutput; 28 | out.uv = uv * u_ratio.xy; 29 | out.position = vec4(uv * vec2(2.0, -2.0) + vec2(-1.0, 1.0), 0.0, 1.0); 30 | 31 | return out; 32 | } 33 | 34 | @fragment 35 | fn fs_main(input: VertexOutput) -> @location(0) vec4 { 36 | return textureSample(u_texture, u_sampler, input.uv); 37 | } 38 | -------------------------------------------------------------------------------- /wgpu/src/shader/color.wgsl: -------------------------------------------------------------------------------- 1 | fn premultiply(color: vec4) -> vec4 { 2 | return vec4(color.xyz * color.a, color.a); 3 | } 4 | 5 | fn unpack_color(data: vec2) -> vec4 { 6 | return premultiply(unpack_u32(data)); 7 | } 8 | 9 | fn unpack_u32(data: vec2) -> vec4 { 10 | let rg: vec2 = unpack2x16float(data.x); 11 | let ba: vec2 = unpack2x16float(data.y); 12 | 13 | return vec4(rg.y, rg.x, ba.y, ba.x); 14 | } 15 | -------------------------------------------------------------------------------- /wgpu/src/shader/color/linear_rgb.wgsl: -------------------------------------------------------------------------------- 1 | fn interpolate_color(from_: vec4, to_: vec4, factor: f32) -> vec4 { 2 | return mix(from_, to_, factor); 3 | } 4 | -------------------------------------------------------------------------------- /wgpu/src/shader/color/oklab.wgsl: -------------------------------------------------------------------------------- 1 | const to_lms = mat3x4( 2 | vec4(0.4121656120, 0.2118591070, 0.0883097947, 0.0), 3 | vec4(0.5362752080, 0.6807189584, 0.2818474174, 0.0), 4 | vec4(0.0514575653, 0.1074065790, 0.6302613616, 0.0), 5 | ); 6 | 7 | const to_rgb = mat3x4( 8 | vec4( 4.0767245293, -3.3072168827, 0.2307590544, 0.0), 9 | vec4(-1.2681437731, 2.6093323231, -0.3411344290, 0.0), 10 | vec4(-0.0041119885, -0.7034763098, 1.7068625689, 0.0), 11 | ); 12 | 13 | fn interpolate_color(from_: vec4, to_: vec4, factor: f32) -> vec4 { 14 | // To Oklab 15 | let lms_a = pow(from_ * to_lms, vec3(1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0)); 16 | let lms_b = pow(to_ * to_lms, vec3(1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0)); 17 | let mixed = mix(lms_a, lms_b, factor); 18 | 19 | // Back to linear RGB 20 | var color = to_rgb * (mixed * mixed * mixed); 21 | 22 | // Alpha interpolation 23 | color.a = mix(from_.a, to_.a, factor); 24 | 25 | return color; 26 | } 27 | -------------------------------------------------------------------------------- /wgpu/src/shader/quad.wgsl: -------------------------------------------------------------------------------- 1 | struct Globals { 2 | transform: mat4x4, 3 | scale: f32, 4 | } 5 | 6 | @group(0) @binding(0) var globals: Globals; 7 | 8 | fn rounded_box_sdf(p: vec2, size: vec2, corners: vec4) -> f32 { 9 | var box_half = select(corners.yz, corners.xw, p.x > 0.0); 10 | var corner = select(box_half.y, box_half.x, p.y > 0.0); 11 | var q = abs(p) - size + corner; 12 | return min(max(q.x, q.y), 0.0) + length(max(q, vec2(0.0))) - corner; 13 | } 14 | -------------------------------------------------------------------------------- /wgpu/src/shader/triangle.wgsl: -------------------------------------------------------------------------------- 1 | struct Globals { 2 | transform: mat4x4, 3 | } 4 | 5 | @group(0) @binding(0) var globals: Globals; 6 | -------------------------------------------------------------------------------- /wgpu/src/shader/triangle/solid.wgsl: -------------------------------------------------------------------------------- 1 | struct SolidVertexInput { 2 | @location(0) position: vec2, 3 | @location(1) color: vec4, 4 | } 5 | 6 | struct SolidVertexOutput { 7 | @builtin(position) position: vec4, 8 | @location(0) color: vec4, 9 | } 10 | 11 | @vertex 12 | fn solid_vs_main(input: SolidVertexInput) -> SolidVertexOutput { 13 | var out: SolidVertexOutput; 14 | 15 | out.color = premultiply(input.color); 16 | out.position = globals.transform * vec4(input.position, 0.0, 1.0); 17 | 18 | return out; 19 | } 20 | 21 | @fragment 22 | fn solid_fs_main(input: SolidVertexOutput) -> @location(0) vec4 { 23 | return input.color; 24 | } 25 | -------------------------------------------------------------------------------- /wgpu/src/shader/vertex.wgsl: -------------------------------------------------------------------------------- 1 | // Compute the normalized quad coordinates based on the vertex index. 2 | fn vertex_position(vertex_index: u32) -> vec2 { 3 | // #: 0 1 2 3 4 5 4 | // x: 1 1 0 0 0 1 5 | // y: 1 0 0 0 1 1 6 | return vec2((vec2(1u, 2u) + vertex_index) % vec2(6u) < vec2(3u)); 7 | } 8 | -------------------------------------------------------------------------------- /wgpu/src/window.rs: -------------------------------------------------------------------------------- 1 | //! Display rendering results on windows. 2 | pub mod compositor; 3 | 4 | pub use compositor::Compositor; 5 | pub use wgpu::Surface; 6 | -------------------------------------------------------------------------------- /widget/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "iced_widget" 3 | description = "The built-in widgets for iced" 4 | version.workspace = true 5 | edition.workspace = true 6 | authors.workspace = true 7 | license.workspace = true 8 | repository.workspace = true 9 | homepage.workspace = true 10 | categories.workspace = true 11 | keywords.workspace = true 12 | 13 | [lints] 14 | workspace = true 15 | 16 | [package.metadata.docs.rs] 17 | rustdoc-args = ["--cfg", "docsrs"] 18 | all-features = true 19 | 20 | [features] 21 | lazy = ["ouroboros"] 22 | image = ["iced_renderer/image"] 23 | svg = ["iced_renderer/svg"] 24 | canvas = ["iced_renderer/geometry"] 25 | qr_code = ["canvas", "dep:qrcode"] 26 | wgpu = ["iced_renderer/wgpu"] 27 | markdown = ["dep:pulldown-cmark", "dep:url"] 28 | highlighter = ["dep:iced_highlighter"] 29 | advanced = [] 30 | crisp = [] 31 | 32 | [dependencies] 33 | iced_renderer.workspace = true 34 | iced_runtime.workspace = true 35 | 36 | num-traits.workspace = true 37 | log.workspace = true 38 | rustc-hash.workspace = true 39 | thiserror.workspace = true 40 | unicode-segmentation.workspace = true 41 | 42 | ouroboros.workspace = true 43 | ouroboros.optional = true 44 | 45 | qrcode.workspace = true 46 | qrcode.optional = true 47 | 48 | pulldown-cmark.workspace = true 49 | pulldown-cmark.optional = true 50 | 51 | iced_highlighter.workspace = true 52 | iced_highlighter.optional = true 53 | 54 | url.workspace = true 55 | url.optional = true 56 | -------------------------------------------------------------------------------- /widget/assets/iced-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /widget/src/lazy/cache.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | use crate::core::Element; 3 | use crate::core::overlay; 4 | 5 | use ouroboros::self_referencing; 6 | 7 | #[self_referencing(pub_extras)] 8 | pub struct Cache<'a, Message: 'a, Theme: 'a, Renderer: 'a> { 9 | pub element: Element<'a, Message, Theme, Renderer>, 10 | 11 | #[borrows(mut element)] 12 | #[covariant] 13 | overlay: Option>, 14 | } 15 | -------------------------------------------------------------------------------- /widget/src/lazy/helpers.rs: -------------------------------------------------------------------------------- 1 | use crate::core::{self, Element, Size}; 2 | use crate::lazy::component; 3 | 4 | use std::hash::Hash; 5 | 6 | #[allow(deprecated)] 7 | pub use crate::lazy::{Component, Lazy, Responsive}; 8 | 9 | /// Creates a new [`Lazy`] widget with the given data `Dependency` and a 10 | /// closure that can turn this data into a widget tree. 11 | #[cfg(feature = "lazy")] 12 | pub fn lazy<'a, Message, Theme, Renderer, Dependency, View>( 13 | dependency: Dependency, 14 | view: impl Fn(&Dependency) -> View + 'a, 15 | ) -> Lazy<'a, Message, Theme, Renderer, Dependency, View> 16 | where 17 | Dependency: Hash + 'a, 18 | View: Into>, 19 | { 20 | Lazy::new(dependency, view) 21 | } 22 | 23 | /// Turns an implementor of [`Component`] into an [`Element`] that can be 24 | /// embedded in any application. 25 | #[cfg(feature = "lazy")] 26 | #[deprecated( 27 | since = "0.13.0", 28 | note = "components introduce encapsulated state and hamper the use of a single source of truth. \ 29 | Instead, leverage the Elm Architecture directly, or implement a custom widget" 30 | )] 31 | #[allow(deprecated)] 32 | pub fn component<'a, C, Message, Theme, Renderer>( 33 | component: C, 34 | ) -> Element<'a, Message, Theme, Renderer> 35 | where 36 | C: Component + 'a, 37 | C::State: 'static, 38 | Message: 'a, 39 | Theme: 'a, 40 | Renderer: core::Renderer + 'a, 41 | { 42 | component::view(component) 43 | } 44 | 45 | /// Creates a new [`Responsive`] widget with a closure that produces its 46 | /// contents. 47 | /// 48 | /// The `view` closure will be provided with the current [`Size`] of 49 | /// the [`Responsive`] widget and, therefore, can be used to build the 50 | /// contents of the widget in a responsive way. 51 | #[cfg(feature = "lazy")] 52 | pub fn responsive<'a, Message, Theme, Renderer>( 53 | f: impl Fn(Size) -> Element<'a, Message, Theme, Renderer> + 'a, 54 | ) -> Responsive<'a, Message, Theme, Renderer> 55 | where 56 | Renderer: core::Renderer, 57 | { 58 | Responsive::new(f) 59 | } 60 | -------------------------------------------------------------------------------- /widget/src/overlay.rs: -------------------------------------------------------------------------------- 1 | //! Display interactive elements on top of other widgets. 2 | pub mod menu; 3 | -------------------------------------------------------------------------------- /widget/src/pane_grid/configuration.rs: -------------------------------------------------------------------------------- 1 | use crate::pane_grid::Axis; 2 | 3 | /// The arrangement of a [`PaneGrid`]. 4 | /// 5 | /// [`PaneGrid`]: super::PaneGrid 6 | #[derive(Debug, Clone)] 7 | pub enum Configuration { 8 | /// A split of the available space. 9 | Split { 10 | /// The direction of the split. 11 | axis: Axis, 12 | 13 | /// The ratio of the split in [0.0, 1.0]. 14 | ratio: f32, 15 | 16 | /// The left/top [`Configuration`] of the split. 17 | a: Box>, 18 | 19 | /// The right/bottom [`Configuration`] of the split. 20 | b: Box>, 21 | }, 22 | /// A [`Pane`]. 23 | /// 24 | /// [`Pane`]: super::Pane 25 | Pane(T), 26 | } 27 | -------------------------------------------------------------------------------- /widget/src/pane_grid/controls.rs: -------------------------------------------------------------------------------- 1 | use crate::container; 2 | use crate::core::{self, Element}; 3 | 4 | /// The controls of a [`Pane`]. 5 | /// 6 | /// [`Pane`]: super::Pane 7 | #[allow(missing_debug_implementations)] 8 | pub struct Controls< 9 | 'a, 10 | Message, 11 | Theme = crate::Theme, 12 | Renderer = crate::Renderer, 13 | > where 14 | Theme: container::Catalog, 15 | Renderer: core::Renderer, 16 | { 17 | pub(super) full: Element<'a, Message, Theme, Renderer>, 18 | pub(super) compact: Option>, 19 | } 20 | 21 | impl<'a, Message, Theme, Renderer> Controls<'a, Message, Theme, Renderer> 22 | where 23 | Theme: container::Catalog, 24 | Renderer: core::Renderer, 25 | { 26 | /// Creates a new [`Controls`] with the given content. 27 | pub fn new( 28 | content: impl Into>, 29 | ) -> Self { 30 | Self { 31 | full: content.into(), 32 | compact: None, 33 | } 34 | } 35 | 36 | /// Creates a new [`Controls`] with a full and compact variant. 37 | /// If there is not enough room to show the full variant without overlap, 38 | /// then the compact variant will be shown instead. 39 | pub fn dynamic( 40 | full: impl Into>, 41 | compact: impl Into>, 42 | ) -> Self { 43 | Self { 44 | full: full.into(), 45 | compact: Some(compact.into()), 46 | } 47 | } 48 | } 49 | 50 | impl<'a, Message, Theme, Renderer> From> 51 | for Controls<'a, Message, Theme, Renderer> 52 | where 53 | Theme: container::Catalog, 54 | Renderer: core::Renderer, 55 | { 56 | fn from(value: Element<'a, Message, Theme, Renderer>) -> Self { 57 | Self::new(value) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /widget/src/pane_grid/direction.rs: -------------------------------------------------------------------------------- 1 | /// A four cardinal direction. 2 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 3 | pub enum Direction { 4 | /// ↑ 5 | Up, 6 | /// ↓ 7 | Down, 8 | /// ← 9 | Left, 10 | /// → 11 | Right, 12 | } 13 | -------------------------------------------------------------------------------- /widget/src/pane_grid/draggable.rs: -------------------------------------------------------------------------------- 1 | use crate::core::{Layout, Point}; 2 | 3 | /// A pane that can be dragged. 4 | pub trait Draggable { 5 | /// Returns whether the [`Draggable`] with the given [`Layout`] can be picked 6 | /// at the provided cursor position. 7 | fn can_be_dragged_at(&self, layout: Layout<'_>, cursor: Point) -> bool; 8 | } 9 | -------------------------------------------------------------------------------- /widget/src/pane_grid/pane.rs: -------------------------------------------------------------------------------- 1 | /// A rectangular region in a [`PaneGrid`] used to display widgets. 2 | /// 3 | /// [`PaneGrid`]: super::PaneGrid 4 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 5 | pub struct Pane(pub(super) usize); 6 | -------------------------------------------------------------------------------- /widget/src/pane_grid/split.rs: -------------------------------------------------------------------------------- 1 | /// A divider that splits a region in a [`PaneGrid`] into two different panes. 2 | /// 3 | /// [`PaneGrid`]: super::PaneGrid 4 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 5 | pub struct Split(pub(super) usize); 6 | -------------------------------------------------------------------------------- /widget/src/shader/program.rs: -------------------------------------------------------------------------------- 1 | use crate::core::Rectangle; 2 | use crate::core::mouse; 3 | use crate::renderer::wgpu::Primitive; 4 | use crate::shader::{self, Action}; 5 | 6 | /// The state and logic of a [`Shader`] widget. 7 | /// 8 | /// A [`Program`] can mutate the internal state of a [`Shader`] widget 9 | /// and produce messages for an application. 10 | /// 11 | /// [`Shader`]: crate::Shader 12 | pub trait Program { 13 | /// The internal state of the [`Program`]. 14 | type State: Default + 'static; 15 | 16 | /// The type of primitive this [`Program`] can draw. 17 | type Primitive: Primitive + 'static; 18 | 19 | /// Update the internal [`State`] of the [`Program`]. This can be used to reflect state changes 20 | /// based on mouse & other events. You can return an [`Action`] to publish a message, request a 21 | /// redraw, or capture the event. 22 | /// 23 | /// By default, this method returns `None`. 24 | /// 25 | /// [`State`]: Self::State 26 | fn update( 27 | &self, 28 | _state: &mut Self::State, 29 | _event: &shader::Event, 30 | _bounds: Rectangle, 31 | _cursor: mouse::Cursor, 32 | ) -> Option> { 33 | None 34 | } 35 | 36 | /// Draws the [`Primitive`]. 37 | /// 38 | /// [`Primitive`]: Self::Primitive 39 | fn draw( 40 | &self, 41 | state: &Self::State, 42 | cursor: mouse::Cursor, 43 | bounds: Rectangle, 44 | ) -> Self::Primitive; 45 | 46 | /// Returns the current mouse interaction of the [`Program`]. 47 | /// 48 | /// The interaction returned will be in effect even if the cursor position is out of 49 | /// bounds of the [`Shader`]'s program. 50 | /// 51 | /// [`Shader`]: crate::Shader 52 | fn mouse_interaction( 53 | &self, 54 | _state: &Self::State, 55 | _bounds: Rectangle, 56 | _cursor: mouse::Cursor, 57 | ) -> mouse::Interaction { 58 | mouse::Interaction::default() 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /widget/src/text.rs: -------------------------------------------------------------------------------- 1 | //! Draw and interact with text. 2 | mod rich; 3 | 4 | pub use crate::core::text::{Fragment, Highlighter, IntoFragment, Span}; 5 | pub use crate::core::widget::text::*; 6 | pub use rich::Rich; 7 | 8 | /// A bunch of text. 9 | /// 10 | /// # Example 11 | /// ```no_run 12 | /// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; } 13 | /// # pub type State = (); 14 | /// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>; 15 | /// use iced::widget::text; 16 | /// use iced::color; 17 | /// 18 | /// enum Message { 19 | /// // ... 20 | /// } 21 | /// 22 | /// fn view(state: &State) -> Element<'_, Message> { 23 | /// text("Hello, this is iced!") 24 | /// .size(20) 25 | /// .color(color!(0x0000ff)) 26 | /// .into() 27 | /// } 28 | /// ``` 29 | pub type Text<'a, Theme = crate::Theme, Renderer = crate::Renderer> = 30 | crate::core::widget::Text<'a, Theme, Renderer>; 31 | -------------------------------------------------------------------------------- /winit/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "iced_winit" 3 | description = "A runtime for iced on top of winit" 4 | version.workspace = true 5 | edition.workspace = true 6 | authors.workspace = true 7 | license.workspace = true 8 | repository.workspace = true 9 | homepage.workspace = true 10 | categories.workspace = true 11 | keywords.workspace = true 12 | 13 | [lints] 14 | workspace = true 15 | 16 | [features] 17 | default = ["x11", "wayland", "wayland-dlopen", "wayland-csd-adwaita"] 18 | debug = ["iced_debug/enable"] 19 | system = ["sysinfo"] 20 | program = [] 21 | x11 = ["winit/x11"] 22 | wayland = ["winit/wayland"] 23 | wayland-dlopen = ["winit/wayland-dlopen"] 24 | wayland-csd-adwaita = ["winit/wayland-csd-adwaita"] 25 | unconditional-rendering = [] 26 | 27 | [dependencies] 28 | iced_debug.workspace = true 29 | iced_program.workspace = true 30 | 31 | log.workspace = true 32 | rustc-hash.workspace = true 33 | thiserror.workspace = true 34 | tracing.workspace = true 35 | window_clipboard.workspace = true 36 | winit.workspace = true 37 | 38 | sysinfo.workspace = true 39 | sysinfo.optional = true 40 | 41 | [target.'cfg(target_arch = "wasm32")'.dependencies] 42 | web-sys.workspace = true 43 | web-sys.features = ["Document", "Window", "HtmlCanvasElement"] 44 | wasm-bindgen-futures.workspace = true 45 | -------------------------------------------------------------------------------- /winit/README.md: -------------------------------------------------------------------------------- 1 | # `iced_winit` 2 | [![Documentation](https://docs.rs/iced_winit/badge.svg)][documentation] 3 | [![Crates.io](https://img.shields.io/crates/v/iced_winit.svg)](https://crates.io/crates/iced_winit) 4 | [![License](https://img.shields.io/crates/l/iced_winit.svg)](https://github.com/iced-rs/iced/blob/master/LICENSE) 5 | [![Discord Server](https://img.shields.io/discord/628993209984614400?label=&labelColor=6A7EC2&logo=discord&logoColor=ffffff&color=7389D8)](https://discord.gg/3xZJ65GAhd) 6 | 7 | `iced_winit` offers some convenient abstractions on top of [`iced_native`] to quickstart development when using [`winit`]. 8 | 9 | It exposes a renderer-agnostic `Application` trait that can be implemented and then run with a simple call. The use of this trait is optional. A `conversion` module is provided for users that decide to implement a custom event loop. 10 | 11 |

12 | The native target 13 |

14 | 15 | [documentation]: https://docs.rs/iced_winit 16 | [`iced_native`]: ../native 17 | [`winit`]: https://github.com/rust-windowing/winit 18 | -------------------------------------------------------------------------------- /winit/src/error.rs: -------------------------------------------------------------------------------- 1 | use crate::futures::futures; 2 | use crate::graphics; 3 | 4 | /// An error that occurred while running an application. 5 | #[derive(Debug, thiserror::Error)] 6 | pub enum Error { 7 | /// The futures executor could not be created. 8 | #[error("the futures executor could not be created")] 9 | ExecutorCreationFailed(futures::io::Error), 10 | 11 | /// The application window could not be created. 12 | #[error("the application window could not be created")] 13 | WindowCreationFailed(winit::error::OsError), 14 | 15 | /// The application graphics context could not be created. 16 | #[error("the application graphics context could not be created")] 17 | GraphicsCreationFailed(graphics::Error), 18 | } 19 | 20 | impl From for Error { 21 | fn from(error: graphics::Error) -> Error { 22 | Error::GraphicsCreationFailed(error) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /winit/src/system.rs: -------------------------------------------------------------------------------- 1 | //! Access the native system. 2 | use crate::graphics::compositor; 3 | use crate::runtime::system::{Action, Information}; 4 | use crate::runtime::{self, Task}; 5 | 6 | /// Query for available system information. 7 | pub fn fetch_information() -> Task { 8 | runtime::task::oneshot(|channel| { 9 | runtime::Action::System(Action::QueryInformation(channel)) 10 | }) 11 | } 12 | 13 | pub(crate) fn information( 14 | graphics_info: compositor::Information, 15 | ) -> Information { 16 | use sysinfo::{Process, System}; 17 | let mut system = System::new_all(); 18 | system.refresh_all(); 19 | 20 | let cpu_brand = system 21 | .cpus() 22 | .first() 23 | .map(|cpu| cpu.brand().to_string()) 24 | .unwrap_or_default(); 25 | 26 | let memory_used = sysinfo::get_current_pid() 27 | .and_then(|pid| system.process(pid).ok_or("Process not found")) 28 | .map(Process::memory) 29 | .ok(); 30 | 31 | Information { 32 | system_name: System::name(), 33 | system_kernel: System::kernel_version(), 34 | system_version: System::long_os_version(), 35 | system_short_version: System::os_version(), 36 | cpu_brand, 37 | cpu_cores: system.physical_core_count(), 38 | memory_total: system.total_memory(), 39 | memory_used, 40 | graphics_adapter: graphics_info.adapter, 41 | graphics_backend: graphics_info.backend, 42 | } 43 | } 44 | --------------------------------------------------------------------------------