iced_aw Documentation

repository·main·Indexed 20 days ago

https://github.com/iced-rs/iced_aw

A collection of additional widgets for the Iced GUI library, providing advanced UI components such as ColorPicker, DatePicker, MenuBar, Card, and Sidebar. Widgets are available via feature gates to allow for cherry-picking, and versions must match the corresponding iced version for compatibility.

Tokens
12.8K
Snippets
35
Records
62
Agent score
69%

What's inside iced_aw

  1. How the MenuBar widget and its tree structure work

    main

    The MenuBar widget manages a tree of menus and items. It acts as the 'root menu' and owns the global state. The hierarchy consists of:

    • MenuBar: The entry point widget added to your UI.
    • Menu: A container for items, used to build the tree.
    • Item: A single entry in a menu. An item can contain a widget and optionally a child Menu.

    Note that Item and Menu are helper structures used to build the tree and cannot function independently of a MenuBar.

    MenuBar {
        roots: Vec<Item>,
    }
    
    Item {
        widget,
        menu: Option<Menu>,
    }
    
    Menu {
        items: Vec<Item>,
    }
  2. Avoid complex nested overlays in MenuBar

    main

    The MenuBar does not have special handling for complex, interactive overlays (like a PickList opened from a menu item). This can lead to:

    1. Multiple overlays: If a cursor moves off a nested overlay, the underlying menu may not realize the overlay is gone and remain visible.
    2. Stuck menus: If a nested overlay captures events, the MenuBar might receive Cursor::Unavailable and fail to distinguish between a legitimate overlay and the cursor leaving the window, preventing the menu from closing correctly.

    Recommendation: If you need nested overlay functionality, replicate it using menus themselves rather than using widgets like PickList inside a menu.

  3. Understand Safe Bounds and closing logic

    main

    The safe bounds is an invisible margin around the background bounds. It prevents accidental closing when the cursor moves from the menu background into this area.

    Close Logic Summary

    • If the cursor is over background bounds: Update items.
    • If the cursor is over parent bounds: Parent menu processes the event.
    • If the cursor is over ancestor background bounds: Close the menu.
    • If the cursor is over safe bounds: Keep the menu open.
    • Otherwise: Close the menu.

    Implementing 'Close on Click' behavior

    Closing behavior follows an inheritance pattern: Global <- MenuBar/Menu <- Item. An item's setting overrides its parent, which overrides the global setting.

    To make menus stay open until a user explicitly clicks an item or the background (rather than closing when the cursor leaves the bounds), set the safe_bounds_margin to f32::MAX and configure click behavior:

    let mb = menu_bar!(
        ...
    )
    .close_on_item_click_global(true)
    .close_on_background_click_global(true)
    .safe_bounds_margin(f32::MAX);

    Warning: If you use this pattern, ensure at least one item or the background is set to close on click, otherwise menus may never close.

  4. Install iced_aw

    main

    To use iced_aw, add it to your Cargo.toml as a dependency. Because widgets are hidden behind feature gates to allow for cherry-picking, you should either enable specific widget features or use the full feature to enable everything.

    Note that iced_aw versions must match your iced version according to the compatibility table.

    [dependencies]
    iced = "0.14.0"
    iced_aw = { version = "0.14.0", features = ["full"] }
  5. Enable debug logging for MenuBar

    main

    To debug MenuBar issues, enable the debug_log feature in your Cargo.toml:

    iced_aw = {version = "0.14", features = ["menu", "debug_log"]}

    Then, initialize a logger (like env_logger) in your main function:

    fn main() {
        env_logger::init();
        // ...
    }

    Run your application with the RUST_LOG environment variable set to menu=debug:

    RUST_LOG=menu=debug cargo run

    To run the built-in menu example with debugging enabled:

    RUST_LOG=menu=debug cargo run --example menu --features "debug_log"
  6. Build menus using macros

    main

    To avoid the boilerplate of manually wrapping every widget in Item::new() or Item::with_menu(), use the provided macros:

    • menu_items!: Returns a Vec<Item>. This is the core macro.
    • menu!: A wrapper around menu_items! that returns a Menu.
    • menu_bar!: A wrapper around menu_items! that returns a MenuBar.
    menu_items!(
        (widget),       // creates an Item::new(widget)
        (widget, menu), // creates an Item::with_menu(widget, menu)
        expression,     // any expression that returns an Item
    )

    You can use helper functions or closures within the macro to apply custom settings to items:

    let hold_item = |widget| Item::new(widget).close_on_click(false);
    
    menu_items!(
        hold_item(widget),
        // ...
    )

    Note: If you encounter a recursion limit reached error, check for syntax errors like double commas ,, or unexpected symbols.

  7. Available widgets in iced_aw

    main

    The iced_aw crate provides a collection of additional widgets for the Iced GUI library. Most widgets are available as feature-gated modules. To use a specific widget, you must enable its corresponding feature in your Cargo.toml.

    Available widgets include:

    • Badge (via badge feature)
    • Card (via card feature)
    • ColorPicker (via color_picker feature)
    • DatePicker (via date_picker feature)
    • TabBar and Tabs (via tab_bar and tabs features)
    • TimePicker (via time_picker feature)
    • Wrap (via wrap feature)
    • NumberInput (via number_input feature)
    • TypedInput (via typed_input feature)
    • SelectionList (via selection_list feature)
    • Menu and MenuBar (via menu feature)
    • Quad (via quad feature)
    • Spinner (via spinner feature)
    • SlideBar (via slide_bar feature)
    • ContextMenu (via context_menu feature)
    • DropDown (via drop_down feature)
    • sidebar (via sidebar feature)
  8. How Sidebar and SidebarWithContent differ

    main

    The iced_aw library provides two ways to implement a sidebar layout:

    1. Sidebar: A standalone widget used to display tabs for selecting content. It is typically placed to the side of your main content. You are responsible for managing the logic that determines which content is displayed based on the selected tab.
    2. SidebarWithContent: A single, unified widget that contains both the sidebar and the content area. It manages the display of the content automatically based on the selected tab.
  9. Configure Sidebar tab positioning

    main

    The Position enum controls the layout of elements within a tab when using TabLabel::IconText or when a close icon is present:

    • Position::Start: The icon (or close icon) is placed at the beginning of the tab.
    • Position::End: The icon (or close icon) is placed at the end of the tab.

    Use Sidebar::set_position(position) to set the icon/text order and Sidebar::set_close_position(position) to set the close icon's position.

  10. Set icon position in TabLabel::IconText

    main

    When using TabLabel::IconText, you can control the layout of the icon relative to the text using the Position enum via the .set_position() method.

    Available positions:

    • Position::Left (Default): Icon is to the left of the text.
    • Position::Right: Icon is to the right of the text.
    • Position::Top: Icon is above the text.
    • Position::Bottom: Icon is below the text.
    use iced_aw::Position;
    
    let tab_bar = TabBar::new(Message::TabSelected)
        .push(TabId::One, TabLabel::IconText('⭐', "Star".into()))
        .set_position(Position::Top);
  11. How NumberInput handles bounds and validity

    main

    The NumberInput widget enforces constraints based on the provided range:

    • Min/Max: The widget tracks the minimum and maximum values. If using an exclusive range like 10..90, the effective maximum is 89 (the last valid step within the range).
    • Disabled State: The widget is considered disabled() if the minimum and maximum bounds are equal (e.g., 50..=50), as there is no room for change.
    • Button Availability: The increment and decrement buttons automatically enable or disable based on whether the current value can move further within the bounds (can_increase() and can_decrease()).
    • Validation: The widget ensures that pasted or typed values are valid within the defined range before updating the internal state.
  12. Time data types

    main

    The TimePicker uses the Time type from iced_aw::core::time.

    Common ways to create Time instances:

    • Time::now_hm(use_24h: bool): Current hour and minute.
    • Time::now_hms(use_24h: bool): Current hour, minute, and second.

    Variants of Time:

    • Time::Hm { hour, minute, period }: Hour and minute with an AM/PM Period or H24.
    • Time::Hms { hour, minute, second, period }: Hour, minute, and second with a Period.