iced_widget/
helpers.rs

1//! Helper functions to create pure widgets.
2use crate::button::{self, Button};
3use crate::checkbox::{self, Checkbox};
4use crate::combo_box::{self, ComboBox};
5use crate::container::{self, Container};
6use crate::core;
7use crate::core::theme;
8use crate::core::widget::operation::{self, Operation};
9use crate::core::window;
10use crate::core::{Element, Length, Size, Widget};
11use crate::float::{self, Float};
12use crate::keyed;
13use crate::overlay;
14use crate::pane_grid::{self, PaneGrid};
15use crate::pick_list::{self, PickList};
16use crate::progress_bar::{self, ProgressBar};
17use crate::radio::{self, Radio};
18use crate::scrollable::{self, Scrollable};
19use crate::slider::{self, Slider};
20use crate::text::{self, Text};
21use crate::text_editor::{self, TextEditor};
22use crate::text_input::{self, TextInput};
23use crate::toggler::{self, Toggler};
24use crate::tooltip::{self, Tooltip};
25use crate::vertical_slider::{self, VerticalSlider};
26use crate::{Column, Grid, MouseArea, Pin, Responsive, Row, Sensor, Space, Stack, Themer};
27
28use std::borrow::Borrow;
29use std::ops::RangeInclusive;
30
31pub use crate::table::table;
32
33/// Creates a [`Column`] with the given children.
34///
35/// Columns distribute their children vertically.
36///
37/// # Example
38/// ```no_run
39/// # mod iced { pub mod widget { pub use iced_widget::*; } }
40/// # pub type State = ();
41/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
42/// use iced::widget::{button, column};
43///
44/// #[derive(Debug, Clone)]
45/// enum Message {
46///     // ...
47/// }
48///
49/// fn view(state: &State) -> Element<'_, Message> {
50///     column![
51///         "I am on top!",
52///         button("I am in the center!"),
53///         "I am below.",
54///     ].into()
55/// }
56/// ```
57#[macro_export]
58macro_rules! column {
59    () => (
60        $crate::Column::new()
61    );
62    ($($x:expr),+ $(,)?) => (
63        $crate::Column::with_children([$($crate::core::Element::from($x)),+])
64    );
65}
66
67/// Creates a [`Row`] with the given children.
68///
69/// Rows distribute their children horizontally.
70///
71/// # Example
72/// ```no_run
73/// # mod iced { pub mod widget { pub use iced_widget::*; } }
74/// # pub type State = ();
75/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
76/// use iced::widget::{button, row};
77///
78/// #[derive(Debug, Clone)]
79/// enum Message {
80///     // ...
81/// }
82///
83/// fn view(state: &State) -> Element<'_, Message> {
84///     row![
85///         "I am to the left!",
86///         button("I am in the middle!"),
87///         "I am to the right!",
88///     ].into()
89/// }
90/// ```
91#[macro_export]
92macro_rules! row {
93    () => (
94        $crate::Row::new()
95    );
96    ($($x:expr),+ $(,)?) => (
97        $crate::Row::with_children([$($crate::core::Element::from($x)),+])
98    );
99}
100
101/// Creates a [`Stack`] with the given children.
102///
103/// [`Stack`]: crate::Stack
104#[macro_export]
105macro_rules! stack {
106    () => (
107        $crate::Stack::new()
108    );
109    ($($x:expr),+ $(,)?) => (
110        $crate::Stack::with_children([$($crate::core::Element::from($x)),+])
111    );
112}
113
114/// Creates a [`Grid`] with the given children.
115///
116/// [`Grid`]: crate::Grid
117#[macro_export]
118macro_rules! grid {
119    () => (
120        $crate::Grid::new()
121    );
122    ($($x:expr),+ $(,)?) => (
123        $crate::Grid::with_children([$($crate::core::Element::from($x)),+])
124    );
125}
126
127/// Creates a new [`Text`] widget with the provided content.
128///
129/// [`Text`]: core::widget::Text
130///
131/// This macro uses the same syntax as [`format!`], but creates a new [`Text`] widget instead.
132///
133/// See [the formatting documentation in `std::fmt`](std::fmt)
134/// for details of the macro argument syntax.
135///
136/// # Examples
137///
138/// ```no_run
139/// # mod iced {
140/// #     pub mod widget {
141/// #         macro_rules! text {
142/// #           ($($arg:tt)*) => {unimplemented!()}
143/// #         }
144/// #         pub(crate) use text;
145/// #     }
146/// # }
147/// # pub type State = ();
148/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::core::Theme, ()>;
149/// use iced::widget::text;
150///
151/// enum Message {
152///     // ...
153/// }
154///
155/// fn view(_state: &State) -> Element<Message> {
156///     let simple = text!("Hello, world!");
157///
158///     let keyword = text!("Hello, {}", "world!");
159///
160///     let planet = "Earth";
161///     let local_variable = text!("Hello, {planet}!");
162///     // ...
163///     # unimplemented!()
164/// }
165/// ```
166#[macro_export]
167macro_rules! text {
168    ($($arg:tt)*) => {
169        $crate::Text::new(format!($($arg)*))
170    };
171}
172
173/// Creates some [`Rich`] text with the given spans.
174///
175/// [`Rich`]: text::Rich
176///
177/// # Example
178/// ```no_run
179/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::core::*; }
180/// # pub type State = ();
181/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
182/// use iced::font;
183/// use iced::widget::{rich_text, span};
184/// use iced::{color, never, Font};
185///
186/// #[derive(Debug, Clone)]
187/// enum Message {
188///     // ...
189/// }
190///
191/// fn view(state: &State) -> Element<'_, Message> {
192///     rich_text![
193///         span("I am red!").color(color!(0xff0000)),
194///         span(" "),
195///         span("And I am bold!").font(Font { weight: font::Weight::Bold, ..Font::default() }),
196///     ]
197///     .on_link_click(never)
198///     .size(20)
199///     .into()
200/// }
201/// ```
202#[macro_export]
203macro_rules! rich_text {
204    () => (
205        $crate::text::Rich::new()
206    );
207    ($($x:expr),+ $(,)?) => (
208        $crate::text::Rich::from_iter([$($crate::text::Span::from($x)),+])
209    );
210}
211
212/// Creates a new [`Container`] with the provided content.
213///
214/// Containers let you align a widget inside their boundaries.
215///
216/// # Example
217/// ```no_run
218/// # mod iced { pub mod widget { pub use iced_widget::*; } }
219/// # pub type State = ();
220/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
221/// use iced::widget::container;
222///
223/// enum Message {
224///     // ...
225/// }
226///
227/// fn view(state: &State) -> Element<'_, Message> {
228///     container("This text is centered inside a rounded box!")
229///         .padding(10)
230///         .center(800)
231///         .style(container::rounded_box)
232///         .into()
233/// }
234/// ```
235pub fn container<'a, Message, Theme, Renderer>(
236    content: impl Into<Element<'a, Message, Theme, Renderer>>,
237) -> Container<'a, Message, Theme, Renderer>
238where
239    Theme: container::Catalog + 'a,
240    Renderer: core::Renderer,
241{
242    Container::new(content)
243}
244
245/// Creates a new [`Container`] that fills all the available space
246/// and centers its contents inside.
247///
248/// This is equivalent to:
249/// ```rust,no_run
250/// # use iced_widget::core::Length::Fill;
251/// # use iced_widget::Container;
252/// # fn container<A>(x: A) -> Container<'static, ()> { unreachable!() }
253/// let center = container("Center!").center(Fill);
254/// ```
255///
256/// [`Container`]: crate::Container
257pub fn center<'a, Message, Theme, Renderer>(
258    content: impl Into<Element<'a, Message, Theme, Renderer>>,
259) -> Container<'a, Message, Theme, Renderer>
260where
261    Theme: container::Catalog + 'a,
262    Renderer: core::Renderer,
263{
264    container(content).center(Length::Fill)
265}
266
267/// Creates a new [`Container`] that fills all the available space
268/// horizontally and centers its contents inside.
269///
270/// This is equivalent to:
271/// ```rust,no_run
272/// # use iced_widget::core::Length::Fill;
273/// # use iced_widget::Container;
274/// # fn container<A>(x: A) -> Container<'static, ()> { unreachable!() }
275/// let center_x = container("Horizontal Center!").center_x(Fill);
276/// ```
277///
278/// [`Container`]: crate::Container
279pub fn center_x<'a, Message, Theme, Renderer>(
280    content: impl Into<Element<'a, Message, Theme, Renderer>>,
281) -> Container<'a, Message, Theme, Renderer>
282where
283    Theme: container::Catalog + 'a,
284    Renderer: core::Renderer,
285{
286    container(content).center_x(Length::Fill)
287}
288
289/// Creates a new [`Container`] that fills all the available space
290/// vertically and centers its contents inside.
291///
292/// This is equivalent to:
293/// ```rust,no_run
294/// # use iced_widget::core::Length::Fill;
295/// # use iced_widget::Container;
296/// # fn container<A>(x: A) -> Container<'static, ()> { unreachable!() }
297/// let center_y = container("Vertical Center!").center_y(Fill);
298/// ```
299///
300/// [`Container`]: crate::Container
301pub fn center_y<'a, Message, Theme, Renderer>(
302    content: impl Into<Element<'a, Message, Theme, Renderer>>,
303) -> Container<'a, Message, Theme, Renderer>
304where
305    Theme: container::Catalog + 'a,
306    Renderer: core::Renderer,
307{
308    container(content).center_y(Length::Fill)
309}
310
311/// Creates a new [`Container`] that fills all the available space
312/// horizontally and right-aligns its contents inside.
313///
314/// This is equivalent to:
315/// ```rust,no_run
316/// # use iced_widget::core::Length::Fill;
317/// # use iced_widget::Container;
318/// # fn container<A>(x: A) -> Container<'static, ()> { unreachable!() }
319/// let right = container("Right!").align_right(Fill);
320/// ```
321///
322/// [`Container`]: crate::Container
323pub fn right<'a, Message, Theme, Renderer>(
324    content: impl Into<Element<'a, Message, Theme, Renderer>>,
325) -> Container<'a, Message, Theme, Renderer>
326where
327    Theme: container::Catalog + 'a,
328    Renderer: core::Renderer,
329{
330    container(content).align_right(Length::Fill)
331}
332
333/// Creates a new [`Container`] that fills all the available space
334/// and aligns its contents inside to the right center.
335///
336/// This is equivalent to:
337/// ```rust,no_run
338/// # use iced_widget::core::Length::Fill;
339/// # use iced_widget::Container;
340/// # fn container<A>(x: A) -> Container<'static, ()> { unreachable!() }
341/// let right_center = container("Bottom Center!").align_right(Fill).center_y(Fill);
342/// ```
343///
344/// [`Container`]: crate::Container
345pub fn right_center<'a, Message, Theme, Renderer>(
346    content: impl Into<Element<'a, Message, Theme, Renderer>>,
347) -> Container<'a, Message, Theme, Renderer>
348where
349    Theme: container::Catalog + 'a,
350    Renderer: core::Renderer,
351{
352    container(content)
353        .align_right(Length::Fill)
354        .center_y(Length::Fill)
355}
356
357/// Creates a new [`Container`] that fills all the available space
358/// vertically and bottom-aligns its contents inside.
359///
360/// This is equivalent to:
361/// ```rust,no_run
362/// # use iced_widget::core::Length::Fill;
363/// # use iced_widget::Container;
364/// # fn container<A>(x: A) -> Container<'static, ()> { unreachable!() }
365/// let bottom = container("Bottom!").align_bottom(Fill);
366/// ```
367///
368/// [`Container`]: crate::Container
369pub fn bottom<'a, Message, Theme, Renderer>(
370    content: impl Into<Element<'a, Message, Theme, Renderer>>,
371) -> Container<'a, Message, Theme, Renderer>
372where
373    Theme: container::Catalog + 'a,
374    Renderer: core::Renderer,
375{
376    container(content).align_bottom(Length::Fill)
377}
378
379/// Creates a new [`Container`] that fills all the available space
380/// and aligns its contents inside to the bottom center.
381///
382/// This is equivalent to:
383/// ```rust,no_run
384/// # use iced_widget::core::Length::Fill;
385/// # use iced_widget::Container;
386/// # fn container<A>(x: A) -> Container<'static, ()> { unreachable!() }
387/// let bottom_center = container("Bottom Center!").center_x(Fill).align_bottom(Fill);
388/// ```
389///
390/// [`Container`]: crate::Container
391pub fn bottom_center<'a, Message, Theme, Renderer>(
392    content: impl Into<Element<'a, Message, Theme, Renderer>>,
393) -> Container<'a, Message, Theme, Renderer>
394where
395    Theme: container::Catalog + 'a,
396    Renderer: core::Renderer,
397{
398    container(content)
399        .center_x(Length::Fill)
400        .align_bottom(Length::Fill)
401}
402
403/// Creates a new [`Container`] that fills all the available space
404/// and aligns its contents inside to the bottom right corner.
405///
406/// This is equivalent to:
407/// ```rust,no_run
408/// # use iced_widget::core::Length::Fill;
409/// # use iced_widget::Container;
410/// # fn container<A>(x: A) -> Container<'static, ()> { unreachable!() }
411/// let bottom_right = container("Bottom!").align_right(Fill).align_bottom(Fill);
412/// ```
413///
414/// [`Container`]: crate::Container
415pub fn bottom_right<'a, Message, Theme, Renderer>(
416    content: impl Into<Element<'a, Message, Theme, Renderer>>,
417) -> Container<'a, Message, Theme, Renderer>
418where
419    Theme: container::Catalog + 'a,
420    Renderer: core::Renderer,
421{
422    container(content)
423        .align_right(Length::Fill)
424        .align_bottom(Length::Fill)
425}
426
427/// Creates a new [`Pin`] widget with the given content.
428///
429/// A [`Pin`] widget positions its contents at some fixed coordinates inside of its boundaries.
430///
431/// # Example
432/// ```no_run
433/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::core::Length::Fill; }
434/// # pub type State = ();
435/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
436/// use iced::widget::pin;
437/// use iced::Fill;
438///
439/// enum Message {
440///     // ...
441/// }
442///
443/// fn view(state: &State) -> Element<'_, Message> {
444///     pin("This text is displayed at coordinates (50, 50)!")
445///         .x(50)
446///         .y(50)
447///         .into()
448/// }
449/// ```
450pub fn pin<'a, Message, Theme, Renderer>(
451    content: impl Into<Element<'a, Message, Theme, Renderer>>,
452) -> Pin<'a, Message, Theme, Renderer>
453where
454    Renderer: core::Renderer,
455{
456    Pin::new(content)
457}
458
459/// Creates a new [`Column`] with the given children.
460///
461/// Columns distribute their children vertically.
462///
463/// # Example
464/// ```no_run
465/// # mod iced { pub mod widget { pub use iced_widget::*; } }
466/// # pub type State = ();
467/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
468/// use iced::widget::{column, text};
469///
470/// enum Message {
471///     // ...
472/// }
473///
474/// fn view(state: &State) -> Element<'_, Message> {
475///     column((0..5).map(|i| text!("Item {i}").into())).into()
476/// }
477/// ```
478pub fn column<'a, Message, Theme, Renderer>(
479    children: impl IntoIterator<Item = Element<'a, Message, Theme, Renderer>>,
480) -> Column<'a, Message, Theme, Renderer>
481where
482    Renderer: core::Renderer,
483{
484    Column::with_children(children)
485}
486
487/// Creates a new [`keyed::Column`] from an iterator of elements.
488///
489/// Keyed columns distribute content vertically while keeping continuity.
490///
491/// # Example
492/// ```no_run
493/// # mod iced { pub mod widget { pub use iced_widget::*; } }
494/// # pub type State = ();
495/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
496/// use iced::widget::{keyed_column, text};
497///
498/// enum Message {
499///     // ...
500/// }
501///
502/// fn view(state: &State) -> Element<'_, Message> {
503///     keyed_column((0..=100).map(|i| {
504///         (i, text!("Item {i}").into())
505///     })).into()
506/// }
507/// ```
508pub fn keyed_column<'a, Key, Message, Theme, Renderer>(
509    children: impl IntoIterator<Item = (Key, Element<'a, Message, Theme, Renderer>)>,
510) -> keyed::Column<'a, Key, Message, Theme, Renderer>
511where
512    Key: Copy + PartialEq,
513    Renderer: core::Renderer,
514{
515    keyed::Column::with_children(children)
516}
517
518/// Creates a new [`Row`] from an iterator.
519///
520/// Rows distribute their children horizontally.
521///
522/// # Example
523/// ```no_run
524/// # mod iced { pub mod widget { pub use iced_widget::*; } }
525/// # pub type State = ();
526/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
527/// use iced::widget::{row, text};
528///
529/// enum Message {
530///     // ...
531/// }
532///
533/// fn view(state: &State) -> Element<'_, Message> {
534///     row((0..5).map(|i| text!("Item {i}").into())).into()
535/// }
536/// ```
537pub fn row<'a, Message, Theme, Renderer>(
538    children: impl IntoIterator<Item = Element<'a, Message, Theme, Renderer>>,
539) -> Row<'a, Message, Theme, Renderer>
540where
541    Renderer: core::Renderer,
542{
543    Row::with_children(children)
544}
545
546/// Creates a new [`Grid`] from an iterator.
547pub fn grid<'a, Message, Theme, Renderer>(
548    children: impl IntoIterator<Item = Element<'a, Message, Theme, Renderer>>,
549) -> Grid<'a, Message, Theme, Renderer>
550where
551    Renderer: core::Renderer,
552{
553    Grid::with_children(children)
554}
555
556/// Creates a new [`Stack`] with the given children.
557///
558/// [`Stack`]: crate::Stack
559pub fn stack<'a, Message, Theme, Renderer>(
560    children: impl IntoIterator<Item = Element<'a, Message, Theme, Renderer>>,
561) -> Stack<'a, Message, Theme, Renderer>
562where
563    Renderer: core::Renderer,
564{
565    Stack::with_children(children)
566}
567
568/// Wraps the given widget and captures any mouse button presses inside the bounds of
569/// the widget—effectively making it _opaque_.
570///
571/// This helper is meant to be used to mark elements in a [`Stack`] to avoid mouse
572/// events from passing through layers.
573///
574/// [`Stack`]: crate::Stack
575pub fn opaque<'a, Message, Theme, Renderer>(
576    content: impl Into<Element<'a, Message, Theme, Renderer>>,
577) -> Element<'a, Message, Theme, Renderer>
578where
579    Message: 'a,
580    Theme: 'a,
581    Renderer: core::Renderer + 'a,
582{
583    use crate::core::layout::{self, Layout};
584    use crate::core::mouse;
585    use crate::core::renderer;
586    use crate::core::widget::tree::{self, Tree};
587    use crate::core::{Event, Rectangle, Shell, Size};
588
589    struct Opaque<'a, Message, Theme, Renderer> {
590        content: Element<'a, Message, Theme, Renderer>,
591    }
592
593    impl<Message, Theme, Renderer> Widget<Message, Theme, Renderer>
594        for Opaque<'_, Message, Theme, Renderer>
595    where
596        Renderer: core::Renderer,
597    {
598        fn tag(&self) -> tree::Tag {
599            self.content.as_widget().tag()
600        }
601
602        fn state(&self) -> tree::State {
603            self.content.as_widget().state()
604        }
605
606        fn children(&self) -> Vec<Tree> {
607            self.content.as_widget().children()
608        }
609
610        fn diff(&self, tree: &mut Tree) {
611            self.content.as_widget().diff(tree);
612        }
613
614        fn size(&self) -> Size<Length> {
615            self.content.as_widget().size()
616        }
617
618        fn size_hint(&self) -> Size<Length> {
619            self.content.as_widget().size_hint()
620        }
621
622        fn layout(
623            &mut self,
624            tree: &mut Tree,
625            renderer: &Renderer,
626            limits: &layout::Limits,
627        ) -> layout::Node {
628            self.content.as_widget_mut().layout(tree, renderer, limits)
629        }
630
631        fn draw(
632            &self,
633            tree: &Tree,
634            renderer: &mut Renderer,
635            theme: &Theme,
636            style: &renderer::Style,
637            layout: Layout<'_>,
638            cursor: mouse::Cursor,
639            viewport: &Rectangle,
640        ) {
641            self.content
642                .as_widget()
643                .draw(tree, renderer, theme, style, layout, cursor, viewport);
644        }
645
646        fn operate(
647            &mut self,
648            tree: &mut Tree,
649            layout: Layout<'_>,
650            renderer: &Renderer,
651            operation: &mut dyn operation::Operation,
652        ) {
653            self.content
654                .as_widget_mut()
655                .operate(tree, layout, renderer, operation);
656        }
657
658        fn update(
659            &mut self,
660            tree: &mut Tree,
661            event: &Event,
662            layout: Layout<'_>,
663            cursor: mouse::Cursor,
664            renderer: &Renderer,
665            clipboard: &mut dyn core::Clipboard,
666            shell: &mut Shell<'_, Message>,
667            viewport: &Rectangle,
668        ) {
669            let is_mouse_press =
670                matches!(event, core::Event::Mouse(mouse::Event::ButtonPressed(_)));
671
672            self.content.as_widget_mut().update(
673                tree, event, layout, cursor, renderer, clipboard, shell, viewport,
674            );
675
676            if is_mouse_press && cursor.is_over(layout.bounds()) {
677                shell.capture_event();
678            }
679        }
680
681        fn mouse_interaction(
682            &self,
683            state: &core::widget::Tree,
684            layout: core::Layout<'_>,
685            cursor: core::mouse::Cursor,
686            viewport: &core::Rectangle,
687            renderer: &Renderer,
688        ) -> core::mouse::Interaction {
689            let interaction = self
690                .content
691                .as_widget()
692                .mouse_interaction(state, layout, cursor, viewport, renderer);
693
694            if interaction == mouse::Interaction::None && cursor.is_over(layout.bounds()) {
695                mouse::Interaction::Idle
696            } else {
697                interaction
698            }
699        }
700
701        fn overlay<'b>(
702            &'b mut self,
703            state: &'b mut core::widget::Tree,
704            layout: core::Layout<'b>,
705            renderer: &Renderer,
706            viewport: &Rectangle,
707            translation: core::Vector,
708        ) -> Option<core::overlay::Element<'b, Message, Theme, Renderer>> {
709            self.content
710                .as_widget_mut()
711                .overlay(state, layout, renderer, viewport, translation)
712        }
713    }
714
715    Element::new(Opaque {
716        content: content.into(),
717    })
718}
719
720/// Displays a widget on top of another one, only when the base widget is hovered.
721///
722/// This works analogously to a [`stack`], but it will only display the layer on top
723/// when the cursor is over the base. It can be useful for removing visual clutter.
724///
725/// [`stack`]: stack()
726pub fn hover<'a, Message, Theme, Renderer>(
727    base: impl Into<Element<'a, Message, Theme, Renderer>>,
728    top: impl Into<Element<'a, Message, Theme, Renderer>>,
729) -> Element<'a, Message, Theme, Renderer>
730where
731    Message: 'a,
732    Theme: 'a,
733    Renderer: core::Renderer + 'a,
734{
735    use crate::core::layout::{self, Layout};
736    use crate::core::mouse;
737    use crate::core::renderer;
738    use crate::core::widget::tree::{self, Tree};
739    use crate::core::{Event, Rectangle, Shell, Size};
740
741    struct Hover<'a, Message, Theme, Renderer> {
742        base: Element<'a, Message, Theme, Renderer>,
743        top: Element<'a, Message, Theme, Renderer>,
744        is_top_focused: bool,
745        is_top_overlay_active: bool,
746        is_hovered: bool,
747    }
748
749    impl<Message, Theme, Renderer> Widget<Message, Theme, Renderer>
750        for Hover<'_, Message, Theme, Renderer>
751    where
752        Renderer: core::Renderer,
753    {
754        fn tag(&self) -> tree::Tag {
755            struct Tag;
756            tree::Tag::of::<Tag>()
757        }
758
759        fn children(&self) -> Vec<Tree> {
760            vec![Tree::new(&self.base), Tree::new(&self.top)]
761        }
762
763        fn diff(&self, tree: &mut Tree) {
764            tree.diff_children(&[&self.base, &self.top]);
765        }
766
767        fn size(&self) -> Size<Length> {
768            self.base.as_widget().size()
769        }
770
771        fn size_hint(&self) -> Size<Length> {
772            self.base.as_widget().size_hint()
773        }
774
775        fn layout(
776            &mut self,
777            tree: &mut Tree,
778            renderer: &Renderer,
779            limits: &layout::Limits,
780        ) -> layout::Node {
781            let base = self
782                .base
783                .as_widget_mut()
784                .layout(&mut tree.children[0], renderer, limits);
785
786            let top = self.top.as_widget_mut().layout(
787                &mut tree.children[1],
788                renderer,
789                &layout::Limits::new(Size::ZERO, base.size()),
790            );
791
792            layout::Node::with_children(base.size(), vec![base, top])
793        }
794
795        fn draw(
796            &self,
797            tree: &Tree,
798            renderer: &mut Renderer,
799            theme: &Theme,
800            style: &renderer::Style,
801            layout: Layout<'_>,
802            cursor: mouse::Cursor,
803            viewport: &Rectangle,
804        ) {
805            if let Some(bounds) = layout.bounds().intersection(viewport) {
806                let mut children = layout.children().zip(&tree.children);
807
808                let (base_layout, base_tree) = children.next().unwrap();
809
810                self.base.as_widget().draw(
811                    base_tree,
812                    renderer,
813                    theme,
814                    style,
815                    base_layout,
816                    cursor,
817                    viewport,
818                );
819
820                if cursor.is_over(layout.bounds())
821                    || self.is_top_focused
822                    || self.is_top_overlay_active
823                {
824                    let (top_layout, top_tree) = children.next().unwrap();
825
826                    renderer.with_layer(bounds, |renderer| {
827                        self.top.as_widget().draw(
828                            top_tree, renderer, theme, style, top_layout, cursor, viewport,
829                        );
830                    });
831                }
832            }
833        }
834
835        fn operate(
836            &mut self,
837            tree: &mut Tree,
838            layout: Layout<'_>,
839            renderer: &Renderer,
840            operation: &mut dyn operation::Operation,
841        ) {
842            let children = [&mut self.base, &mut self.top]
843                .into_iter()
844                .zip(layout.children().zip(&mut tree.children));
845
846            for (child, (layout, tree)) in children {
847                child
848                    .as_widget_mut()
849                    .operate(tree, layout, renderer, operation);
850            }
851        }
852
853        fn update(
854            &mut self,
855            tree: &mut Tree,
856            event: &Event,
857            layout: Layout<'_>,
858            cursor: mouse::Cursor,
859            renderer: &Renderer,
860            clipboard: &mut dyn core::Clipboard,
861            shell: &mut Shell<'_, Message>,
862            viewport: &Rectangle,
863        ) {
864            let mut children = layout.children().zip(&mut tree.children);
865            let (base_layout, base_tree) = children.next().unwrap();
866            let (top_layout, top_tree) = children.next().unwrap();
867
868            let is_hovered = cursor.is_over(layout.bounds());
869
870            if matches!(event, Event::Window(window::Event::RedrawRequested(_))) {
871                let mut count_focused = operation::focusable::count();
872
873                self.top.as_widget_mut().operate(
874                    top_tree,
875                    top_layout,
876                    renderer,
877                    &mut operation::black_box(&mut count_focused),
878                );
879
880                self.is_top_focused = match count_focused.finish() {
881                    operation::Outcome::Some(count) => count.focused.is_some(),
882                    _ => false,
883                };
884
885                self.is_hovered = is_hovered;
886            } else if is_hovered != self.is_hovered {
887                shell.request_redraw();
888            }
889
890            let is_visible = is_hovered || self.is_top_focused || self.is_top_overlay_active;
891
892            if matches!(
893                event,
894                Event::Mouse(mouse::Event::CursorMoved { .. } | mouse::Event::ButtonReleased(_))
895            ) || is_visible
896            {
897                let redraw_request = shell.redraw_request();
898
899                self.top.as_widget_mut().update(
900                    top_tree, event, top_layout, cursor, renderer, clipboard, shell, viewport,
901                );
902
903                // Ignore redraw requests of invisible content
904                if !is_visible {
905                    Shell::replace_redraw_request(shell, redraw_request);
906                }
907
908                if shell.is_event_captured() {
909                    return;
910                }
911            };
912
913            self.base.as_widget_mut().update(
914                base_tree,
915                event,
916                base_layout,
917                cursor,
918                renderer,
919                clipboard,
920                shell,
921                viewport,
922            );
923        }
924
925        fn mouse_interaction(
926            &self,
927            tree: &Tree,
928            layout: Layout<'_>,
929            cursor: mouse::Cursor,
930            viewport: &Rectangle,
931            renderer: &Renderer,
932        ) -> mouse::Interaction {
933            [&self.base, &self.top]
934                .into_iter()
935                .rev()
936                .zip(layout.children().rev().zip(tree.children.iter().rev()))
937                .map(|(child, (layout, tree))| {
938                    child
939                        .as_widget()
940                        .mouse_interaction(tree, layout, cursor, viewport, renderer)
941                })
942                .find(|&interaction| interaction != mouse::Interaction::None)
943                .unwrap_or_default()
944        }
945
946        fn overlay<'b>(
947            &'b mut self,
948            tree: &'b mut core::widget::Tree,
949            layout: core::Layout<'b>,
950            renderer: &Renderer,
951            viewport: &Rectangle,
952            translation: core::Vector,
953        ) -> Option<core::overlay::Element<'b, Message, Theme, Renderer>> {
954            let mut overlays = [&mut self.base, &mut self.top]
955                .into_iter()
956                .zip(layout.children().zip(tree.children.iter_mut()))
957                .map(|(child, (layout, tree))| {
958                    child
959                        .as_widget_mut()
960                        .overlay(tree, layout, renderer, viewport, translation)
961                });
962
963            if let Some(base_overlay) = overlays.next()? {
964                return Some(base_overlay);
965            }
966
967            let top_overlay = overlays.next()?;
968            self.is_top_overlay_active = top_overlay.is_some();
969
970            top_overlay
971        }
972    }
973
974    Element::new(Hover {
975        base: base.into(),
976        top: top.into(),
977        is_top_focused: false,
978        is_top_overlay_active: false,
979        is_hovered: false,
980    })
981}
982
983/// Creates a new [`Sensor`] widget.
984///
985/// A [`Sensor`] widget can generate messages when its contents are shown,
986/// hidden, or resized.
987///
988/// It can even notify you with anticipation at a given distance!
989pub fn sensor<'a, Message, Theme, Renderer>(
990    content: impl Into<Element<'a, Message, Theme, Renderer>>,
991) -> Sensor<'a, (), Message, Theme, Renderer>
992where
993    Renderer: core::Renderer,
994{
995    Sensor::new(content)
996}
997
998/// Creates a new [`Scrollable`] with the provided content.
999///
1000/// Scrollables let users navigate an endless amount of content with a scrollbar.
1001///
1002/// # Example
1003/// ```no_run
1004/// # mod iced { pub mod widget { pub use iced_widget::*; } }
1005/// # pub type State = ();
1006/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1007/// use iced::widget::{column, scrollable, space};
1008///
1009/// enum Message {
1010///     // ...
1011/// }
1012///
1013/// fn view(state: &State) -> Element<'_, Message> {
1014///     scrollable(column![
1015///         "Scroll me!",
1016///         space().height(3000),
1017///         "You did it!",
1018///     ]).into()
1019/// }
1020/// ```
1021pub fn scrollable<'a, Message, Theme, Renderer>(
1022    content: impl Into<Element<'a, Message, Theme, Renderer>>,
1023) -> Scrollable<'a, Message, Theme, Renderer>
1024where
1025    Theme: scrollable::Catalog + 'a,
1026    Renderer: core::text::Renderer,
1027{
1028    Scrollable::new(content)
1029}
1030
1031/// Creates a new [`Button`] with the provided content.
1032///
1033/// # Example
1034/// ```no_run
1035/// # mod iced { pub mod widget { pub use iced_widget::*; } }
1036/// # pub type State = ();
1037/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1038/// use iced::widget::button;
1039///
1040/// #[derive(Clone)]
1041/// enum Message {
1042///     ButtonPressed,
1043/// }
1044///
1045/// fn view(state: &State) -> Element<'_, Message> {
1046///     button("Press me!").on_press(Message::ButtonPressed).into()
1047/// }
1048/// ```
1049pub fn button<'a, Message, Theme, Renderer>(
1050    content: impl Into<Element<'a, Message, Theme, Renderer>>,
1051) -> Button<'a, Message, Theme, Renderer>
1052where
1053    Theme: button::Catalog + 'a,
1054    Renderer: core::Renderer,
1055{
1056    Button::new(content)
1057}
1058
1059/// Creates a new [`Tooltip`] for the provided content with the given
1060/// [`Element`] and [`tooltip::Position`].
1061///
1062/// Tooltips display a hint of information over some element when hovered.
1063///
1064/// # Example
1065/// ```no_run
1066/// # mod iced { pub mod widget { pub use iced_widget::*; } }
1067/// # pub type State = ();
1068/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1069/// use iced::widget::{container, tooltip};
1070///
1071/// enum Message {
1072///     // ...
1073/// }
1074///
1075/// fn view(_state: &State) -> Element<'_, Message> {
1076///     tooltip(
1077///         "Hover me to display the tooltip!",
1078///         container("This is the tooltip contents!")
1079///             .padding(10)
1080///             .style(container::rounded_box),
1081///         tooltip::Position::Bottom,
1082///     ).into()
1083/// }
1084/// ```
1085pub fn tooltip<'a, Message, Theme, Renderer>(
1086    content: impl Into<Element<'a, Message, Theme, Renderer>>,
1087    tooltip: impl Into<Element<'a, Message, Theme, Renderer>>,
1088    position: tooltip::Position,
1089) -> crate::Tooltip<'a, Message, Theme, Renderer>
1090where
1091    Theme: container::Catalog + 'a,
1092    Renderer: core::text::Renderer,
1093{
1094    Tooltip::new(content, tooltip, position)
1095}
1096
1097/// Creates a new [`Text`] widget with the provided content.
1098///
1099/// # Example
1100/// ```no_run
1101/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1102/// # pub type State = ();
1103/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::core::Theme, ()>;
1104/// use iced::widget::text;
1105/// use iced::color;
1106///
1107/// enum Message {
1108///     // ...
1109/// }
1110///
1111/// fn view(state: &State) -> Element<'_, Message> {
1112///     text("Hello, this is iced!")
1113///         .size(20)
1114///         .color(color!(0x0000ff))
1115///         .into()
1116/// }
1117/// ```
1118pub fn text<'a, Theme, Renderer>(text: impl text::IntoFragment<'a>) -> Text<'a, Theme, Renderer>
1119where
1120    Theme: text::Catalog + 'a,
1121    Renderer: core::text::Renderer,
1122{
1123    Text::new(text)
1124}
1125
1126/// Creates a new [`Text`] widget that displays the provided value.
1127pub fn value<'a, Theme, Renderer>(value: impl ToString) -> Text<'a, Theme, Renderer>
1128where
1129    Theme: text::Catalog + 'a,
1130    Renderer: core::text::Renderer,
1131{
1132    Text::new(value.to_string())
1133}
1134
1135/// Creates a new [`Rich`] text widget with the provided spans.
1136///
1137/// [`Rich`]: text::Rich
1138///
1139/// # Example
1140/// ```no_run
1141/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::core::*; }
1142/// # pub type State = ();
1143/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1144/// use iced::font;
1145/// use iced::widget::{rich_text, span};
1146/// use iced::{color, never, Font};
1147///
1148/// #[derive(Debug, Clone)]
1149/// enum Message {
1150///     LinkClicked(&'static str),
1151///     // ...
1152/// }
1153///
1154/// fn view(state: &State) -> Element<'_, Message> {
1155///     rich_text([
1156///         span("I am red!").color(color!(0xff0000)),
1157///         span(" "),
1158///         span("And I am bold!").font(Font { weight: font::Weight::Bold, ..Font::default() }),
1159///     ])
1160///     .on_link_click(never)
1161///     .size(20)
1162///     .into()
1163/// }
1164/// ```
1165pub fn rich_text<'a, Link, Message, Theme, Renderer>(
1166    spans: impl AsRef<[text::Span<'a, Link, Renderer::Font>]> + 'a,
1167) -> text::Rich<'a, Link, Message, Theme, Renderer>
1168where
1169    Link: Clone + 'static,
1170    Theme: text::Catalog + 'a,
1171    Renderer: core::text::Renderer,
1172    Renderer::Font: 'a,
1173{
1174    text::Rich::with_spans(spans)
1175}
1176
1177/// Creates a new [`Span`] of text with the provided content.
1178///
1179/// A [`Span`] is a fragment of some [`Rich`] text.
1180///
1181/// [`Span`]: text::Span
1182/// [`Rich`]: text::Rich
1183///
1184/// # Example
1185/// ```no_run
1186/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::core::*; }
1187/// # pub type State = ();
1188/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1189/// use iced::font;
1190/// use iced::widget::{rich_text, span};
1191/// use iced::{color, never, Font};
1192///
1193/// #[derive(Debug, Clone)]
1194/// enum Message {
1195///     // ...
1196/// }
1197///
1198/// fn view(state: &State) -> Element<'_, Message> {
1199///     rich_text![
1200///         span("I am red!").color(color!(0xff0000)),
1201///         " ",
1202///         span("And I am bold!").font(Font { weight: font::Weight::Bold, ..Font::default() }),
1203///     ]
1204///     .on_link_click(never)
1205///     .size(20)
1206///     .into()
1207/// }
1208/// ```
1209pub fn span<'a, Link, Font>(text: impl text::IntoFragment<'a>) -> text::Span<'a, Link, Font> {
1210    text::Span::new(text)
1211}
1212
1213#[cfg(feature = "markdown")]
1214#[doc(inline)]
1215pub use crate::markdown::view as markdown;
1216
1217/// Creates a new [`Checkbox`].
1218///
1219/// # Example
1220/// ```no_run
1221/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1222/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1223/// #
1224/// use iced::widget::checkbox;
1225///
1226/// struct State {
1227///    is_checked: bool,
1228/// }
1229///
1230/// enum Message {
1231///     CheckboxToggled(bool),
1232/// }
1233///
1234/// fn view(state: &State) -> Element<'_, Message> {
1235///     checkbox(state.is_checked)
1236///         .label("Toggle me!")
1237///         .on_toggle(Message::CheckboxToggled)
1238///         .into()
1239/// }
1240///
1241/// fn update(state: &mut State, message: Message) {
1242///     match message {
1243///         Message::CheckboxToggled(is_checked) => {
1244///             state.is_checked = is_checked;
1245///         }
1246///     }
1247/// }
1248/// ```
1249/// ![Checkbox drawn by `iced_wgpu`](https://github.com/iced-rs/iced/blob/7760618fb112074bc40b148944521f312152012a/docs/images/checkbox.png?raw=true)
1250pub fn checkbox<'a, Message, Theme, Renderer>(
1251    is_checked: bool,
1252) -> Checkbox<'a, Message, Theme, Renderer>
1253where
1254    Theme: checkbox::Catalog + 'a,
1255    Renderer: core::text::Renderer,
1256{
1257    Checkbox::new(is_checked)
1258}
1259
1260/// Creates a new [`Radio`].
1261///
1262/// Radio buttons let users choose a single option from a bunch of options.
1263///
1264/// # Example
1265/// ```no_run
1266/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1267/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1268/// #
1269/// use iced::widget::{column, radio};
1270///
1271/// struct State {
1272///    selection: Option<Choice>,
1273/// }
1274///
1275/// #[derive(Debug, Clone, Copy)]
1276/// enum Message {
1277///     RadioSelected(Choice),
1278/// }
1279///
1280/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
1281/// enum Choice {
1282///     A,
1283///     B,
1284///     C,
1285///     All,
1286/// }
1287///
1288/// fn view(state: &State) -> Element<'_, Message> {
1289///     let a = radio(
1290///         "A",
1291///         Choice::A,
1292///         state.selection,
1293///         Message::RadioSelected,
1294///     );
1295///
1296///     let b = radio(
1297///         "B",
1298///         Choice::B,
1299///         state.selection,
1300///         Message::RadioSelected,
1301///     );
1302///
1303///     let c = radio(
1304///         "C",
1305///         Choice::C,
1306///         state.selection,
1307///         Message::RadioSelected,
1308///     );
1309///
1310///     let all = radio(
1311///         "All of the above",
1312///         Choice::All,
1313///         state.selection,
1314///         Message::RadioSelected
1315///     );
1316///
1317///     column![a, b, c, all].into()
1318/// }
1319/// ```
1320pub fn radio<'a, Message, Theme, Renderer, V>(
1321    label: impl Into<String>,
1322    value: V,
1323    selected: Option<V>,
1324    on_click: impl FnOnce(V) -> Message,
1325) -> Radio<'a, Message, Theme, Renderer>
1326where
1327    Message: Clone,
1328    Theme: radio::Catalog + 'a,
1329    Renderer: core::text::Renderer,
1330    V: Copy + Eq,
1331{
1332    Radio::new(label, value, selected, on_click)
1333}
1334
1335/// Creates a new [`Toggler`].
1336///
1337/// Togglers let users make binary choices by toggling a switch.
1338///
1339/// # Example
1340/// ```no_run
1341/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1342/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1343/// #
1344/// use iced::widget::toggler;
1345///
1346/// struct State {
1347///    is_checked: bool,
1348/// }
1349///
1350/// enum Message {
1351///     TogglerToggled(bool),
1352/// }
1353///
1354/// fn view(state: &State) -> Element<'_, Message> {
1355///     toggler(state.is_checked)
1356///         .label("Toggle me!")
1357///         .on_toggle(Message::TogglerToggled)
1358///         .into()
1359/// }
1360///
1361/// fn update(state: &mut State, message: Message) {
1362///     match message {
1363///         Message::TogglerToggled(is_checked) => {
1364///             state.is_checked = is_checked;
1365///         }
1366///     }
1367/// }
1368/// ```
1369pub fn toggler<'a, Message, Theme, Renderer>(
1370    is_checked: bool,
1371) -> Toggler<'a, Message, Theme, Renderer>
1372where
1373    Theme: toggler::Catalog + 'a,
1374    Renderer: core::text::Renderer,
1375{
1376    Toggler::new(is_checked)
1377}
1378
1379/// Creates a new [`TextInput`].
1380///
1381/// Text inputs display fields that can be filled with text.
1382///
1383/// # Example
1384/// ```no_run
1385/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1386/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1387/// #
1388/// use iced::widget::text_input;
1389///
1390/// struct State {
1391///    content: String,
1392/// }
1393///
1394/// #[derive(Debug, Clone)]
1395/// enum Message {
1396///     ContentChanged(String)
1397/// }
1398///
1399/// fn view(state: &State) -> Element<'_, Message> {
1400///     text_input("Type something here...", &state.content)
1401///         .on_input(Message::ContentChanged)
1402///         .into()
1403/// }
1404///
1405/// fn update(state: &mut State, message: Message) {
1406///     match message {
1407///         Message::ContentChanged(content) => {
1408///             state.content = content;
1409///         }
1410///     }
1411/// }
1412/// ```
1413pub fn text_input<'a, Message, Theme, Renderer>(
1414    placeholder: &str,
1415    value: &str,
1416) -> TextInput<'a, Message, Theme, Renderer>
1417where
1418    Message: Clone,
1419    Theme: text_input::Catalog + 'a,
1420    Renderer: core::text::Renderer,
1421{
1422    TextInput::new(placeholder, value)
1423}
1424
1425/// Creates a new [`TextEditor`].
1426///
1427/// Text editors display a multi-line text input for text editing.
1428///
1429/// # Example
1430/// ```no_run
1431/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1432/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1433/// #
1434/// use iced::widget::text_editor;
1435///
1436/// struct State {
1437///    content: text_editor::Content,
1438/// }
1439///
1440/// #[derive(Debug, Clone)]
1441/// enum Message {
1442///     Edit(text_editor::Action)
1443/// }
1444///
1445/// fn view(state: &State) -> Element<'_, Message> {
1446///     text_editor(&state.content)
1447///         .placeholder("Type something here...")
1448///         .on_action(Message::Edit)
1449///         .into()
1450/// }
1451///
1452/// fn update(state: &mut State, message: Message) {
1453///     match message {
1454///         Message::Edit(action) => {
1455///             state.content.perform(action);
1456///         }
1457///     }
1458/// }
1459/// ```
1460pub fn text_editor<'a, Message, Theme, Renderer>(
1461    content: &'a text_editor::Content<Renderer>,
1462) -> TextEditor<'a, core::text::highlighter::PlainText, Message, Theme, Renderer>
1463where
1464    Message: Clone,
1465    Theme: text_editor::Catalog + 'a,
1466    Renderer: core::text::Renderer,
1467{
1468    TextEditor::new(content)
1469}
1470
1471/// Creates a new [`Slider`].
1472///
1473/// Sliders let users set a value by moving an indicator.
1474///
1475/// # Example
1476/// ```no_run
1477/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1478/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1479/// #
1480/// use iced::widget::slider;
1481///
1482/// struct State {
1483///    value: f32,
1484/// }
1485///
1486/// #[derive(Debug, Clone)]
1487/// enum Message {
1488///     ValueChanged(f32),
1489/// }
1490///
1491/// fn view(state: &State) -> Element<'_, Message> {
1492///     slider(0.0..=100.0, state.value, Message::ValueChanged).into()
1493/// }
1494///
1495/// fn update(state: &mut State, message: Message) {
1496///     match message {
1497///         Message::ValueChanged(value) => {
1498///             state.value = value;
1499///         }
1500///     }
1501/// }
1502/// ```
1503pub fn slider<'a, T, Message, Theme>(
1504    range: std::ops::RangeInclusive<T>,
1505    value: T,
1506    on_change: impl Fn(T) -> Message + 'a,
1507) -> Slider<'a, T, Message, Theme>
1508where
1509    T: Copy + From<u8> + std::cmp::PartialOrd,
1510    Message: Clone,
1511    Theme: slider::Catalog + 'a,
1512{
1513    Slider::new(range, value, on_change)
1514}
1515
1516/// Creates a new [`VerticalSlider`].
1517///
1518/// Sliders let users set a value by moving an indicator.
1519///
1520/// # Example
1521/// ```no_run
1522/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1523/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1524/// #
1525/// use iced::widget::vertical_slider;
1526///
1527/// struct State {
1528///    value: f32,
1529/// }
1530///
1531/// #[derive(Debug, Clone)]
1532/// enum Message {
1533///     ValueChanged(f32),
1534/// }
1535///
1536/// fn view(state: &State) -> Element<'_, Message> {
1537///     vertical_slider(0.0..=100.0, state.value, Message::ValueChanged).into()
1538/// }
1539///
1540/// fn update(state: &mut State, message: Message) {
1541///     match message {
1542///         Message::ValueChanged(value) => {
1543///             state.value = value;
1544///         }
1545///     }
1546/// }
1547/// ```
1548pub fn vertical_slider<'a, T, Message, Theme>(
1549    range: std::ops::RangeInclusive<T>,
1550    value: T,
1551    on_change: impl Fn(T) -> Message + 'a,
1552) -> VerticalSlider<'a, T, Message, Theme>
1553where
1554    T: Copy + From<u8> + std::cmp::PartialOrd,
1555    Message: Clone,
1556    Theme: vertical_slider::Catalog + 'a,
1557{
1558    VerticalSlider::new(range, value, on_change)
1559}
1560
1561/// Creates a new [`PickList`].
1562///
1563/// Pick lists display a dropdown list of selectable options.
1564///
1565/// # Example
1566/// ```no_run
1567/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1568/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1569/// #
1570/// use iced::widget::pick_list;
1571///
1572/// struct State {
1573///    favorite: Option<Fruit>,
1574/// }
1575///
1576/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
1577/// enum Fruit {
1578///     Apple,
1579///     Orange,
1580///     Strawberry,
1581///     Tomato,
1582/// }
1583///
1584/// #[derive(Debug, Clone)]
1585/// enum Message {
1586///     FruitSelected(Fruit),
1587/// }
1588///
1589/// fn view(state: &State) -> Element<'_, Message> {
1590///     let fruits = [
1591///         Fruit::Apple,
1592///         Fruit::Orange,
1593///         Fruit::Strawberry,
1594///         Fruit::Tomato,
1595///     ];
1596///
1597///     pick_list(
1598///         fruits,
1599///         state.favorite,
1600///         Message::FruitSelected,
1601///     )
1602///     .placeholder("Select your favorite fruit...")
1603///     .into()
1604/// }
1605///
1606/// fn update(state: &mut State, message: Message) {
1607///     match message {
1608///         Message::FruitSelected(fruit) => {
1609///             state.favorite = Some(fruit);
1610///         }
1611///     }
1612/// }
1613///
1614/// impl std::fmt::Display for Fruit {
1615///     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1616///         f.write_str(match self {
1617///             Self::Apple => "Apple",
1618///             Self::Orange => "Orange",
1619///             Self::Strawberry => "Strawberry",
1620///             Self::Tomato => "Tomato",
1621///         })
1622///     }
1623/// }
1624/// ```
1625pub fn pick_list<'a, T, L, V, Message, Theme, Renderer>(
1626    options: L,
1627    selected: Option<V>,
1628    on_selected: impl Fn(T) -> Message + 'a,
1629) -> PickList<'a, T, L, V, Message, Theme, Renderer>
1630where
1631    T: ToString + PartialEq + Clone + 'a,
1632    L: Borrow<[T]> + 'a,
1633    V: Borrow<T> + 'a,
1634    Message: Clone,
1635    Theme: pick_list::Catalog + overlay::menu::Catalog,
1636    Renderer: core::text::Renderer,
1637{
1638    PickList::new(options, selected, on_selected)
1639}
1640
1641/// Creates a new [`ComboBox`].
1642///
1643/// Combo boxes display a dropdown list of searchable and selectable options.
1644///
1645/// # Example
1646/// ```no_run
1647/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1648/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1649/// #
1650/// use iced::widget::combo_box;
1651///
1652/// struct State {
1653///    fruits: combo_box::State<Fruit>,
1654///    favorite: Option<Fruit>,
1655/// }
1656///
1657/// #[derive(Debug, Clone)]
1658/// enum Fruit {
1659///     Apple,
1660///     Orange,
1661///     Strawberry,
1662///     Tomato,
1663/// }
1664///
1665/// #[derive(Debug, Clone)]
1666/// enum Message {
1667///     FruitSelected(Fruit),
1668/// }
1669///
1670/// fn view(state: &State) -> Element<'_, Message> {
1671///     combo_box(
1672///         &state.fruits,
1673///         "Select your favorite fruit...",
1674///         state.favorite.as_ref(),
1675///         Message::FruitSelected
1676///     )
1677///     .into()
1678/// }
1679///
1680/// fn update(state: &mut State, message: Message) {
1681///     match message {
1682///         Message::FruitSelected(fruit) => {
1683///             state.favorite = Some(fruit);
1684///         }
1685///     }
1686/// }
1687///
1688/// impl std::fmt::Display for Fruit {
1689///     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1690///         f.write_str(match self {
1691///             Self::Apple => "Apple",
1692///             Self::Orange => "Orange",
1693///             Self::Strawberry => "Strawberry",
1694///             Self::Tomato => "Tomato",
1695///         })
1696///     }
1697/// }
1698/// ```
1699pub fn combo_box<'a, T, Message, Theme, Renderer>(
1700    state: &'a combo_box::State<T>,
1701    placeholder: &str,
1702    selection: Option<&T>,
1703    on_selected: impl Fn(T) -> Message + 'static,
1704) -> ComboBox<'a, T, Message, Theme, Renderer>
1705where
1706    T: std::fmt::Display + Clone,
1707    Theme: combo_box::Catalog + 'a,
1708    Renderer: core::text::Renderer,
1709{
1710    ComboBox::new(state, placeholder, selection, on_selected)
1711}
1712
1713/// Creates some empty [`Space`] with no size.
1714///
1715/// This is considered the "identity" widget. It will take
1716/// no space and do nothing.
1717pub fn space() -> Space {
1718    Space::new()
1719}
1720
1721/// Creates a new [`ProgressBar`].
1722///
1723/// Progress bars visualize the progression of an extended computer operation, such as a download, file transfer, or installation.
1724///
1725/// It expects:
1726///   * an inclusive range of possible values, and
1727///   * the current value of the [`ProgressBar`].
1728///
1729/// # Example
1730/// ```no_run
1731/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1732/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1733/// #
1734/// use iced::widget::progress_bar;
1735///
1736/// struct State {
1737///    progress: f32,
1738/// }
1739///
1740/// enum Message {
1741///     // ...
1742/// }
1743///
1744/// fn view(state: &State) -> Element<'_, Message> {
1745///     progress_bar(0.0..=100.0, state.progress).into()
1746/// }
1747/// ```
1748pub fn progress_bar<'a, Theme>(range: RangeInclusive<f32>, value: f32) -> ProgressBar<'a, Theme>
1749where
1750    Theme: progress_bar::Catalog + 'a,
1751{
1752    ProgressBar::new(range, value)
1753}
1754
1755/// Creates a new [`Image`].
1756///
1757/// Images display raster graphics in different formats (PNG, JPG, etc.).
1758///
1759/// [`Image`]: crate::Image
1760///
1761/// # Example
1762/// ```no_run
1763/// # mod iced { pub mod widget { pub use iced_widget::*; } }
1764/// # pub type State = ();
1765/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1766/// use iced::widget::image;
1767///
1768/// enum Message {
1769///     // ...
1770/// }
1771///
1772/// fn view(state: &State) -> Element<'_, Message> {
1773///     image("ferris.png").into()
1774/// }
1775/// ```
1776/// <img src="https://github.com/iced-rs/iced/blob/9712b319bb7a32848001b96bd84977430f14b623/examples/resources/ferris.png?raw=true" width="300">
1777#[cfg(feature = "image")]
1778pub fn image<Handle>(handle: impl Into<Handle>) -> crate::Image<Handle> {
1779    crate::Image::new(handle.into())
1780}
1781
1782/// Creates a new [`Svg`] widget from the given [`Handle`].
1783///
1784/// Svg widgets display vector graphics in your application.
1785///
1786/// [`Svg`]: crate::Svg
1787/// [`Handle`]: crate::svg::Handle
1788///
1789/// # Example
1790/// ```no_run
1791/// # mod iced { pub mod widget { pub use iced_widget::*; } }
1792/// # pub type State = ();
1793/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1794/// use iced::widget::svg;
1795///
1796/// enum Message {
1797///     // ...
1798/// }
1799///
1800/// fn view(state: &State) -> Element<'_, Message> {
1801///     svg("tiger.svg").into()
1802/// }
1803/// ```
1804#[cfg(feature = "svg")]
1805pub fn svg<'a, Theme>(handle: impl Into<core::svg::Handle>) -> crate::Svg<'a, Theme>
1806where
1807    Theme: crate::svg::Catalog,
1808{
1809    crate::Svg::new(handle)
1810}
1811
1812/// Creates an [`Element`] that displays the iced logo with the given `text_size`.
1813///
1814/// Useful for showing some love to your favorite GUI library in your "About" screen,
1815/// for instance.
1816pub fn iced<'a, Message, Theme, Renderer>(
1817    text_size: impl Into<core::Pixels>,
1818) -> Element<'a, Message, Theme, Renderer>
1819where
1820    Message: 'a,
1821    Renderer: core::Renderer + core::text::Renderer<Font = core::Font> + 'a,
1822    Theme: text::Catalog + container::Catalog + 'a,
1823    <Theme as container::Catalog>::Class<'a>: From<container::StyleFn<'a, Theme>>,
1824    <Theme as text::Catalog>::Class<'a>: From<text::StyleFn<'a, Theme>>,
1825{
1826    use crate::core::border;
1827    use crate::core::color;
1828    use crate::core::gradient;
1829    use crate::core::{Alignment, Color, Font, Radians};
1830
1831    let text_size = text_size.into();
1832
1833    row![
1834        container(
1835            text(Renderer::ICED_LOGO)
1836                .line_height(1.0)
1837                .size(text_size)
1838                .font(Renderer::ICON_FONT)
1839                .color(Color::WHITE)
1840        )
1841        .padding(text_size * 0.15)
1842        .style(move |_| container::Style {
1843            background: Some(
1844                gradient::Linear::new(Radians::PI / 4.0)
1845                    .add_stop(0.0, color!(0x0033ff))
1846                    .add_stop(1.0, color!(0x1177ff))
1847                    .into()
1848            ),
1849            border: border::rounded(border::radius(text_size * 0.4)),
1850            ..container::Style::default()
1851        }),
1852        text("iced").size(text_size).font(Font::MONOSPACE)
1853    ]
1854    .spacing(text_size.0 / 3.0)
1855    .align_y(Alignment::Center)
1856    .into()
1857}
1858
1859/// Creates a new [`Canvas`].
1860///
1861/// Canvases can be leveraged to draw interactive 2D graphics.
1862///
1863/// [`Canvas`]: crate::Canvas
1864///
1865/// # Example: Drawing a Simple Circle
1866/// ```no_run
1867/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1868/// # pub type State = ();
1869/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1870/// #
1871/// use iced::mouse;
1872/// use iced::widget::canvas;
1873/// use iced::{Color, Rectangle, Renderer, Theme};
1874///
1875/// // First, we define the data we need for drawing
1876/// #[derive(Debug)]
1877/// struct Circle {
1878///     radius: f32,
1879/// }
1880///
1881/// // Then, we implement the `Program` trait
1882/// impl<Message> canvas::Program<Message> for Circle {
1883///     // No internal state
1884///     type State = ();
1885///
1886///     fn draw(
1887///         &self,
1888///         _state: &(),
1889///         renderer: &Renderer,
1890///         _theme: &Theme,
1891///         bounds: Rectangle,
1892///         _cursor: mouse::Cursor
1893///     ) -> Vec<canvas::Geometry> {
1894///         // We prepare a new `Frame`
1895///         let mut frame = canvas::Frame::new(renderer, bounds.size());
1896///
1897///         // We create a `Path` representing a simple circle
1898///         let circle = canvas::Path::circle(frame.center(), self.radius);
1899///
1900///         // And fill it with some color
1901///         frame.fill(&circle, Color::BLACK);
1902///
1903///         // Then, we produce the geometry
1904///         vec![frame.into_geometry()]
1905///     }
1906/// }
1907///
1908/// // Finally, we simply use our `Circle` to create the `Canvas`!
1909/// fn view<'a, Message: 'a>(_state: &'a State) -> Element<'a, Message> {
1910///     canvas(Circle { radius: 50.0 }).into()
1911/// }
1912/// ```
1913#[cfg(feature = "canvas")]
1914pub fn canvas<P, Message, Theme, Renderer>(program: P) -> crate::Canvas<P, Message, Theme, Renderer>
1915where
1916    Renderer: crate::graphics::geometry::Renderer,
1917    P: crate::canvas::Program<Message, Theme, Renderer>,
1918{
1919    crate::Canvas::new(program)
1920}
1921
1922/// Creates a new [`QRCode`] widget from the given [`Data`].
1923///
1924/// QR codes display information in a type of two-dimensional matrix barcode.
1925///
1926/// [`QRCode`]: crate::QRCode
1927/// [`Data`]: crate::qr_code::Data
1928///
1929/// # Example
1930/// ```no_run
1931/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1932/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1933/// #
1934/// use iced::widget::qr_code;
1935///
1936/// struct State {
1937///    data: qr_code::Data,
1938/// }
1939///
1940/// #[derive(Debug, Clone)]
1941/// enum Message {
1942///     // ...
1943/// }
1944///
1945/// fn view(state: &State) -> Element<'_, Message> {
1946///     qr_code(&state.data).into()
1947/// }
1948/// ```
1949#[cfg(feature = "qr_code")]
1950pub fn qr_code<'a, Theme>(data: &'a crate::qr_code::Data) -> crate::QRCode<'a, Theme>
1951where
1952    Theme: crate::qr_code::Catalog + 'a,
1953{
1954    crate::QRCode::new(data)
1955}
1956
1957/// Creates a new [`Shader`].
1958///
1959/// [`Shader`]: crate::Shader
1960#[cfg(feature = "wgpu")]
1961pub fn shader<Message, P>(program: P) -> crate::Shader<Message, P>
1962where
1963    P: crate::shader::Program<Message>,
1964{
1965    crate::Shader::new(program)
1966}
1967
1968/// Creates a new [`MouseArea`].
1969pub fn mouse_area<'a, Message, Theme, Renderer>(
1970    widget: impl Into<Element<'a, Message, Theme, Renderer>>,
1971) -> MouseArea<'a, Message, Theme, Renderer>
1972where
1973    Renderer: core::Renderer,
1974{
1975    MouseArea::new(widget)
1976}
1977
1978/// A widget that applies any `Theme` to its contents.
1979pub fn themer<'a, Message, Theme, Renderer>(
1980    theme: Option<Theme>,
1981    content: impl Into<Element<'a, Message, Theme, Renderer>>,
1982) -> Themer<'a, Message, Theme, Renderer>
1983where
1984    Theme: theme::Base,
1985    Renderer: core::Renderer,
1986{
1987    Themer::new(theme, content)
1988}
1989
1990/// Creates a [`PaneGrid`] with the given [`pane_grid::State`] and view function.
1991///
1992/// Pane grids let your users split regions of your application and organize layout dynamically.
1993///
1994/// # Example
1995/// ```no_run
1996/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1997/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1998/// #
1999/// use iced::widget::{pane_grid, text};
2000///
2001/// struct State {
2002///     panes: pane_grid::State<Pane>,
2003/// }
2004///
2005/// enum Pane {
2006///     SomePane,
2007///     AnotherKindOfPane,
2008/// }
2009///
2010/// enum Message {
2011///     PaneDragged(pane_grid::DragEvent),
2012///     PaneResized(pane_grid::ResizeEvent),
2013/// }
2014///
2015/// fn view(state: &State) -> Element<'_, Message> {
2016///     pane_grid(&state.panes, |pane, state, is_maximized| {
2017///         pane_grid::Content::new(match state {
2018///             Pane::SomePane => text("This is some pane"),
2019///             Pane::AnotherKindOfPane => text("This is another kind of pane"),
2020///         })
2021///     })
2022///     .on_drag(Message::PaneDragged)
2023///     .on_resize(10, Message::PaneResized)
2024///     .into()
2025/// }
2026/// ```
2027pub fn pane_grid<'a, T, Message, Theme, Renderer>(
2028    state: &'a pane_grid::State<T>,
2029    view: impl Fn(pane_grid::Pane, &'a T, bool) -> pane_grid::Content<'a, Message, Theme, Renderer>,
2030) -> PaneGrid<'a, Message, Theme, Renderer>
2031where
2032    Theme: pane_grid::Catalog,
2033    Renderer: core::Renderer,
2034{
2035    PaneGrid::new(state, view)
2036}
2037
2038/// Creates a new [`Float`] widget with the given content.
2039pub fn float<'a, Message, Theme, Renderer>(
2040    content: impl Into<Element<'a, Message, Theme, Renderer>>,
2041) -> Float<'a, Message, Theme, Renderer>
2042where
2043    Theme: float::Catalog,
2044    Renderer: core::Renderer,
2045{
2046    Float::new(content)
2047}
2048
2049/// Creates a new [`Responsive`] widget with a closure that produces its
2050/// contents.
2051///
2052/// The `view` closure will receive the maximum available space for
2053/// the [`Responsive`] during layout. You can use this [`Size`] to
2054/// conditionally build the contents.
2055pub fn responsive<'a, Message, Theme, Renderer>(
2056    f: impl Fn(Size) -> Element<'a, Message, Theme, Renderer> + 'a,
2057) -> Responsive<'a, Message, Theme, Renderer>
2058where
2059    Renderer: core::Renderer,
2060{
2061    Responsive::new(f)
2062}