iced_aw/widget/
helpers.rs

1//! widget Helpers.
2//!
3//!
4#[cfg(feature = "selection_list")]
5use crate::style::{Status, StyleFn};
6#[allow(unused_imports)]
7use iced_core::{self, Color, Element, Padding, renderer};
8
9#[cfg(feature = "number_input")]
10use num_traits::bounds::Bounded;
11#[allow(unused_imports)]
12use std::{borrow::Cow, fmt::Display, hash::Hash, ops::RangeBounds};
13
14/// Creates a horizontal [`Wrap`] with the given children.
15///
16/// [`Wrap`]: crate::Wrap
17#[cfg(feature = "wrap")]
18#[macro_export]
19macro_rules! wrap_horizontal {
20    () => (
21        $crate::Wrap::new()
22    );
23    ($($x:expr),+ $(,)?) => (
24        $crate::Wrap::with_elements(vec![$($crate::Element::from($x)),+])
25    );
26}
27
28/// Creates a vertical [`Wrap`] with the given children.
29///
30/// [`Wrap`]: crate::Wrap
31#[cfg(feature = "wrap")]
32#[macro_export]
33macro_rules! wrap_vertical {
34    () => (
35        $crate::Wrap::new_vertical()
36    );
37    ($($x:expr),+ $(,)?) => (
38        $crate::Wrap::with_elements_vertical(vec![$($crate::Element::from($x)),+])
39    );
40}
41
42/// Creates a vec of menu [`Item`]s
43///
44/// [`Item`]: crate::menu::Item
45///
46/// Syntax:
47/// ```ignore
48/// menu_items!(
49///     (widget),
50///     (widget, menu),
51///     expression,
52///     ...
53/// )
54/// ```
55#[cfg(feature = "menu")]
56#[macro_export]
57macro_rules! menu_items {
58    // base case
59    (@process [$($output:expr,)*]) => {
60        vec![$($output),*]
61    };
62
63    // rule for (widget, menu)
64    (@process [$($output:expr,)*] ($i:expr, $m:expr) , $($rest:tt)*) => {
65        $crate::menu_items!(@process [$($output,)* $crate::menu::Item::with_menu($i, $m),] $($rest)*)
66    };
67    (@process [$($output:expr,)*] ($i:expr, $m:expr)) => {
68        $crate::menu_items!(@process [$($output,)* $crate::menu::Item::with_menu($i, $m),])
69    };
70
71    // rule for (widget)
72    (@process [$($output:expr,)*] ($i:expr) , $($rest:tt)*) => {
73        $crate::menu_items!(@process [$($output,)* $crate::menu::Item::new($i),] $($rest)*)
74    };
75    (@process [$($output:expr,)*] ($i:expr)) => {
76        $crate::menu_items!(@process [$($output,)* $crate::menu::Item::new($i),])
77    };
78
79    // rule for expr
80    (@process [$($output:expr,)*] $item:expr , $($rest:tt)*) => {
81        $crate::menu_items!(@process [$($output,)* $item,] $($rest)*)
82    };
83    (@process [$($output:expr,)*] $item:expr) => {
84        $crate::menu_items!(@process [$($output,)* $item,])
85    };
86
87    // entry point
88    ($($input:tt)*) => {
89        $crate::menu_items!(@process [] $($input)*)
90    };
91}
92
93/// Creates a [`Menu`] with the given items.
94///
95/// [`Menu`]: crate::menu::Menu
96///
97/// Syntax:
98/// ```ignore
99/// menu!(
100///     (widget),
101///     (widget, menu),
102///     expression,
103///     ...
104/// )
105/// ```
106#[cfg(feature = "menu")]
107#[macro_export]
108macro_rules! menu {
109    ($($x:tt)+) => {
110        $crate::menu::Menu::new( $crate::menu_items!( $($x)+ ) )
111    }
112}
113
114/// Creates a [`MenuBar`] with the given children.
115///
116/// [`MenuBar`]: crate::menu::MenuBar
117///
118/// Syntax:
119/// ```ignore
120/// menu_bar!(
121///     (widget),
122///     (widget, menu),
123///     expression,
124///     ...
125/// )
126/// ```
127#[cfg(feature = "menu")]
128#[macro_export]
129macro_rules! menu_bar {
130    ($($input:tt)+) => (
131        $crate::menu::MenuBar::new(menu_items!( $($input)+ ))
132    );
133}
134
135#[cfg(feature = "badge")]
136/// Shortcut helper to create a [`Badge`] Widget.
137///
138/// [`Badge`]: crate::Badge
139pub fn badge<'a, Message, Theme, Renderer>(
140    content: impl Into<Element<'a, Message, Theme, Renderer>>,
141) -> crate::Badge<'a, Message, Theme, Renderer>
142where
143    Renderer: renderer::Renderer,
144    Theme: crate::style::badge::Catalog,
145{
146    crate::Badge::new(content)
147}
148
149#[cfg(feature = "card")]
150/// Shortcut helper to create a [`Card`] Widget.
151///
152/// [`Card`]: crate::Card
153pub fn card<'a, Message, Theme, Renderer>(
154    head: impl Into<Element<'a, Message, Theme, Renderer>>,
155    body: impl Into<Element<'a, Message, Theme, Renderer>>,
156) -> crate::Card<'a, Message, Theme, Renderer>
157where
158    Renderer: renderer::Renderer,
159    Theme: crate::style::card::Catalog,
160{
161    crate::Card::new(head, body)
162}
163
164#[cfg(feature = "color_picker")]
165/// Shortcut helper to create a [`ColorPicker`] Widget.
166///
167/// [`ColorPicker`]: crate::ColorPicker
168pub fn color_picker<'a, Message, Theme, F>(
169    show_picker: bool,
170    color: Color,
171    underlay: impl Into<Element<'a, Message, Theme, iced_widget::Renderer>>,
172    on_cancel: Message,
173    on_submit: F,
174) -> crate::ColorPicker<'a, Message, Theme>
175where
176    Message: 'a + Clone,
177    Theme: 'a
178        + crate::style::color_picker::Catalog
179        + iced_widget::button::Catalog
180        + iced_widget::text::Catalog,
181    F: 'static + Fn(Color) -> Message,
182{
183    crate::ColorPicker::new(show_picker, color, underlay, on_cancel, on_submit)
184}
185
186#[cfg(feature = "date_picker")]
187/// Shortcut helper to create a [`DatePicker`] Widget.
188///
189/// [`DatePicker`]: crate::DatePicker
190pub fn date_picker<'a, Message, Theme, F>(
191    show_picker: bool,
192    date: impl Into<crate::core::date::Date>,
193    underlay: impl Into<Element<'a, Message, Theme, iced_widget::Renderer>>,
194    on_cancel: Message,
195    on_submit: F,
196) -> crate::DatePicker<'a, Message, Theme>
197where
198    Message: 'a + Clone,
199    Theme: 'a
200        + crate::style::date_picker::Catalog
201        + iced_widget::button::Catalog
202        + iced_widget::text::Catalog
203        + iced_widget::container::Catalog,
204    F: 'static + Fn(crate::core::date::Date) -> Message,
205{
206    crate::DatePicker::new(show_picker, date, underlay, on_cancel, on_submit)
207}
208
209#[cfg(feature = "time_picker")]
210/// Shortcut helper to create a [`DatePicker`] Widget.
211///
212/// [`DatePicker`]: crate::DatePicker
213pub fn time_picker<'a, Message, Theme, U, F>(
214    show_picker: bool,
215    time: impl Into<crate::core::time::Time>,
216    underlay: U,
217    on_cancel: Message,
218    on_submit: F,
219) -> crate::TimePicker<'a, Message, Theme>
220where
221    Message: 'a + Clone,
222    Theme: 'a
223        + crate::style::time_picker::Catalog
224        + iced_widget::button::Catalog
225        + iced_widget::text::Catalog,
226    U: Into<Element<'a, Message, Theme, iced_widget::Renderer>>,
227    F: 'static + Fn(crate::core::time::Time) -> Message,
228{
229    crate::TimePicker::new(show_picker, time, underlay, on_cancel, on_submit)
230}
231
232#[cfg(feature = "wrap")]
233/// Shortcut helper to create a horizontal [`Wrap`] Widget.
234///
235/// [`Wrap`]: crate::Wrap
236#[must_use]
237pub fn wrap_horizontal<Message, Theme, Renderer>(
238    children: Vec<Element<Message, Theme, Renderer>>,
239) -> crate::Wrap<Message, crate::direction::Horizontal, Theme, Renderer>
240where
241    Renderer: renderer::Renderer,
242{
243    crate::Wrap::with_elements(children)
244}
245
246#[cfg(feature = "wrap")]
247/// Shortcut helper to create a vertical [`Wrap`] Widget.
248///
249/// [`Wrap`]: crate::Wrap
250#[must_use]
251pub fn wrap_vertical<Message, Theme, Renderer>(
252    children: Vec<Element<Message, Theme, Renderer>>,
253) -> crate::Wrap<Message, crate::direction::Vertical, Theme, Renderer>
254where
255    Renderer: renderer::Renderer,
256{
257    crate::Wrap::with_elements_vertical(children)
258}
259
260#[cfg(feature = "number_input")]
261/// Shortcut helper to create a [`NumberInput`] Widget.
262///
263/// [`NumberInput`]: crate::NumberInput
264#[must_use]
265pub fn number_input<'a, T, Message, Theme, Renderer, F>(
266    value: &T,
267    bounds: impl RangeBounds<T>,
268    on_change: F,
269) -> crate::NumberInput<'a, T, Message, Theme, Renderer>
270where
271    Message: Clone + 'a,
272    Renderer: iced_core::text::Renderer<Font = iced_core::Font>,
273    Theme: crate::style::number_input::ExtendedCatalog,
274    F: 'static + Fn(T) -> Message + Copy,
275    T: 'static
276        + num_traits::Num
277        + num_traits::NumAssignOps
278        + PartialOrd
279        + std::fmt::Display
280        + std::str::FromStr
281        + Copy
282        + Bounded,
283{
284    crate::NumberInput::new(value, bounds, on_change)
285}
286
287#[cfg(feature = "typed_input")]
288/// Shortcut helper to create a [`TypedInput`] Widget.
289///
290/// [`TypedInput`]: crate::TypedInput
291#[must_use]
292pub fn typed_input<'a, T, Message, Theme, Renderer, F>(
293    value: &T,
294    on_change: F,
295) -> crate::TypedInput<'a, T, Message, Theme, Renderer>
296where
297    Message: Clone,
298    Renderer: iced_core::text::Renderer<Font = iced_core::Font>,
299    Theme: iced_widget::text_input::Catalog,
300    F: 'static + Fn(T) -> Message + Copy,
301    T: 'static + std::fmt::Display + std::str::FromStr + Clone,
302{
303    crate::TypedInput::new("", value).on_input(on_change)
304}
305
306#[cfg(feature = "selection_list")]
307/// Shortcut helper to create a [`SelectionList`] Widget.
308///
309/// [`SelectionList`]: crate::SelectionList
310#[must_use]
311pub fn selection_list_with<'a, T, Message, Theme, Renderer>(
312    options: &'a [T],
313    on_selected: impl Fn(usize, T) -> Message + 'static,
314    text_size: f32,
315    padding: impl Into<Padding>,
316    style: impl Fn(&Theme, Status) -> crate::style::selection_list::Style + 'a + Clone,
317    selected: Option<usize>,
318    font: iced_core::Font,
319) -> crate::SelectionList<'a, T, Message, Theme, Renderer>
320where
321    Message: 'a + Clone,
322    Renderer: 'a + renderer::Renderer + iced_core::text::Renderer<Font = iced_core::Font>,
323    Theme: 'a
324        + crate::style::selection_list::Catalog
325        + iced_widget::container::Catalog
326        + iced_widget::scrollable::Catalog,
327    T: Clone + Display + Eq + Hash,
328    [T]: ToOwned<Owned = Vec<T>>,
329    <Theme as crate::style::selection_list::Catalog>::Class<'a>:
330        From<StyleFn<'a, Theme, crate::style::selection_list::Style>>,
331{
332    crate::SelectionList::new_with(
333        options,
334        on_selected,
335        text_size,
336        padding,
337        style,
338        selected,
339        font,
340    )
341}
342
343#[cfg(feature = "selection_list")]
344/// Shortcut helper to create a [`SelectionList`] Widget.
345///
346/// [`SelectionList`]: crate::SelectionList
347#[must_use]
348pub fn selection_list<'a, T, Message, Theme, Renderer>(
349    options: &'a [T],
350    on_selected: impl Fn(usize, T) -> Message + 'static,
351) -> crate::SelectionList<'a, T, Message, Theme, Renderer>
352where
353    Message: 'a + Clone,
354    Renderer: 'a + renderer::Renderer + iced_core::text::Renderer<Font = iced_core::Font>,
355    Theme: 'a
356        + crate::style::selection_list::Catalog
357        + iced_widget::container::Catalog
358        + iced_widget::scrollable::Catalog,
359    T: Clone + Display + Eq + Hash,
360    [T]: ToOwned<Owned = Vec<T>>,
361{
362    crate::SelectionList::new(options, on_selected)
363}