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