├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── CI.yml ├── .gitignore ├── .rustfmt.toml ├── .vscode └── settings.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Cargo.toml ├── LICENSE ├── README.md ├── build.rs ├── config.toml ├── icedpygui ├── __init__.py └── icedpygui.pyi ├── pyproject.toml ├── python_examples ├── defined_colors.py ├── demo.py ├── demo_readme_code.py ├── py_button.py ├── py_button_add_new.py ├── py_button_update.py ├── py_canvas.py ├── py_canvas_draw.py ├── py_card.py ├── py_checkbox_simple.py ├── py_checkbox_styling.py ├── py_color_picker.py ├── py_column.py ├── py_container.py ├── py_container_styling.py ├── py_date_picker.py ├── py_divider_combined.py ├── py_divider_horizontal.py ├── py_divider_vertical.py ├── py_event_keyboard.py ├── py_event_mouse.py ├── py_image.py ├── py_menu.py ├── py_mouse_area.py ├── py_move_widget.py ├── py_picklist_styling.py ├── py_progress_bar.py ├── py_radio.py ├── py_radio_test_quantity.py ├── py_row.py ├── py_rule.py ├── py_scrollable.py ├── py_scrollable_styling.py ├── py_selectable_text.py ├── py_separator.py ├── py_slider_pg_bar.py ├── py_solar_sytem.py ├── py_solitaire.py ├── py_space.py ├── py_stack.py ├── py_svg.py ├── py_table.py ├── py_table_styling.py ├── py_text.py ├── py_text_input.py ├── py_timer.py ├── py_toggler.py ├── py_toggler_styling.py ├── py_tooltip.py ├── py_windows.py └── resources │ ├── canvas.json │ ├── cards │ ├── card_back.png │ ├── clubs │ │ ├── 1.png │ │ ├── 10.png │ │ ├── 11.png │ │ ├── 12.png │ │ ├── 13.png │ │ ├── 2.png │ │ ├── 3.png │ │ ├── 4.png │ │ ├── 5.png │ │ ├── 6.png │ │ ├── 7.png │ │ ├── 8.png │ │ └── 9.png │ ├── diamonds │ │ ├── 1.png │ │ ├── 10.png │ │ ├── 11.png │ │ ├── 12.png │ │ ├── 13.png │ │ ├── 2.png │ │ ├── 3.png │ │ ├── 4.png │ │ ├── 5.png │ │ ├── 6.png │ │ ├── 7.png │ │ ├── 8.png │ │ └── 9.png │ ├── hearts │ │ ├── 1.png │ │ ├── 10.png │ │ ├── 11.png │ │ ├── 12.png │ │ ├── 13.png │ │ ├── 2.png │ │ ├── 3.png │ │ ├── 4.png │ │ ├── 5.png │ │ ├── 6.png │ │ ├── 7.png │ │ ├── 8.png │ │ └── 9.png │ └── spades │ │ ├── 1.png │ │ ├── 10.png │ │ ├── 11.png │ │ ├── 12.png │ │ ├── 13.png │ │ ├── 2.png │ │ ├── 3.png │ │ ├── 4.png │ │ ├── 5.png │ │ ├── 6.png │ │ ├── 7.png │ │ ├── 8.png │ │ └── 9.png │ ├── ferris_0.png │ ├── ferris_1.png │ ├── ferris_2.png │ ├── ferris_3.png │ ├── ferris_4.png │ ├── ferris_5.png │ ├── ferris_6.png │ ├── ferris_7.png │ ├── ferris_8.png │ ├── ferris_9.png │ ├── solar_system_assets │ ├── earth.png │ ├── moon.png │ └── sun.png │ ├── tiger_0.svg │ ├── tiger_1.svg │ ├── tiger_2.svg │ ├── tiger_3.svg │ └── tiger_4.svg └── src ├── app.rs ├── canvas ├── canvas_helpers.rs ├── colors.rs ├── draw_canvas.rs ├── geometries.rs ├── import_export.rs ├── mod.rs └── path_builds.rs ├── graphics ├── bootstrap.rs ├── bootstrap_icon.rs ├── colors.rs ├── fonts │ ├── SFUIRounded.ttf │ ├── bootstrap-icons.ttf │ ├── icons.ttf │ └── nerd-icons.ttf ├── mod.rs ├── nerd.rs └── required.rs ├── iced_aw_widgets ├── card.rs ├── menu │ ├── common.rs │ ├── flex.rs │ ├── menu_bar.rs │ ├── menu_bar_overlay.rs │ ├── menu_bar_style.rs │ ├── menu_tree.rs │ ├── mod.rs │ ├── quad.rs │ ├── style.rs │ └── style_status.rs └── mod.rs ├── iced_widgets ├── mod.rs └── mousearea_table.rs ├── ipg_widgets ├── callbacks.rs ├── divider.rs ├── helpers.rs ├── ipg_button.rs ├── ipg_canvas.rs ├── ipg_card.rs ├── ipg_checkbox.rs ├── ipg_color_picker.rs ├── ipg_column.rs ├── ipg_container.rs ├── ipg_date_picker.rs ├── ipg_divider.rs ├── ipg_enums.rs ├── ipg_events.rs ├── ipg_image.rs ├── ipg_menu.rs ├── ipg_modal.rs ├── ipg_mousearea.rs ├── ipg_opaque.rs ├── ipg_pane_grid.rs ├── ipg_pick_list.rs ├── ipg_progress_bar.rs ├── ipg_radio.rs ├── ipg_row.rs ├── ipg_rule.rs ├── ipg_scrollable.rs ├── ipg_selectable_text.rs ├── ipg_separator.rs ├── ipg_slider.rs ├── ipg_space.rs ├── ipg_stack.rs ├── ipg_svg.rs ├── ipg_table.rs ├── ipg_text.rs ├── ipg_text_editor.rs ├── ipg_text_input.rs ├── ipg_text_rich.rs ├── ipg_timer.rs ├── ipg_timer_canvas.rs ├── ipg_toggle.rs ├── ipg_tool_tip.rs ├── ipg_window.rs ├── mod.rs └── table.rs ├── lib.rs └── style ├── mod.rs └── styling.rs /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Version [e.g. 22] 29 | 30 | 31 | **Additional context** 32 | Add any other context about the problem here. 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/CI.yml: -------------------------------------------------------------------------------- 1 | # This file is autogenerated by maturin v1.8.3 2 | # To update, run 3 | # 4 | # maturin generate-ci github 5 | # 6 | name: CI 7 | 8 | on: 9 | push: 10 | branches: 11 | - main 12 | tags: 13 | - '*' 14 | pull_request: 15 | workflow_dispatch: 16 | 17 | permissions: 18 | contents: read 19 | 20 | jobs: 21 | # linux: 22 | # runs-on: ${{ matrix.platform.runner }} 23 | # strategy: 24 | # matrix: 25 | # platform: 26 | # - runner: ubuntu-22.04 27 | # target: x86_64 28 | # - runner: ubuntu-22.04 29 | # target: x86 30 | # - runner: ubuntu-22.04 31 | # target: aarch64 32 | # - runner: ubuntu-22.04 33 | # target: armv7 34 | # - runner: ubuntu-22.04 35 | # target: s390x 36 | # - runner: ubuntu-22.04 37 | # target: ppc64le 38 | # steps: 39 | # - uses: actions/checkout@v4 40 | # - uses: actions/setup-python@v5 41 | # with: 42 | # python-version: 3.x 43 | # - name: Build wheels 44 | # uses: PyO3/maturin-action@v1 45 | # with: 46 | # target: ${{ matrix.platform.target }} 47 | # args: --release --out dist --find-interpreter 48 | # sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} 49 | # manylinux: auto 50 | # - name: Upload wheels 51 | # uses: actions/upload-artifact@v4 52 | # with: 53 | # name: wheels-linux-${{ matrix.platform.target }} 54 | # path: dist 55 | 56 | # musllinux: 57 | # runs-on: ${{ matrix.platform.runner }} 58 | # strategy: 59 | # matrix: 60 | # platform: 61 | # - runner: ubuntu-22.04 62 | # target: x86_64 63 | # - runner: ubuntu-22.04 64 | # target: x86 65 | # - runner: ubuntu-22.04 66 | # target: aarch64 67 | # - runner: ubuntu-22.04 68 | # target: armv7 69 | # steps: 70 | # - uses: actions/checkout@v4 71 | # - uses: actions/setup-python@v5 72 | # with: 73 | # python-version: 3.x 74 | # - name: Build wheels 75 | # uses: PyO3/maturin-action@v1 76 | # with: 77 | # target: ${{ matrix.platform.target }} 78 | # args: --release --out dist --find-interpreter 79 | # sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} 80 | # manylinux: musllinux_1_2 81 | # - name: Upload wheels 82 | # uses: actions/upload-artifact@v4 83 | # with: 84 | # name: wheels-musllinux-${{ matrix.platform.target }} 85 | # path: dist 86 | 87 | # windows: 88 | # runs-on: ${{ matrix.platform.runner }} 89 | # strategy: 90 | # matrix: 91 | # platform: 92 | # - runner: windows-latest 93 | # target: x64 94 | # - runner: windows-latest 95 | # target: x86 96 | # steps: 97 | # - uses: actions/checkout@v4 98 | # - uses: actions/setup-python@v5 99 | # with: 100 | # python-version: 3.10 101 | # architecture: ${{ matrix.platform.target }} 102 | # - name: Build wheels 103 | # uses: PyO3/maturin-action@v1 104 | # with: 105 | # target: ${{ matrix.platform.target }} 106 | # args: --release --out dist --find-interpreter 107 | # sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} 108 | # - name: Upload wheels 109 | # uses: actions/upload-artifact@v4 110 | # with: 111 | # name: wheels-windows-${{ matrix.platform.target }} 112 | # path: dist 113 | 114 | macos: 115 | runs-on: ${{ matrix.platform.runner }} 116 | strategy: 117 | matrix: 118 | platform: 119 | - runner: macos-13 120 | target: x86_64 121 | - runner: macos-14 122 | target: aarch64 123 | steps: 124 | - uses: actions/checkout@v4 125 | - uses: actions/setup-python@v5 126 | with: 127 | python-version: 3.x 128 | - name: Build wheels 129 | uses: PyO3/maturin-action@v1 130 | with: 131 | target: ${{ matrix.platform.target }} 132 | args: --release --out dist --find-interpreter 133 | sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} 134 | - name: Upload wheels 135 | uses: actions/upload-artifact@v4 136 | with: 137 | name: wheels-macos-${{ matrix.platform.target }} 138 | path: dist 139 | 140 | sdist: 141 | runs-on: ubuntu-latest 142 | steps: 143 | - uses: actions/checkout@v4 144 | - name: Build sdist 145 | uses: PyO3/maturin-action@v1 146 | with: 147 | command: sdist 148 | args: --out dist 149 | - name: Upload sdist 150 | uses: actions/upload-artifact@v4 151 | with: 152 | name: wheels-sdist 153 | path: dist 154 | 155 | # release: 156 | # name: Release 157 | # runs-on: ubuntu-latest 158 | # if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' }} 159 | # needs: [linux, musllinux, windows, macos, sdist] 160 | # permissions: 161 | # # Use to sign the release artifacts 162 | # id-token: write 163 | # # Used to upload release artifacts 164 | # contents: write 165 | # # Used to generate artifact attestation 166 | # attestations: write 167 | # steps: 168 | # - uses: actions/download-artifact@v4 169 | # - name: Generate artifact attestation 170 | # uses: actions/attest-build-provenance@v2 171 | # with: 172 | # subject-path: 'wheels-*/*' 173 | # - name: Publish to PyPI 174 | # if: ${{ startsWith(github.ref, 'refs/tags/') }} 175 | # uses: PyO3/maturin-action@v1 176 | # env: 177 | # MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }} 178 | # with: 179 | # command: upload 180 | # args: --non-interactive --skip-existing wheels-*/* 181 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | 12 | # MSVC Windows builds of rustc generate these, which store debugging information 13 | *.pdb 14 | .idea/misc.xml 15 | .venv 16 | icedpygui/__pycache__/__init__.cpython*.pyc 17 | icedpygui/icedpygui.cpython-*.so 18 | py_example/__pycache__/callbacks.cpython*.pyc 19 | -------------------------------------------------------------------------------- /.rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 120 2 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "rust-analyzer.linkedProjects": [ 3 | "./Cargo.toml", 4 | ], 5 | "rust-analyzer.showUnlinkedFileNotification": false, 6 | "rust-analyzer.cargo.features": "all", 7 | 8 | "editor.selectionClipboard": false, 9 | "rust-analyzer.hover.documentation.keywords.enable": true, 10 | 11 | "[python]": { 12 | "editor.detectIndentation": false, 13 | "editor.insertSpaces": true, 14 | "editor.tabSize": 4 15 | } 16 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## Current Main 9 | 10 | None 11 | 12 | ## [0.4.0] - 2025-05-08 13 | - updated to 0.4.0 14 | - many internal optimizations 15 | - canvas draw widget 16 | - new table using polars dataframe 17 | - divider widget, allow resizing containers 18 | 19 | ## [0.3.0] - 2024-10-29 20 | 21 | - updated to iced 0.13.1 22 | - added canvas with examples 23 | - added stack with example 24 | - added ability to move widget between containers 25 | - table widget updated widgets 26 | - closing, opening, hidding windows more consistent 27 | - refacted area to improve consistency and efficiency 28 | - touched many area while updating to iced 0.13.1 29 | 30 | ## [0.2.0] - 2024-08-12 31 | 32 | - updated to iced rev="07f94d6" 33 | - all widgets and containers now have styling 34 | - significant changes to the table. 35 | - refactored a number of areas to improve consistency. 36 | 37 | ## [0.1.0] - 2024-05-27 38 | 39 | - Added svg widget 40 | - Added mouse area widget 41 | - Improved callback error message on all widgets 42 | - Refactor table and added ability to added the widgets button, checkbox, selectable text, image, and svg. 43 | - Updated to Iced rev=b30d34f 44 | 45 | ## [0.1.0-alpha] - 2024-05-02 46 | 47 | - First release! 48 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to make participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | - Using welcoming and inclusive language 18 | - Being respectful of differing viewpoints and experiences 19 | - Gracefully accepting constructive criticism 20 | - Focusing on what is best for the community 21 | - Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | - The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | - Trolling, insulting/derogatory comments, and personal or political attacks 28 | - Public or private harassment 29 | - Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | - Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies within all project spaces, and it also applies when 49 | an individual is representing the project or its community in public spaces. 50 | Examples of representing a project or community include using an official 51 | project e-mail address, posting via an official social media account, or acting 52 | as an appointed representative at an online or offline event. Representation of 53 | a project may be further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at icedpygui@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["Charles Ray "] 3 | name = "IcedPyGui" 4 | version = "0.4.0" 5 | edition = "2021" 6 | license = "GNU" 7 | description = "Python wrapper for Rust Iced" 8 | readme = "README.md" 9 | 10 | [lib] 11 | name = "icedpygui" 12 | crate-type = ["cdylib"] 13 | 14 | 15 | [dependencies] 16 | pyo3 = { version = "0.23.3", features = ["extension-module"] } 17 | iced = { version = "0.13.1", features = ["advanced", "canvas", "debug", "highlighter", "image", 18 | "lazy", "smol", "svg", "tokio", "multi-window", "auto-detect-theme"] } 19 | iced_aw = {git = "https://github.com/iced-rs/iced_aw", rev = "3485f3a"} 20 | 21 | polars = { version="0.46.0", features=["strings", "lazy"]} 22 | pyo3-polars = "0.20.0" 23 | 24 | tokio = { version = "1.0", features = ["fs"]} 25 | rfd = "0.13" 26 | once_cell = "1.19.0" 27 | chrono = "0.4.31" 28 | unicode-segmentation = "1.9.0" 29 | palette = "0.7.4" 30 | 31 | serde = { version = "1.0", features = ["derive"] } 32 | serde_json = "*" 33 | phf = { version = "0.11", default-features = false } 34 | 35 | [build-dependencies] 36 | pyo3-build-config = { version = "0.23.3", features = ["resolve-config"] } 37 | 38 | [profile.release] 39 | strip = true 40 | lto = "fat" 41 | codegen-units = 1 42 | opt-level = 3 43 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | 2 | 3 | fn main() { 4 | pyo3_build_config::use_pyo3_cfgs(); 5 | } 6 | -------------------------------------------------------------------------------- /config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | rustflags = ["-Z", "threads=8"] 3 | -------------------------------------------------------------------------------- /icedpygui/__init__.py: -------------------------------------------------------------------------------- 1 | from .icedpygui import IPG 2 | from .icedpygui import IpgAlignment, IpgHorizontalAlignment, IpgVerticalAlignment 3 | from .icedpygui import IpgButtonArrow, IpgButtonParam, IpgButtonStyleParam 4 | from .icedpygui import IpgDrawMode, IpgCanvasParam, IpgCanvasWidget 5 | from .icedpygui import IpgCanvasGeometryParam 6 | from .icedpygui import IpgCardStyleParam, IpgCardParam 7 | from .icedpygui import IpgCheckboxParam, IpgCheckboxStyleParam 8 | from .icedpygui import IpgColor 9 | from .icedpygui import IpgColorPickerParam, IpgColorPickerStyleParam 10 | from .icedpygui import IpgColumnParam 11 | from .icedpygui import IpgContainerParam, IpgContainerStyleParam 12 | from .icedpygui import IpgDatePickerParam 13 | from .icedpygui import IpgDividerParam, IpgDividerStyleParam 14 | from .icedpygui import IpgImageParam, IpgImageContentFit, IpgImageFilterMethod, IpgImageRotation 15 | from .icedpygui import IpgMenuParam, IpgMenuStyleParam, IpgMenuBarStyleParam 16 | from .icedpygui import IpgMousePointer 17 | from .icedpygui import IpgOpaqueParam 18 | from .icedpygui import IpgPickListParam, IpgPickListHandle, IpgPickListStyleParam 19 | from .icedpygui import IpgProgressBarParam, IpgProgressBarStyleParam 20 | from .icedpygui import IpgRadioParam, IpgRadioDirection, IpgRadioStyleParam 21 | from .icedpygui import IpgRowParam 22 | from .icedpygui import IpgRuleStyleParam 23 | from .icedpygui import IpgScrollableDirection, IpgScrollableParam, IpgScrollableStyleParam 24 | from .icedpygui import IpgSelectableTextParam 25 | from .icedpygui import IpgSeparatorType, IpgSeparatorParam, IpgSeparatorStyleParam 26 | from .icedpygui import IpgSliderParam, IpgSliderStyleParam 27 | from .icedpygui import IpgStackParam 28 | from .icedpygui import IpgStyleStandard 29 | from .icedpygui import IpgSvgParam 30 | from .icedpygui import IpgTableParam, IpgTableStyleParam 31 | from .icedpygui import IpgTextInputParam, IpgTextInputStyleParam 32 | from .icedpygui import IpgTextParam 33 | from .icedpygui import IpgTimerParam, IpgTimerStyleParam 34 | from .icedpygui import IpgCanvasTimerParam, IpgCanvasTimerStyleParam 35 | from .icedpygui import IpgTogglerParam, IpgTogglerStyleParam 36 | from .icedpygui import IpgToolTipPosition, IpgToolTipParam, IpgToolTipStyleParam 37 | from .icedpygui import IpgWindowLevel, IpgWindowMode, IpgWindowTheme, IpgWindowParam 38 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["maturin>=1.2,<2.0"] 3 | build-backend = "maturin" 4 | 5 | [project] 6 | name = "IcedPyGui" 7 | description = "Python wrapper for Rust Iced" 8 | version = "0.4.0" 9 | authors = [ 10 | {name = 'Charles Ray', email = 'icedpygui@gmail.com'} 11 | ] 12 | readme = "README.md" 13 | # PyO3 doesn't support python 3.13 yet. 14 | requires-python = ">=3.10, < 3.13" 15 | keywords = ["iced", "iced_aw", "gui", "rust", "python"] 16 | 17 | classifiers = [ 18 | "Programming Language :: Rust", 19 | "Programming Language :: Python :: Implementation :: CPython", 20 | "Programming Language :: Python :: Implementation :: PyPy", 21 | ] 22 | 23 | [project.urls] 24 | Homepage = "https://github.com/icedpygui/IcedPyGui" 25 | Issues = "https://github.com/icedpygui/IcedPyGui/issues" 26 | 27 | [tool.maturin] 28 | features = ["pyo3/extension-module"] 29 | -------------------------------------------------------------------------------- /python_examples/demo_readme_code.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG 2 | from icedpygui import IpgAlignment, IpgTextParam 3 | 4 | 5 | def button_pressed(btn_id): 6 | print(btn_id) 7 | 8 | 9 | def checked(_chk_id: int, checked: bool): 10 | if checked: 11 | ipg.update_item( 12 | wid=checked_text_id, 13 | param=IpgTextParam.Content, 14 | value="I'm checked") 15 | 16 | else: 17 | ipg.update_item( 18 | wid=checked_text_id, 19 | param=IpgTextParam.Content, 20 | value="I'm not checked") 21 | 22 | 23 | ipg = IPG() 24 | 25 | # add the window centered on the screen 26 | ipg.add_window( 27 | window_id="main", 28 | title="Demo Window", 29 | width=600, 30 | height=500, 31 | pos_centered=True) 32 | 33 | # container alignment defaults to centering 34 | ipg.add_container( 35 | window_id="main", 36 | container_id="cont", 37 | width_fill=True, 38 | height_fill=True) 39 | 40 | # The column width will shrink to the size of the largest widget by default. 41 | ipg.add_column( 42 | window_id="main", 43 | container_id="col", 44 | parent_id="cont", 45 | align=IpgAlignment.Center) 46 | 47 | ipg.add_button( 48 | parent_id="col", 49 | label="Press Me!", 50 | on_press=button_pressed) 51 | 52 | ipg.add_checkbox( 53 | parent_id="col", 54 | label="Check Me!!!", 55 | on_toggle=checked) 56 | 57 | checked_text_id = ipg.add_text( 58 | parent_id="col", 59 | content="This will change when I'm checked") 60 | 61 | ipg.start_session() 62 | -------------------------------------------------------------------------------- /python_examples/py_button.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgColor, IpgWindowTheme, IpgAlignment, IpgStyleStandard, IpgButtonArrow 2 | from icedpygui import IpgHorizontalAlignment, IpgVerticalAlignment 3 | ipg = IPG() 4 | 5 | 6 | def on_press(btn_id): 7 | print("button pressed") 8 | 9 | def add_buttons(window: str): 10 | # Add a container to hold everything aligning all in the center 11 | ipg.add_container( 12 | window_id=window, 13 | container_id="cont", 14 | width_fill=True, 15 | height_fill=True) 16 | 17 | # Add a column to hold multiple widgets, vertically. 18 | ipg.add_column( 19 | window_id=window, 20 | container_id="col", 21 | parent_id="cont") 22 | 23 | # Add a row to hold widgets, horizontally. 24 | ipg.add_row( 25 | window_id=window, 26 | container_id="row_btn", 27 | parent_id="col", 28 | align=IpgAlignment.Center) 29 | 30 | # Add buttons 31 | ipg.add_button( 32 | parent_id="row_btn", 33 | label="Default", 34 | on_press=on_press) 35 | 36 | ipg.add_button( 37 | parent_id="row_btn", 38 | label="Primary", 39 | on_press=on_press, 40 | style_standard=IpgStyleStandard.Primary) 41 | 42 | ipg.add_button( 43 | parent_id="row_btn", 44 | label="Success", 45 | on_press=on_press, 46 | style_standard=IpgStyleStandard.Success) 47 | 48 | ipg.add_button( 49 | parent_id="row_btn", 50 | label="Danger", 51 | on_press=on_press, 52 | style_standard=IpgStyleStandard.Danger) 53 | 54 | ipg.add_button( 55 | parent_id="row_btn", 56 | label="Text", 57 | on_press=on_press, 58 | style_standard=IpgStyleStandard.Text) 59 | 60 | ipg.add_button( 61 | parent_id="row_btn", 62 | label="", 63 | on_press=on_press, 64 | style_arrow=IpgButtonArrow.ArrowRight) 65 | 66 | ipg.add_row( 67 | window_id=window, 68 | container_id="row_btn2", 69 | parent_id="col", 70 | align=IpgAlignment.Center) 71 | 72 | dodger = ipg.add_button_style( 73 | background_color=IpgColor.DODGER_BLUE) 74 | 75 | ipg.add_button( 76 | parent_id="row_btn2", 77 | label="Custom Base Only Defined", 78 | style_id=dodger) 79 | 80 | custom = ipg.add_button_style( 81 | background_color=IpgColor.DODGER_BLUE, 82 | background_color_hovered=IpgColor.BLUE, 83 | border_color=IpgColor.DARK_GOLDEN_ROD, 84 | shadow_color=IpgColor.DARK_ORANGE, 85 | text_color=IpgColor.BLACK, 86 | border_radius=[12.0], 87 | border_width=5.0, 88 | shadow_offset_x=0.0, 89 | shadow_offset_y=0.0, 90 | shadow_blur_radius=15.0) 91 | 92 | ipg.add_button( 93 | parent_id="row_btn2", 94 | label="All Colors Custom", 95 | style_id=custom) 96 | 97 | ipg.add_row( 98 | window_id=window, 99 | container_id="row_btn3", 100 | parent_id="col", 101 | align=IpgAlignment.Center) 102 | 103 | std_border = ipg.add_button_style( 104 | border_color=IpgColor.GREEN, 105 | border_radius=[12.0], 106 | border_width=5.0, 107 | shadow_color=IpgColor.DARK_GREEN, 108 | shadow_blur_radius=10.0, 109 | shadow_offset_x=5.0, 110 | shadow_offset_y=5.0, 111 | ) 112 | 113 | ipg.add_button( 114 | parent_id="row_btn3", 115 | label="Standard with Border and shadow", 116 | style_id=std_border, 117 | style_standard=IpgStyleStandard.Success) 118 | 119 | if window == "main1": 120 | ipg.add_button( 121 | parent_id="col", 122 | label="Alignment = Center/Center", 123 | width=300.0, 124 | height=50.0) 125 | 126 | ipg.add_button( 127 | parent_id="col", 128 | label="Alignment = Left/Bottom", 129 | width=300.0, 130 | height=50.0, 131 | text_align_x=IpgHorizontalAlignment.Left, 132 | text_align_y=IpgVerticalAlignment.Bottom) 133 | 134 | ipg.add_button( 135 | parent_id="col", 136 | label="Alignment = Right/Top", 137 | width=300.0, 138 | height=50.0, 139 | text_align_x=IpgHorizontalAlignment.Right, 140 | text_align_y=IpgVerticalAlignment.Top) 141 | 142 | 143 | # Add the windows 144 | ipg.add_window( 145 | window_id="main1", 146 | title="Button Styling", 147 | width=500, 148 | height=600, 149 | pos_x=100, 150 | pos_y=25) 151 | 152 | ipg.add_window( 153 | window_id="main2", 154 | title="Button Styling", 155 | width=500, 156 | height=600, 157 | pos_x=650, 158 | pos_y=25, 159 | theme=IpgWindowTheme.GruvboxLight) 160 | 161 | add_buttons("main1") 162 | 163 | add_buttons("main2") 164 | 165 | ipg.start_session() 166 | -------------------------------------------------------------------------------- /python_examples/py_button_add_new.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG 2 | 3 | 4 | ipg = IPG() 5 | 6 | count = 0 7 | def on_press(btn_id, user_data: int): 8 | global count 9 | count += 1 10 | ipg.add_button( 11 | parent_id="col", 12 | label=f"Button_{count}", 13 | on_press=on_press, 14 | user_data=0) 15 | 16 | 17 | # Add the windows 18 | ipg.add_window( 19 | window_id="main", 20 | title="Button", 21 | width=400, 22 | height=400, 23 | pos_centered=True) 24 | 25 | # Add a container to hold everything aligning all in the center 26 | ipg.add_container( 27 | window_id="main", 28 | container_id="cont", 29 | width_fill=True, 30 | height_fill=True, 31 | centered=True) 32 | 33 | # Add a column to hold multiple widgets, vertically. 34 | ipg.add_column( 35 | window_id="main", 36 | container_id="col", 37 | parent_id="cont") 38 | 39 | ipg.add_button( 40 | parent_id="col", 41 | label="Press Me to Add A Button", 42 | on_press=on_press, 43 | user_data=0) 44 | 45 | ipg.start_session() 46 | -------------------------------------------------------------------------------- /python_examples/py_canvas.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgColor 2 | import math 3 | 4 | ipg = IPG() 5 | 6 | 7 | ipg.add_window( 8 | window_id="main", 9 | title="Canvas", 10 | width=400.0, 11 | height=400.0, 12 | pos_centered=True) 13 | 14 | ipg.add_canvas( 15 | window_id="main", 16 | canvas_id="canvas", 17 | width_fill=True, 18 | height_fill=True) 19 | 20 | ipg.add_arc( 21 | canvas_id="canvas", 22 | center_xy=(250.0, 100.0), 23 | radius=50.0, 24 | start_angle=0.0, 25 | end_angle=180.0, 26 | stroke_width=2.0) 27 | 28 | ipg.add_bezier( 29 | canvas_id="canvas", 30 | points=((50.0, 200.0), (50.0, 125.0), (150.0, 200.0)), 31 | stroke_width=2.0) 32 | 33 | ipg.add_circle( 34 | canvas_id="canvas", 35 | position_xy=(100.0, 100.0), 36 | radius=25.0, 37 | stroke_width=1.0, 38 | fill_ipg_color=IpgColor.DARK_OLIVE_GREEN) 39 | 40 | ipg.add_ellipse( 41 | canvas_id="canvas", 42 | position_xy=(100.0, 275.0), 43 | radius_x=60.0, 44 | radius_y=10.0, 45 | degrees=math.pi, 46 | stroke_width=2.0) 47 | 48 | ipg.add_line( 49 | canvas_id="canvas", 50 | start=(50.0, 350.0), 51 | end=(300.0, 370.0), 52 | stroke_ipg_color=IpgColor.YELLOW, 53 | stroke_width=2.0,) 54 | 55 | ipg.add_rectangle( 56 | canvas_id="canvas", 57 | top_left_xy=(250.0, 200.0), 58 | width=50.0, 59 | height=75.0, 60 | stroke_width=2.0,) 61 | 62 | 63 | ipg.start_session() 64 | -------------------------------------------------------------------------------- /python_examples/py_card.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgCardParam, IpgCardStyleParam 2 | from icedpygui import IpgAlignment, IpgColor, IpgStyleStandard 3 | 4 | 5 | # Needed first, see other demos for using a class 6 | ipg = IPG() 7 | 8 | card_id = 0 9 | # Callback function for changing the card style 10 | # The update function is (wid, param, value) 11 | # wid = widget id 12 | def update_card(_btn_id: int): 13 | global card_id 14 | # The card_id is the first card in the series. The only one that is changed. 15 | # The btn_id is not used. 16 | ipg.update_item( 17 | wid=card_id, 18 | param=IpgCardParam.Head, 19 | value="This is a new head text") 20 | 21 | ipg.update_item( 22 | wid=card_id, 23 | param=IpgCardParam.Body, 24 | value="This is a new body text.") 25 | 26 | ipg.update_item( 27 | wid=card_id, 28 | param=IpgCardParam.Foot, 29 | value="This is a new foot text") 30 | 31 | 32 | 33 | # The callback will minimizes the first card, the button at the bottom left will maximize it. 34 | def minimize_card(card_id: int): 35 | # In this case the card has a built in button, it can trigger the minimization. 36 | # Therefore, unlike most other widgets, the id is the card_id needed. 37 | # The update widget will always need a type where the correct 38 | # parameter can be selected. In this case is was IsOpen. 39 | # id you look at the Card widget docs, you will know what the value 40 | # type will be, in this case a boolean. 41 | ipg.update_item( 42 | wid=card_id, 43 | param=IpgCardParam.IsOpen, 44 | value=False) 45 | 46 | 47 | # Pressing the bottom button will maximize the card, returning it to the top. 48 | # Note the callback is from the button so the card_id has to be global. 49 | # Normally, you would use a class or dataclass to store these ids. 50 | def maximize_card(_btn_id: int): 51 | global card_id 52 | ipg.update_item( 53 | wid=card_id, 54 | param=IpgCardParam.IsOpen, 55 | value=True) 56 | 57 | # The style id is used in the card style_id to set the style 58 | # In this case we create 4 simple styles for later use 59 | colors = [IpgColor.PRIMARY, IpgColor.SUCCESS, IpgColor.DANGER, IpgColor.BLUE] 60 | style_ids = [] 61 | for i in range(0, 4): 62 | id = ipg.add_card_style( 63 | body_background_color=colors[i], 64 | foot_background_color=IpgColor.DARK_GREY) 65 | style_ids.append(id) 66 | 67 | # window added first 68 | ipg.add_window( 69 | window_id="main", 70 | title="Card Demo", 71 | width=800, 72 | height=600, 73 | pos_x=100, 74 | pos_y=25) 75 | 76 | # Add a container for the first button to center it. 77 | # A width_fill is used but the height remains a shrink 78 | # We have center aligned along the x axis. 79 | ipg.add_container( 80 | window_id="main", 81 | container_id="btn_cont", 82 | width_fill=True) 83 | 84 | # add a button with a callback on_press to update the first card. 85 | ipg.add_button("btn_cont", 86 | label="Pressing this will change the updatable items in the first card\n if you close card 1, " 87 | "restore it by pressing on the bottom button.", 88 | on_press=update_card) 89 | 90 | # add another is added container to center the column of cards to follow 91 | ipg.add_container( 92 | window_id="main", 93 | container_id="cont", 94 | width_fill=True, 95 | height_fill=True) 96 | 97 | 98 | # Put a column in the scrollable. Note that the height of the scrollable is fill 99 | # and then the column is made shorter that the scrollable. This seems to work 100 | # most of the time but in some situations you'll need to use the window debug setting 101 | # to see how things line up and getting the contents to scroll. Just remember the 102 | # scrollable has to be larger than the container, column, or row. 103 | ipg.add_column( 104 | window_id="main", 105 | container_id="col", 106 | parent_id="cont", 107 | align=IpgAlignment.Center, 108 | width=400.0, 109 | spacing=5.0, 110 | padding=[10.0]) 111 | 112 | # Add a row at the bottom to hold the button 113 | ipg.add_row( 114 | window_id="main", 115 | container_id="bottom_row", 116 | parent_id="main", 117 | width_fill=True, 118 | spacing=0.0) 119 | 120 | # Add the button. This button could have been hidden and when the card is minimized, then show it. 121 | # You could also have changed the label to min or max. 122 | ipg.add_button( 123 | parent_id="bottom_row", 124 | label="Card 1", 125 | style_standard=IpgStyleStandard.Primary, 126 | on_press=maximize_card) 127 | 128 | # define the head and body of the cards. 129 | head = "Python Iced_aw Card" 130 | body = "This is the body of the card." 131 | foot = "Foot" 132 | 133 | for i in range(0, 4): 134 | id = ipg.add_card( 135 | parent_id="col", 136 | head=head, 137 | body=body, 138 | foot=foot, 139 | style_id=style_ids[i], 140 | on_close=minimize_card) 141 | if i == 0: 142 | card_id = id 143 | 144 | 145 | # Required to be the last widget sent to Iced, If you start the program 146 | # and nothing happens, it might mean you forgot to add this command. 147 | ipg.start_session() 148 | -------------------------------------------------------------------------------- /python_examples/py_checkbox_simple.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgCheckboxParam, IpgAlignment 2 | 3 | # This is a simple demo to change the checkmark of the checkbox to an x. 4 | ipg = IPG() 5 | 6 | # A technique explored in another demo where the 7 | # id is generated ahead of time. Useful in some cases. 8 | x_id = ipg.generate_id() 9 | 10 | 11 | # The callback used for the checkbox. 12 | # This callback id for this is not used since we are 13 | # changing the other checkbox. Therefore we needed to know 14 | # its id. Normally you would probably use a class to store theses 15 | # needed ids for later use. 16 | # The is_checked is a boolean which will toggle each time the 17 | # checkbox is clicked. 18 | def on_toggle(_chkbx_id: int, is_checked: bool, user_data: any): 19 | ipg.update_item( 20 | wid=x_id, 21 | param=IpgCheckboxParam.IconX, 22 | value=is_checked) 23 | 24 | 25 | # Add a window first 26 | ipg.add_window( 27 | window_id="main", 28 | title="CheckBox Demo", 29 | width=600, 30 | height=600, 31 | pos_centered=True) 32 | 33 | # Add a container to center the widgets in the middle 34 | ipg.add_container( 35 | window_id="main", 36 | container_id="cont", 37 | width_fill=True, 38 | height_fill=True) 39 | 40 | # Since a container can only hold one widget, use a column to hold the 41 | # two checkboxes. We let the width and height default to shrink, so no entry. 42 | # The alignment defaults to Start but for demonstration purpose, we 43 | # added the IpgColumnAlignment.Start 44 | ipg.add_column( 45 | window_id="main", 46 | container_id="col", 47 | parent_id="cont", 48 | align=IpgAlignment.Start) 49 | 50 | # Add the first checkbox with the callback on_toggle. 51 | ipg.add_checkbox( 52 | parent_id="col", 53 | label="Check Me!!!", 54 | on_toggle=on_toggle, 55 | user_data="Something") # not used in this demo 56 | 57 | # Add the second checkbox. This has no callback since it not used. 58 | ipg.add_checkbox( 59 | parent_id="col", 60 | gen_id=x_id, 61 | label="See my check check change to an x", 62 | is_checked=True) 63 | 64 | # Required to be the last widget sent to Iced, If you start the program 65 | # and nothing happens, it might mean you forgot to add this command. 66 | ipg.start_session() 67 | -------------------------------------------------------------------------------- /python_examples/py_checkbox_styling.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgAlignment, IpgColor 2 | from icedpygui import IpgWindowTheme, IpgStyleStandard 3 | 4 | # Required to instantiate IPG 5 | ipg = IPG() 6 | 7 | # Add some standard styled checkboxes 8 | def add_checkboxes(): 9 | ipg.add_checkbox( 10 | parent_id="row", 11 | label="Primary", 12 | style_standard=IpgStyleStandard.Primary) 13 | 14 | ipg.add_checkbox( 15 | parent_id="row", 16 | label="Success", 17 | style_standard=IpgStyleStandard.Success) 18 | 19 | ipg.add_checkbox( 20 | parent_id="row", 21 | label="Danger", 22 | style_standard=IpgStyleStandard.Danger) 23 | 24 | # Add a checkbox with custom styling. 25 | ipg.add_checkbox( 26 | parent_id="col", 27 | label="I have custom styling", 28 | style_id=colors_no_border) 29 | 30 | # Add a checkbox with custom styling. 31 | ipg.add_checkbox( 32 | parent_id="col", 33 | label="I have custom styling with ugly border", 34 | style_id=colors_with_border) 35 | 36 | # Add a checkbox with border styling. 37 | ipg.add_checkbox( 38 | parent_id="col", 39 | label="I have custom border styling with rounded and thicker border", 40 | style_id=border) 41 | 42 | # Add a checkbox with no styling, should get primary 43 | ipg.add_checkbox( 44 | parent_id="col", 45 | label="No style defined = primary") 46 | 47 | 48 | def add_info(): 49 | text = "Using the mouse, check, uncheck, and hover to see the style changes\n" 50 | text += "The standard style colors depends on the window theme color\n" 51 | text += "The custom style colors will not change based on the theme color\n" 52 | 53 | ipg.add_text( 54 | parent_id="col", 55 | content=text) 56 | 57 | # The styling can be added at any time before use. 58 | # No border color is set here so the unchecked box border 59 | # should be the base color. The accent color is the background 60 | # color when the checkbox is checked. 61 | colors_no_border = ipg.add_checkbox_style( 62 | background_color=IpgColor.BLUE, 63 | accent_color=IpgColor.YELLOW, 64 | accent_color_hovered=IpgColor.DARK_SALMON, 65 | icon_color=IpgColor.LIGHT_BLUE, 66 | text_color=IpgColor.BLUE) 67 | 68 | # Border color defined here. 69 | colors_with_border = ipg.add_checkbox_style( 70 | background_color=IpgColor.BLUE, 71 | border_color=IpgColor.YELLOW, 72 | icon_color=IpgColor.LIGHT_BLUE, 73 | text_color=IpgColor.BLUE) 74 | 75 | # The default border is 1 and the radius is 2, these are used just to exaggerate. 76 | border = ipg.add_checkbox_style( 77 | border_radius=[4.0], 78 | border_width=3.0) 79 | 80 | 81 | # Add a window first 82 | ipg.add_window( 83 | window_id="main", 84 | title="CheckBox Demo", 85 | width=600, 86 | height=600, 87 | pos_x=100, 88 | pos_y=25) 89 | 90 | # Add a container to center the widgets in the middle 91 | ipg.add_container( 92 | window_id="main", 93 | container_id="cont", 94 | width_fill=True, 95 | height_fill=True) 96 | 97 | # Since a container can only hold one widget, use a column to hold the 98 | # two checkboxes. We let the width and height default to shrink, so no entry. 99 | # The alignment defaults to Start but for demonstration purpose, we 100 | # added the IpgColumnAlignment.Start 101 | ipg.add_column( 102 | window_id="main", 103 | container_id="col", 104 | parent_id="cont", 105 | align=IpgAlignment.Center) 106 | 107 | add_info() 108 | 109 | # Adding a row for the horizontal alignment of the checkboxes 110 | ipg.add_row( 111 | window_id="main", 112 | container_id="row", 113 | parent_id="col", 114 | spacing=10.0) 115 | 116 | 117 | # Adding checkboxes 118 | add_checkboxes() 119 | 120 | 121 | # Let's add another window with a different background theme 122 | # to see how things look 123 | ipg.add_window( 124 | window_id="main2", 125 | title="CheckBox Demo", 126 | width=600, 127 | height=600, 128 | pos_x=750, 129 | pos_y=25, 130 | theme=IpgWindowTheme.SolarizedLight) 131 | 132 | ipg.add_container( 133 | window_id="main2", 134 | container_id="cont", 135 | width_fill=True, 136 | height_fill=True) 137 | 138 | ipg.add_column( 139 | window_id="main2", 140 | container_id="col", 141 | parent_id="cont", 142 | align=IpgAlignment.Center) 143 | 144 | add_info() 145 | 146 | # Adding a row for the horizontal alignment of the checkboxes 147 | ipg.add_row( 148 | window_id="main2", 149 | container_id="row", 150 | parent_id="col", 151 | spacing=10.0) 152 | 153 | # Adding checkboxes 154 | add_checkboxes() 155 | 156 | # Required to be the last widget sent to Iced, If you start the program 157 | # and nothing happens, it might mean you forgot to add this command. 158 | ipg.start_session() 159 | -------------------------------------------------------------------------------- /python_examples/py_color_picker.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgColor, IpgTextParam, IpgColorPickerStyleParam 2 | 3 | ipg = IPG() 4 | 5 | 6 | def color_selected(cp_id: int, color: list, user_data: any): 7 | # Need to change the list color to a str type 8 | string = "[" 9 | for i in range(0, len(color)): 10 | string += str(color[i]) + ", " 11 | string += "]" 12 | # update the text 13 | ipg.update_item( 14 | wid=text_id, 15 | param=IpgTextParam.Content, 16 | value=string) 17 | 18 | # change the buttton color 19 | ipg.update_item( 20 | wid=cp_style, 21 | param=IpgColorPickerStyleParam.BackgroundRbga, 22 | value=color) 23 | 24 | 25 | def cp_opened(cp_id: int, user_data: any): 26 | print("color picker opened") 27 | 28 | 29 | def cp_canceled(cp_id: int, user_data: any): 30 | print("color picker canceled") 31 | 32 | 33 | cp_style = ipg.add_color_picker_style( 34 | background_color=IpgColor.LIGHT_YELLOW, 35 | background_color_hovered=IpgColor.YELLOW, 36 | text_color=IpgColor.BLACK, 37 | border_radius=[10.0], 38 | border_width=5.0, 39 | border_color=IpgColor.YELLOW) 40 | 41 | 42 | # Add a window first 43 | ipg.add_window( 44 | window_id="main", 45 | title="Canvas", 46 | width=500.0, 47 | height=500.0, 48 | pos_centered=True) 49 | 50 | # Add the container to center both x and y (default). Holds only one widget. 51 | ipg.add_container( 52 | window_id="main", 53 | container_id="cont", 54 | width_fill=True, 55 | height_fill=True) 56 | 57 | # Add a column to hold multiple widgets 58 | ipg.add_column( 59 | window_id="main", 60 | container_id="col", 61 | parent_id="cont") 62 | 63 | ipg.add_color_picker( 64 | parent_id="col", 65 | on_submit=color_selected, 66 | on_press=cp_opened, 67 | on_cancel=cp_canceled, 68 | style_id=cp_style, 69 | user_data="Something") #user data not used but supplied for testing 70 | # If you use user_data, all callback will require the user_data parameter 71 | # or whatever name you want for it. 72 | 73 | text_id = ipg.add_text( 74 | parent_id="col", 75 | content="Color value here") 76 | 77 | ipg.start_session() -------------------------------------------------------------------------------- /python_examples/py_column.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgColor, IpgColumnParam, IpgAlignment 2 | 3 | 4 | # Moves the text to the center position 5 | def align_center(btn_id): 6 | ipg.update_item( 7 | wid=col_id, 8 | param=IpgColumnParam.AlignX, 9 | value=IpgAlignment.Center) 10 | 11 | 12 | # Moves the text to the end position 13 | def align_end(btn_id): 14 | ipg.update_item( 15 | wid=col_id, 16 | param=IpgColumnParam.AlignX, 17 | value=IpgAlignment.End) 18 | 19 | 20 | # Moves the text back to the start position 21 | def align_start(btn_id): 22 | ipg.update_item( 23 | wid=col_id, 24 | param=IpgColumnParam.AlignX, 25 | value=IpgAlignment.Start) 26 | 27 | 28 | # Moves text off start because padding on the left side 29 | # padding = [top, right, bottom, left] 30 | def padding(btn_id): 31 | ipg.update_item( 32 | wid=col_id, 33 | param=IpgColumnParam.Padding, 34 | value=[0.0, 0.0, 0.0, 50.0]) 35 | 36 | # change container width 37 | def width(btn_id): 38 | ipg.update_item( 39 | wid=col_id, 40 | param=IpgColumnParam.Width, 41 | value=200.0) 42 | 43 | 44 | # change container height 45 | def height(btn_id): 46 | ipg.update_item( 47 | wid=col_id, 48 | param=IpgColumnParam.Height, 49 | value=300.0) 50 | 51 | # change container height 52 | def spacing(btn_id): 53 | ipg.update_item( 54 | wid=col_id, 55 | param=IpgColumnParam.Spacing, 56 | value=20.0) 57 | 58 | 59 | ipg = IPG() 60 | 61 | cont_style = ipg.add_container_style( 62 | border_width=2.0, 63 | border_color=IpgColor.WHITE) 64 | 65 | 66 | 67 | # Add the windows 68 | ipg.add_window( 69 | window_id="main", 70 | title="Container Styling", 71 | width=600, 72 | height=600, 73 | pos_centered=True, 74 | debug=True) 75 | 76 | ipg.add_row( 77 | window_id="main", 78 | container_id="row", 79 | width_fill=True) 80 | 81 | 82 | # Add a column to hold the text widgets 83 | col_id = ipg.add_column( 84 | window_id="main", 85 | container_id="col_txt", 86 | parent_id="row", 87 | align=IpgAlignment.Start, 88 | width_fill=True,height=400.0 89 | ) 90 | 91 | ipg.add_text( 92 | parent_id="col_txt", 93 | content="Some Text") 94 | 95 | ipg.add_text( 96 | parent_id="col_txt", 97 | content="Some Text") 98 | 99 | ipg.add_text( 100 | parent_id="col_txt", 101 | content="Some Text") 102 | 103 | 104 | ipg.add_column( 105 | window_id="main", 106 | container_id="col_right", 107 | parent_id="row", 108 | width_fill=True, 109 | height=400.0 110 | ) 111 | 112 | # Add a button the center the alignment 113 | ipg.add_button( 114 | parent_id="col_right", 115 | label="Align Center", 116 | on_press=align_center) 117 | 118 | # Add a button align end 119 | ipg.add_button( 120 | parent_id="col_right", 121 | label="Align End", 122 | on_press=align_end) 123 | 124 | # Add a button align back to the start 125 | ipg.add_button( 126 | parent_id="col_right", 127 | label="Align Start", 128 | on_press=align_start) 129 | 130 | # Add a button add padding of the contained items 131 | ipg.add_button( 132 | parent_id="col_right", 133 | label="Padding", 134 | on_press=padding) 135 | 136 | # Add a button change the container width 137 | ipg.add_button( 138 | parent_id="col_right", 139 | label="Width", 140 | on_press=width) 141 | 142 | # Add a button change the container height 143 | ipg.add_button( 144 | parent_id="col_right", 145 | label="Height", 146 | on_press=height) 147 | 148 | # Add a button change the solumn spacing 149 | ipg.add_button( 150 | parent_id="col_right", 151 | label="Spacing", 152 | on_press=spacing) 153 | 154 | # last thing is to start the session 155 | ipg.start_session() -------------------------------------------------------------------------------- /python_examples/py_container.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgColor, IpgContainerParam, IpgHorizontalAlignment, IpgVerticalAlignment 2 | 3 | 4 | # Moves the text to the top left position 5 | def change_alignment(btn_id): 6 | ipg.update_item( 7 | wid=cont2, 8 | param=IpgContainerParam.AlignX, 9 | value=IpgHorizontalAlignment.Left) 10 | 11 | ipg.update_item( 12 | wid=cont2, 13 | param=IpgContainerParam.AlignY, 14 | value=IpgVerticalAlignment.Top) 15 | 16 | 17 | # Moves the text to the center position 18 | def recenter(btn_id): 19 | ipg.update_item( 20 | wid=cont2, 21 | param=IpgContainerParam.Centered, 22 | value=True) 23 | 24 | 25 | # Moves text off center because padding on the left side 26 | # padding = [top, right, bottom, left] 27 | def padding(btn_id): 28 | ipg.update_item( 29 | wid=cont2, 30 | param=IpgContainerParam.Padding, 31 | value=[0.0, 0.0, 0.0, 50.0]) 32 | 33 | # change container width 34 | def width(btn_id): 35 | ipg.update_item( 36 | wid=cont2, 37 | param=IpgContainerParam.Width, 38 | value=300.0) 39 | 40 | 41 | # change container height 42 | def height(btn_id): 43 | ipg.update_item( 44 | wid=cont2, 45 | param=IpgContainerParam.Height, 46 | value=300.0) 47 | 48 | 49 | ipg = IPG() 50 | 51 | # Add the styling container widget 52 | cont_style = ipg.add_container_style( 53 | background_color=IpgColor.GRAY) 54 | 55 | # Add the windows 56 | ipg.add_window( 57 | window_id="main", 58 | title="Container Styling", 59 | width=600, 60 | height=600, 61 | pos_centered=True) 62 | 63 | # add a container to hold the demo container 64 | # in the middle of the window 65 | ipg.add_container( 66 | window_id="main", 67 | container_id="cont1", 68 | width_fill=True, 69 | height_fill=True, 70 | centered=True) 71 | 72 | # Add a column to hold the widgets 73 | # the column has an transparent background 74 | # so the container style shows through 75 | ipg.add_column( 76 | window_id="main", 77 | container_id="col", 78 | parent_id="cont1") 79 | 80 | # add the container to work on 81 | cont2 = ipg.add_container( 82 | window_id="main", 83 | container_id="cont2", 84 | parent_id="col", 85 | width=200.0, 86 | height=200.0, 87 | style_id=cont_style) 88 | 89 | ipg.add_text( 90 | parent_id="cont2", 91 | content="Some Text") 92 | 93 | # Add a button the change the alignment 94 | ipg.add_button( 95 | parent_id="col", 96 | label="Change Alignment", 97 | on_press=change_alignment) 98 | 99 | # Add a button recenter the text 100 | ipg.add_button( 101 | parent_id="col", 102 | label="Recenter", 103 | on_press=recenter) 104 | 105 | # Add a button add padding of the contained items 106 | ipg.add_button( 107 | parent_id="col", 108 | label="Padding", 109 | on_press=padding) 110 | 111 | # Add a button change the container width 112 | ipg.add_button( 113 | parent_id="col", 114 | label="Width", 115 | on_press=width) 116 | 117 | # Add a button change the container height 118 | ipg.add_button( 119 | parent_id="col", 120 | label="Height", 121 | on_press=height) 122 | 123 | # last thing is to start the session 124 | ipg.start_session() 125 | -------------------------------------------------------------------------------- /python_examples/py_container_styling.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgColor, IpgContainerStyleParam 2 | 3 | # To change the style of the container, 4 | # use the style id, not the container id. 5 | def change_container_styling(btn_id): 6 | ipg.update_item( 7 | wid=cont_style, 8 | param=IpgContainerStyleParam.BackgroundIpgColor, 9 | value=IpgColor.RED) 10 | 11 | ipg.update_item( 12 | wid=cont_style, 13 | param=IpgContainerStyleParam.BorderIpgColor, 14 | value=IpgColor.LIGHT_SALMON) 15 | 16 | ipg.update_item( 17 | wid=cont_style, 18 | param=IpgContainerStyleParam.BorderRadius, 19 | value=[5.0]) 20 | 21 | ipg.update_item( 22 | wid=cont_style, 23 | param=IpgContainerStyleParam.BorderWidth, 24 | value=5.0) 25 | 26 | ipg.update_item( 27 | wid=cont_style, 28 | param=IpgContainerStyleParam.ShadowBlurRadius, 29 | value=10.0) 30 | 31 | ipg.update_item( 32 | wid=cont_style, 33 | param=IpgContainerStyleParam.ShadowIpgColor, 34 | value=IpgColor.RED) 35 | 36 | ipg.update_item( 37 | wid=cont_style, 38 | param=IpgContainerStyleParam.ShadowOffsetXY, 39 | value=[0.0, 0.0]) 40 | 41 | ipg.update_item( 42 | wid=cont_style, 43 | param=IpgContainerStyleParam.TextIpgColor, 44 | value=IpgColor.WHITE) 45 | 46 | ipg = IPG() 47 | 48 | # Add the styling container widget 49 | cont_style = ipg.add_container_style( 50 | background_color=IpgColor.AQUA, 51 | border_color=IpgColor.BLUE, 52 | border_radius=[10.0], 53 | border_width=10.0, 54 | shadow_color=IpgColor.YELLOW, 55 | shadow_blur_radius=20.0, 56 | shadow_offset_xy=[8.0, 8.0], 57 | text_color=IpgColor.BLACK) 58 | 59 | # Add the windows 60 | ipg.add_window( 61 | window_id="main", 62 | title="Container Styling", 63 | width=500, 64 | height=600, 65 | pos_centered=True) 66 | 67 | # add a container to hold the demo container 68 | # in the middle of the window 69 | ipg.add_container( 70 | window_id="main", 71 | container_id="cont1", 72 | width_fill=True, 73 | height_fill=True, 74 | centered=True) 75 | 76 | # add the container to work on 77 | ipg.add_container( 78 | window_id="main", 79 | container_id="cont2", 80 | parent_id="cont1", 81 | width=200.0, 82 | height=200.0, 83 | style_id=cont_style) 84 | 85 | # Add a column to hold the widgets 86 | # the column has an transparent background 87 | # so the container style shows through 88 | ipg.add_column( 89 | window_id="main", 90 | container_id="col", 91 | parent_id="cont2") 92 | 93 | # Add some text. Since this text is not styled 94 | # it would be a bit hard to see because the container 95 | # will attempt to default style the text but 96 | # won't always work best, So you can either 97 | # style the text or use the container text_color 98 | # to style all of the text in the container. 99 | # This text styling will override the container 100 | # text color 101 | ipg.add_text( 102 | parent_id="col", 103 | content="Some Text") 104 | 105 | # Add a button the change the background color 106 | # or any of the style settings 107 | ipg.add_button( 108 | parent_id="col", 109 | label="Change styling", 110 | on_press=change_container_styling) 111 | 112 | 113 | # last thing is to start the session 114 | ipg.start_session() -------------------------------------------------------------------------------- /python_examples/py_date_picker.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgTextParam, IpgButtonParam, IpgDatePickerParam 2 | from icedpygui import IpgAlignment, IpgStyleStandard 3 | 4 | ipg = IPG() 5 | 6 | # Callback for the date picker. The id is the date_picker id, so you have to get 7 | # the id of whatever widget you want to update using a class or, for small projects, 8 | # a global variable. Dataclass is not supported at this time, but you can use a class 9 | # as seen in other demo files. 10 | def date_selected( 11 | _dp_id: int, 12 | date: str 13 | ): 14 | ipg.update_item( 15 | wid=selected_date_id, 16 | param=IpgTextParam.Content, 17 | value=f"You submitted {date}" 18 | ) 19 | 20 | # Another callback with some user data 21 | def date_selected_with_ud( 22 | _dp_id: int, 23 | date: str, 24 | user_data: any 25 | ): 26 | ipg.update_item( 27 | wid=selected_with_ud_id, 28 | param=IpgTextParam.Content, 29 | value=f"You submitted {date} with user_data = {user_data}" 30 | ) 31 | 32 | ipg.update_item( 33 | wid=btn_id, 34 | param=IpgButtonParam.Show, 35 | value=True 36 | ) 37 | 38 | # Another callback for the date picker that changes its size 39 | def date_resize( 40 | _dp_id: int 41 | ): 42 | ipg.update_item( 43 | wid=dp2_id, 44 | param=IpgDatePickerParam.SizeFactor, 45 | value=1.5 46 | ) 47 | 48 | # Add a window first 49 | ipg.add_window( 50 | window_id="main", 51 | title="Date Picker Demo", 52 | width=400, 53 | height=700, 54 | pos_centered=True 55 | ) 56 | 57 | # Add the container to center both x and y. Holds only one widget. 58 | ipg.add_container( 59 | window_id="main", 60 | container_id="cont", 61 | width_fill=True, 62 | height_fill=True, 63 | centered=True, 64 | ) 65 | 66 | # Add a column to hold more than one widget and put this into the container. 67 | ipg.add_column( 68 | window_id="main", 69 | container_id="col", 70 | parent_id="cont", 71 | align=IpgAlignment.Center 72 | ) 73 | 74 | # Add info text 75 | ipg.add_text( 76 | parent_id="col", 77 | content="Press the first calendar buttons to access the calendar. " + 78 | "Select a date, then press submit. Do the same for the second " + 79 | "button, and you will see another button to resize the calendar." 80 | ) 81 | 82 | # The date picker size can be scaled from > 1.0. Anything less than 1 will 83 | # give an error and is not readable anyway. 84 | ipg.add_date_picker( 85 | parent_id="col", 86 | size_factor=1.2, 87 | on_submit=date_selected 88 | ) 89 | 90 | # Text widget id needed for callback. 91 | selected_date_id = ipg.add_text( 92 | parent_id="col", 93 | content="No selection" 94 | ) 95 | 96 | # Another date picker to test the user_data and button style 97 | dp2_id = ipg.add_date_picker( 98 | parent_id="col", 99 | size_factor=1.2, 100 | on_submit=date_selected_with_ud, 101 | user_data="Some user data", 102 | button_style_standard=IpgStyleStandard.Success 103 | ) 104 | 105 | # Text widget id needed for callback. 106 | selected_with_ud_id = ipg.add_text( 107 | parent_id="col", 108 | content="No selection" 109 | ) 110 | 111 | # Add the button for the resize but hide it until the second calendar is opened 112 | btn_id = ipg.add_button( 113 | parent_id="col", 114 | label="Click to resize the calendar", 115 | on_press=date_resize, 116 | show=False 117 | ) 118 | 119 | # Required to be the last widget sent to Iced. If you start the program 120 | # and nothing happens, it might mean you forgot to add this command. 121 | ipg.start_session() 122 | -------------------------------------------------------------------------------- /python_examples/py_divider_combined.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgDividerParam, IpgContainerParam, IpgRowParam, IpgColor, IpgStackParam 2 | 3 | # This is a demo to show how the divider_horizontal 4 | # in combination with the divider_vertical is used. 5 | # Just put the cursor over a highlighted border and drag 6 | 7 | ipg = IPG() 8 | 9 | 10 | # NOTE: To reduce the number of items that need to be changed, 11 | # make the changes to the row's height instead of each container 12 | # in the row by using a height_fill on the containers. This only then 13 | # leaves having to do each container in the rows when the column 14 | # is changed where the indexing of the 2d list is easier. 15 | 16 | def divider_row_change(div_id: int, index: int, value: float): 17 | # Get the difference to be added to the below row 18 | diff = rows[index] - value 19 | 20 | # Update the local data 21 | rows[index] = value 22 | if index < len(rows)-1: 23 | rows[index+1] += diff 24 | 25 | # Update the row above the divider 26 | ipg.update_item( 27 | wid=row_ids[index], 28 | param=IpgRowParam.Height, 29 | value=value) 30 | 31 | # Update the row below the divider 32 | if index < len(rows)-1: 33 | ipg.update_item( 34 | wid=row_ids[index+1], 35 | param=IpgRowParam.Height, 36 | value=rows[index+1]) 37 | 38 | # Update the divider 39 | ipg.update_item( 40 | wid=div_id, 41 | param=IpgDividerParam.Heights, 42 | value=rows) 43 | 44 | # Update the height of the column divider 45 | ipg.update_item( 46 | wid=col_div, 47 | param=IpgDividerParam.HandleHeight, 48 | value=sum(rows) 49 | ) 50 | 51 | 52 | def divider_col_change(div_id: int, index: int, value: float): 53 | # get the difference to be added to the right side of the divider 54 | diff = columns[index] - value 55 | 56 | # update the local values for storing the data 57 | columns[index] = value 58 | if index < len(columns)-1: 59 | columns[index+1] += diff 60 | 61 | for i in range(0, len(rows)): 62 | # Update all the containers on the left of the divider 63 | ipg.update_item( 64 | wid=container_ids[i][index], 65 | param=IpgContainerParam.Width, 66 | value=value) 67 | 68 | # Update all the containers on the right of the divider 69 | if index < len(columns)-1: 70 | ipg.update_item( 71 | wid=container_ids[i][index+1], 72 | param=IpgContainerParam.Width, 73 | value=columns[index+1]) 74 | 75 | # Update the column divider 76 | ipg.update_item( 77 | wid=div_id, 78 | param=IpgDividerParam.Widths, 79 | value=columns) 80 | 81 | # Update the width of the row divider 82 | ipg.update_item( 83 | wid=row_div, 84 | param=IpgDividerParam.HandleWidth, 85 | value=sum(columns) 86 | ) 87 | 88 | # Update the stack width 89 | # The stack width had to be adjusted unlike 90 | # the case above. Looking at the iced code 91 | # doesn't reveal any issues with the stack 92 | # but when it comes to calculating widths and heights 93 | # sometimes different combinations of the 94 | # containing widgets cause issues where a width 95 | # or height needs to be set. 96 | ipg.update_item( 97 | wid=stack_id, 98 | param=IpgStackParam.Width, 99 | value=sum(columns)) 100 | 101 | # It can be easy visualize to use row/column vs widths/heights 102 | rows = [100.0, 100.0, 100.0] 103 | columns = [150.0, 148.0] 104 | row_ids = [] 105 | container_ids = [] 106 | row_handle_width = sum(columns) 107 | row_handle_height = 4.0 108 | 109 | col_handle_width = 4.0 110 | col_handle_height = sum(rows) 111 | 112 | 113 | cont_style_id = ipg.add_container_style( 114 | border_color=IpgColor.WHITE, 115 | border_width=1.0) 116 | 117 | divider_style_id = ipg.add_divider_style( 118 | background_transparent=True) 119 | 120 | 121 | # Add a window first 122 | ipg.add_window( 123 | window_id="main", 124 | title="CheckBox Demo", 125 | width=600, 126 | height=600, 127 | pos_centered=True, 128 | # debug=True 129 | ) 130 | 131 | # Add a container to center the widgets in the middle 132 | ipg.add_container( 133 | window_id="main", 134 | container_id="main_cont", 135 | width_fill=True, 136 | height_fill=True, 137 | centered=False, 138 | padding=[100, 0, 0, 100]) 139 | 140 | # add a column to hold the text and the stack 141 | ipg.add_column( 142 | window_id="main", 143 | container_id="main_col", 144 | parent_id="main_cont", 145 | spacing=30) 146 | 147 | content = "Pace the cursor over the highlighted divider and drag" 148 | 149 | ipg.add_text( 150 | parent_id="main_col", 151 | content=content) 152 | 153 | # make the stack to lay the dividers over the containers 154 | stack_id = ipg.add_stack( 155 | window_id="main", 156 | container_id="stack", 157 | parent_id="main_col") 158 | 159 | 160 | # make a column to hold the two columns 161 | # this is added to stack 162 | ipg.add_column( 163 | window_id="main", 164 | parent_id="stack", 165 | container_id="col", 166 | spacing=0, 167 | padding=[0], 168 | width=row_handle_width) 169 | 170 | for i, height in enumerate(rows): 171 | row_ids.append(ipg.add_row( 172 | window_id="main", 173 | container_id=f"row{i}", 174 | parent_id="col", 175 | height=height, 176 | spacing=0)) 177 | 178 | cont_ids = [] 179 | for j, width in enumerate(columns): 180 | cont_ids.append(ipg.add_container( 181 | window_id="main", 182 | container_id=f"cont{i} {j}", 183 | parent_id=f"row{i}", 184 | width=width, 185 | height_fill=True, 186 | style_id=cont_style_id)) 187 | 188 | ipg.add_text( 189 | parent_id=f"cont{i} {j}", 190 | content=f"Some Text") 191 | 192 | container_ids.append(cont_ids) 193 | 194 | 195 | # Make the vertical divider (rows) 196 | row_div = ipg.add_divider_vertical( 197 | parent_id="stack", 198 | heights=rows, 199 | handle_width=row_handle_width, 200 | handle_height=row_handle_height, 201 | on_change=divider_row_change, 202 | # use the style to see just the outline and not the divider 203 | # style_id=divider_style_id 204 | ) 205 | 206 | #Make the horizontal divider (columns) 207 | col_div = ipg.add_divider_horizontal( 208 | parent_id="stack", 209 | widths=columns, 210 | handle_width=col_handle_width, 211 | handle_height=col_handle_height, 212 | on_change=divider_col_change, 213 | # use the style to see just the outline and not the divider 214 | # style_id=divider_style_id 215 | ) 216 | 217 | # Required to be the last widget sent to Iced, If you start the program 218 | # and nothing happens, it might mean you forgot to add this command. 219 | ipg.start_session() 220 | -------------------------------------------------------------------------------- /python_examples/py_divider_horizontal.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgDividerParam, IpgColumnParam, IpgColor, IpgTextParam 2 | 3 | # This is a demo to show how the divider_horizontal is used. 4 | # Just put the cursor over a highlighted border and drag 5 | 6 | ipg = IPG() 7 | 8 | 9 | def divider_change(div_id: int, index: int, value: float): 10 | # Get the difference to be added to the right column 11 | diff = column_widths[index] - value 12 | 13 | # Update the left side locally and in ipg 14 | column_widths[index] = value 15 | ipg.update_item( 16 | wid=column_ids[index], 17 | param=IpgColumnParam.Width, 18 | value=value) 19 | 20 | # Update the right side locally and in ipg 21 | if index < len(column_widths)-1: 22 | column_widths[index+1] += diff 23 | ipg.update_item( 24 | wid=column_ids[index+1], 25 | param=IpgColumnParam.Width, 26 | value=column_widths[index+1]) 27 | 28 | # Update the divider 29 | ipg.update_item( 30 | wid=div_id, 31 | param=IpgDividerParam.Widths, 32 | value=column_widths) 33 | 34 | # Update the two text items 35 | ipg.update_item(wid=text_ids[index], 36 | param=IpgTextParam.Content, 37 | value=f"Width={value}") 38 | 39 | if index < len(column_widths)-1: 40 | ipg.update_item(wid=text_ids[index+1], 41 | param=IpgTextParam.Content, 42 | value=f"Width={column_widths[index+1]}") 43 | 44 | 45 | column_widths = [250.0, 250.0] 46 | column_ids = [] 47 | text_ids = [] 48 | handle_width = 4.0 # defaults to 4 just using for demo info 49 | handle_height = 200.0 50 | 51 | cont_style_id = ipg.add_container_style( 52 | border_color=IpgColor.WHITE, 53 | border_width=1.0) 54 | 55 | divider_style_id = ipg.add_divider_style( 56 | background_transparent=True) 57 | 58 | 59 | # Add a window first 60 | ipg.add_window( 61 | window_id="main", 62 | title="CheckBox Demo", 63 | width=600, 64 | height=600, 65 | pos_centered=True) 66 | 67 | # Add a container to center the widgets in the middle 68 | ipg.add_container( 69 | window_id="main", 70 | container_id="main_cont", 71 | width_fill=True, 72 | height_fill=True) 73 | 74 | # add a column to hold the text and the stack 75 | ipg.add_column( 76 | window_id="main", 77 | container_id="main_col", 78 | parent_id="main_cont", 79 | ) 80 | 81 | content = "Pace the cursor over the highlighted divider and drag" 82 | 83 | ipg.add_text( 84 | parent_id="main_col", 85 | content=content) 86 | 87 | # make the stack to lay the dividers over the containers 88 | ipg.add_stack( 89 | window_id="main", 90 | container_id="stack", 91 | parent_id="main_col") 92 | 93 | 94 | # make a row to hold the two columns 95 | # this is added to stack 96 | # The outer container used in the stack 97 | # cannot have any padding, since divider 98 | # cannot detect whether padding is used 99 | # it becomes misaligned. 100 | ipg.add_row( 101 | window_id="main", 102 | parent_id="stack", 103 | container_id="row", 104 | spacing=0, 105 | padding=[0]) 106 | 107 | for index, width in enumerate(column_widths): 108 | # add a container for styling purposes 109 | ipg.add_container( 110 | window_id="main", 111 | container_id=f"cont{index}", 112 | parent_id="row", 113 | style_id=cont_style_id) 114 | 115 | column_ids.append(ipg.add_column( 116 | window_id="main", 117 | container_id=f"col{index}", 118 | parent_id=f"cont{index}", 119 | width=width)) 120 | 121 | text_ids.append(ipg.add_text( 122 | parent_id=f"col{index}", 123 | content=f"Width={width}")) 124 | 125 | ipg.add_button( 126 | parent_id=f"col{index}", 127 | label="Some Button") 128 | 129 | ipg.add_button( 130 | parent_id=f"col{index}", 131 | label="Another Button") 132 | 133 | ipg.add_toggler( 134 | parent_id=f"col{index}", 135 | label="Toggler"), 136 | 137 | 138 | 139 | # Make the divider 140 | ipg.add_divider_horizontal( 141 | parent_id="stack", 142 | widths=column_widths, 143 | handle_width=handle_width, 144 | handle_height=handle_height, 145 | on_change=divider_change, 146 | # use the style to see just the outline and not the divider 147 | # style_id=divider_style_id 148 | ) 149 | 150 | 151 | # Required to be the last widget sent to Iced, If you start the program 152 | # and nothing happens, it might mean you forgot to add this command. 153 | ipg.start_session() 154 | -------------------------------------------------------------------------------- /python_examples/py_divider_vertical.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgDividerParam, IpgColumnParam, IpgColor, IpgTextParam 2 | 3 | # This is a demo to show how the divider_vertical is used. 4 | # Just put the cursor over a highlighted border and drag 5 | 6 | ipg = IPG() 7 | 8 | 9 | def divider_change(div_id: int, index: int, value: float): 10 | # Get the difference to be added to the right column 11 | diff = heights[index] - value 12 | 13 | # Update the top locally and in ipg 14 | heights[index] = value 15 | ipg.update_item( 16 | wid=column_ids[index], 17 | param=IpgColumnParam.Height, 18 | value=value) 19 | 20 | # Update the bottom locally and in ipg 21 | if index < len(heights)-1: 22 | heights[index+1] += diff 23 | ipg.update_item( 24 | wid=column_ids[index+1], 25 | param=IpgColumnParam.Height, 26 | value=heights[index+1]) 27 | 28 | # Update the divider 29 | ipg.update_item( 30 | wid=div_id, 31 | param=IpgDividerParam.Heights, 32 | value=heights) 33 | 34 | # Update the two text items 35 | ipg.update_item(wid=text_ids[index], 36 | param=IpgTextParam.Content, 37 | value=f"Width={value}") 38 | 39 | if index < len(heights)-1: 40 | ipg.update_item(wid=text_ids[index+1], 41 | param=IpgTextParam.Content, 42 | value=f"Width={heights[index+1]}") 43 | 44 | 45 | heights = [175.0, 175.0] 46 | column_ids = [] 47 | text_ids = [] 48 | handle_width = 200.0 49 | handle_height = 4.0 50 | 51 | cont_style_id = ipg.add_container_style(border_color=IpgColor.WHITE, 52 | border_width=1.0) 53 | 54 | divider_style_id = ipg.add_divider_style(background_transparent=True) 55 | 56 | 57 | # Add a window first 58 | ipg.add_window( 59 | window_id="main", 60 | title="CheckBox Demo", 61 | width=600, 62 | height=600, 63 | pos_centered=True) 64 | 65 | # Add a container to center the widgets in the middle 66 | ipg.add_container( 67 | window_id="main", 68 | container_id="main_cont", 69 | width_fill=True, 70 | height_fill=True) 71 | 72 | # add a column to hold the text and the stack 73 | ipg.add_column( 74 | window_id="main", 75 | container_id="main_col", 76 | parent_id="main_cont") 77 | 78 | content = "Pace the cursor over the highlighted divider and drag" 79 | 80 | ipg.add_text( 81 | parent_id="main_col", 82 | content=content) 83 | 84 | # make the stack to lay the dividers over the containers 85 | ipg.add_stack( 86 | window_id="main", 87 | container_id="stack", 88 | parent_id="main_col") 89 | 90 | 91 | # make a column to hold the two columns 92 | # this is added to stack 93 | # The outer container used in the stack 94 | # cannot have any padding, since divider 95 | # cannot detect whether padding is used 96 | # it becomes misaligned. 97 | ipg.add_column( 98 | window_id="main", 99 | parent_id="stack", 100 | container_id="col", 101 | spacing=0, 102 | padding=[0], 103 | width=handle_width) 104 | 105 | for index, height in enumerate(heights): 106 | # add a container for styling purposes 107 | ipg.add_container( 108 | window_id="main", 109 | container_id=f"cont{index}", 110 | parent_id="col", 111 | style_id=cont_style_id) 112 | 113 | column_ids.append(ipg.add_column(window_id="main", 114 | container_id=f"col{index}", 115 | parent_id=f"cont{index}", 116 | width=handle_width, 117 | height=height)) 118 | 119 | text_ids.append(ipg.add_text( 120 | parent_id=f"col{index}", 121 | content=f"Width={height}")) 122 | 123 | ipg.add_button( 124 | parent_id=f"col{index}", 125 | label="Some Button") 126 | 127 | ipg.add_button( 128 | parent_id=f"col{index}", 129 | label="Another Button") 130 | 131 | ipg.add_toggler( 132 | parent_id=f"col{index}", 133 | label="Toggler") 134 | 135 | 136 | 137 | # Make the divider 138 | ipg.add_divider_vertical( 139 | parent_id="stack", 140 | heights=heights, 141 | handle_width=handle_width, 142 | handle_height=handle_height, 143 | on_change=divider_change, 144 | # use the style to see just the outline and not the divider 145 | # style_id=divider_style_id 146 | ) 147 | 148 | 149 | # Required to be the last widget sent to Iced, If you start the program 150 | # and nothing happens, it might mean you forgot to add this command. 151 | ipg.start_session() 152 | -------------------------------------------------------------------------------- /python_examples/py_event_keyboard.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgTextParam 2 | from icedpygui import IpgAlignment 3 | 4 | 5 | ipg = IPG() 6 | 7 | 8 | # When ctrl, alt, logo(MAC), or shift are processed, they are keys. Therefore modifier is "None". 9 | # When a key follows the command key, then modifier is the command key and key is the key. 10 | # So to reduce confusion with the text widget values, when the command key is first pressed, 11 | # the modifier is set to "" versus printing out a "None". 12 | # user_data was set in this case just to show how it works. 13 | def key_pressed( 14 | _event_id: int, 15 | key: dict, 16 | user_data: any): 17 | 18 | modifier = key.get("modifier") 19 | if key.get("modifier") == "None": 20 | modifier = "" 21 | 22 | name = key.get("name") 23 | 24 | ipg.update_item( 25 | wid=text_pressed, 26 | param=IpgTextParam.Content, 27 | value=f"{name}: {modifier} {key.get('key')}") 28 | 29 | ipg.update_item( 30 | wid=text_user_data, 31 | param=IpgTextParam.Content, 32 | value=f"user data is {user_data}") 33 | 34 | 35 | # key released callback. Even though user_data is not used, it still needs to be 36 | # in the parameters because it was supplied as a parameter when added 37 | def key_released( 38 | _event_id: int, 39 | key: dict, 40 | _user_data: any): 41 | 42 | name = key.get("name") 43 | 44 | ipg.update_item( 45 | wid=text_released, 46 | param=IpgTextParam.Content, 47 | value=f"{name}: {key.get('modifier')} {key.get('key')}") 48 | 49 | 50 | # add the event and the two callbacks along with the user_data if needed. 51 | ipg.add_event_keyboard( 52 | enabled=True, 53 | on_key_press=key_pressed, 54 | on_key_release=key_released, 55 | user_data=[25]) 56 | 57 | 58 | # Unlike widgets, the events can be added at any time since they are not widgets 59 | # A window is added before any widgets 60 | ipg.add_window( 61 | window_id="main", 62 | title="KeyBoard Handler Demo", 63 | width=600, 64 | height=400, 65 | pos_centered=True) 66 | 67 | # A column is added to hold the widgets 68 | ipg.add_column( 69 | window_id="main", 70 | container_id="col", 71 | align=IpgAlignment.Center, 72 | width_fill=True, 73 | height_fill=True) 74 | 75 | # a space for readability 76 | ipg.add_space( 77 | parent_id="col", 78 | height=50.0) 79 | 80 | # Some text to display the output 81 | text_pressed = ipg.add_text( 82 | parent_id="col", 83 | content="Key presses will show here") 84 | 85 | text_released = ipg.add_text( 86 | parent_id="col", 87 | content="Key releases will show here") 88 | 89 | ipg.add_space( 90 | parent_id="col", 91 | height=50.0) 92 | 93 | text_user_data = ipg.add_text( 94 | parent_id="col", 95 | content="Some user data will be displayed here") 96 | 97 | 98 | # Required to be the last widget sent to Iced, If you start the program 99 | # and nothing happens, it might mean you forgot to add this command. 100 | ipg.start_session() 101 | -------------------------------------------------------------------------------- /python_examples/py_event_mouse.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgTextParam 2 | from icedpygui import IpgAlignment 3 | 4 | # instantiate IPG 5 | ipg = IPG() 6 | 7 | # make a global var to hold some scroll data 8 | scroll_total_line_y = 0 9 | 10 | 11 | # The mouse move callback will fire when the window opens. 12 | # The user_data is not used here, but needed since it was supplied as a parameter 13 | # The mouse_id is not used since we're just updating the text widget. 14 | # The move data is a dictionary as all of the events data are. 15 | def mouse_move(_mouse_id: int, point: dict, user_data: any): 16 | ipg.update_item(text_for_moved, IpgTextParam.Content, f"Moved {point}") 17 | 18 | 19 | # I've used the same function for all mouse buttons pressed but you probably 20 | # want to separate them out in the real world. 21 | def mouse_button_pressed(_mouse_id: int, user_data: any): 22 | ipg.update_item(text_for_pressed, IpgTextParam.Content, f"Button pressed") 23 | ipg.update_item(text_for_user_data, IpgTextParam.Content, f"user data = {user_data}") 24 | 25 | 26 | # Essentially the same as above. Since user_data was supplied for one event, all need it. 27 | def mouse_button_released(_mouse_id: int, _user_data: any): 28 | ipg.update_item(text_for_released, IpgTextParam.Content, f"Button released") 29 | 30 | 31 | # The scroll data is a dictionary 32 | def mouse_button_scrolled_line(_mouse_id: int, scroll: dict, _user_data: any): 33 | global scroll_total_line_y 34 | scroll_total_line_y += scroll.get("y") 35 | ipg.update_item(text_for_scroll_line, IpgTextParam.Content, 36 | f"Scrolled {scroll} total = {scroll_total_line_y}") 37 | 38 | 39 | # An event can be added at any time since they are not widgets or containers. 40 | ipg.add_event_mouse(enabled=True, 41 | on_move=mouse_move, 42 | on_left_press=mouse_button_pressed, 43 | on_left_release=mouse_button_released, 44 | on_middle_press=mouse_button_pressed, 45 | on_middle_release=mouse_button_released, 46 | on_right_press=mouse_button_pressed, 47 | on_right_release=mouse_button_released, 48 | on_middle_scroll_line=mouse_button_scrolled_line, 49 | user_data="Some Data", 50 | ) 51 | 52 | # Adding a window 53 | ipg.add_window( 54 | window_id="main", 55 | title="Mouse Handler Demo", 56 | width=600, 57 | height=600, 58 | pos_centered=True) 59 | 60 | # Add a column to hold the widgets 61 | ipg.add_column( 62 | window_id="main", 63 | container_id="col", 64 | align=IpgAlignment.Center, 65 | width_fill=True, 66 | height_fill=True) 67 | 68 | # Add some spacing 69 | ipg.add_space( 70 | parent_id="col", 71 | height=150.0) 72 | 73 | # Add all of the text widget for info display 74 | text_for_moved = ipg.add_text( 75 | parent_id="col", 76 | content="Mouse position will be here") 77 | text_for_pressed = ipg.add_text( 78 | parent_id="col", 79 | content="Button presses will show here") 80 | text_for_released = ipg.add_text( 81 | parent_id="col", 82 | content="Button releases will show here") 83 | text_for_scroll_line = ipg.add_text( 84 | parent_id="col", 85 | content="Button scroll line data will show here") 86 | text_for_user_data = ipg.add_text( 87 | parent_id="col", 88 | content="Button user data will show here") 89 | 90 | # Required to be the last widget sent to Iced, If you start the program 91 | # and nothing happens, it might mean you forgot to add this command. 92 | ipg.start_session() 93 | -------------------------------------------------------------------------------- /python_examples/py_menu.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgColor 2 | from icedpygui import IpgStyleStandard, IpgSeparatorType 3 | from icedpygui import IpgMenuStyleParam, IpgMenuBarStyleParam 4 | 5 | 6 | def bar_button_pressed(btn_id: int, data: int): 7 | print("bar button pressed", data) 8 | 9 | 10 | def menu_button_pressed(btn_id: int, data: list): 11 | print("menu button pressed", data) 12 | 13 | 14 | def checkbox_toppgled(chk_id: int, checked: bool): 15 | print("checkbox checked ", checked) 16 | 17 | 18 | # Not pretty changes, just demoing/testing the technique. 19 | def change_menu_colors(item_id: int, data: list): 20 | ipg.update_item(item_style, IpgMenuStyleParam.BaseIpgColor, IpgColor.BLUE) 21 | ipg.update_item(item_style, IpgMenuStyleParam.BorderRadius, [5.0]) 22 | ipg.update_item(item_style, IpgMenuStyleParam.BorderWidth, 6.0) 23 | ipg.update_item(item_style, IpgMenuStyleParam.BorderIpgColor, IpgColor.LIGHT_BLUE) 24 | ipg.update_item(item_style, IpgMenuStyleParam.ShadowBlurRadius, 10.0) 25 | ipg.update_item(item_style, IpgMenuStyleParam.ShadowOffsetXY, [10.0, 10.0]) 26 | 27 | 28 | ipg = IPG() 29 | 30 | 31 | btn_style = ipg.add_button_style( 32 | border_radius=[10.0] 33 | ) 34 | 35 | mb_style = ipg.add_menu_bar_style( 36 | base_color=IpgColor.LIGHT_BLUE, 37 | border_color=IpgColor.DARK_BLUE, 38 | border_radius=[10.0], 39 | border_width=4.0, 40 | shadow_color=IpgColor.LIGHT_BLUE, 41 | shadow_blur_radius=5.0, 42 | shadow_offset_xy=[5.0, 5.0], 43 | ) 44 | 45 | item_style = ipg.add_menu_style( 46 | base_color=IpgColor.DARK_BLUE, 47 | border_color=IpgColor.LIGHT_BLUE, 48 | border_radius=[10.0], 49 | border_width=4.0, 50 | shadow_color=IpgColor.BLUE, 51 | shadow_blur_radius=5.0, 52 | shadow_offset_xy=[5.0, 5.0], 53 | ) 54 | 55 | 56 | # Adding two windows to show color contrasts 57 | # Add the 1st window, the default theme is Dark 58 | ipg.add_window( 59 | window_id="main", 60 | title="Menu", 61 | width=400, 62 | height=400, 63 | pos_centered=True) 64 | 65 | 66 | # The menu is a container which allows one to add any widget to 67 | # the menu bar or menu items. The key note here is that you must 68 | # set the number of bar_items count, followed by a list of the menu items. 69 | # This number of int in the list must equal the number of bar items. 70 | ipg.add_menu( 71 | window_id="main", 72 | container_id="menu", 73 | bar_items=2, 74 | bar_spacing=10.0, 75 | menu_items=[4, 4], 76 | bar_padding=[5.0], 77 | item_widths=[100.0], # A list of the widths which must equal the number of menu bar items or list of 1 for all 78 | item_spacing=[15.0], # A list of the spacings which must equal the number of menu items or list of 1 for all 79 | item_offset=[15.0], 80 | menu_bar_style=mb_style, 81 | menu_style=item_style, 82 | ) 83 | 84 | 85 | # To make a bar item, create your widget and 86 | # have to parent_id equal to the menu container_id. 87 | # NOTE: The order of widget adding is important. 88 | # The bar item comes first, followed by it's menu 89 | # items. The pattern is repeated until the menu is complete. 90 | # The user_data parameter is used to denote which 91 | # bar or item is pressed and/or any other info you need. 92 | ipg.add_button(parent_id="menu", 93 | label="Bar Button1", 94 | on_press=bar_button_pressed, 95 | style_id=btn_style, 96 | user_data=1) 97 | 98 | for i in range(0, 4): 99 | label = f"Text{i}" 100 | cb=menu_button_pressed 101 | if i == 3: 102 | label="base color" 103 | cb=change_menu_colors 104 | 105 | ipg.add_button(parent_id="menu", 106 | label=label, 107 | style_standard=IpgStyleStandard.Text, 108 | user_data=[1, i], 109 | on_press=cb) 110 | 111 | 112 | # Second menu bar and items follow 113 | ipg.add_button(parent_id="menu", 114 | label="Bar Button2", 115 | on_press=bar_button_pressed, 116 | style_id=btn_style, 117 | user_data=2) 118 | 119 | for i in range(0, 4): 120 | if i == 2: 121 | ipg.add_separator(parent_id="menu", 122 | separator_type=IpgSeparatorType.Line, 123 | width=100.0, 124 | height=20.0) 125 | elif i == 3: 126 | ipg.add_checkbox(parent_id="menu", 127 | label="Check Me", 128 | on_toggle=checkbox_toppgled) 129 | else: 130 | ipg.add_button(parent_id="menu", 131 | label=f"Text{i}", 132 | style_standard=IpgStyleStandard.Text, 133 | user_data=[2, i], 134 | on_press=menu_button_pressed) 135 | 136 | 137 | 138 | # Required to be the last widget sent to Iced, If you start the program 139 | # and nothing happens, it might mean you forgot to add this command. 140 | ipg.start_session() 141 | -------------------------------------------------------------------------------- /python_examples/py_mouse_area.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG 2 | 3 | 4 | 5 | # Since user data is include, it will need to be 6 | # added to all whether used on or. 7 | def on_press(id, _user_data): 8 | print("on press", id) 9 | 10 | 11 | def on_release(id, _user_data): 12 | print("on release", id) 13 | 14 | 15 | def on_right_press(id, _user_data): 16 | print("on right press, id") 17 | 18 | 19 | def on_right_release(id, _user_data): 20 | print("on right release", id) 21 | 22 | 23 | def on_middle_press(id, _user_data): 24 | print("on middle press", id) 25 | 26 | 27 | def on_middle_release(id, _user_data): 28 | print("on middle release", id) 29 | 30 | 31 | def on_enter(id, user_data): 32 | print("entered", id, user_data) 33 | 34 | 35 | def on_move(id: int, point: dict, _user_data): 36 | print("on move", id, point) 37 | 38 | 39 | def on_exit(id, _user_data): 40 | print("on exit", id) 41 | 42 | 43 | 44 | 45 | ipg = IPG() 46 | 47 | ipg.add_window( 48 | window_id="main", 49 | title="Main", 50 | width=400, 51 | height=400, 52 | pos_centered=True, 53 | debug=True) 54 | 55 | ipg.add_container( 56 | window_id="main", 57 | container_id="cont", 58 | width_fill=True, 59 | height_fill=True) 60 | 61 | ipg.add_mousearea(window_id="main", 62 | container_id="ma", 63 | parent_id="cont", 64 | on_enter=on_enter, 65 | on_exit=on_exit, 66 | on_move=on_move, 67 | on_press=on_press, 68 | on_release=on_release, 69 | on_middle_press=on_middle_press, 70 | on_middle_release=on_middle_release, 71 | on_right_press=on_right_press, 72 | on_right_release=on_right_release, 73 | user_data="Some Data" 74 | ) 75 | 76 | # A text widget was added here but you can also add containers or other widgets too. 77 | ipg.add_text("ma", content="my content 1") 78 | 79 | # you will probably rarely add more than one item to a mousearea 80 | # but the option for more is there. 81 | ipg.add_text("ma", content="my content 2") 82 | 83 | ipg.start_session() 84 | -------------------------------------------------------------------------------- /python_examples/py_move_widget.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG 2 | 3 | ids = [] 4 | 5 | 6 | def move_widget(btn_id: int, item: any): 7 | # equate the tuple items to help interpretation 8 | widget_id = item[0] 9 | container_id = item[1] 10 | move_after = item[2] 11 | move_before = item[3] 12 | 13 | # move the widget 14 | ipg.move_widget( 15 | window_id="main", 16 | widget_id=widget_id, 17 | target_container_str_id=container_id, 18 | move_after=move_after, 19 | move_before=move_before) 20 | 21 | 22 | ipg = IPG() 23 | 24 | ipg.add_window(window_id="main", 25 | title="Move Widget", 26 | width=400.0, 27 | height=600.0, 28 | pos_centered=True, 29 | ) 30 | 31 | ipg.add_row( 32 | window_id="main", 33 | container_id="row") 34 | 35 | ipg.add_column( 36 | window_id="main", 37 | container_id="col_1", 38 | parent_id="row") 39 | 40 | for i in range(0, 10): 41 | ids.append(ipg.add_text(parent_id="col_1", content=f"{i}")) 42 | 43 | ipg.add_space( 44 | parent_id="row", 45 | width=100.0) 46 | 47 | ipg.add_column( 48 | window_id="main", 49 | container_id="col_2", 50 | parent_id="row") 51 | 52 | 53 | ipg.add_column( 54 | window_id="main", 55 | container_id="move_btns") 56 | 57 | ipg.add_button( 58 | parent_id="move_btns", 59 | label="Move number 5 to end", 60 | on_press=move_widget, 61 | user_data=(ids[5], "col_1", None, None)) 62 | 63 | ipg.add_button( 64 | parent_id="move_btns", 65 | label="Move number 5 after 0", 66 | on_press=move_widget, 67 | user_data=(ids[5], "col_1", ids[1], None)) 68 | 69 | ipg.add_button( 70 | parent_id="move_btns", 71 | label="Move number 5 before 0", 72 | on_press=move_widget, 73 | user_data=(ids[5], "col_1", None, ids[0])) 74 | 75 | ipg.start_session() 76 | -------------------------------------------------------------------------------- /python_examples/py_picklist_styling.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgPickListHandle 2 | from icedpygui import IpgAlignment, IpgButtonArrow, IpgColor 3 | 4 | 5 | ipg = IPG() 6 | 7 | 8 | # The data returns the item selected and can be named anything. 9 | # The update items uses the text widget id and the "content" parameter 10 | # to update. The value is what you want the content parameter to equal. 11 | def picked_item(pl_id: int, data: str): 12 | print(f"pl_id = {pl_id} data = {data}") 13 | 14 | 15 | def picked_item_with_user_data(pl_id: int, data: str, user_data: any): 16 | print(f"pl_id = {pl_id} data = {data}, user_data = {user_data}") 17 | 18 | 19 | # Add window must be the first widget. Other windows can be added 20 | # at anytime. 21 | ipg.add_window( 22 | window_id="main", 23 | title="Pick List Demo", 24 | width=700, 25 | height=400, 26 | pos_centered=True) 27 | 28 | # all widgets need to be added to a container, so a container 29 | # is the second widget needed. 30 | ipg.add_column( 31 | window_id="main", 32 | container_id="col", 33 | align=IpgAlignment.Start, 34 | width_fill=True) 35 | 36 | ipg.add_space( 37 | parent_id="col", 38 | height=50.0) 39 | 40 | # add a row for picklist and a button to change option 41 | ipg.add_row( 42 | window_id="main", 43 | container_id="row1", 44 | parent_id="col") 45 | 46 | # A PickList requires that the options you want to select be in a list. 47 | # The list cannot be of mixed types, all will be converted to strings 48 | options = ["One", "Two", "Three"] 49 | 50 | # A PickList is added and the handle is not defined which 51 | # will result in a down arrow used in the PickList box. 52 | ipg.add_pick_list( 53 | parent_id="row1", 54 | options=options, 55 | placeholder="Choose a Number...", 56 | on_select=picked_item) 57 | 58 | ipg.add_text( 59 | parent_id="row1", 60 | content="Default Arrow Style used") 61 | 62 | # add a row for picklist and a button to change option 63 | ipg.add_row( 64 | window_id="main", 65 | container_id="row2", 66 | parent_id="col") 67 | 68 | # Another PickList is added and the handle is defined as an arrow which 69 | # will result in a down arrow used again but the size can be changed. 70 | ipg.add_pick_list( 71 | parent_id="row2", 72 | options=options, 73 | placeholder="Choose a Number...", 74 | handle=IpgPickListHandle.Arrow, 75 | arrow_size=30.0, 76 | on_select=picked_item) 77 | 78 | ipg.add_text( 79 | parent_id="row2", 80 | content="Arrow Style with down arrow sized to 30") 81 | 82 | # add another row for picklist 83 | ipg.add_row( 84 | window_id="main", 85 | container_id="row3", 86 | parent_id="col") 87 | 88 | # Another PickList is added and the handle is defined as Dynamic which 89 | # will result in an arrow used for the open and closed position. 90 | ipg.add_pick_list( 91 | parent_id="row3", 92 | options=options, 93 | placeholder="Choose a Number...", 94 | handle=IpgPickListHandle.Dynamic, 95 | arrow_size=20.0, # the dynamic arrows can be sized too, if needed 96 | dynamic_closed=IpgButtonArrow.ArrowUp, 97 | dynamic_opened=IpgButtonArrow.ArrowDown, 98 | on_select=picked_item) 99 | 100 | ipg.add_text( 101 | parent_id="row3", 102 | content="Arrow Style with right and down arrow sized to 20") 103 | 104 | # add another row for picklist 105 | ipg.add_row( 106 | window_id="main", 107 | container_id="row4", 108 | parent_id="col") 109 | 110 | # Another PickList is added and the handle is defined as an Custom which 111 | # will result in a down arrow used again but the size can be changed. 112 | ipg.add_pick_list( 113 | parent_id="row4", 114 | options=options, 115 | placeholder="Choose a Number...", 116 | handle=IpgPickListHandle.Static, 117 | arrow_size=20.0, # the custom arrows can be sized too, if needed 118 | custom_static=IpgButtonArrow.ArrowNinezerodegDown, 119 | on_select=picked_item) 120 | 121 | ipg.add_text( 122 | parent_id="row4", 123 | content="Arrow Custom Style sized to 20.") 124 | 125 | 126 | # Add some styling 127 | colors = ipg.add_pick_list_style( 128 | background_color=IpgColor.DARK_OLIVE_GREEN, 129 | border_color=IpgColor.ANTIQUE_WHITE, 130 | border_color_hovered=IpgColor.BLUE, 131 | handle_color=IpgColor.DARK_SEA_GREEN, 132 | text_color=IpgColor.LIGHT_GREEN, 133 | border_width=3.0,) 134 | 135 | # add another row for picklist 136 | ipg.add_row( 137 | window_id="main", 138 | container_id="row5", 139 | parent_id="col") 140 | 141 | # Another PickList is added and the handle is defined as an Custom which 142 | # will result in a down arrow used again but the size can be changed. 143 | ipg.add_pick_list( 144 | parent_id="row5", 145 | options=options, 146 | arrow_size=25.0, 147 | placeholder="Choose a Number...", 148 | style_id=colors, 149 | on_select=picked_item_with_user_data, 150 | user_data="Some data") 151 | 152 | ipg.add_text( 153 | parent_id="row5", 154 | content="Background, Border, Handle, and Text styling") 155 | 156 | # Required to be the last widget sent to Iced, If you start the program 157 | # and nothing happens, it might mean you forgot to add this command. 158 | ipg.start_session() 159 | -------------------------------------------------------------------------------- /python_examples/py_radio_test_quantity.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgRadioParam, IpgRadioDirection, IpgTextParam 2 | from icedpygui import IpgAlignment, IpgHorizontalAlignment, IpgColor 3 | 4 | 5 | 6 | # Simple demo to show that the limit of the radios 7 | # is 26 groups of 26 radio buttons. 8 | # If you need more, request an increase. 9 | 10 | ipg = IPG() 11 | 12 | def radio_cb(id: int, selected: tuple): 13 | radio_index = selected[0] 14 | radio_label=selected[1] 15 | print(id, radio_index, radio_label) 16 | 17 | ipg.add_window( 18 | window_id="main", 19 | title="Radio Demo", 20 | width=1400, 21 | height=600, 22 | pos_x=100, 23 | pos_y=25) 24 | 25 | ipg.add_scrollable( 26 | window_id="main", 27 | container_id="scroller") 28 | 29 | ipg.add_column( 30 | window_id="main", 31 | container_id="col", 32 | parent_id="scroller", 33 | align=IpgAlignment.Start, 34 | padding=[5]) 35 | 36 | # The radio button limits are 26 groups with 26 items 37 | for i in range(0, 25): 38 | ipg.add_row( 39 | window_id="main", 40 | container_id=f"row{i}", 41 | parent_id="col") 42 | ipg.add_text( 43 | parent_id=f"row{i}", 44 | content=F"Row-{i}") 45 | ipg.add_radio( 46 | parent_id=f"row{i}", 47 | labels=["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", 48 | "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"], 49 | direction=IpgRadioDirection.Horizontal, 50 | size=15.0, 51 | on_select=radio_cb) 52 | 53 | 54 | # Required to be the last widget sent to Iced, If you start the program 55 | # and nothing happens, it might mean you forgot to add this command. 56 | ipg.start_session() 57 | -------------------------------------------------------------------------------- /python_examples/py_row.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgColor, IpgRowParam, IpgAlignment 2 | 3 | 4 | # Moves the text to the center position 5 | def align_center(btn_id): 6 | ipg.update_item( 7 | wid=col_id, 8 | param=IpgRowParam.Align, 9 | value=IpgAlignment.Center) 10 | 11 | 12 | # Moves the text to the end position 13 | def align_end(btn_id): 14 | ipg.update_item( 15 | wid=col_id, 16 | param=IpgRowParam.Align, 17 | value=IpgAlignment.End) 18 | 19 | 20 | # Moves the text back to the start position 21 | def align_start(btn_id): 22 | ipg.update_item( 23 | wid=col_id, 24 | param=IpgRowParam.Align, 25 | value=IpgAlignment.Start) 26 | 27 | 28 | # Moves text off start because padding on the left side 29 | # padding = [top, right, bottom, left] 30 | def padding(btn_id): 31 | ipg.update_item( 32 | wid=col_id, 33 | param=IpgRowParam.Padding, 34 | value=[0.0, 0.0, 0.0, 50.0]) 35 | 36 | # change container width 37 | def width(btn_id): 38 | ipg.update_item( 39 | wid=col_id, 40 | param=IpgRowParam.Width, 41 | value=350.0) 42 | 43 | 44 | # change container height 45 | def height(btn_id): 46 | ipg.update_item( 47 | wid=col_id, 48 | param=IpgRowParam.Height, 49 | value=100.0) 50 | 51 | # change container height 52 | def spacing(btn_id): 53 | ipg.update_item( 54 | wid=col_id, 55 | param=IpgRowParam.Spacing, 56 | value=20.0) 57 | 58 | 59 | ipg = IPG() 60 | 61 | cont_style = ipg.add_container_style( 62 | border_width=2.0, 63 | border_color=IpgColor.WHITE) 64 | 65 | 66 | 67 | # Add the windows 68 | ipg.add_window( 69 | window_id="main", 70 | title="Container Styling", 71 | width=600, 72 | height=600, 73 | pos_centered=True, 74 | debug=True) 75 | 76 | # Add column to hold everything 77 | ipg.add_column( 78 | window_id="main", 79 | container_id="col", 80 | width_fill=True) 81 | 82 | 83 | # Add a row to hold the text widgets 84 | col_id = ipg.add_row( 85 | window_id="main", 86 | container_id="row_txt", 87 | parent_id="col", 88 | align=IpgAlignment.Start, 89 | width_fill=True, 90 | height=50.0 91 | ) 92 | 93 | ipg.add_text( 94 | parent_id="row_txt", 95 | content="Some Text") 96 | 97 | ipg.add_text( 98 | parent_id="row_txt", 99 | content="Some Text") 100 | 101 | ipg.add_text( 102 | parent_id="row_txt", 103 | content="Some Text") 104 | 105 | 106 | ipg.add_column( 107 | window_id="main", 108 | container_id="col_bottom", 109 | parent_id="col", 110 | width_fill=True, 111 | height=400.0 112 | ) 113 | 114 | # Add a button the center the alignment 115 | ipg.add_button( 116 | parent_id="col_bottom", 117 | label="Align Center", 118 | on_press=align_center) 119 | 120 | # Add a button align end 121 | ipg.add_button( 122 | parent_id="col_bottom", 123 | label="Align End", 124 | on_press=align_end) 125 | 126 | # Add a button align back to the start 127 | ipg.add_button( 128 | parent_id="col_bottom", 129 | label="Align Start", 130 | on_press=align_start) 131 | 132 | # Add a button add padding of the contained items 133 | ipg.add_button( 134 | parent_id="col_bottom", 135 | label="Padding", 136 | on_press=padding) 137 | 138 | # Add a button change the container width 139 | ipg.add_button( 140 | parent_id="col_bottom", 141 | label="Width", 142 | on_press=width) 143 | 144 | # Add a button change the container height 145 | ipg.add_button( 146 | parent_id="col_bottom", 147 | label="Height", 148 | on_press=height) 149 | 150 | # Add a button change the solumn spacing 151 | ipg.add_button( 152 | parent_id="col_bottom", 153 | label="Spacing", 154 | on_press=spacing) 155 | 156 | # last thing is to start the session 157 | ipg.start_session() -------------------------------------------------------------------------------- /python_examples/py_rule.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG 2 | from icedpygui import IpgAlignment, IpgColor 3 | 4 | 5 | ipg = IPG() 6 | 7 | # Add the window 8 | ipg.add_window( 9 | window_id="main", 10 | title="Rule Demo", 11 | width=500, 12 | height=650, 13 | pos_x=100, 14 | pos_y=25) 15 | 16 | # Add a container for alignment 17 | ipg.add_container( 18 | window_id="main", 19 | container_id="cont", 20 | width_fill=True, 21 | height_fill=True) 22 | 23 | # Add a column to hold the widgets 24 | ipg.add_column( 25 | window_id="main", 26 | container_id="col", 27 | parent_id="cont", 28 | align=IpgAlignment.Center) 29 | 30 | # Add some spacing 31 | ipg.add_space( 32 | parent_id="col", 33 | width_fill=True, 34 | height=20.0) 35 | 36 | # Add info 37 | ipg.add_text( 38 | parent_id="col", 39 | content="Below are vertical and horizontal rules") 40 | 41 | # add some styling 42 | st1 = ipg.add_rule_style( 43 | color=IpgColor.YELLOW, 44 | border_radius=[10.0]) 45 | 46 | st2 = ipg.add_rule_style( 47 | color=IpgColor.BLUE, 48 | border_radius=[10.0]) 49 | 50 | # The fill_mode styling 51 | st3 = ipg.add_rule_style( 52 | color=IpgColor.BLUE, 53 | fillmode_percent=50.0) 54 | 55 | # The padding is almost like percent except it gives you 56 | # an unsymmetrical ability. It can be seen better if you uncomment the 57 | # debug mode in the window. 58 | st4 = ipg.add_rule_style( 59 | color=IpgColor.BLUE, 60 | fillmode_asymmetric_padding=(10, 50)) 61 | 62 | 63 | # Add the rules 64 | ipg.add_rule_vertical( 65 | parent_id="col", 66 | height=250, 67 | thickness=5, 68 | style_id=st1) 69 | 70 | ipg.add_rule_horizontal( 71 | parent_id="col", 72 | width=250, 73 | thickness=15, 74 | style_id=st2) 75 | 76 | ipg.add_text( 77 | parent_id="col", 78 | content="Styling added to above with color and corner radius") 79 | 80 | ipg.add_rule_horizontal( 81 | parent_id="col", 82 | width=250, 83 | thickness=15, 84 | style_id=st3) 85 | 86 | ipg.add_text( 87 | parent_id="col", 88 | content="Additional Styling added to above with 50% color fill") 89 | 90 | ipg.add_rule_horizontal( 91 | parent_id="col", 92 | width=250, 93 | thickness=15, 94 | style_id=st4) 95 | 96 | ipg.add_text( 97 | parent_id="col", 98 | content="Additional Styling added to above with unsymmetrical padding") 99 | 100 | # Required to be the last widget sent to Iced, If you start the program 101 | # and nothing happens, it might mean you forgot to add this command. 102 | ipg.start_session() 103 | -------------------------------------------------------------------------------- /python_examples/py_scrollable_styling.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgColor 2 | from icedpygui import IpgAlignment 3 | 4 | 5 | ipg = IPG() 6 | 7 | 8 | ipg.add_window( 9 | window_id="main", 10 | title="Scrollable - Styling", 11 | width=600, height=600, 12 | pos_centered=True) 13 | 14 | 15 | # Add a container just to get some spacing from the top 16 | ipg.add_container( 17 | window_id="main", 18 | container_id="cont", 19 | width_fill=True, 20 | height_fill=True) 21 | 22 | # Let's add some styling for the scrollable before adding it. 23 | # Let's style the bar first with a dark color 24 | color = ipg.add_scrollable_style( 25 | background_color=IpgColor.GRAY, 26 | border_color=IpgColor.LIGHT_GREEN, 27 | border_width=4.0, 28 | border_radius=[8.0], 29 | scrollbar_color=IpgColor.LIGHT_BLUE, 30 | scroller_color=IpgColor.BLUE, 31 | scroller_color_hovered=IpgColor.GREEN, 32 | scroller_color_dragged=IpgColor.HOT_PINK, 33 | shadow_color=IpgColor.BEIGE, 34 | shadow_blur_radius=20.0, 35 | text_color=IpgColor.RED) 36 | 37 | # Add the scrollable restricting the width so it can center and height 38 | # which is less than the length of the data in the column for scrolling. 39 | scroll_id_1 = ipg.add_scrollable( 40 | window_id="main", 41 | container_id="scroll", 42 | parent_id="cont", 43 | width=500, height=150.0, 44 | style_id=color, 45 | v_bar_width=20.0, 46 | v_scroller_width=15.0, 47 | ) 48 | 49 | # Add the column for the data 50 | ipg.add_column( 51 | window_id="main", 52 | container_id="col", 53 | parent_id="scroll", 54 | width_fill=True, 55 | align=IpgAlignment.Center) 56 | 57 | # Add some content to scroll 58 | for i in range(0, 25): 59 | ipg.add_text( 60 | parent_id="col", 61 | content="Scroll Me Up and Down! Scroll Me Up and Down!") 62 | 63 | 64 | ipg.start_session() -------------------------------------------------------------------------------- /python_examples/py_slider_pg_bar.py: -------------------------------------------------------------------------------- 1 | from icedpygui.icedpygui import IPG, IpgProgressBarParam, IpgTextParam 2 | from icedpygui.icedpygui import IpgAlignment, IpgSliderParam, IpgColor 3 | 4 | ipg = IPG() 5 | 6 | show = True 7 | 8 | # Couple of callbacks for change and release 9 | # The slider_id is not used since we are updating the bar and the text 10 | def slider_on_change(_slider_id: int, data: float): 11 | ipg.update_item(on_change_id, IpgTextParam.Content, f"On Change value is {data}") 12 | ipg.update_item(bar_id, IpgProgressBarParam.Value, data) 13 | 14 | def slider_on_release(_slider_id: int, data: float): 15 | ipg.update_item(on_release_id, IpgTextParam.Content, f"On Release value is {data}") 16 | 17 | 18 | # The callbacks below allow you to change all of the parameters for a widget. 19 | # They may or may not have frequent usage but it makes the gui very flexible 20 | # when the data that may be loaded effects the placement, sizes, etc. used. 21 | # These callbacks also demonstrate the usage of the widget parameters and 22 | # are used in the testing of the code to make sure it behaves as expected. 23 | def change_width(btn_id): 24 | ipg.update_item(sl_id, IpgSliderParam.Width, 200.0) 25 | # change bar too 26 | ipg.update_item(bar_id, IpgProgressBarParam.Width, 200.0) 27 | 28 | 29 | def change_height(btn_id): 30 | ipg.update_item(sl_id, IpgSliderParam.Height, 30.0) 31 | 32 | 33 | def change_min(btn_id): 34 | ipg.update_item(sl_id, IpgSliderParam.Min, 50.0) 35 | ipg.update_item(min_txt_id, IpgTextParam.Content, "50") 36 | 37 | 38 | def change_max(btn_id): 39 | ipg.update_item(sl_id, IpgSliderParam.Max, 150.0) 40 | ipg.update_item(max_txt_id, IpgTextParam.Content, "150") 41 | 42 | 43 | def change_step(btn_id): 44 | ipg.update_item(sl_id, IpgSliderParam.Step, 5.0) 45 | 46 | 47 | def change_value(btn_id): 48 | ipg.update_item(sl_id, IpgSliderParam.Value, 100.0) 49 | 50 | 51 | def toggle_show(btn_id): 52 | global show 53 | show = not show 54 | ipg.update_item(sl_id, IpgSliderParam.Show, show) 55 | 56 | 57 | 58 | # Add a slider style for the colors 59 | sl_style = ipg.add_slider_style( 60 | rail_color=IpgColor.GREEN, 61 | rail_color_hovered=IpgColor.GREEN_YELLOW, 62 | handle_color=IpgColor.LIGHT_GREEN, 63 | rail_width=10.0, 64 | rail_border_radius=[8.0], 65 | handle_rectangle_width=20, 66 | handle_rectangle_border_radius=[5.0], 67 | handle_border_width=2.0, 68 | handle_border_color=IpgColor.DARK_GREEN,) 69 | 70 | 71 | # Add the window 72 | ipg.add_window( 73 | window_id="main", 74 | title="Slider Demo", 75 | width=600, 76 | height=600, 77 | pos_x=100, 78 | pos_y=25) 79 | 80 | # Add the column and center the widgets in it. 81 | ipg.add_column( 82 | window_id="main", 83 | container_id="col", 84 | align=IpgAlignment.Center, 85 | width_fill=True, 86 | height_fill=True, 87 | spacing=5) 88 | 89 | # Add some instructions, adding spacing since the columns spacing was decreased to 5. 90 | # Optionally I could have added another column with different spacing or used the padding. 91 | ipg.add_space( 92 | parent_id="col", 93 | height=10) 94 | 95 | ipg.add_text( 96 | parent_id="col", 97 | content="Use the Slider to Change the Values") 98 | 99 | ipg.add_space( 100 | parent_id="col", 101 | height=10.0) 102 | 103 | # Equate the bar to get an id for the callback use. 104 | bar_id = ipg.add_progress_bar( 105 | parent_id="col", 106 | min=0.0, 107 | max=100.0, 108 | value=50.0, 109 | width=300.0) 110 | 111 | # Add a slide to change the value with two callbacks 112 | sl_id = ipg.add_slider( 113 | parent_id="col", 114 | min=0.0, max=100.0, 115 | step=0.5, value=50.0, 116 | width=300.0, 117 | on_change=slider_on_change, 118 | on_release=slider_on_release, 119 | style_id=sl_style) 120 | 121 | # Add some value at beginning and end 122 | ipg.add_row( 123 | window_id="main", 124 | container_id="row_0", 125 | parent_id="col", 126 | width=320.0, 127 | padding=[5.0]) 128 | 129 | min_txt_id = ipg.add_text( 130 | parent_id="row_0", 131 | content="0") 132 | 133 | ipg.add_space( 134 | parent_id="row_0", 135 | width=220.0) 136 | 137 | max_txt_id = ipg.add_text( 138 | parent_id="row_0", 139 | content="100") 140 | 141 | # Add some space for readability 142 | ipg.add_space( 143 | parent_id="col", 144 | height=20.0) 145 | 146 | # Add a couple of text widget to display some data 147 | on_change_id = ipg.add_text( 148 | parent_id="col", 149 | content=f"On Change value is 0") 150 | 151 | on_release_id = ipg.add_text( 152 | parent_id="col", 153 | content=f"On Release value is 0") 154 | 155 | # Add a little extra spacing 156 | ipg.add_space( 157 | parent_id="col", 158 | height=20) 159 | 160 | # add_rows for buttons 161 | ipg.add_row( 162 | window_id="main", 163 | container_id="row_1", 164 | parent_id="col") 165 | 166 | ipg.add_button( 167 | parent_id="row_1", 168 | label="Press Me to Change Width", 169 | on_press=change_width) 170 | 171 | ipg.add_button( 172 | parent_id="row_1", 173 | label="Press Me to Change Height", 174 | on_press=change_height) 175 | 176 | ipg.add_row( 177 | window_id="main", 178 | container_id="row_2", 179 | parent_id="col") 180 | 181 | ipg.add_button( 182 | parent_id="row_2", 183 | label="Press Me to Change Min", 184 | on_press=change_min) 185 | 186 | ipg.add_button( 187 | parent_id="row_2", 188 | label="Press Me to Change Max", 189 | on_press=change_max) 190 | 191 | ipg.add_row( 192 | window_id="main", 193 | container_id="row_3", 194 | parent_id="col") 195 | 196 | ipg.add_button( 197 | parent_id="row_3", 198 | label="Press Me to Change Step", 199 | on_press=change_step) 200 | 201 | ipg.add_button( 202 | parent_id="row_3", 203 | label="Press Me to Change Value", 204 | on_press=change_value) 205 | 206 | ipg.add_row( 207 | window_id="main", 208 | container_id="row_4", 209 | parent_id="col") 210 | 211 | ipg.add_button( 212 | parent_id="row_4", 213 | label="Press Me to Toggle Show", 214 | on_press=toggle_show) 215 | 216 | # Required to be the last widget sent to Iced, If you start the program 217 | # and nothing happens, it might mean you forgot to add this command. 218 | ipg.start_session() 219 | -------------------------------------------------------------------------------- /python_examples/py_solar_sytem.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgDrawMode, IpgCanvasParam, IpgColor 2 | from icedpygui import IpgCanvasWidget, IpgWindowTheme, IpgTextParam 3 | from icedpygui import IpgCanvasTimerParam, IpgCanvasGeometryParam 4 | import os 5 | import random 6 | import math 7 | 8 | 9 | # Moon orbits Earth 27.3 days 10 | # Sun rotates 25 earth days 11 | # earth orbits the sun 365.25 days 12 | 13 | 14 | def point_on_circle(center_x, center_y, radius, angle): 15 | x = center_x + radius * math.cos(angle) 16 | y = center_y + radius * math.sin(angle) 17 | return [x, y] 18 | 19 | 20 | def on_start(timer_id: int): 21 | ipg.update_item(timer_id, IpgCanvasTimerParam.Label, "Stop Timer") 22 | 23 | 24 | # When the timer is stopped, 2nd parameter is sent for elapsed time. 25 | def on_stop(timer_id: int, _elapsed: int): 26 | ipg.update_item(timer_id, IpgCanvasTimerParam.Label, "Start Timer") 27 | 28 | 29 | def on_tick(timer_id: int, elapsed: int): 30 | earth_rotation = 3.142 * elapsed 31 | earth_orbit = earth_rotation/365.25 32 | moon_orbit = earth_rotation/27.3 33 | sun_rotation = earth_rotation/27 34 | earth_point = point_on_circle(canvas_width/2.0, canvas_height/2.0, 150.0, earth_orbit) 35 | ipg.update_canvas_item(earth_id, IpgCanvasGeometryParam.Position, earth_point) 36 | ipg.update_canvas_item(earth_id, IpgCanvasGeometryParam.Rotation, earth_rotation) 37 | moon_point = point_on_circle(earth_point[0], earth_point[1], 15.0, moon_orbit) 38 | ipg.update_canvas_item(moon_id, IpgCanvasGeometryParam.Position, moon_point) 39 | ipg.update_canvas_item(sun_id, IpgCanvasGeometryParam.Rotation, sun_rotation) 40 | 41 | 42 | ipg = IPG() 43 | 44 | 45 | global default_file_path 46 | cwd = os.getcwd() 47 | sun_path = f"{cwd}/python_examples/resources/solar_system_assets/sun.png" 48 | earth_path = f"{cwd}/python_examples/resources/solar_system_assets/earth.png" 49 | moon_path = f"{cwd}/python_examples/resources/solar_system_assets/moon.png" 50 | 51 | canvas_width = 800.0 52 | canvas_height = 725.0 53 | 54 | ipg.add_window(window_id="main", title="Canvas", 55 | width=800.0, height=800.0, 56 | pos_centered=True, 57 | ) 58 | 59 | ipg.add_column(window_id="main", container_id="col", 60 | width_fill=True, height_fill=True) 61 | 62 | ipg.add_row(window_id="main", 63 | container_id="row", 64 | parent_id="col", 65 | ) 66 | 67 | ipg.add_canvas_timer(parent_id="row", 68 | duration_ms=15, 69 | on_tick=on_tick, 70 | on_start=on_start, 71 | on_stop=on_stop, 72 | ) 73 | 74 | canvas_id = ipg.add_canvas(window_id="main", 75 | canvas_id="canvas", 76 | parent_id="col", 77 | width=canvas_width, 78 | height=canvas_height, 79 | background_ipg_color=IpgColor.BLACK) 80 | 81 | sun_id = ipg.add_canvas_image(canvas_id="canvas", 82 | image_path=sun_path, 83 | width=140.0, 84 | height=140.0, 85 | position_xy=(canvas_width/2.0, canvas_height/2.0), 86 | align_center=True, 87 | ) 88 | 89 | earth_start = point_on_circle(canvas_width/2.0, canvas_height/2.0, 150.0, 0) 90 | 91 | earth_id = ipg.add_canvas_image(canvas_id="canvas", 92 | image_path=earth_path, 93 | width=24.0, 94 | height=24.0, 95 | position_xy=earth_start, 96 | align_center=True, 97 | ) 98 | 99 | moon_start = point_on_circle(earth_start[0], earth_start[1], 15.0, 0) 100 | 101 | moon_id = ipg.add_canvas_image(canvas_id="canvas", 102 | image_path=moon_path, 103 | width=8.0, 104 | height=8.0, 105 | position_xy=moon_start, 106 | align_center=True, 107 | ) 108 | 109 | earth_obit_id = ipg.add_circle(canvas_id="canvas", 110 | position_xy=(canvas_width/2.0, canvas_height/2.0), 111 | radius=150.0, 112 | stroke_width=1.0, 113 | stroke_ipg_color=IpgColor.WHITE, 114 | stroke_color_alpha=0.1, 115 | stroke_dash_offset=0, 116 | stroke_dash_segments=[3.0, 6.0], 117 | ) 118 | 119 | # generate a random star pattern 120 | for _ in range(0, 100): 121 | x = float(random.randint(0, int(canvas_width))) 122 | y = float(random.randint(0, int(canvas_height))) 123 | ipg.add_rectangle(canvas_id="canvas", 124 | top_left_xy=(x, y), 125 | width=0.1, 126 | height=0.1, 127 | fill_ipg_color=IpgColor.WHITE 128 | ) 129 | 130 | 131 | 132 | 133 | ipg.start_session() 134 | -------------------------------------------------------------------------------- /python_examples/py_space.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgAlignment 2 | 3 | ipg = IPG() 4 | 5 | # Add the window, debug is set to true to be able to see the space widget. 6 | ipg.add_window( 7 | window_id="main1", 8 | title="Space Demo 1", 9 | width=400, 10 | height=600, 11 | pos_x=100, 12 | pos_y=25, 13 | debug=True) 14 | 15 | # Add the column for the widgets, centered 16 | ipg.add_column( 17 | window_id="main1", 18 | container_id="col1", 19 | align=IpgAlignment.Center, 20 | width_fill=True, 21 | height_fill=True) 22 | 23 | # Add the space 24 | ipg.add_space( 25 | parent_id="col1", 26 | width=50.0, 27 | height=200.0) 28 | 29 | # Add some info text 30 | ipg.add_text( 31 | parent_id="col1", 32 | content="\nThere is a space outlined above," 33 | " \nwidth=100.0, height=50.0\n " 34 | "If you resize the window, the spacing does not change because it is set, " 35 | "unlike on window 2") 36 | 37 | # Add another window 38 | ipg.add_window( 39 | window_id="main2", 40 | title="Space Demo 2", 41 | width=400, 42 | height=600, 43 | pos_x=600, 44 | pos_y=25, 45 | debug=True) 46 | 47 | # Add the column for the widgets, centered 48 | ipg.add_column( 49 | window_id="main2", 50 | container_id="col2", 51 | align=IpgAlignment.Center, 52 | width_fill=True, 53 | height_fill=True) 54 | 55 | # Add the space, since the window debug=True you will be able to see it. 56 | ipg.add_space( 57 | parent_id="col2", 58 | width_fill=True, 59 | height=100.0) 60 | 61 | # Add some text for info 62 | ipg.add_text( 63 | parent_id="col2", 64 | content="\nThere is a space outlined above, \nwidth_fill=True, height=100.0\n ") 65 | 66 | ipg.add_text( 67 | parent_id="col2", 68 | content="\nif you drag the window width, the spacing grows because width_fill=True\n ") 69 | 70 | # Required to be the last widget sent to Iced, If you start the program 71 | # and nothing happens, it might mean you forgot to add this command. 72 | ipg.start_session() 73 | -------------------------------------------------------------------------------- /python_examples/py_stack.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | from icedpygui import IPG, IpgColor, IpgStackParam, IpgMousePointer, IpgImageContentFit 4 | from icedpygui import IpgTextParam 5 | 6 | 7 | 8 | def card_selected(card_id, name): 9 | ipg.update_item( 10 | wid=text_id, 11 | param=IpgTextParam.Content, 12 | value=f"Card selected is {name}") 13 | 14 | 15 | ipg=IPG() 16 | 17 | cwd = os.getcwd() 18 | path = path = cwd + "/python_examples/resources/cards/hearts/" 19 | 20 | names = ["Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"] 21 | 22 | ipg.add_window( 23 | window_id="main", 24 | title="Stack", 25 | width=400.0, 26 | height=800.0, 27 | pos_centered=True) 28 | 29 | ipg.add_container( 30 | window_id="main", 31 | container_id="cont", 32 | width_fill=True, 33 | height_fill=True) 34 | 35 | ipg.add_column( 36 | window_id="main", 37 | container_id="main_col", 38 | parent_id="cont", 39 | height_fill=True) 40 | 41 | text_id = ipg.add_text( 42 | parent_id="main_col", 43 | content="Card Selected is None") 44 | 45 | # Adds the stack container to the window. 46 | stack_id = ipg.add_stack( 47 | window_id="main", 48 | container_id="stack", 49 | parent_id="main_col", 50 | width=200.0, 51 | height=750.0) 52 | 53 | for i in range(1, 14): 54 | # Adds the column to the stack to hold the space and card. 55 | ipg.add_column( 56 | window_id="main", 57 | container_id=f"col_{i}", 58 | parent_id="stack") 59 | 60 | file = f"{path}{i}.png" 61 | 62 | # The space, whcich grows with each card, allows for an offset 63 | # to be able to see all of the cards. If not used, they are 64 | # stacked on top of each other. 65 | ipg.add_space( 66 | parent_id=f"col_{i}", 67 | height=35*i-35) 68 | 69 | ipg.add_image( 70 | parent_id=f"col_{i}", 71 | image_path=file, 72 | width=200.0, 73 | height=300.0, 74 | content_fit=IpgImageContentFit.Fill, 75 | mouse_pointer=IpgMousePointer.Grabbing, 76 | on_press=card_selected, 77 | user_data=f"{names[i-1]}") 78 | 79 | 80 | ipg.start_session() 81 | 82 | -------------------------------------------------------------------------------- /python_examples/py_svg.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgAlignment 2 | from icedpygui import IpgSvgParam 3 | import os 4 | 5 | # some global vars 6 | width = 400.0 7 | height = 400.0 8 | 9 | 10 | # Since user data is include, it will need to be 11 | # added to all whether used on or. 12 | def on_press(btn_id, _user_data): 13 | print("on press", btn_id) 14 | 15 | 16 | def on_release(btn_id: int, _user_data): 17 | print("on release", btn_id) 18 | 19 | 20 | def on_right_press(btn_id: int, _user_data): 21 | print("on right press, btn_id") 22 | 23 | 24 | def on_right_release(id: int, _user_data): 25 | print("on right release", id) 26 | 27 | 28 | def on_middle_press(btn_id: int, _user_data): 29 | print("on middle press", btn_id) 30 | 31 | 32 | def on_middle_release(btn_id: int, _user_data): 33 | print("on middle release", btn_id) 34 | 35 | 36 | def on_enter(btn_id: int, user_data: any): 37 | print("entered", btn_id, user_data) 38 | 39 | 40 | def on_move(btn_id: int, point: dict, _user_data): 41 | print("on move", btn_id, point) 42 | 43 | 44 | def on_exit(btn_id, _user_data): 45 | print("on exit", btn_id) 46 | 47 | 48 | # The six of the svg will only get as big as the size of 49 | # the container it's in. 50 | def increase_size(btn_id): 51 | global width, height 52 | width += 10 53 | height += 10 54 | ipg.update_item(svg_id, IpgSvgParam.Width, width) 55 | ipg.update_item(svg_id, IpgSvgParam.Height, height) 56 | 57 | 58 | def decrease_size(btn_id): 59 | global width, height 60 | width -= 10 61 | height -= 10 62 | ipg.update_item(svg_id, IpgSvgParam.Width, width) 63 | ipg.update_item(svg_id, IpgSvgParam.Height, height) 64 | 65 | 66 | ipg = IPG() 67 | 68 | ipg.add_window( 69 | window_id="main", 70 | title="Main", 71 | width=600, 72 | height=600, 73 | pos_centered=True, 74 | debug=True) 75 | 76 | ipg.add_container( 77 | window_id="main", 78 | container_id="cont", 79 | width_fill=True, 80 | centered=True) 81 | 82 | # Setting up the image path 83 | cwd = os.getcwd() 84 | tiger_path = cwd + "/python_examples/resources/tiger_0.svg" 85 | 86 | ipg.add_column( 87 | window_id="main", 88 | container_id="col", 89 | align=IpgAlignment.Center) 90 | 91 | 92 | svg_id = ipg.add_svg( 93 | parent_id="col", 94 | svg_path=tiger_path, 95 | width=width, 96 | height=height, 97 | on_enter=on_enter, 98 | on_exit=on_exit, 99 | on_move=on_move, 100 | on_press=on_press, 101 | on_release=on_release, 102 | on_middle_press=on_middle_press, 103 | on_middle_release=on_middle_release, 104 | on_right_press=on_right_press, 105 | on_right_release=on_right_release, 106 | user_data="Some Data") 107 | 108 | ipg.add_button( 109 | parent_id="col", 110 | label="Increase Size", 111 | on_press=increase_size) 112 | 113 | ipg.add_button( 114 | parent_id="col", 115 | label="Decrease Size", 116 | on_press=decrease_size) 117 | 118 | ipg.start_session() 119 | -------------------------------------------------------------------------------- /python_examples/py_text.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgTextWrapping, IpgTextParam 2 | 3 | # This is a simple demo for text with wrapping 4 | ipg = IPG() 5 | 6 | 7 | def change_text (sldr_id: int, value: float): 8 | ipg.update_item( 9 | wid=txt1, 10 | param=IpgTextParam.Width, 11 | value=value) 12 | ipg.update_item( 13 | wid=txt2, 14 | param=IpgTextParam.Width, 15 | value=value) 16 | 17 | 18 | 19 | # Add a window first 20 | ipg.add_window( 21 | window_id="main", 22 | title="CheckBox Demo", 23 | width=600, 24 | height=600, 25 | pos_centered=True, 26 | debug=True) 27 | 28 | # Add a container to center the widgets in the middle 29 | ipg.add_container( 30 | window_id="main", 31 | container_id="cont", 32 | width_fill=True, 33 | height_fill=True, 34 | centered=True) 35 | 36 | ipg.add_column( 37 | window_id="main", 38 | container_id="col", 39 | parent_id="cont") 40 | 41 | ipg.add_slider( 42 | parent_id="col", 43 | min=0.0, 44 | max=200.0, 45 | step=1.0, 46 | value=200.0, 47 | on_change=change_text, 48 | width=175.0) 49 | 50 | txt1 = ipg.add_text( 51 | parent_id="col", 52 | content="This is some very very very very very very very very long text.", 53 | wrapping=IpgTextWrapping.Word, 54 | width=160.0) 55 | 56 | txt2 = ipg.add_text( 57 | parent_id="col", 58 | content="This is some very very very very very very very very long text.", 59 | wrapping=IpgTextWrapping.NoWrapping, 60 | width=160.0) 61 | 62 | 63 | # Required to be the last widget sent to Iced, If you start the program 64 | # and nothing happens, it might mean you forgot to add this command. 65 | ipg.start_session() 66 | -------------------------------------------------------------------------------- /python_examples/py_toggler.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgAlignment, IpgTogglerParam, IpgTextParam 2 | from icedpygui import IpgAlignment, IpgAlignment, IpgHorizontalAlignment 3 | 4 | ipg = IPG() 5 | 6 | 7 | # Callback from toggler, updated a text widget 8 | def toggled(_tog_id, is_toggled): 9 | ipg.update_item( 10 | text_id, 11 | IpgTextParam.Content, 12 | f"The toggler is {is_toggled}.") 13 | 14 | 15 | # The callbacks below allow you to change all of the parameters for a widget. 16 | # They may or may not have frequent usage but it makes the gui very flexible 17 | # when the data that may be loaded effects the placement, sizes, etc. used. 18 | # These callbacks also demonstrate the usage of the widget parameters and 19 | # are used in the testing of the code to make sure it behaves as expected. 20 | def update_label(_btn_id): 21 | ipg.update_item( 22 | tog_id, 23 | IpgTogglerParam.Label, 24 | "New Toggle Label") 25 | 26 | 27 | def update_width(_btn_id): 28 | ipg.update_item( 29 | tog_id, 30 | IpgTogglerParam.Width, 31 | 100.0) 32 | 33 | 34 | def update_width_fill(_btn_id): 35 | ipg.update_item( 36 | tog_id, 37 | IpgTogglerParam.WidthFill, 38 | True) 39 | 40 | 41 | def update_alignment(_btn_id): 42 | ipg.update_item( 43 | tog_id, 44 | IpgTogglerParam.HorizontalAlignment, 45 | IpgHorizontalAlignment.Left) 46 | 47 | 48 | def update_size(_btn_id): 49 | ipg.update_item( 50 | tog_id, 51 | IpgTogglerParam.Size, 52 | 30.0) 53 | 54 | 55 | def update_text_size(_btn_id): 56 | ipg.update_item( 57 | tog_id, 58 | IpgTogglerParam.TextSize, 59 | 30.0) 60 | 61 | 62 | def update_line_height(_btn_id): 63 | ipg.update_item( 64 | tog_id, 65 | IpgTogglerParam.LineHeight, 66 | 2.0) 67 | 68 | 69 | # Add the window 70 | ipg.add_window( 71 | window_id="main", 72 | title="Toggler Demo", 73 | width=700, 74 | height=625, 75 | pos_x=100, 76 | pos_y=25) 77 | 78 | # Add a main column to hold everything 79 | ipg.add_column( 80 | window_id="main", 81 | container_id="col", 82 | width_fill=True, 83 | height_fill=True, 84 | align=IpgAlignment.Center, 85 | spacing=5.0) 86 | 87 | # Add a column at the top for the toggler and a text widget 88 | ipg.add_column( 89 | window_id="main", 90 | container_id="col_top", 91 | parent_id="col", 92 | align=IpgAlignment.Center, 93 | height=110.0, 94 | spacing=5.0, 95 | padding=[5.0], 96 | width_fill=True) 97 | 98 | tog_id = ipg.add_toggler( 99 | parent_id="col_top", 100 | toggled=toggled) 101 | 102 | text_id = ipg.add_text( 103 | parent_id="col_top", 104 | content="The toggler is False.") 105 | 106 | # Add another column to hold the remaining buttons 107 | ipg.add_column( 108 | window_id="main", 109 | container_id="col_bot", 110 | parent_id="col", 111 | align=IpgAlignment.Center, 112 | spacing=10.0, 113 | padding=[5.0]) 114 | 115 | ipg.add_text( 116 | parent_id='col_bot', 117 | content="Press the buttons, below, in order to best see the effects, top to bottom, left to right") 118 | 119 | ipg.add_button( 120 | parent_id="col_bot", 121 | label="Update Label", 122 | on_press=update_label) 123 | 124 | ipg.add_button( 125 | parent_id="col_bot", 126 | label="Update Width\n the width will shrink stacking the label", 127 | on_press=update_width) 128 | 129 | ipg.add_button( 130 | parent_id="col_bot", 131 | label="Setting WidthFill=True\n The toggler expand the width of the container. the label is centered, " 132 | "the default setting", 133 | on_press=update_width_fill) 134 | 135 | ipg.add_button( 136 | parent_id="col_bot", 137 | label="Setting the alignment to Left\n This caused the label to move left", 138 | on_press=update_alignment) 139 | 140 | ipg.add_button( 141 | parent_id="col_bot", 142 | label="Setting the size\n This makes the toggler bigger", 143 | on_press=update_size) 144 | 145 | # putting last two buttons in a row to make more room on screen 146 | ipg.add_row( 147 | window_id="main", 148 | container_id="row", 149 | parent_id="col_bot", 150 | align=IpgAlignment.Center, 151 | width_fill=True) 152 | 153 | ipg.add_button( 154 | parent_id="row", 155 | label="Increasing the TextSize", 156 | on_press=update_text_size) 157 | 158 | # The text line height basically makes the outer box container the widget bigger 159 | ipg.add_button( 160 | parent_id="row", 161 | label="Increasing the TextLineHeight\n Set window debug=True to see this better,", 162 | on_press=update_line_height) 163 | 164 | # Required to be the last widget sent to Iced, If you start the program 165 | # and nothing happens, it might mean you forgot to add this command. 166 | ipg.start_session() 167 | -------------------------------------------------------------------------------- /python_examples/py_toggler_styling.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgColor 2 | from icedpygui import IpgAlignment, IpgAlignment 3 | 4 | ipg = IPG() 5 | 6 | 7 | 8 | # Add the window 9 | ipg.add_window( 10 | window_id="main", 11 | title="Toggler Demo", 12 | width=700, 13 | height=625, 14 | pos_centered=True) 15 | 16 | # Add a main column to hold everything 17 | ipg.add_column( 18 | window_id="main", 19 | container_id="col", 20 | width_fill=True, 21 | height_fill=True, 22 | align=IpgAlignment.Center, 23 | spacing=5.0) 24 | 25 | ipg.add_space( 26 | parent_id="col", 27 | height=50.0) 28 | 29 | # Add some styling to the toggler 30 | tog_style = ipg.add_toggler_style( 31 | background_color=IpgColor.GREEN, 32 | background_color_toggled=IpgColor.LIGHT_GREEN, 33 | foreground_color=IpgColor.ANTIQUE_WHITE, 34 | foreground_color_toggled=IpgColor.BLUE, 35 | ) 36 | 37 | # Add the toggler and change size to see styling better 38 | tog_id = ipg.add_toggler( 39 | parent_id="col", 40 | label="Some Toggler Label", 41 | size=40.0, 42 | text_size=25.0, 43 | style_id=tog_style) 44 | 45 | 46 | 47 | # Required to be the last widget sent to Iced, If you start the program 48 | # and nothing happens, it might mean you forgot to add this command. 49 | ipg.start_session() 50 | -------------------------------------------------------------------------------- /python_examples/py_tooltip.py: -------------------------------------------------------------------------------- 1 | from icedpygui import IPG, IpgToolTipPosition 2 | from icedpygui import IpgToolTipParam, IpgButtonParam, IpgColor 3 | 4 | ipg = IPG() 5 | 6 | positions = [ 7 | IpgToolTipPosition.Top, 8 | IpgToolTipPosition.Right, 9 | IpgToolTipPosition.Bottom, 10 | IpgToolTipPosition.Left, 11 | IpgToolTipPosition.FollowCursor, 12 | ] 13 | 14 | index = 0 15 | 16 | def change_position(btn_id): 17 | global index 18 | index += 1 19 | if index == 5: 20 | index = 0 21 | 22 | ipg.update_item( 23 | wid=tt_id, 24 | param=IpgToolTipParam.Position, 25 | value=positions[index]) 26 | 27 | match index: 28 | case 0: 29 | label = "Tool Tip On Top, Press to Change" 30 | case 1: 31 | label = "Tool Tip On Right, Press to Change" 32 | case 2: 33 | label = "Tool Tip On Bottom, Press to Change" 34 | case 3: 35 | label = "Tool Tip On Left, Press to Change" 36 | case 4: 37 | label = "Tool Tip Follows Cursor, Press to Change" 38 | 39 | ipg.update_item( 40 | wid=btn_id, 41 | param=IpgButtonParam.Label, 42 | value=label) 43 | 44 | 45 | ts_id = ipg.add_tooltip_style( 46 | background_color=IpgColor.DARK_GRAY, 47 | text_color=IpgColor.BLACK, 48 | border_radius=[5.0], 49 | border_color=IpgColor.WHITE, 50 | border_width=2.0) 51 | 52 | # Add a window first 53 | ipg.add_window( 54 | window_id="main", 55 | title="CheckBox Demo", 56 | width=600, 57 | height=600, 58 | pos_centered=True) 59 | 60 | # Add a container to center the widgets in the middle 61 | ipg.add_container( 62 | window_id="main", 63 | container_id="cont", 64 | width_fill=True, 65 | height_fill=True, 66 | centered=True) 67 | 68 | 69 | tt_id = ipg.add_tool_tip( 70 | window_id="main", 71 | container_id="tt", 72 | parent_id="cont", 73 | text_to_display="Some Tip", 74 | position=IpgToolTipPosition.Top, 75 | padding=5.0, 76 | gap=20, 77 | style_id=ts_id) 78 | 79 | btn_id = ipg.add_button( 80 | parent_id="tt", 81 | label="Tool Tip On Top, Press to Change", 82 | on_press=change_position) 83 | 84 | # Required to be the last widget sent to Iced, If you start the program 85 | # and nothing happens, it might mean you forgot to add this command. 86 | ipg.start_session() 87 | -------------------------------------------------------------------------------- /python_examples/resources/cards/card_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/card_back.png -------------------------------------------------------------------------------- /python_examples/resources/cards/clubs/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/clubs/1.png -------------------------------------------------------------------------------- /python_examples/resources/cards/clubs/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/clubs/10.png -------------------------------------------------------------------------------- /python_examples/resources/cards/clubs/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/clubs/11.png -------------------------------------------------------------------------------- /python_examples/resources/cards/clubs/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/clubs/12.png -------------------------------------------------------------------------------- /python_examples/resources/cards/clubs/13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/clubs/13.png -------------------------------------------------------------------------------- /python_examples/resources/cards/clubs/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/clubs/2.png -------------------------------------------------------------------------------- /python_examples/resources/cards/clubs/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/clubs/3.png -------------------------------------------------------------------------------- /python_examples/resources/cards/clubs/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/clubs/4.png -------------------------------------------------------------------------------- /python_examples/resources/cards/clubs/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/clubs/5.png -------------------------------------------------------------------------------- /python_examples/resources/cards/clubs/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/clubs/6.png -------------------------------------------------------------------------------- /python_examples/resources/cards/clubs/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/clubs/7.png -------------------------------------------------------------------------------- /python_examples/resources/cards/clubs/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/clubs/8.png -------------------------------------------------------------------------------- /python_examples/resources/cards/clubs/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/clubs/9.png -------------------------------------------------------------------------------- /python_examples/resources/cards/diamonds/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/diamonds/1.png -------------------------------------------------------------------------------- /python_examples/resources/cards/diamonds/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/diamonds/10.png -------------------------------------------------------------------------------- /python_examples/resources/cards/diamonds/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/diamonds/11.png -------------------------------------------------------------------------------- /python_examples/resources/cards/diamonds/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/diamonds/12.png -------------------------------------------------------------------------------- /python_examples/resources/cards/diamonds/13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/diamonds/13.png -------------------------------------------------------------------------------- /python_examples/resources/cards/diamonds/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/diamonds/2.png -------------------------------------------------------------------------------- /python_examples/resources/cards/diamonds/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/diamonds/3.png -------------------------------------------------------------------------------- /python_examples/resources/cards/diamonds/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/diamonds/4.png -------------------------------------------------------------------------------- /python_examples/resources/cards/diamonds/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/diamonds/5.png -------------------------------------------------------------------------------- /python_examples/resources/cards/diamonds/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/diamonds/6.png -------------------------------------------------------------------------------- /python_examples/resources/cards/diamonds/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/diamonds/7.png -------------------------------------------------------------------------------- /python_examples/resources/cards/diamonds/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/diamonds/8.png -------------------------------------------------------------------------------- /python_examples/resources/cards/diamonds/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/diamonds/9.png -------------------------------------------------------------------------------- /python_examples/resources/cards/hearts/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/hearts/1.png -------------------------------------------------------------------------------- /python_examples/resources/cards/hearts/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/hearts/10.png -------------------------------------------------------------------------------- /python_examples/resources/cards/hearts/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/hearts/11.png -------------------------------------------------------------------------------- /python_examples/resources/cards/hearts/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/hearts/12.png -------------------------------------------------------------------------------- /python_examples/resources/cards/hearts/13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/hearts/13.png -------------------------------------------------------------------------------- /python_examples/resources/cards/hearts/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/hearts/2.png -------------------------------------------------------------------------------- /python_examples/resources/cards/hearts/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/hearts/3.png -------------------------------------------------------------------------------- /python_examples/resources/cards/hearts/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/hearts/4.png -------------------------------------------------------------------------------- /python_examples/resources/cards/hearts/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/hearts/5.png -------------------------------------------------------------------------------- /python_examples/resources/cards/hearts/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/hearts/6.png -------------------------------------------------------------------------------- /python_examples/resources/cards/hearts/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/hearts/7.png -------------------------------------------------------------------------------- /python_examples/resources/cards/hearts/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/hearts/8.png -------------------------------------------------------------------------------- /python_examples/resources/cards/hearts/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/hearts/9.png -------------------------------------------------------------------------------- /python_examples/resources/cards/spades/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/spades/1.png -------------------------------------------------------------------------------- /python_examples/resources/cards/spades/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/spades/10.png -------------------------------------------------------------------------------- /python_examples/resources/cards/spades/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/spades/11.png -------------------------------------------------------------------------------- /python_examples/resources/cards/spades/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/spades/12.png -------------------------------------------------------------------------------- /python_examples/resources/cards/spades/13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/spades/13.png -------------------------------------------------------------------------------- /python_examples/resources/cards/spades/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/spades/2.png -------------------------------------------------------------------------------- /python_examples/resources/cards/spades/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/spades/3.png -------------------------------------------------------------------------------- /python_examples/resources/cards/spades/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/spades/4.png -------------------------------------------------------------------------------- /python_examples/resources/cards/spades/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/spades/5.png -------------------------------------------------------------------------------- /python_examples/resources/cards/spades/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/spades/6.png -------------------------------------------------------------------------------- /python_examples/resources/cards/spades/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/spades/7.png -------------------------------------------------------------------------------- /python_examples/resources/cards/spades/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/spades/8.png -------------------------------------------------------------------------------- /python_examples/resources/cards/spades/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/cards/spades/9.png -------------------------------------------------------------------------------- /python_examples/resources/ferris_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/ferris_0.png -------------------------------------------------------------------------------- /python_examples/resources/ferris_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/ferris_1.png -------------------------------------------------------------------------------- /python_examples/resources/ferris_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/ferris_2.png -------------------------------------------------------------------------------- /python_examples/resources/ferris_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/ferris_3.png -------------------------------------------------------------------------------- /python_examples/resources/ferris_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/ferris_4.png -------------------------------------------------------------------------------- /python_examples/resources/ferris_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/ferris_5.png -------------------------------------------------------------------------------- /python_examples/resources/ferris_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/ferris_6.png -------------------------------------------------------------------------------- /python_examples/resources/ferris_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/ferris_7.png -------------------------------------------------------------------------------- /python_examples/resources/ferris_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/ferris_8.png -------------------------------------------------------------------------------- /python_examples/resources/ferris_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/ferris_9.png -------------------------------------------------------------------------------- /python_examples/resources/solar_system_assets/earth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/solar_system_assets/earth.png -------------------------------------------------------------------------------- /python_examples/resources/solar_system_assets/moon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/solar_system_assets/moon.png -------------------------------------------------------------------------------- /python_examples/resources/solar_system_assets/sun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/python_examples/resources/solar_system_assets/sun.png -------------------------------------------------------------------------------- /src/canvas/mod.rs: -------------------------------------------------------------------------------- 1 | 2 | pub mod colors; 3 | pub mod draw_canvas; 4 | pub mod geometries; 5 | pub mod import_export; 6 | mod path_builds; 7 | pub mod canvas_helpers; 8 | -------------------------------------------------------------------------------- /src/graphics/fonts/SFUIRounded.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/src/graphics/fonts/SFUIRounded.ttf -------------------------------------------------------------------------------- /src/graphics/fonts/bootstrap-icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/src/graphics/fonts/bootstrap-icons.ttf -------------------------------------------------------------------------------- /src/graphics/fonts/icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/src/graphics/fonts/icons.ttf -------------------------------------------------------------------------------- /src/graphics/fonts/nerd-icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icedpygui/IcedPyGui/13c52706af8e374f915bcc3abe8990371f1a560d/src/graphics/fonts/nerd-icons.ttf -------------------------------------------------------------------------------- /src/graphics/mod.rs: -------------------------------------------------------------------------------- 1 | //! A module fitting `iced_graphics`. 2 | #![allow(dead_code)] 3 | pub mod bootstrap_icon; 4 | pub mod bootstrap; 5 | pub mod colors; 6 | pub mod required; 7 | pub mod nerd; 8 | 9 | use iced::Font; 10 | 11 | /// The default icon font bytes for loading the font into iced. 12 | pub const BOOTSTRAP_FONT_BYTES: &[u8] = include_bytes!("./fonts/bootstrap-icons.ttf"); 13 | /// the icon font that has all nerd fonts. 14 | pub const NERD_FONT_BYTES: &[u8] = include_bytes!("./fonts/nerd-icons.ttf"); 15 | 16 | /// The bootstrap icon font. 17 | pub const BOOTSTRAP_FONT: Font = Font::with_name("bootstrap-icons"); 18 | /// The nerd icon font. 19 | pub const NERD_FONT: Font = Font::with_name("Symbols Nerd Font"); 20 | 21 | /// The default cupertino font bytes for loading the font into the system. 22 | pub const SF_UI_ROUNDED_BYTES: &[u8] = include_bytes!("./fonts/SFUIRounded.ttf"); 23 | 24 | /// The default cupertino font for alerts and button. 25 | pub const SF_UI_ROUNDED: iced::Font = iced::Font::with_name(".SF UI Rounded"); -------------------------------------------------------------------------------- /src/graphics/required.rs: -------------------------------------------------------------------------------- 1 | //! Bootstrap icons. 2 | 3 | /// Bootstrap icons 4 | #[derive(Copy, Clone, Debug, Hash)] 5 | pub enum Icon { 6 | /// caret-down-fill 7 | CaretDownFill, 8 | /// caret-left-fill 9 | CaretLeftFill, 10 | /// caret-right-fill 11 | CaretRightFill, 12 | /// caret-up-fill 13 | CaretUpFill, 14 | /// check 15 | Check, 16 | /// x 17 | X, 18 | } 19 | 20 | /// Converts an icon into a char. 21 | #[must_use] 22 | pub const fn icon_to_char(icon: Icon) -> char { 23 | match icon { 24 | Icon::CaretDownFill => '\u{f217}', 25 | Icon::CaretLeftFill => '\u{f21b}', 26 | Icon::CaretRightFill => '\u{f21f}', 27 | Icon::CaretUpFill => '\u{f223}', 28 | Icon::Check => '\u{f25c}', 29 | Icon::X => '\u{f5ae}', 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/iced_aw_widgets/menu/common.rs: -------------------------------------------------------------------------------- 1 | use iced::{Padding, Rectangle}; 2 | 3 | /* /// The condition of when to close a menu 4 | #[derive(Debug, Clone, Copy)] 5 | pub struct CloseCondition { 6 | /// Close menus when the cursor moves outside the check bounds 7 | pub leave: bool, 8 | 9 | /// Close menus when the cursor clicks outside the check bounds 10 | pub click_outside: bool, 11 | 12 | /// Close menus when the cursor clicks inside the check bounds 13 | pub click_inside: bool, 14 | } 15 | */ 16 | 17 | /// 18 | /// ## FakeHovering: 19 | /// 20 | /// Places cursors at the path items, 21 | /// useful when you want to customize the styling of each item in the path, 22 | /// or you simple want the look of the items when they are hovered over. 23 | /// 24 | /// The downside is when some widgets in the path don't response to hovering, 25 | /// the path won't be fully drawn, and when you want uniform path styling 26 | /// but some widgets response to hovering differently. 27 | /// 28 | /// ## Backdrop: 29 | /// 30 | /// Draws a rectangle behind each path item, 31 | /// requires path items to have transparent backgrounds, 32 | /// useful when you want uniform path styling. 33 | /// 34 | /// The downside is, 35 | /// depending on the style you're going for, 36 | /// oftentimes manually syncing the path's styling to the path items' is necessary, 37 | /// the default styling simply can't cover most use cases. 38 | pub enum DrawPath { 39 | /// FakeHovering 40 | FakeHovering, 41 | /// Backdrop 42 | Backdrop, 43 | } 44 | 45 | /// X+ goes right and Y+ goes down 46 | #[derive(Debug, Clone, Copy)] 47 | pub(super) enum Direction { 48 | Positive, 49 | Negative, 50 | } 51 | impl Direction { 52 | pub(super) fn flip(self) -> Self { 53 | match self { 54 | Self::Positive => Self::Negative, 55 | Self::Negative => Self::Positive, 56 | } 57 | } 58 | } 59 | 60 | /// Axis 61 | #[allow(missing_docs)] 62 | #[derive(Debug, Clone, Copy)] 63 | pub(super) enum Axis { 64 | Horizontal, 65 | Vertical, 66 | } 67 | 68 | pub(super) type Index = Option; 69 | 70 | /// Should be returned from the recursive event processing function, 71 | /// tells the caller which type of event has been processed 72 | pub(super) enum RecEvent { 73 | Event, 74 | Close, 75 | None, 76 | } 77 | 78 | #[derive(Debug, Clone, Copy)] 79 | /// Scroll speed 80 | pub struct ScrollSpeed { 81 | /// Speed of line-based scroll movement 82 | pub line: f32, 83 | /// Speed of Pixel scroll movement 84 | pub pixel: f32, 85 | } 86 | 87 | pub fn pad_rectangle(rect: Rectangle, padding: Padding) -> Rectangle { 88 | Rectangle { 89 | x: rect.x - padding.left, 90 | y: rect.y - padding.top, 91 | width: rect.width + padding.horizontal(), 92 | height: rect.height + padding.vertical(), 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/iced_aw_widgets/menu/menu_bar_style.rs: -------------------------------------------------------------------------------- 1 | //! Change the appearance of menu bars and their menus. 2 | use super::style_status::{Status, StyleFn}; 3 | use iced::{border::Radius, Background, Border, Color, Padding, Shadow, Theme, Vector}; 4 | 5 | /// The appearance of a menu bar and its menus. 6 | #[derive(Debug, Clone, Copy)] 7 | pub struct Style { 8 | /// The background of the menu bar. 9 | pub bar_background: Background, 10 | /// The border of the menu bar. 11 | pub bar_border: Border, 12 | /// The shadow of the menu bar. 13 | pub bar_shadow: Shadow, 14 | /// Expand the menu bar background 15 | pub bar_background_expand: Padding, 16 | 17 | /// The background of the menus. 18 | pub menu_background: Background, 19 | /// The border of the menus. 20 | pub menu_border: Border, 21 | /// The shadow of the menus 22 | pub menu_shadow: Shadow, 23 | /// Expand the menu background 24 | pub menu_background_expand: Padding, 25 | 26 | /// The backgraound of the path 27 | pub path: Background, 28 | /// The border of the path 29 | pub path_border: Border, 30 | } 31 | 32 | impl std::default::Default for Style { 33 | fn default() -> Self { 34 | Self { 35 | bar_background: Color::from([0.85; 3]).into(), 36 | bar_border: Border { 37 | radius: Radius::new(8.0), 38 | ..Default::default() 39 | }, 40 | bar_shadow: Shadow::default(), 41 | bar_background_expand: Padding::new(5.0), 42 | 43 | menu_background: Color::from([0.85; 3]).into(), 44 | menu_border: Border { 45 | radius: Radius::new(8.0), 46 | ..Default::default() 47 | }, 48 | menu_shadow: Shadow { 49 | color: Color::from([0.0, 0.0, 0.0, 0.5]), 50 | offset: Vector::ZERO, 51 | blur_radius: 10.0, 52 | }, 53 | menu_background_expand: Padding::new(5.0), 54 | path: Color::from([0.3; 3]).into(), 55 | path_border: Border { 56 | radius: Radius::new(6.0), 57 | ..Default::default() 58 | }, 59 | } 60 | } 61 | } 62 | 63 | /// The Catalog of a [`Menu`](crate::widgets::menu::Menu). 64 | pub trait Catalog { 65 | ///Style for the trait to use. 66 | type Class<'a>; 67 | 68 | /// The default class produced by the [`Catalog`]. 69 | fn default<'a>() -> Self::Class<'a>; 70 | 71 | /// The [`Style`] of a class with the given status. 72 | fn style(&self, class: &Self::Class<'_>, status: Status) -> Style; 73 | } 74 | 75 | impl Catalog for Theme { 76 | type Class<'a> = StyleFn<'a, Self, Style>; 77 | 78 | fn default<'a>() -> Self::Class<'a> { 79 | Box::new(primary) 80 | } 81 | 82 | fn style(&self, class: &Self::Class<'_>, status: Status) -> Style { 83 | class(self, status) 84 | } 85 | } 86 | 87 | /// The primary theme of a [`Menu`](crate::widgets::menu::Menu). 88 | #[must_use] 89 | pub fn primary(theme: &Theme, _status: Status) -> Style { 90 | let palette = theme.extended_palette(); 91 | 92 | Style { 93 | bar_background: palette.background.base.color.into(), 94 | menu_background: palette.background.base.color.into(), 95 | path: palette.primary.weak.color.into(), 96 | ..Default::default() 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/iced_aw_widgets/menu/mod.rs: -------------------------------------------------------------------------------- 1 | 2 | 3 | pub(crate) mod common; 4 | pub(crate) mod flex; 5 | pub(crate) mod menu_bar; 6 | pub(crate) mod menu_bar_style; 7 | pub(crate) mod menu_bar_overlay; 8 | pub(crate) mod menu_tree; 9 | pub(crate) mod quad; 10 | pub(crate) mod style; 11 | pub(crate) mod style_status; 12 | -------------------------------------------------------------------------------- /src/iced_aw_widgets/menu/quad.rs: -------------------------------------------------------------------------------- 1 | 2 | use iced::{ 3 | advanced::{ 4 | layout::{Limits, Node}, 5 | renderer, 6 | widget::Tree, 7 | Layout, Widget, 8 | }, border::Radius, mouse::Cursor, Background, Border, Color, Element, Length, Rectangle, Shadow, Size 9 | }; 10 | 11 | #[derive(Debug, Clone, Copy)] 12 | pub struct Quad { 13 | /// Width of the quad 14 | pub width: Length, 15 | /// Height of the quad 16 | pub height: Length, 17 | 18 | /// Methods for creating inner bounds 19 | pub inner_bounds: InnerBounds, 20 | 21 | /// Color of the quad 22 | pub quad_color: Background, 23 | /// Border of the quad 24 | pub quad_border: Border, 25 | /// Shadow of the quad 26 | pub quad_shadow: Shadow, 27 | 28 | /// Background color of the quad 29 | pub bg_color: Option, 30 | /// Border of the background 31 | pub bg_border: Border, 32 | /// Shadow of the background 33 | pub bg_shadow: Shadow, 34 | } 35 | impl Default for Quad { 36 | fn default() -> Self { 37 | Self { 38 | width: Length::Fill, 39 | height: Length::Fill, 40 | inner_bounds: InnerBounds::Ratio(0.5, 0.5), 41 | 42 | quad_color: Color::from([0.5; 3]).into(), 43 | quad_border: Border { 44 | color: Color::TRANSPARENT, 45 | width: 0.0, 46 | radius: Radius::default(), 47 | }, 48 | quad_shadow: Shadow::default(), 49 | 50 | bg_color: None, 51 | bg_border: Border { 52 | color: Color::TRANSPARENT, 53 | width: 0.0, 54 | radius: Radius::default(), 55 | }, 56 | bg_shadow: Shadow::default(), 57 | } 58 | } 59 | } 60 | 61 | impl Widget for Quad 62 | where 63 | Renderer: renderer::Renderer, 64 | { 65 | fn size(&self) -> Size { 66 | Size::new(self.width, self.height) 67 | } 68 | 69 | fn layout(&self, _tree: &mut Tree, _renderer: &Renderer, limits: &Limits) -> Node { 70 | let limits = limits.width(self.width).height(self.height); 71 | Node::new(limits.max()) 72 | } 73 | 74 | fn draw( 75 | &self, 76 | _state: &Tree, 77 | renderer: &mut Renderer, 78 | _theme: &Theme, 79 | _style: &renderer::Style, 80 | layout: Layout<'_>, 81 | _cursor: Cursor, 82 | _viewport: &Rectangle, 83 | ) { 84 | if let Some(b) = self.bg_color { 85 | renderer.fill_quad( 86 | renderer::Quad { 87 | bounds: layout.bounds(), 88 | border: self.bg_border, 89 | shadow: self.bg_shadow, 90 | }, 91 | b, 92 | ); 93 | } 94 | renderer.fill_quad( 95 | renderer::Quad { 96 | bounds: self.inner_bounds.get_bounds(layout.bounds()), 97 | border: self.quad_border, 98 | shadow: self.quad_shadow, 99 | }, 100 | self.quad_color, 101 | ); 102 | } 103 | } 104 | 105 | impl<'a, Message, Theme, Renderer> From for Element<'a, Message, Theme, Renderer> 106 | where 107 | Renderer: 'a + renderer::Renderer, 108 | Theme: 'a, 109 | { 110 | fn from(value: Quad) -> Self { 111 | Self::new(value) 112 | } 113 | } 114 | 115 | 116 | use iced::Padding; 117 | 118 | #[derive(Debug, Clone, Copy)] 119 | pub enum InnerBounds { 120 | /// Create inner bounds ratio to the outer bounds 121 | Ratio(f32, f32), 122 | /// Create inner bounds by padding the outer bounds 123 | Padding(Padding), 124 | /// Create square inner bounds 125 | Square(f32), 126 | 127 | } 128 | impl InnerBounds { 129 | /// Gets the inner bounds of the Set type. 130 | #[must_use] 131 | pub fn get_bounds(&self, outer_bounds: Rectangle) -> Rectangle { 132 | use InnerBounds::{Padding, Ratio, Square}; 133 | match self { 134 | Ratio(w, h) => { 135 | let width = w * outer_bounds.width; 136 | let height = h * outer_bounds.height; 137 | let x = outer_bounds.x + (outer_bounds.width - width) * 0.5; 138 | let y = outer_bounds.y + (outer_bounds.height - height) * 0.5; 139 | Rectangle { 140 | x, 141 | y, 142 | width, 143 | height, 144 | } 145 | } 146 | Padding(p) => { 147 | let x = outer_bounds.x + p.left; 148 | let y = outer_bounds.y + p.top; 149 | let width = outer_bounds.width - p.horizontal(); 150 | let height = outer_bounds.width - p.vertical(); 151 | Rectangle { 152 | x, 153 | y, 154 | width, 155 | height, 156 | } 157 | } 158 | Square(l) => { 159 | let width = *l; 160 | let height = *l; 161 | let x = outer_bounds.x + (outer_bounds.width - width) * 0.5; 162 | let y = outer_bounds.y + (outer_bounds.height - height) * 0.5; 163 | Rectangle { 164 | x, 165 | y, 166 | width, 167 | height, 168 | } 169 | } 170 | } 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /src/iced_aw_widgets/menu/style.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | //! Change the appearance of menu bars and their menus. 3 | use iced::{border::Radius, Background, Border, Color, Padding, Shadow, Theme, Vector}; 4 | 5 | /// The appearance of a menu bar and its menus. 6 | #[derive(Debug, Clone, Copy)] 7 | pub struct Appearance { 8 | /// The background of the menu bar. 9 | pub bar_background: Background, 10 | /// The border of the menu bar. 11 | pub bar_border: Border, 12 | /// The shadow of the menu bar. 13 | pub bar_shadow: Shadow, 14 | /// Expand the menu bar background 15 | pub bar_background_expand: Padding, 16 | 17 | /// The background of the menus. 18 | pub menu_background: Background, 19 | /// The border of the menus. 20 | pub menu_border: Border, 21 | /// The shadow of the menus 22 | pub menu_shadow: Shadow, 23 | /// Expand the menu background 24 | pub menu_background_expand: Padding, 25 | 26 | /// The backgraound of the path 27 | pub path: Background, 28 | /// The border of the path 29 | pub path_border: Border, 30 | } 31 | impl std::default::Default for Appearance { 32 | fn default() -> Self { 33 | Self { 34 | bar_background: Color::from([0.85; 3]).into(), 35 | bar_border: Border { 36 | radius: Radius::new(8.0), 37 | ..Default::default() 38 | }, 39 | bar_shadow: Shadow::default(), 40 | bar_background_expand: Padding::new(5.0), 41 | 42 | menu_background: Color::from([0.85; 3]).into(), 43 | menu_border: Border { 44 | radius: Radius::new(8.0), 45 | ..Default::default() 46 | }, 47 | menu_shadow: Shadow { 48 | color: Color::from([0.0, 0.0, 0.0, 0.5]), 49 | offset: Vector::ZERO, 50 | blur_radius: 10.0, 51 | }, 52 | menu_background_expand: Padding::new(5.0), 53 | path: Color::from([0.3; 3]).into(), 54 | path_border: Border { 55 | radius: Radius::new(6.0), 56 | ..Default::default() 57 | }, 58 | } 59 | } 60 | } 61 | 62 | /// The style sheet of a menu bar and its menus. 63 | pub trait StyleSheet { 64 | /// The supported style of the [`StyleSheet`]. 65 | type Style: Default; 66 | 67 | /// Produces the [`Appearance`] of a menu bar and its menus. 68 | fn appearance(&self, style: &Self::Style) -> Appearance; 69 | } 70 | 71 | /// The style of a menu bar and its menus 72 | #[derive(Default)] 73 | #[allow(missing_debug_implementations)] 74 | pub enum MenuBarStyle { 75 | /// The default style. 76 | #[default] 77 | Default, 78 | /// A [`Theme`] that uses a `Custom` palette. 79 | Custom(Box>), 80 | } 81 | 82 | impl Appearance + 'static> From for MenuBarStyle { 83 | fn from(f: F) -> Self { 84 | Self::Custom(Box::new(f)) 85 | } 86 | } 87 | 88 | impl Appearance> StyleSheet for F { 89 | type Style = Theme; 90 | 91 | fn appearance(&self, style: &Self::Style) -> Appearance { 92 | (self)(style) 93 | } 94 | } 95 | 96 | impl StyleSheet for Theme { 97 | type Style = MenuBarStyle; 98 | 99 | fn appearance(&self, style: &Self::Style) -> Appearance { 100 | let palette = self.extended_palette(); 101 | 102 | match style { 103 | MenuBarStyle::Default => Appearance { 104 | bar_background: palette.background.base.color.into(), 105 | menu_background: palette.background.base.color.into(), 106 | path: palette.primary.weak.color.into(), 107 | ..Default::default() 108 | }, 109 | MenuBarStyle::Custom(c) => c.appearance(self), 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/iced_aw_widgets/menu/style_status.rs: -------------------------------------------------------------------------------- 1 | //! Status Enum of an mouse Event. 2 | //! 3 | /// The Status of a widget event. 4 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 5 | pub enum Status { 6 | /// can be pressed. 7 | Active, 8 | /// can be pressed and it is being hovered. 9 | Hovered, 10 | /// is being pressed. 11 | Pressed, 12 | /// cannot be pressed. 13 | Disabled, 14 | /// is focused. 15 | Focused, 16 | /// is Selected. 17 | Selected, 18 | } 19 | 20 | /// The style function of widgets. 21 | pub type StyleFn<'a, Theme, Style> = Box Style + 'a>; 22 | -------------------------------------------------------------------------------- /src/iced_aw_widgets/mod.rs: -------------------------------------------------------------------------------- 1 | 2 | 3 | pub mod card; 4 | pub mod menu; 5 | -------------------------------------------------------------------------------- /src/iced_widgets/mod.rs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/ipg_widgets/ipg_column.rs: -------------------------------------------------------------------------------- 1 | //! ipg_column 2 | use iced::{Element, Length, Padding}; 3 | use iced::widget::Column; 4 | use pyo3::{pyclass, PyObject, Python}; 5 | 6 | use crate::app::Message; 7 | 8 | use super::helpers::{get_alignment, get_height, get_padding_f64, get_width, try_extract_boolean, try_extract_f64, try_extract_ipg_alignment, try_extract_vec_f64}; 9 | use super::ipg_enums::IpgAlignment; 10 | 11 | 12 | #[derive(Debug, Clone)] 13 | pub struct IpgColumn { 14 | pub id: usize, 15 | pub show: bool, 16 | pub spacing: f32, 17 | pub padding: Padding, 18 | pub width: Length, 19 | pub height: Length, 20 | pub max_width: f32, 21 | pub align: IpgAlignment, 22 | pub clip: bool, 23 | } 24 | 25 | impl IpgColumn { 26 | pub fn new( 27 | id: usize, 28 | show: bool, 29 | spacing: f32, 30 | padding: Padding, 31 | width: Length, 32 | height: Length, 33 | max_width: f32, 34 | align: IpgAlignment, 35 | clip: bool, 36 | ) -> Self { 37 | Self { 38 | id, 39 | show, 40 | spacing, 41 | padding, 42 | width, 43 | height, 44 | max_width, 45 | align, 46 | clip, 47 | } 48 | } 49 | } 50 | 51 | #[derive(Debug, Clone, PartialEq)] 52 | #[pyclass(eq, eq_int)] 53 | pub enum IpgColumnParam { 54 | Align, 55 | Clip, 56 | Padding, 57 | Width, 58 | WidthFill, 59 | Height, 60 | HeightFill, 61 | Spacing, 62 | } 63 | 64 | pub fn construct_column<'a>(col: &IpgColumn, content: Vec> ) -> Element<'a, Message> { 65 | 66 | let align_x = get_alignment(col.align.clone()); 67 | 68 | Column::with_children(content) 69 | .align_x(align_x) 70 | .height(col.height) 71 | .padding(col.padding) 72 | .spacing(col.spacing) 73 | .width(col.width) 74 | .clip(col.clip) 75 | .into() 76 | } 77 | 78 | 79 | pub fn column_item_update(col: &mut IpgColumn, 80 | item: &PyObject, 81 | value: &PyObject, 82 | ) 83 | { 84 | let update = try_extract_column_update(item); 85 | let name = "Column".to_string(); 86 | match update { 87 | IpgColumnParam::Align => { 88 | col.align = try_extract_ipg_alignment(value).unwrap(); 89 | }, 90 | IpgColumnParam::Clip => { 91 | col.clip = try_extract_boolean(value, name); 92 | }, 93 | IpgColumnParam::Padding => { 94 | col.padding = get_padding_f64(try_extract_vec_f64(value, name)); 95 | }, 96 | IpgColumnParam::Width => { 97 | let val = try_extract_f64(value, name); 98 | col.width = get_width(Some(val as f32), false); 99 | }, 100 | IpgColumnParam::WidthFill => { 101 | let val = try_extract_boolean(value, name); 102 | col.width = get_width(None, val); 103 | }, 104 | IpgColumnParam::Height => { 105 | let val = try_extract_f64(value, name); 106 | col.height = get_height(Some(val as f32), false); 107 | }, 108 | IpgColumnParam::HeightFill => { 109 | let val = try_extract_boolean(value, name); 110 | col.height = get_height(None, val); 111 | }, 112 | IpgColumnParam::Spacing => { 113 | col.spacing = try_extract_f64(value, name) as f32; 114 | }, 115 | } 116 | } 117 | 118 | pub fn try_extract_column_update(update_obj: &PyObject) -> IpgColumnParam { 119 | 120 | Python::with_gil(|py| { 121 | let res = update_obj.extract::(py); 122 | match res { 123 | Ok(update) => update, 124 | Err(_) => panic!("Column update extraction failed"), 125 | } 126 | }) 127 | } 128 | -------------------------------------------------------------------------------- /src/ipg_widgets/ipg_enums.rs: -------------------------------------------------------------------------------- 1 | //! ipg_enums 2 | #![allow(clippy::enum_variant_names)] 3 | use pyo3::pyclass; 4 | 5 | use super::ipg_button::{IpgButton, IpgButtonStyle}; 6 | use super::ipg_canvas::IpgCanvas; 7 | use super::ipg_card::{IpgCard, IpgCardStyle}; 8 | use super::ipg_checkbox::{IpgCheckBox, IpgCheckboxStyle}; 9 | use super::ipg_color_picker::{IpgColorPicker, IpgColorPickerStyle}; 10 | // use super::ipg_color_picker::IpgColorPicker; 11 | use super::ipg_container::{IpgContainer, IpgContainerStyle}; 12 | use super::ipg_column::IpgColumn; 13 | use super::ipg_date_picker::IpgDatePicker; 14 | use super::ipg_divider::{IpgDividerHorizontal, IpgDividerVertical, IpgDividerStyle}; 15 | use super::ipg_image::IpgImage; 16 | use super::ipg_menu::{IpgMenu, IpgMenuBarStyle, IpgMenuStyle}; 17 | // use super::ipg_modal::IpgModal; 18 | use super::ipg_mousearea::IpgMouseArea; 19 | use super::ipg_opaque::{IpgOpaque, IpgOpaqueStyle}; 20 | // use super::ipg_pane_grid::{IpgPaneGrid, IpgPane}; 21 | use super::ipg_pick_list::{IpgPickList, IpgPickListStyle}; 22 | use super::ipg_progress_bar::{IpgProgressBar, IpgProgressBarStyle}; 23 | use super::ipg_radio::{IpgRadio, IpgRadioStyle}; 24 | use super::ipg_row::IpgRow; 25 | use super::ipg_rule::{IpgRule, IpgRuleStyle}; 26 | use super::ipg_scrollable::{IpgScrollable, IpgScrollableStyle}; 27 | use super::ipg_selectable_text::IpgSelectableText; 28 | use super::ipg_separator::{IpgSeparator, IpgSeparatorStyle}; 29 | use super::ipg_slider::{IpgSlider, IpgSliderStyle}; 30 | use super::ipg_space::IpgSpace; 31 | use super::ipg_stack::IpgStack; 32 | use super::ipg_svg::IpgSvg; 33 | use super::ipg_table::{IpgTable, IpgTableStyle}; 34 | use super::ipg_text::IpgText; 35 | // use super::ipg_text_editor::IpgTextEditor; 36 | use super::ipg_text_input::{IpgTextInput, IpgTextInputStyle}; 37 | // use super::ipg_text_rich::IpgRichText; 38 | use super::ipg_timer::{IpgTimer, IpgTimerStyle}; 39 | use super::ipg_timer_canvas::{IpgCanvasTimer, IpgCanvasTimerStyle}; 40 | use super::ipg_toggle::{IpgToggler, IpgTogglerStyle}; 41 | use super::ipg_tool_tip::{IpgToolTip, IpgToolTipStyle}; 42 | use super::ipg_window::IpgWindow; 43 | 44 | 45 | #[derive(Debug, Clone)] 46 | pub enum IpgContainers { 47 | IpgCanvas(IpgCanvas), 48 | IpgColumn(IpgColumn), 49 | IpgContainer(IpgContainer), 50 | IpgMenu(IpgMenu), 51 | // IpgModal(IpgModal), 52 | IpgMouseArea(IpgMouseArea), 53 | IpgOpaque(IpgOpaque), 54 | IpgStack(IpgStack), 55 | IpgTable(IpgTable), 56 | // IpgPaneGrid(IpgPaneGrid), 57 | // IpgPane(IpgPane), 58 | IpgRow(IpgRow), 59 | IpgScrollable(IpgScrollable), 60 | IpgToolTip(IpgToolTip), 61 | IpgWindow(IpgWindow), 62 | } 63 | 64 | #[derive(Debug, Clone)] 65 | pub enum IpgWidgets { 66 | IpgButton(IpgButton), 67 | IpgButtonStyle(IpgButtonStyle), 68 | IpgCard(IpgCard), 69 | IpgCardStyle(IpgCardStyle), 70 | IpgCheckBox(IpgCheckBox), 71 | IpgCheckboxStyle(IpgCheckboxStyle), 72 | IpgColorPicker(IpgColorPicker), 73 | IpgColorPickerStyle(IpgColorPickerStyle), 74 | IpgContainerStyle(IpgContainerStyle), 75 | IpgDividerHorizontal(IpgDividerHorizontal), 76 | IpgDividerVertical(IpgDividerVertical), 77 | IpgDividerStyle(IpgDividerStyle), 78 | IpgDatePicker(IpgDatePicker), 79 | IpgImage(IpgImage), 80 | IpgMenuStyle(IpgMenuStyle), 81 | IpgMenuBarStyle(IpgMenuBarStyle), 82 | IpgOpaqueStyle(IpgOpaqueStyle), 83 | IpgPickList(IpgPickList), 84 | IpgPickListStyle(IpgPickListStyle), 85 | IpgProgressBar(IpgProgressBar), 86 | IpgProgressBarStyle(IpgProgressBarStyle), 87 | IpgRadio(IpgRadio), 88 | IpgRadioStyle(IpgRadioStyle), 89 | IpgRule(IpgRule), 90 | IpgRuleStyle(IpgRuleStyle), 91 | IpgScrollableStyle(IpgScrollableStyle), 92 | IpgSelectableText(IpgSelectableText), 93 | IpgSeparator(IpgSeparator), 94 | IpgSeparatorStyle(IpgSeparatorStyle), 95 | IpgSlider(IpgSlider), 96 | IpgSliderStyle(IpgSliderStyle), 97 | IpgSpace(IpgSpace), 98 | IpgSvg(IpgSvg), 99 | IpgTableStyle(IpgTableStyle), 100 | IpgText(IpgText), 101 | // IpgRichText(IpgRichText), 102 | // IpgTextEditor(IpgTextEditor), 103 | IpgTextInput(IpgTextInput), 104 | IpgTextInputStyle(IpgTextInputStyle), 105 | IpgTimer(IpgTimer), 106 | IpgTimerStyle(IpgTimerStyle), 107 | IpgCanvasTimer(IpgCanvasTimer), 108 | IpgCanvasTimerStyle(IpgCanvasTimerStyle), 109 | IpgToggler(IpgToggler), 110 | IpgTogglerStyle(IpgTogglerStyle), 111 | IpgToolTipStyle(IpgToolTipStyle), 112 | } 113 | 114 | 115 | #[derive(Debug, Clone, PartialEq)] 116 | #[pyclass(eq, eq_int)] 117 | pub enum IpgAlignment { 118 | Start, 119 | Center, 120 | End, 121 | } 122 | 123 | #[derive(Debug, Clone, PartialEq)] 124 | #[pyclass(eq, eq_int)] 125 | pub enum IpgHorizontalAlignment { 126 | Left, 127 | Center, 128 | Right, 129 | } 130 | 131 | #[derive(Debug, Clone, PartialEq)] 132 | #[pyclass(eq, eq_int)] 133 | pub enum IpgVerticalAlignment { 134 | Top, 135 | Center, 136 | Bottom, 137 | } 138 | -------------------------------------------------------------------------------- /src/ipg_widgets/ipg_opaque.rs: -------------------------------------------------------------------------------- 1 | //! ipg_opaque 2 | use iced::mouse::Interaction; 3 | use iced::{Color, Element, Length}; 4 | use iced::widget::{horizontal_space, mouse_area, opaque, Container}; 5 | use pyo3::{pyclass, PyObject, Python}; 6 | 7 | use crate::graphics::colors::get_color; 8 | use crate::{access_callbacks, access_user_data1, IpgState}; 9 | use crate::app::Message; 10 | 11 | use super::helpers::{get_horizontal_alignment, get_vertical_alignment, try_extract_boolean, try_extract_ipg_color, try_extract_rgba_color}; 12 | use super::ipg_container::{self, get_cont_style}; 13 | use super::ipg_enums::{IpgHorizontalAlignment, IpgVerticalAlignment, IpgWidgets}; 14 | 15 | 16 | #[derive(Debug, Clone)] 17 | pub struct IpgOpaque { 18 | pub id: usize, 19 | pub width: Length, 20 | pub height: Length, 21 | pub align_x: IpgHorizontalAlignment, 22 | pub align_y: IpgVerticalAlignment, 23 | pub include_mouse_area: bool, 24 | pub show: bool, 25 | pub style_id: Option, 26 | } 27 | 28 | impl IpgOpaque { 29 | pub fn new( 30 | id: usize, 31 | width: Length, 32 | height: Length, 33 | align_x: IpgHorizontalAlignment, 34 | align_y: IpgVerticalAlignment, 35 | include_mouse_area: bool, 36 | show: bool, 37 | style_id: Option, 38 | ) -> Self { 39 | Self { 40 | id, 41 | width, 42 | height, 43 | align_x, 44 | align_y, 45 | include_mouse_area, 46 | show, 47 | style_id, 48 | } 49 | } 50 | } 51 | 52 | #[derive(Debug, Clone)] 53 | pub struct IpgOpaqueStyle { 54 | pub id: usize, 55 | pub background_color: Option, 56 | } 57 | 58 | impl IpgOpaqueStyle { 59 | pub fn new( 60 | id: usize, 61 | background_color: Option, 62 | ) -> Self { 63 | Self { 64 | id, 65 | background_color, 66 | } 67 | } 68 | } 69 | 70 | pub fn construct_opaque<'a>(op: &'a IpgOpaque, 71 | mut content: Vec>, 72 | style_opt: Option<&'a IpgWidgets> ) 73 | -> Element<'a, Message> { 74 | 75 | if !op.show {return horizontal_space().into()} 76 | 77 | let new_content = content.remove(0); 78 | 79 | let align_h = get_horizontal_alignment(&op.align_x); 80 | let align_v = get_vertical_alignment(&op.align_y); 81 | let style = get_cont_style(style_opt); 82 | 83 | let cont: Element<'a, Message> = Container::new(new_content) 84 | .width(op.width) 85 | .height(op.height) 86 | .align_x(align_h) 87 | .align_y(align_v) 88 | .style(move|theme| 89 | ipg_container::get_styling(theme, 90 | style.clone(), 91 | )) 92 | .into(); 93 | 94 | if op.include_mouse_area { 95 | opaque(mouse_area(cont) 96 | .on_press(Message::OpaqueOnPress(op.id)) 97 | .interaction(Interaction::Pointer)) 98 | } else { 99 | opaque(cont) 100 | } 101 | 102 | 103 | } 104 | 105 | 106 | #[derive(Debug, Clone, PartialEq)] 107 | #[pyclass(eq, eq_int)] 108 | pub enum IpgOpaqueParam { 109 | Show, 110 | } 111 | 112 | pub fn opaque_item_update(op: &mut IpgOpaque, 113 | item: &PyObject, 114 | value: &PyObject,) { 115 | 116 | let update = try_extract_stack_update(item); 117 | let name = "OpaqueContainer".to_string(); 118 | match update { 119 | IpgOpaqueParam::Show => { 120 | op.show = try_extract_boolean(value, name); 121 | }, 122 | } 123 | } 124 | 125 | pub fn try_extract_stack_update(update_obj: &PyObject) -> IpgOpaqueParam { 126 | 127 | Python::with_gil(|py| { 128 | let res = update_obj.extract::(py); 129 | match res { 130 | Ok(update) => update, 131 | Err(_) => panic!("Opaque update extraction failed"), 132 | } 133 | }) 134 | } 135 | 136 | pub fn opaque_callback(_state: &mut IpgState, id: usize, event_name: String) { 137 | 138 | process_callback(id, event_name); 139 | } 140 | 141 | 142 | fn process_callback(id: usize, event_name: String) 143 | { 144 | let ud = access_user_data1(); 145 | let user_data_opt = ud.user_data.get(&id); 146 | 147 | let app_cbs = access_callbacks(); 148 | 149 | let callback_present = 150 | app_cbs.callbacks.get(&(id, event_name)); 151 | 152 | let callback = match callback_present { 153 | Some(cb) => cb, 154 | None => return, 155 | }; 156 | 157 | let cb = 158 | Python::with_gil(|py| { 159 | callback.clone_ref(py) 160 | }); 161 | 162 | drop(app_cbs); 163 | 164 | Python::with_gil(|py| { 165 | if user_data_opt.is_some() { 166 | let res = cb.call1(py, ( 167 | id, 168 | user_data_opt.unwrap() 169 | )); 170 | match res { 171 | Ok(_) => (), 172 | Err(er) => panic!("Opaque: Only 2 parameter (id, user_data) 173 | is required or a python error in this function. {er}"), 174 | } 175 | } else { 176 | let res = cb.call1(py, ( 177 | id, 178 | )); 179 | match res { 180 | Ok(_) => (), 181 | Err(er) => panic!("Opaque: Only 1 parameter (id) 182 | is required or a python error in this function. {er}"), 183 | } 184 | } 185 | 186 | 187 | }); 188 | 189 | drop(ud); 190 | 191 | } 192 | 193 | #[derive(Debug, Clone, PartialEq)] 194 | #[pyclass(eq, eq_int)] 195 | pub enum IpgOpaqueStyleParam { 196 | BackgroundIpgColor, 197 | BackgroundRgbaColor, 198 | } 199 | 200 | pub fn opaque_style_update_item(style: &mut IpgOpaqueStyle, 201 | item: &PyObject, 202 | value: &PyObject) 203 | { 204 | let update = try_extract_opaque_style_update(item); 205 | let name = "ContainerStyle".to_string(); 206 | match update { 207 | IpgOpaqueStyleParam::BackgroundIpgColor => { 208 | let color = try_extract_ipg_color(value, name); 209 | style.background_color = get_color(None, Some(color), 1.0, false); 210 | }, 211 | IpgOpaqueStyleParam::BackgroundRgbaColor => { 212 | style.background_color = Some(Color::from(try_extract_rgba_color(value, name))); 213 | }, 214 | } 215 | } 216 | 217 | pub fn try_extract_opaque_style_update(update_obj: &PyObject) -> IpgOpaqueStyleParam { 218 | 219 | Python::with_gil(|py| { 220 | let res = update_obj.extract::(py); 221 | match res { 222 | Ok(update) => update, 223 | Err(_) => panic!("Opaque style parameter update extraction failed"), 224 | } 225 | }) 226 | } 227 | 228 | -------------------------------------------------------------------------------- /src/ipg_widgets/ipg_row.rs: -------------------------------------------------------------------------------- 1 | //! ipg_row 2 | use iced::{Alignment, Padding, Length, Element}; 3 | use iced::widget::Row; 4 | use pyo3::{pyclass, PyObject, Python}; 5 | 6 | use crate::app::Message; 7 | 8 | use super::helpers::{get_height, get_padding_f64, get_width, 9 | try_extract_boolean, try_extract_f64, try_extract_ipg_alignment, 10 | try_extract_vec_f64}; 11 | use super::ipg_enums::IpgAlignment; 12 | 13 | 14 | #[derive(Debug, Clone)] 15 | pub struct IpgRow { 16 | pub id: usize, 17 | pub show: bool, 18 | 19 | pub spacing: f32, 20 | pub padding: Padding, 21 | pub width: Length, 22 | pub height: Length, 23 | pub align: IpgAlignment, 24 | pub clip: bool, 25 | } 26 | 27 | impl IpgRow { 28 | pub fn new( 29 | id: usize, 30 | show: bool, 31 | spacing: f32, 32 | padding: Padding, 33 | width: Length, 34 | height: Length, 35 | align: IpgAlignment, 36 | clip: bool, 37 | ) -> Self { 38 | Self { 39 | id, 40 | show, 41 | spacing, 42 | padding, 43 | width, 44 | height, 45 | align, 46 | clip 47 | } 48 | } 49 | } 50 | 51 | pub fn construct_row<'a>(row: &IpgRow, content: Vec>) -> Element<'a, Message> { 52 | 53 | let align = get_alignment(row.align.clone()); 54 | 55 | Row::with_children(content) 56 | .align_y(align) 57 | .height(row.height) 58 | .padding(row.padding) 59 | .spacing(row.spacing) 60 | .width(row.width) 61 | .clip(row.clip) 62 | .into() 63 | } 64 | 65 | 66 | fn get_alignment(align: IpgAlignment) -> Alignment { 67 | 68 | match align { 69 | IpgAlignment::Start => Alignment::Start, 70 | IpgAlignment::Center => Alignment::Center, 71 | IpgAlignment::End => Alignment::End, 72 | } 73 | } 74 | 75 | #[derive(Debug, Clone, PartialEq)] 76 | #[pyclass(eq, eq_int)] 77 | pub enum IpgRowParam { 78 | Align, 79 | Clip, 80 | Padding, 81 | Width, 82 | WidthFill, 83 | Height, 84 | HeightFill, 85 | Spacing, 86 | } 87 | 88 | pub fn row_item_update(col: &mut IpgRow, 89 | item: &PyObject, 90 | value: &PyObject, 91 | ) 92 | { 93 | let update = try_extract_row_update(item); 94 | let name = "Row".to_string(); 95 | match update { 96 | IpgRowParam::Align => { 97 | col.align = try_extract_ipg_alignment(value).unwrap(); 98 | }, 99 | IpgRowParam::Clip => { 100 | col.clip = try_extract_boolean(value, name); 101 | }, 102 | IpgRowParam::Padding => { 103 | col.padding = get_padding_f64(try_extract_vec_f64(value, name)); 104 | }, 105 | IpgRowParam::Width => { 106 | let val = try_extract_f64(value, name); 107 | col.width = get_width(Some(val as f32), false); 108 | }, 109 | IpgRowParam::WidthFill => { 110 | let val = try_extract_boolean(value, name); 111 | col.width = get_width(None, val); 112 | }, 113 | IpgRowParam::Height => { 114 | let val = try_extract_f64(value, name); 115 | col.height = get_height(Some(val as f32), false); 116 | }, 117 | IpgRowParam::HeightFill => { 118 | let val = try_extract_boolean(value, name); 119 | col.height = get_height(None, val); 120 | }, 121 | IpgRowParam::Spacing => { 122 | col.spacing = try_extract_f64(value, name) as f32; 123 | }, 124 | } 125 | } 126 | 127 | pub fn try_extract_row_update(update_obj: &PyObject) -> IpgRowParam { 128 | 129 | Python::with_gil(|py| { 130 | let res = update_obj.extract::(py); 131 | match res { 132 | Ok(update) => update, 133 | Err(_) => panic!("Row update extraction failed"), 134 | } 135 | }) 136 | } 137 | -------------------------------------------------------------------------------- /src/ipg_widgets/ipg_space.rs: -------------------------------------------------------------------------------- 1 | //! ipg_space 2 | use iced::{Element, Length}; 3 | use iced::widget::Space; 4 | use crate::app; 5 | 6 | 7 | #[derive(Debug, Clone)] 8 | pub struct IpgSpace { 9 | pub id: usize, 10 | pub parent_id: String, 11 | pub width: Length, 12 | pub height: Length, 13 | pub show: bool, 14 | } 15 | 16 | impl IpgSpace { 17 | pub fn new( 18 | id: usize, 19 | parent_id: String, 20 | width: Length, 21 | height: Length, 22 | show: bool) -> Self { 23 | Self { 24 | id, 25 | parent_id, 26 | width, 27 | height, 28 | show, 29 | } 30 | } 31 | } 32 | 33 | 34 | pub fn construct_space(sp: &IpgSpace) -> Option> { 35 | 36 | if sp.show { 37 | Some(Space::new(sp.width, sp.height).into()) 38 | } else { 39 | None 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/ipg_widgets/ipg_stack.rs: -------------------------------------------------------------------------------- 1 | //! ipg_stack 2 | use iced::{Element, Length}; 3 | use iced::widget::Stack; 4 | use pyo3::{pyclass, PyObject, Python}; 5 | 6 | use crate::app::Message; 7 | 8 | use super::helpers::{get_height, get_width, try_extract_boolean, try_extract_f32}; 9 | 10 | #[derive(Debug, Clone)] 11 | pub struct IpgStack { 12 | pub id: usize, 13 | pub width: Length, 14 | pub height: Length, 15 | pub hide_index: Option, 16 | pub show: bool, 17 | } 18 | 19 | impl IpgStack { 20 | pub fn new( 21 | id: usize, 22 | width: Length, 23 | height: Length, 24 | hide_index: Option, 25 | show: bool, 26 | ) -> Self { 27 | Self { 28 | id, 29 | width, 30 | height, 31 | hide_index, 32 | show, 33 | } 34 | } 35 | } 36 | 37 | 38 | pub fn construct_stack(stk: IpgStack, mut content: Vec> ) 39 | -> Element { 40 | 41 | content = if stk.hide_index.is_some() { 42 | let index = stk.hide_index.unwrap(); 43 | if index >= content.len() { 44 | panic!("Stack: The hide_index exceeds the number of stack containers."); 45 | } 46 | 47 | for i in (0..index).rev() { 48 | content.remove(i); 49 | } 50 | content 51 | } else { 52 | content 53 | }; 54 | 55 | Stack::with_children(content) 56 | .width(stk.width) 57 | .height(stk.height) 58 | .into() 59 | 60 | } 61 | 62 | #[derive(Debug, Clone, PartialEq)] 63 | #[pyclass(eq, eq_int)] 64 | pub enum IpgStackParam { 65 | Width, 66 | WidthFill, 67 | Height, 68 | HeightFill, 69 | Show, 70 | } 71 | 72 | pub fn stack_item_update(stk: &mut IpgStack, 73 | item: &PyObject, 74 | value: &PyObject,) { 75 | 76 | let update = try_extract_stack_update(item); 77 | let name = "Stack".to_string(); 78 | match update { 79 | IpgStackParam::Width => { 80 | let w = Some(try_extract_f32(value, name)); 81 | stk.width = get_width(w, false) 82 | }, 83 | IpgStackParam::WidthFill => { 84 | stk.width = get_width(None, try_extract_boolean(value, name)); 85 | }, 86 | IpgStackParam::Height => { 87 | let h = Some(try_extract_f32(value, name)); 88 | stk.height = get_height(h, false) 89 | }, 90 | IpgStackParam::HeightFill => { 91 | stk.height = get_height(None, try_extract_boolean(value, name)); 92 | }, 93 | IpgStackParam::Show => { 94 | stk.show = try_extract_boolean(value, name); 95 | }, 96 | } 97 | } 98 | 99 | pub fn try_extract_stack_update(update_obj: &PyObject) -> IpgStackParam { 100 | 101 | Python::with_gil(|py| { 102 | let res = update_obj.extract::(py); 103 | match res { 104 | Ok(update) => update, 105 | Err(_) => panic!("Stack update extraction failed"), 106 | } 107 | }) 108 | } 109 | -------------------------------------------------------------------------------- /src/ipg_widgets/ipg_text.rs: -------------------------------------------------------------------------------- 1 | //! ipg_text 2 | use iced::{Color, Element, Length}; 3 | use iced::widget::text::{LineHeight, Shaping, Style}; 4 | use iced::widget::Text; 5 | use crate::app::Message; 6 | use crate::graphics::colors::get_color; 7 | 8 | use pyo3::{pyclass, PyObject, Python}; 9 | 10 | use super::helpers::{get_height, get_horizontal_alignment, 11 | get_vertical_alignment, get_width, try_extract_boolean, 12 | try_extract_f64, try_extract_ipg_color, try_extract_string, 13 | try_extract_vec_f32}; 14 | use super::ipg_enums::{IpgHorizontalAlignment, IpgVerticalAlignment}; 15 | 16 | #[derive(Debug, Clone)] 17 | pub struct IpgText { 18 | pub id: usize, 19 | pub parent_id: String, 20 | pub content: String, 21 | pub size: f32, 22 | pub line_height: LineHeight, 23 | pub width: Length, 24 | pub height: Length, 25 | pub align_x: IpgHorizontalAlignment, 26 | pub align_y: IpgVerticalAlignment, 27 | // pub font: Font, 28 | pub shaping: Shaping, 29 | pub show: bool, 30 | pub style: Option, 31 | } 32 | 33 | impl IpgText { 34 | pub fn new( 35 | id: usize, 36 | parent_id: String, 37 | content: String, 38 | size: f32, 39 | line_height: LineHeight, 40 | width: Length, 41 | height: Length, 42 | align_x: IpgHorizontalAlignment, 43 | align_y: IpgVerticalAlignment, 44 | // font: Font, 45 | shaping: Shaping, 46 | show: bool, 47 | style: Option, 48 | ) -> Self { 49 | Self { 50 | id, 51 | parent_id, 52 | content, 53 | size, 54 | line_height, 55 | width, 56 | height, 57 | align_x, 58 | align_y, 59 | // font, 60 | shaping, 61 | show, 62 | style, 63 | } 64 | } 65 | } 66 | 67 | pub fn construct_text(text: &IpgText) 68 | -> Option> { 69 | 70 | if !text.show { 71 | return None 72 | } 73 | 74 | let hor_align = get_horizontal_alignment(&text.align_x); 75 | let vert_align = get_vertical_alignment(&text.align_y); 76 | 77 | Some(Text::new(text.content.clone() 78 | ) 79 | .size(text.size) 80 | .line_height(text.line_height) 81 | .width(text.width) 82 | .height(text.height) 83 | .align_x(hor_align) 84 | .align_y(vert_align) 85 | // .font() 86 | .shaping(text.shaping) 87 | .style(move|_theme|{ 88 | let mut style = Style::default(); 89 | style.color = text.style; 90 | style 91 | } 92 | ) 93 | .into() ) 94 | } 95 | 96 | 97 | #[derive(Debug, Clone, PartialEq)] 98 | #[pyclass(eq, eq_int)] 99 | pub enum IpgTextParam { 100 | Content, 101 | // Font, 102 | Height, 103 | HeightFill, 104 | AlignX, 105 | AlignY, 106 | LineHeight, 107 | Show, 108 | // Shaping, 109 | Size, 110 | TextColor, 111 | TextRgba, 112 | Width, 113 | WidthFill, 114 | } 115 | 116 | pub fn text_item_update(txt: &mut IpgText, 117 | item: &PyObject, 118 | value: &PyObject) { 119 | 120 | let update = try_extract_text_update(item); 121 | let name = "Text".to_string(); 122 | match update { 123 | IpgTextParam::Content => { 124 | txt.content = try_extract_string(value, name); 125 | }, 126 | IpgTextParam::Height => { 127 | let val = try_extract_f64(value, name); 128 | txt.height = get_height(Some(val as f32), false); 129 | }, 130 | IpgTextParam::HeightFill => { 131 | let val = try_extract_boolean(value, name); 132 | txt.height = get_height(None, val); 133 | }, 134 | IpgTextParam::AlignX => { 135 | txt.align_x = try_extract_hor_alignment(value); 136 | }, 137 | IpgTextParam::AlignY => { 138 | txt.align_y = try_extract_vert_alignment(value); 139 | }, 140 | IpgTextParam::LineHeight => { 141 | let val = try_extract_f64(value, name) as f32; 142 | txt.line_height = LineHeight::Relative(val); 143 | }, 144 | IpgTextParam::Show => { 145 | txt.show = try_extract_boolean(value, name); 146 | }, 147 | IpgTextParam::Size => { 148 | txt.size = try_extract_f64(value, name) as f32; 149 | }, 150 | IpgTextParam::TextColor => { 151 | let ipg_color = Some(try_extract_ipg_color(value, name)); 152 | txt.style = get_color(None, ipg_color, 1.0, false); 153 | }, 154 | IpgTextParam::TextRgba => { 155 | let v = try_extract_vec_f32(value, name); 156 | let color_rgba = Some([v[0], v[1], v[2], v[3]]); 157 | txt.style = get_color(color_rgba, None, 1.0, false); 158 | }, 159 | IpgTextParam::Width => { 160 | let val = try_extract_f64(value, name); 161 | txt.width = get_width(Some(val as f32), false); 162 | }, 163 | IpgTextParam::WidthFill => { 164 | let val = try_extract_boolean(value, name); 165 | txt.width = get_width(None, val); 166 | }, 167 | } 168 | } 169 | 170 | 171 | fn try_extract_text_update(update_obj: &PyObject) -> IpgTextParam { 172 | 173 | Python::with_gil(|py| { 174 | let res = update_obj.extract::(py); 175 | match res { 176 | Ok(update) => update, 177 | Err(_) => panic!("Text update extraction failed"), 178 | } 179 | }) 180 | } 181 | 182 | fn try_extract_hor_alignment(update_obj: &PyObject) -> IpgHorizontalAlignment { 183 | 184 | Python::with_gil(|py| { 185 | let res = update_obj.extract::(py); 186 | match res { 187 | Ok(update) => update, 188 | Err(_) => panic!("Text HorizontalAlignment extraction failed"), 189 | } 190 | }) 191 | } 192 | 193 | fn try_extract_vert_alignment(update_obj: &PyObject) -> IpgVerticalAlignment { 194 | 195 | Python::with_gil(|py| { 196 | let res = update_obj.extract::(py); 197 | match res { 198 | Ok(update) => update, 199 | Err(_) => panic!("Text VerticalAlignment extraction failed"), 200 | } 201 | }) 202 | } 203 | -------------------------------------------------------------------------------- /src/ipg_widgets/ipg_text_rich.rs: -------------------------------------------------------------------------------- 1 | //! ipg_text_rich 2 | use iced::advanced::text::Highlight; 3 | use iced::{Background, Border, Color, Element, Font, Padding, Pixels, Renderer, Theme}; 4 | use iced::widget::text::{LineHeight, Rich, Span}; 5 | use iced::widget::rich_text; 6 | use crate::app::Message; 7 | 8 | use pyo3::{pyclass, PyObject, Python}; 9 | 10 | use super::helpers::{get_height, 11 | get_width, try_extract_boolean, 12 | try_extract_f64, try_extract_ipg_color, try_extract_string, 13 | try_extract_vec_f32}; 14 | use super::ipg_enums::{IpgHorizontalAlignment, IpgVerticalAlignment}; 15 | 16 | #[derive(Debug, Clone)] 17 | pub struct IpgRichText { 18 | pub id: usize, 19 | pub parent_id: String, 20 | pub size: Option, 21 | pub line_height: Option, 22 | pub color: Option, 23 | pub highlight: Option, 24 | pub padding: Padding, 25 | pub underline: bool, 26 | pub strikethrough: bool, 27 | pub show: bool, 28 | pub style_id: Option, 29 | } 30 | 31 | impl IpgRichText { 32 | pub fn new( 33 | id: usize, 34 | parent_id: String, 35 | size: Option, 36 | line_height: Option, 37 | color: Option, 38 | highlight: Option, 39 | padding: Padding, 40 | underline: bool, 41 | strikethrough: bool, 42 | show: bool, 43 | style_id: Option, 44 | ) -> Self { 45 | Self { 46 | id, 47 | parent_id, 48 | size, 49 | line_height, 50 | color, 51 | highlight, 52 | padding, 53 | underline, 54 | strikethrough, 55 | show, 56 | style_id, 57 | } 58 | } 59 | } 60 | 61 | #[derive(Debug, Clone)] 62 | pub struct IpgSpan { 63 | pub id: usize, 64 | pub parent_id: String, 65 | pub text: String, 66 | pub size: Option, 67 | pub line_height: Option, 68 | pub color: Option, 69 | pub font: Option, 70 | pub highlight: Option, 71 | pub padding: Option, 72 | pub underline: bool, 73 | pub strikethrough: bool, 74 | pub show: bool, 75 | pub style_id: Option, 76 | } 77 | 78 | impl IpgSpan { 79 | pub fn new( 80 | id: usize, 81 | parent_id: String, 82 | text: String, 83 | size: Option, 84 | line_height: Option, 85 | color: Option, 86 | font: Option, 87 | highlight: Option, 88 | padding: Option, 89 | underline: bool, 90 | strikethrough: bool, 91 | show: bool, 92 | style_id: Option, 93 | ) -> Self { 94 | Self { 95 | id, 96 | parent_id, 97 | text, 98 | size, 99 | line_height, 100 | color, 101 | font, 102 | highlight, 103 | padding, 104 | underline, 105 | strikethrough, 106 | show, 107 | style_id, 108 | } 109 | } 110 | } 111 | 112 | #[derive(Debug, Clone, PartialEq)] 113 | pub struct IpgHighlight { 114 | pub background: Background, 115 | pub border: Border, 116 | } 117 | 118 | pub fn construct_rich_text<'a>(text: &IpgRichText) 119 | -> Option> { 120 | 121 | if !text.show { 122 | return None 123 | } 124 | 125 | let mut spans = vec![]; 126 | for sp in text.spans.iter() { 127 | let mut span = Span::new(sp.text.clone()); 128 | if sp.size.is_some() { 129 | span.size = Some(Pixels(sp.size.unwrap())); 130 | } 131 | if sp.line_height.is_some() { 132 | span.line_height = sp.line_height; 133 | } 134 | if sp.font.is_some() { 135 | span.font = sp.font; 136 | } 137 | if sp.color.is_some() { 138 | span.color = sp.color; 139 | } 140 | if sp.highlight.is_some() { 141 | span.highlight = get_highlight(sp.highlight.clone().unwrap()); 142 | } 143 | if sp.padding.is_some() { 144 | span.padding = sp.padding.unwrap(); 145 | } 146 | span.underline = sp.underline; 147 | span.strikethrough = sp.underline; 148 | 149 | spans.push(spans); 150 | } 151 | let rt: Rich<'a, Message, Theme, Renderer> = rich_text::(spans); 152 | Some(rt.into()) 153 | 154 | } 155 | 156 | fn get_highlight(hl: IpgHighlight) -> Option { 157 | Some(Highlight{ 158 | background: hl.background, 159 | border: hl.border }) 160 | } 161 | 162 | 163 | #[derive(Debug, Clone, PartialEq)] 164 | #[pyclass(eq, eq_int)] 165 | pub enum IpgTextParam { 166 | Content, 167 | Height, 168 | HeightFill, 169 | AlignX, 170 | AlignY, 171 | LineHeight, 172 | Show, 173 | Size, 174 | TextColor, 175 | TextRgba, 176 | Width, 177 | WidthFill, 178 | } 179 | 180 | pub fn text_item_update(txt: &mut IpgRichText, 181 | item: &PyObject, 182 | value: &PyObject) { 183 | 184 | let update = try_extract_text_update(item); 185 | let name = "Text".to_string(); 186 | match update { 187 | IpgTextParam::Content => todo!(), 188 | IpgTextParam::Height => todo!(), 189 | IpgTextParam::HeightFill => todo!(), 190 | IpgTextParam::AlignX => todo!(), 191 | IpgTextParam::AlignY => todo!(), 192 | IpgTextParam::LineHeight => todo!(), 193 | IpgTextParam::Show => todo!(), 194 | IpgTextParam::Size => todo!(), 195 | IpgTextParam::TextColor => todo!(), 196 | IpgTextParam::TextRgba => todo!(), 197 | IpgTextParam::Width => todo!(), 198 | IpgTextParam::WidthFill => todo!(), 199 | } 200 | } 201 | 202 | 203 | fn try_extract_text_update(update_obj: &PyObject) -> IpgTextParam { 204 | 205 | Python::with_gil(|py| { 206 | let res = update_obj.extract::(py); 207 | match res { 208 | Ok(update) => update, 209 | Err(_) => panic!("Text update extraction failed"), 210 | } 211 | }) 212 | } 213 | 214 | fn try_extract_hor_alignment(update_obj: &PyObject) -> IpgHorizontalAlignment { 215 | 216 | Python::with_gil(|py| { 217 | let res = update_obj.extract::(py); 218 | match res { 219 | Ok(update) => update, 220 | Err(_) => panic!("Text HorizontalAlignment extraction failed"), 221 | } 222 | }) 223 | } 224 | 225 | fn try_extract_vert_alignment(update_obj: &PyObject) -> IpgVerticalAlignment { 226 | 227 | Python::with_gil(|py| { 228 | let res = update_obj.extract::(py); 229 | match res { 230 | Ok(update) => update, 231 | Err(_) => panic!("Text VerticalAlignment extraction failed"), 232 | } 233 | }) 234 | } 235 | -------------------------------------------------------------------------------- /src/ipg_widgets/mod.rs: -------------------------------------------------------------------------------- 1 | //! mod.rs 2 | 3 | pub mod callbacks; 4 | pub mod divider; 5 | pub mod helpers; 6 | // pub mod table; 7 | pub mod ipg_button; 8 | pub mod ipg_canvas; 9 | pub mod ipg_card; 10 | pub mod ipg_checkbox; 11 | pub mod ipg_color_picker; 12 | pub mod ipg_column; 13 | pub mod ipg_container; 14 | pub mod ipg_date_picker; 15 | pub mod ipg_divider; 16 | pub mod ipg_enums; 17 | pub mod ipg_events; 18 | pub mod ipg_image; 19 | pub mod ipg_menu; 20 | // pub mod ipg_modal; 21 | pub mod ipg_mousearea; 22 | pub mod ipg_opaque; 23 | pub mod ipg_pick_list; 24 | pub mod ipg_progress_bar; 25 | pub mod ipg_radio; 26 | pub mod ipg_row; 27 | pub mod ipg_rule; 28 | pub mod ipg_scrollable; 29 | pub mod ipg_selectable_text; 30 | pub mod ipg_separator; 31 | pub mod ipg_slider; 32 | pub mod ipg_space; 33 | pub mod ipg_stack; 34 | pub mod ipg_svg; 35 | pub mod ipg_table; 36 | pub mod ipg_text; 37 | pub mod ipg_text_input; 38 | pub mod ipg_timer; 39 | pub mod ipg_timer_canvas; 40 | pub mod ipg_toggle; 41 | pub mod ipg_tool_tip; 42 | pub mod ipg_window; 43 | -------------------------------------------------------------------------------- /src/style/mod.rs: -------------------------------------------------------------------------------- 1 | 2 | pub mod styling; 3 | -------------------------------------------------------------------------------- /src/style/styling.rs: -------------------------------------------------------------------------------- 1 | //! styling 2 | use iced::Color; 3 | // use palette::{FromColor, Hsl}; 4 | use palette::rgb::Rgb; 5 | use palette::color_difference::Wcag21RelativeContrast; 6 | use pyo3::pyclass; 7 | 8 | 9 | #[derive(Debug, Clone, PartialEq)] 10 | #[pyclass(eq, eq_int)] 11 | pub enum IpgStyleStandard { 12 | Primary, 13 | Success, 14 | Danger, 15 | Text, 16 | } 17 | 18 | // pub fn get_theme_color(wnd_theme: &Theme) -> Color { 19 | // let palette = Theme::palette(wnd_theme); 20 | 21 | // palette.background 22 | // } 23 | 24 | // pub fn is_dark(color: Color) -> bool { 25 | // to_hsl(color).lightness < 0.6 26 | // } 27 | 28 | // pub fn darken(color: Color, amount: f32) -> Color { 29 | // let mut hsl = to_hsl(color); 30 | 31 | // hsl.lightness = if hsl.lightness - amount < 0.0 { 32 | // 0.0 33 | // } else { 34 | // hsl.lightness - amount 35 | // }; 36 | 37 | // from_hsl(hsl) 38 | // } 39 | 40 | // pub fn lighten(color: Color, amount: f32) -> Color { 41 | // let mut hsl = to_hsl(color); 42 | 43 | // hsl.lightness = if hsl.lightness + amount > 1.0 { 44 | // 1.0 45 | // } else { 46 | // hsl.lightness + amount 47 | // }; 48 | 49 | // from_hsl(hsl) 50 | // } 51 | 52 | // fn to_hsl(color: Color) -> Hsl { 53 | // Hsl::from_color(Rgb::from(color)) 54 | // } 55 | 56 | // fn from_hsl(hsl: Hsl) -> Color { 57 | // Rgb::from_color(hsl).into() 58 | // } 59 | 60 | pub fn readable(background: Color, text: Color) -> Color { 61 | if is_readable(background, text) { 62 | text 63 | } else { 64 | let white_contrast = relative_contrast(background, Color::WHITE); 65 | let black_contrast = relative_contrast(background, Color::BLACK); 66 | 67 | if white_contrast >= black_contrast { 68 | Color::WHITE 69 | } else { 70 | Color::BLACK 71 | } 72 | } 73 | } 74 | 75 | fn is_readable(a: Color, b: Color) -> bool { 76 | let a_srgb = Rgb::from(a); 77 | let b_srgb = Rgb::from(b); 78 | 79 | a_srgb.has_enhanced_contrast_text(b_srgb) 80 | } 81 | 82 | fn relative_contrast(a: Color, b: Color) -> f32 { 83 | let a_srgb = Rgb::from(a); 84 | let b_srgb = Rgb::from(b); 85 | 86 | a_srgb.relative_contrast(b_srgb) 87 | } 88 | --------------------------------------------------------------------------------