Skip to main content

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            shell: &mut Shell<'_, Message>,
666            viewport: &Rectangle,
667        ) {
668            let is_mouse_press =
669                matches!(event, core::Event::Mouse(mouse::Event::ButtonPressed(_)));
670
671            self.content
672                .as_widget_mut()
673                .update(tree, event, layout, cursor, renderer, shell, viewport);
674
675            if is_mouse_press && cursor.is_over(layout.bounds()) {
676                shell.capture_event();
677            }
678        }
679
680        fn mouse_interaction(
681            &self,
682            state: &core::widget::Tree,
683            layout: core::Layout<'_>,
684            cursor: core::mouse::Cursor,
685            viewport: &core::Rectangle,
686            renderer: &Renderer,
687        ) -> core::mouse::Interaction {
688            let interaction = self
689                .content
690                .as_widget()
691                .mouse_interaction(state, layout, cursor, viewport, renderer);
692
693            if interaction == mouse::Interaction::None && cursor.is_over(layout.bounds()) {
694                mouse::Interaction::Idle
695            } else {
696                interaction
697            }
698        }
699
700        fn overlay<'b>(
701            &'b mut self,
702            state: &'b mut core::widget::Tree,
703            layout: core::Layout<'b>,
704            renderer: &Renderer,
705            viewport: &Rectangle,
706            translation: core::Vector,
707        ) -> Option<core::overlay::Element<'b, Message, Theme, Renderer>> {
708            self.content
709                .as_widget_mut()
710                .overlay(state, layout, renderer, viewport, translation)
711        }
712    }
713
714    Element::new(Opaque {
715        content: content.into(),
716    })
717}
718
719/// Displays a widget on top of another one, only when the base widget is hovered.
720///
721/// This works analogously to a [`stack`], but it will only display the layer on top
722/// when the cursor is over the base. It can be useful for removing visual clutter.
723///
724/// [`stack`]: stack()
725pub fn hover<'a, Message, Theme, Renderer>(
726    base: impl Into<Element<'a, Message, Theme, Renderer>>,
727    top: impl Into<Element<'a, Message, Theme, Renderer>>,
728) -> Element<'a, Message, Theme, Renderer>
729where
730    Message: 'a,
731    Theme: 'a,
732    Renderer: core::Renderer + 'a,
733{
734    use crate::core::layout::{self, Layout};
735    use crate::core::mouse;
736    use crate::core::renderer;
737    use crate::core::widget::tree::{self, Tree};
738    use crate::core::{Event, Rectangle, Shell, Size};
739
740    struct Hover<'a, Message, Theme, Renderer> {
741        base: Element<'a, Message, Theme, Renderer>,
742        top: Element<'a, Message, Theme, Renderer>,
743        is_top_focused: bool,
744        is_top_overlay_active: bool,
745        is_hovered: bool,
746    }
747
748    impl<Message, Theme, Renderer> Widget<Message, Theme, Renderer>
749        for Hover<'_, Message, Theme, Renderer>
750    where
751        Renderer: core::Renderer,
752    {
753        fn tag(&self) -> tree::Tag {
754            struct Tag;
755            tree::Tag::of::<Tag>()
756        }
757
758        fn children(&self) -> Vec<Tree> {
759            vec![Tree::new(&self.base), Tree::new(&self.top)]
760        }
761
762        fn diff(&self, tree: &mut Tree) {
763            tree.diff_children(&[&self.base, &self.top]);
764        }
765
766        fn size(&self) -> Size<Length> {
767            self.base.as_widget().size()
768        }
769
770        fn size_hint(&self) -> Size<Length> {
771            self.base.as_widget().size_hint()
772        }
773
774        fn layout(
775            &mut self,
776            tree: &mut Tree,
777            renderer: &Renderer,
778            limits: &layout::Limits,
779        ) -> layout::Node {
780            let base = self
781                .base
782                .as_widget_mut()
783                .layout(&mut tree.children[0], renderer, limits);
784
785            let top = self.top.as_widget_mut().layout(
786                &mut tree.children[1],
787                renderer,
788                &layout::Limits::new(Size::ZERO, base.size()),
789            );
790
791            layout::Node::with_children(base.size(), vec![base, top])
792        }
793
794        fn draw(
795            &self,
796            tree: &Tree,
797            renderer: &mut Renderer,
798            theme: &Theme,
799            style: &renderer::Style,
800            layout: Layout<'_>,
801            cursor: mouse::Cursor,
802            viewport: &Rectangle,
803        ) {
804            if let Some(bounds) = layout.bounds().intersection(viewport) {
805                let mut children = layout.children().zip(&tree.children);
806
807                let (base_layout, base_tree) = children.next().unwrap();
808
809                self.base.as_widget().draw(
810                    base_tree,
811                    renderer,
812                    theme,
813                    style,
814                    base_layout,
815                    cursor,
816                    viewport,
817                );
818
819                if cursor.is_over(layout.bounds())
820                    || self.is_top_focused
821                    || self.is_top_overlay_active
822                {
823                    let (top_layout, top_tree) = children.next().unwrap();
824
825                    renderer.with_layer(bounds, |renderer| {
826                        self.top.as_widget().draw(
827                            top_tree, renderer, theme, style, top_layout, cursor, viewport,
828                        );
829                    });
830                }
831            }
832        }
833
834        fn operate(
835            &mut self,
836            tree: &mut Tree,
837            layout: Layout<'_>,
838            renderer: &Renderer,
839            operation: &mut dyn operation::Operation,
840        ) {
841            let children = [&mut self.base, &mut self.top]
842                .into_iter()
843                .zip(layout.children().zip(&mut tree.children));
844
845            for (child, (layout, tree)) in children {
846                child
847                    .as_widget_mut()
848                    .operate(tree, layout, renderer, operation);
849            }
850        }
851
852        fn update(
853            &mut self,
854            tree: &mut Tree,
855            event: &Event,
856            layout: Layout<'_>,
857            cursor: mouse::Cursor,
858            renderer: &Renderer,
859            shell: &mut Shell<'_, Message>,
860            viewport: &Rectangle,
861        ) {
862            let mut children = layout.children().zip(&mut tree.children);
863            let (base_layout, base_tree) = children.next().unwrap();
864            let (top_layout, top_tree) = children.next().unwrap();
865
866            let is_hovered = cursor.is_over(layout.bounds());
867
868            if matches!(event, Event::Window(window::Event::RedrawRequested(_))) {
869                let mut count_focused = operation::focusable::count();
870
871                self.top.as_widget_mut().operate(
872                    top_tree,
873                    top_layout,
874                    renderer,
875                    &mut operation::black_box(&mut count_focused),
876                );
877
878                self.is_top_focused = match count_focused.finish() {
879                    operation::Outcome::Some(count) => count.focused.is_some(),
880                    _ => false,
881                };
882
883                self.is_hovered = is_hovered;
884            } else if is_hovered != self.is_hovered {
885                shell.request_redraw();
886            }
887
888            let is_visible = is_hovered || self.is_top_focused || self.is_top_overlay_active;
889
890            if matches!(
891                event,
892                Event::Mouse(mouse::Event::CursorMoved { .. } | mouse::Event::ButtonReleased(_))
893            ) || is_visible
894            {
895                let redraw_request = shell.redraw_request();
896
897                self.top.as_widget_mut().update(
898                    top_tree, event, top_layout, cursor, renderer, shell, viewport,
899                );
900
901                // Ignore redraw requests of invisible content
902                if !is_visible {
903                    Shell::replace_redraw_request(shell, redraw_request);
904                }
905
906                if shell.is_event_captured() {
907                    return;
908                }
909            };
910
911            self.base.as_widget_mut().update(
912                base_tree,
913                event,
914                base_layout,
915                cursor,
916                renderer,
917                shell,
918                viewport,
919            );
920        }
921
922        fn mouse_interaction(
923            &self,
924            tree: &Tree,
925            layout: Layout<'_>,
926            cursor: mouse::Cursor,
927            viewport: &Rectangle,
928            renderer: &Renderer,
929        ) -> mouse::Interaction {
930            [&self.base, &self.top]
931                .into_iter()
932                .rev()
933                .zip(layout.children().rev().zip(tree.children.iter().rev()))
934                .map(|(child, (layout, tree))| {
935                    child
936                        .as_widget()
937                        .mouse_interaction(tree, layout, cursor, viewport, renderer)
938                })
939                .find(|&interaction| interaction != mouse::Interaction::None)
940                .unwrap_or_default()
941        }
942
943        fn overlay<'b>(
944            &'b mut self,
945            tree: &'b mut core::widget::Tree,
946            layout: core::Layout<'b>,
947            renderer: &Renderer,
948            viewport: &Rectangle,
949            translation: core::Vector,
950        ) -> Option<core::overlay::Element<'b, Message, Theme, Renderer>> {
951            let mut overlays = [&mut self.base, &mut self.top]
952                .into_iter()
953                .zip(layout.children().zip(tree.children.iter_mut()))
954                .map(|(child, (layout, tree))| {
955                    child
956                        .as_widget_mut()
957                        .overlay(tree, layout, renderer, viewport, translation)
958                });
959
960            if let Some(base_overlay) = overlays.next()? {
961                return Some(base_overlay);
962            }
963
964            let top_overlay = overlays.next()?;
965            self.is_top_overlay_active = top_overlay.is_some();
966
967            top_overlay
968        }
969    }
970
971    Element::new(Hover {
972        base: base.into(),
973        top: top.into(),
974        is_top_focused: false,
975        is_top_overlay_active: false,
976        is_hovered: false,
977    })
978}
979
980/// Creates a new [`Sensor`] widget.
981///
982/// A [`Sensor`] widget can generate messages when its contents are shown,
983/// hidden, or resized.
984///
985/// It can even notify you with anticipation at a given distance!
986pub fn sensor<'a, Message, Theme, Renderer>(
987    content: impl Into<Element<'a, Message, Theme, Renderer>>,
988) -> Sensor<'a, (), Message, Theme, Renderer>
989where
990    Renderer: core::Renderer,
991{
992    Sensor::new(content)
993}
994
995/// Creates a new [`Scrollable`] with the provided content.
996///
997/// Scrollables let users navigate an endless amount of content with a scrollbar.
998///
999/// # Example
1000/// ```no_run
1001/// # mod iced { pub mod widget { pub use iced_widget::*; } }
1002/// # pub type State = ();
1003/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1004/// use iced::widget::{column, scrollable, space};
1005///
1006/// enum Message {
1007///     // ...
1008/// }
1009///
1010/// fn view(state: &State) -> Element<'_, Message> {
1011///     scrollable(column![
1012///         "Scroll me!",
1013///         space().height(3000),
1014///         "You did it!",
1015///     ]).into()
1016/// }
1017/// ```
1018pub fn scrollable<'a, Message, Theme, Renderer>(
1019    content: impl Into<Element<'a, Message, Theme, Renderer>>,
1020) -> Scrollable<'a, Message, Theme, Renderer>
1021where
1022    Theme: scrollable::Catalog + 'a,
1023    Renderer: core::text::Renderer,
1024{
1025    Scrollable::new(content)
1026}
1027
1028/// Creates a new [`Button`] with the provided content.
1029///
1030/// # Example
1031/// ```no_run
1032/// # mod iced { pub mod widget { pub use iced_widget::*; } }
1033/// # pub type State = ();
1034/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1035/// use iced::widget::button;
1036///
1037/// #[derive(Clone)]
1038/// enum Message {
1039///     ButtonPressed,
1040/// }
1041///
1042/// fn view(state: &State) -> Element<'_, Message> {
1043///     button("Press me!").on_press(Message::ButtonPressed).into()
1044/// }
1045/// ```
1046pub fn button<'a, Message, Theme, Renderer>(
1047    content: impl Into<Element<'a, Message, Theme, Renderer>>,
1048) -> Button<'a, Message, Theme, Renderer>
1049where
1050    Theme: button::Catalog + 'a,
1051    Renderer: core::Renderer,
1052{
1053    Button::new(content)
1054}
1055
1056/// Creates a new [`Tooltip`] for the provided content with the given
1057/// [`Element`] and [`tooltip::Position`].
1058///
1059/// Tooltips display a hint of information over some element when hovered.
1060///
1061/// # Example
1062/// ```no_run
1063/// # mod iced { pub mod widget { pub use iced_widget::*; } }
1064/// # pub type State = ();
1065/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1066/// use iced::widget::{container, tooltip};
1067///
1068/// enum Message {
1069///     // ...
1070/// }
1071///
1072/// fn view(_state: &State) -> Element<'_, Message> {
1073///     tooltip(
1074///         "Hover me to display the tooltip!",
1075///         container("This is the tooltip contents!")
1076///             .padding(10)
1077///             .style(container::rounded_box),
1078///         tooltip::Position::Bottom,
1079///     ).into()
1080/// }
1081/// ```
1082pub fn tooltip<'a, Message, Theme, Renderer>(
1083    content: impl Into<Element<'a, Message, Theme, Renderer>>,
1084    tooltip: impl Into<Element<'a, Message, Theme, Renderer>>,
1085    position: tooltip::Position,
1086) -> crate::Tooltip<'a, Message, Theme, Renderer>
1087where
1088    Theme: container::Catalog + 'a,
1089    Renderer: core::text::Renderer,
1090{
1091    Tooltip::new(content, tooltip, position)
1092}
1093
1094/// Creates a new [`Text`] widget with the provided content.
1095///
1096/// # Example
1097/// ```no_run
1098/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1099/// # pub type State = ();
1100/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::core::Theme, ()>;
1101/// use iced::widget::text;
1102/// use iced::color;
1103///
1104/// enum Message {
1105///     // ...
1106/// }
1107///
1108/// fn view(state: &State) -> Element<'_, Message> {
1109///     text("Hello, this is iced!")
1110///         .size(20)
1111///         .color(color!(0x0000ff))
1112///         .into()
1113/// }
1114/// ```
1115pub fn text<'a, Theme, Renderer>(text: impl text::IntoFragment<'a>) -> Text<'a, Theme, Renderer>
1116where
1117    Theme: text::Catalog + 'a,
1118    Renderer: core::text::Renderer,
1119{
1120    Text::new(text)
1121}
1122
1123/// Creates a new [`Text`] widget that displays the provided value.
1124pub fn value<'a, Theme, Renderer>(value: impl ToString) -> Text<'a, Theme, Renderer>
1125where
1126    Theme: text::Catalog + 'a,
1127    Renderer: core::text::Renderer,
1128{
1129    Text::new(value.to_string())
1130}
1131
1132/// Creates a new [`Rich`] text widget with the provided spans.
1133///
1134/// [`Rich`]: text::Rich
1135///
1136/// # Example
1137/// ```no_run
1138/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::core::*; }
1139/// # pub type State = ();
1140/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1141/// use iced::font;
1142/// use iced::widget::{rich_text, span};
1143/// use iced::{color, never, Font};
1144///
1145/// #[derive(Debug, Clone)]
1146/// enum Message {
1147///     LinkClicked(&'static str),
1148///     // ...
1149/// }
1150///
1151/// fn view(state: &State) -> Element<'_, Message> {
1152///     rich_text([
1153///         span("I am red!").color(color!(0xff0000)),
1154///         span(" "),
1155///         span("And I am bold!").font(Font { weight: font::Weight::Bold, ..Font::default() }),
1156///     ])
1157///     .on_link_click(never)
1158///     .size(20)
1159///     .into()
1160/// }
1161/// ```
1162pub fn rich_text<'a, Link, Message, Theme, Renderer>(
1163    spans: impl AsRef<[text::Span<'a, Link, Renderer::Font>]> + 'a,
1164) -> text::Rich<'a, Link, Message, Theme, Renderer>
1165where
1166    Link: Clone + 'static,
1167    Theme: text::Catalog + 'a,
1168    Renderer: core::text::Renderer,
1169    Renderer::Font: 'a,
1170{
1171    text::Rich::with_spans(spans)
1172}
1173
1174/// Creates a new [`Span`] of text with the provided content.
1175///
1176/// A [`Span`] is a fragment of some [`Rich`] text.
1177///
1178/// [`Span`]: text::Span
1179/// [`Rich`]: text::Rich
1180///
1181/// # Example
1182/// ```no_run
1183/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::core::*; }
1184/// # pub type State = ();
1185/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1186/// use iced::font;
1187/// use iced::widget::{rich_text, span};
1188/// use iced::{color, never, Font};
1189///
1190/// #[derive(Debug, Clone)]
1191/// enum Message {
1192///     // ...
1193/// }
1194///
1195/// fn view(state: &State) -> Element<'_, Message> {
1196///     rich_text![
1197///         span("I am red!").color(color!(0xff0000)),
1198///         " ",
1199///         span("And I am bold!").font(Font { weight: font::Weight::Bold, ..Font::default() }),
1200///     ]
1201///     .on_link_click(never)
1202///     .size(20)
1203///     .into()
1204/// }
1205/// ```
1206pub fn span<'a, Link, Font>(text: impl text::IntoFragment<'a>) -> text::Span<'a, Link, Font> {
1207    text::Span::new(text)
1208}
1209
1210#[cfg(feature = "markdown")]
1211#[doc(inline)]
1212pub use crate::markdown::view as markdown;
1213
1214/// Creates a new [`Checkbox`].
1215///
1216/// # Example
1217/// ```no_run
1218/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1219/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1220/// #
1221/// use iced::widget::checkbox;
1222///
1223/// struct State {
1224///    is_checked: bool,
1225/// }
1226///
1227/// enum Message {
1228///     CheckboxToggled(bool),
1229/// }
1230///
1231/// fn view(state: &State) -> Element<'_, Message> {
1232///     checkbox(state.is_checked)
1233///         .label("Toggle me!")
1234///         .on_toggle(Message::CheckboxToggled)
1235///         .into()
1236/// }
1237///
1238/// fn update(state: &mut State, message: Message) {
1239///     match message {
1240///         Message::CheckboxToggled(is_checked) => {
1241///             state.is_checked = is_checked;
1242///         }
1243///     }
1244/// }
1245/// ```
1246/// ![Checkbox drawn by `iced_wgpu`](https://github.com/iced-rs/iced/blob/7760618fb112074bc40b148944521f312152012a/docs/images/checkbox.png?raw=true)
1247pub fn checkbox<'a, Message, Theme, Renderer>(
1248    is_checked: bool,
1249) -> Checkbox<'a, Message, Theme, Renderer>
1250where
1251    Theme: checkbox::Catalog + 'a,
1252    Renderer: core::text::Renderer,
1253{
1254    Checkbox::new(is_checked)
1255}
1256
1257/// Creates a new [`Radio`].
1258///
1259/// Radio buttons let users choose a single option from a bunch of options.
1260///
1261/// # Example
1262/// ```no_run
1263/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1264/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1265/// #
1266/// use iced::widget::{column, radio};
1267///
1268/// struct State {
1269///    selection: Option<Choice>,
1270/// }
1271///
1272/// #[derive(Debug, Clone, Copy)]
1273/// enum Message {
1274///     RadioSelected(Choice),
1275/// }
1276///
1277/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
1278/// enum Choice {
1279///     A,
1280///     B,
1281///     C,
1282///     All,
1283/// }
1284///
1285/// fn view(state: &State) -> Element<'_, Message> {
1286///     let a = radio(
1287///         "A",
1288///         Choice::A,
1289///         state.selection,
1290///         Message::RadioSelected,
1291///     );
1292///
1293///     let b = radio(
1294///         "B",
1295///         Choice::B,
1296///         state.selection,
1297///         Message::RadioSelected,
1298///     );
1299///
1300///     let c = radio(
1301///         "C",
1302///         Choice::C,
1303///         state.selection,
1304///         Message::RadioSelected,
1305///     );
1306///
1307///     let all = radio(
1308///         "All of the above",
1309///         Choice::All,
1310///         state.selection,
1311///         Message::RadioSelected
1312///     );
1313///
1314///     column![a, b, c, all].into()
1315/// }
1316/// ```
1317pub fn radio<'a, Message, Theme, Renderer, V>(
1318    label: impl Into<String>,
1319    value: V,
1320    selected: Option<V>,
1321    on_click: impl FnOnce(V) -> Message,
1322) -> Radio<'a, Message, Theme, Renderer>
1323where
1324    Message: Clone,
1325    Theme: radio::Catalog + 'a,
1326    Renderer: core::text::Renderer,
1327    V: Copy + Eq,
1328{
1329    Radio::new(label, value, selected, on_click)
1330}
1331
1332/// Creates a new [`Toggler`].
1333///
1334/// Togglers let users make binary choices by toggling a switch.
1335///
1336/// # Example
1337/// ```no_run
1338/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1339/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1340/// #
1341/// use iced::widget::toggler;
1342///
1343/// struct State {
1344///    is_checked: bool,
1345/// }
1346///
1347/// enum Message {
1348///     TogglerToggled(bool),
1349/// }
1350///
1351/// fn view(state: &State) -> Element<'_, Message> {
1352///     toggler(state.is_checked)
1353///         .label("Toggle me!")
1354///         .on_toggle(Message::TogglerToggled)
1355///         .into()
1356/// }
1357///
1358/// fn update(state: &mut State, message: Message) {
1359///     match message {
1360///         Message::TogglerToggled(is_checked) => {
1361///             state.is_checked = is_checked;
1362///         }
1363///     }
1364/// }
1365/// ```
1366pub fn toggler<'a, Message, Theme, Renderer>(
1367    is_checked: bool,
1368) -> Toggler<'a, Message, Theme, Renderer>
1369where
1370    Theme: toggler::Catalog + 'a,
1371    Renderer: core::text::Renderer,
1372{
1373    Toggler::new(is_checked)
1374}
1375
1376/// Creates a new [`TextInput`].
1377///
1378/// Text inputs display fields that can be filled with text.
1379///
1380/// # Example
1381/// ```no_run
1382/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1383/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1384/// #
1385/// use iced::widget::text_input;
1386///
1387/// struct State {
1388///    content: String,
1389/// }
1390///
1391/// #[derive(Debug, Clone)]
1392/// enum Message {
1393///     ContentChanged(String)
1394/// }
1395///
1396/// fn view(state: &State) -> Element<'_, Message> {
1397///     text_input("Type something here...", &state.content)
1398///         .on_input(Message::ContentChanged)
1399///         .into()
1400/// }
1401///
1402/// fn update(state: &mut State, message: Message) {
1403///     match message {
1404///         Message::ContentChanged(content) => {
1405///             state.content = content;
1406///         }
1407///     }
1408/// }
1409/// ```
1410pub fn text_input<'a, Message, Theme, Renderer>(
1411    placeholder: &str,
1412    value: &str,
1413) -> TextInput<'a, Message, Theme, Renderer>
1414where
1415    Message: Clone,
1416    Theme: text_input::Catalog + 'a,
1417    Renderer: core::text::Renderer,
1418{
1419    TextInput::new(placeholder, value)
1420}
1421
1422/// Creates a new [`TextEditor`].
1423///
1424/// Text editors display a multi-line text input for text editing.
1425///
1426/// # Example
1427/// ```no_run
1428/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1429/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1430/// #
1431/// use iced::widget::text_editor;
1432///
1433/// struct State {
1434///    content: text_editor::Content,
1435/// }
1436///
1437/// #[derive(Debug, Clone)]
1438/// enum Message {
1439///     Edit(text_editor::Action)
1440/// }
1441///
1442/// fn view(state: &State) -> Element<'_, Message> {
1443///     text_editor(&state.content)
1444///         .placeholder("Type something here...")
1445///         .on_action(Message::Edit)
1446///         .into()
1447/// }
1448///
1449/// fn update(state: &mut State, message: Message) {
1450///     match message {
1451///         Message::Edit(action) => {
1452///             state.content.perform(action);
1453///         }
1454///     }
1455/// }
1456/// ```
1457pub fn text_editor<'a, Message, Theme, Renderer>(
1458    content: &'a text_editor::Content<Renderer>,
1459) -> TextEditor<'a, core::text::highlighter::PlainText, Message, Theme, Renderer>
1460where
1461    Message: Clone,
1462    Theme: text_editor::Catalog + 'a,
1463    Renderer: core::text::Renderer,
1464{
1465    TextEditor::new(content)
1466}
1467
1468/// Creates a new [`Slider`].
1469///
1470/// Sliders let users set a value by moving an indicator.
1471///
1472/// # Example
1473/// ```no_run
1474/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1475/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1476/// #
1477/// use iced::widget::slider;
1478///
1479/// struct State {
1480///    value: f32,
1481/// }
1482///
1483/// #[derive(Debug, Clone)]
1484/// enum Message {
1485///     ValueChanged(f32),
1486/// }
1487///
1488/// fn view(state: &State) -> Element<'_, Message> {
1489///     slider(0.0..=100.0, state.value, Message::ValueChanged).into()
1490/// }
1491///
1492/// fn update(state: &mut State, message: Message) {
1493///     match message {
1494///         Message::ValueChanged(value) => {
1495///             state.value = value;
1496///         }
1497///     }
1498/// }
1499/// ```
1500pub fn slider<'a, T, Message, Theme>(
1501    range: std::ops::RangeInclusive<T>,
1502    value: T,
1503    on_change: impl Fn(T) -> Message + 'a,
1504) -> Slider<'a, T, Message, Theme>
1505where
1506    T: Copy + From<u8> + std::cmp::PartialOrd,
1507    Message: Clone,
1508    Theme: slider::Catalog + 'a,
1509{
1510    Slider::new(range, value, on_change)
1511}
1512
1513/// Creates a new [`VerticalSlider`].
1514///
1515/// Sliders let users set a value by moving an indicator.
1516///
1517/// # Example
1518/// ```no_run
1519/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1520/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1521/// #
1522/// use iced::widget::vertical_slider;
1523///
1524/// struct State {
1525///    value: f32,
1526/// }
1527///
1528/// #[derive(Debug, Clone)]
1529/// enum Message {
1530///     ValueChanged(f32),
1531/// }
1532///
1533/// fn view(state: &State) -> Element<'_, Message> {
1534///     vertical_slider(0.0..=100.0, state.value, Message::ValueChanged).into()
1535/// }
1536///
1537/// fn update(state: &mut State, message: Message) {
1538///     match message {
1539///         Message::ValueChanged(value) => {
1540///             state.value = value;
1541///         }
1542///     }
1543/// }
1544/// ```
1545pub fn vertical_slider<'a, T, Message, Theme>(
1546    range: std::ops::RangeInclusive<T>,
1547    value: T,
1548    on_change: impl Fn(T) -> Message + 'a,
1549) -> VerticalSlider<'a, T, Message, Theme>
1550where
1551    T: Copy + From<u8> + std::cmp::PartialOrd,
1552    Message: Clone,
1553    Theme: vertical_slider::Catalog + 'a,
1554{
1555    VerticalSlider::new(range, value, on_change)
1556}
1557
1558/// Creates a new [`PickList`].
1559///
1560/// Pick lists display a dropdown list of selectable options.
1561///
1562/// # Example
1563/// ```no_run
1564/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1565/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1566/// #
1567/// use iced::widget::pick_list;
1568///
1569/// struct State {
1570///    favorite: Option<Fruit>,
1571/// }
1572///
1573/// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
1574/// enum Fruit {
1575///     Apple,
1576///     Orange,
1577///     Strawberry,
1578///     Tomato,
1579/// }
1580///
1581/// #[derive(Debug, Clone)]
1582/// enum Message {
1583///     FruitSelected(Fruit),
1584/// }
1585///
1586/// fn view(state: &State) -> Element<'_, Message> {
1587///     let fruits = [
1588///         Fruit::Apple,
1589///         Fruit::Orange,
1590///         Fruit::Strawberry,
1591///         Fruit::Tomato,
1592///     ];
1593///
1594///     pick_list(
1595///         state.favorite,
1596///         fruits,
1597///         Fruit::to_string,
1598///     )
1599///     .on_select(Message::FruitSelected)
1600///     .placeholder("Select your favorite fruit...")
1601///     .into()
1602/// }
1603///
1604/// fn update(state: &mut State, message: Message) {
1605///     match message {
1606///         Message::FruitSelected(fruit) => {
1607///             state.favorite = Some(fruit);
1608///         }
1609///     }
1610/// }
1611///
1612/// impl std::fmt::Display for Fruit {
1613///     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1614///         f.write_str(match self {
1615///             Self::Apple => "Apple",
1616///             Self::Orange => "Orange",
1617///             Self::Strawberry => "Strawberry",
1618///             Self::Tomato => "Tomato",
1619///         })
1620///     }
1621/// }
1622/// ```
1623pub fn pick_list<'a, T, L, V, Message, Theme, Renderer>(
1624    selected: Option<V>,
1625    options: L,
1626    to_string: impl Fn(&T) -> String + 'a,
1627) -> PickList<'a, T, L, V, Message, Theme, Renderer>
1628where
1629    T: PartialEq + Clone + 'a,
1630    L: Borrow<[T]> + 'a,
1631    V: Borrow<T> + 'a,
1632    Message: Clone,
1633    Theme: pick_list::Catalog + overlay::menu::Catalog,
1634    Renderer: core::text::Renderer,
1635{
1636    PickList::new(selected, options, to_string)
1637}
1638
1639/// Creates a new [`ComboBox`].
1640///
1641/// Combo boxes display a dropdown list of searchable and selectable options.
1642///
1643/// # Example
1644/// ```no_run
1645/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1646/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1647/// #
1648/// use iced::widget::combo_box;
1649///
1650/// struct State {
1651///    fruits: combo_box::State<Fruit>,
1652///    favorite: Option<Fruit>,
1653/// }
1654///
1655/// #[derive(Debug, Clone)]
1656/// enum Fruit {
1657///     Apple,
1658///     Orange,
1659///     Strawberry,
1660///     Tomato,
1661/// }
1662///
1663/// #[derive(Debug, Clone)]
1664/// enum Message {
1665///     FruitSelected(Fruit),
1666/// }
1667///
1668/// fn view(state: &State) -> Element<'_, Message> {
1669///     combo_box(
1670///         &state.fruits,
1671///         "Select your favorite fruit...",
1672///         state.favorite.as_ref(),
1673///         Message::FruitSelected
1674///     )
1675///     .into()
1676/// }
1677///
1678/// fn update(state: &mut State, message: Message) {
1679///     match message {
1680///         Message::FruitSelected(fruit) => {
1681///             state.favorite = Some(fruit);
1682///         }
1683///     }
1684/// }
1685///
1686/// impl std::fmt::Display for Fruit {
1687///     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1688///         f.write_str(match self {
1689///             Self::Apple => "Apple",
1690///             Self::Orange => "Orange",
1691///             Self::Strawberry => "Strawberry",
1692///             Self::Tomato => "Tomato",
1693///         })
1694///     }
1695/// }
1696/// ```
1697pub fn combo_box<'a, T, Message, Theme, Renderer>(
1698    state: &'a combo_box::State<T>,
1699    placeholder: &str,
1700    selection: Option<&T>,
1701    on_selected: impl Fn(T) -> Message + 'a,
1702) -> ComboBox<'a, T, Message, Theme, Renderer>
1703where
1704    T: std::fmt::Display + Clone,
1705    Theme: combo_box::Catalog + 'a,
1706    Renderer: core::text::Renderer,
1707{
1708    ComboBox::new(state, placeholder, selection, on_selected)
1709}
1710
1711/// Creates some empty [`Space`] with no size.
1712///
1713/// This is considered the "identity" widget. It will take
1714/// no space and do nothing.
1715pub fn space() -> Space {
1716    Space::new()
1717}
1718
1719/// Creates a new [`ProgressBar`].
1720///
1721/// Progress bars visualize the progression of an extended computer operation, such as a download, file transfer, or installation.
1722///
1723/// It expects:
1724///   * an inclusive range of possible values, and
1725///   * the current value of the [`ProgressBar`].
1726///
1727/// # Example
1728/// ```no_run
1729/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1730/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1731/// #
1732/// use iced::widget::progress_bar;
1733///
1734/// struct State {
1735///    progress: f32,
1736/// }
1737///
1738/// enum Message {
1739///     // ...
1740/// }
1741///
1742/// fn view(state: &State) -> Element<'_, Message> {
1743///     progress_bar(0.0..=100.0, state.progress).into()
1744/// }
1745/// ```
1746pub fn progress_bar<'a, Theme>(range: RangeInclusive<f32>, value: f32) -> ProgressBar<'a, Theme>
1747where
1748    Theme: progress_bar::Catalog + 'a,
1749{
1750    ProgressBar::new(range, value)
1751}
1752
1753/// Creates a new [`Image`].
1754///
1755/// Images display raster graphics in different formats (PNG, JPG, etc.).
1756///
1757/// [`Image`]: crate::Image
1758///
1759/// # Example
1760/// ```no_run
1761/// # mod iced { pub mod widget { pub use iced_widget::*; } }
1762/// # pub type State = ();
1763/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1764/// use iced::widget::image;
1765///
1766/// enum Message {
1767///     // ...
1768/// }
1769///
1770/// fn view(state: &State) -> Element<'_, Message> {
1771///     use std::sync::LazyLock;
1772///
1773///     static IMAGE: LazyLock<image::Handle> = LazyLock::new(|| image::Handle::from_path("ferris.png"));
1774///
1775///     image(&IMAGE).into()
1776/// }
1777/// ```
1778/// <img src="https://github.com/iced-rs/iced/blob/9712b319bb7a32848001b96bd84977430f14b623/examples/resources/ferris.png?raw=true" width="300">
1779#[cfg(feature = "image")]
1780pub fn image<'a>(handle: &'a crate::image::Handle) -> crate::Image<'a, crate::image::Handle> {
1781    crate::Image::new(handle)
1782}
1783
1784/// Creates a new [`Svg`] widget from the given [`Handle`].
1785///
1786/// Svg widgets display vector graphics in your application.
1787///
1788/// [`Svg`]: crate::Svg
1789/// [`Handle`]: crate::svg::Handle
1790///
1791/// # Example
1792/// ```no_run
1793/// # mod iced { pub mod widget { pub use iced_widget::*; } }
1794/// # pub type State = ();
1795/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1796/// use iced::widget::svg;
1797///
1798/// enum Message {
1799///     // ...
1800/// }
1801///
1802/// fn view(state: &State) -> Element<'_, Message> {
1803///     svg("tiger.svg").into()
1804/// }
1805/// ```
1806#[cfg(feature = "svg")]
1807pub fn svg<'a, Theme>(handle: impl Into<core::svg::Handle>) -> crate::Svg<'a, Theme>
1808where
1809    Theme: crate::svg::Catalog,
1810{
1811    crate::Svg::new(handle)
1812}
1813
1814/// Creates an [`Element`] that displays the iced logo with the given `text_size`.
1815///
1816/// Useful for showing some love to your favorite GUI library in your "About" screen,
1817/// for instance.
1818pub fn iced<'a, Message, Theme, Renderer>(
1819    text_size: impl Into<core::Pixels>,
1820) -> Element<'a, Message, Theme, Renderer>
1821where
1822    Message: 'a,
1823    Renderer: core::Renderer + core::text::Renderer<Font = core::Font> + 'a,
1824    Theme: text::Catalog + container::Catalog + 'a,
1825    <Theme as container::Catalog>::Class<'a>: From<container::StyleFn<'a, Theme>>,
1826    <Theme as text::Catalog>::Class<'a>: From<text::StyleFn<'a, Theme>>,
1827{
1828    use crate::core::border;
1829    use crate::core::color;
1830    use crate::core::gradient;
1831    use crate::core::{Alignment, Color, Font, Radians};
1832
1833    let text_size = text_size.into();
1834
1835    row![
1836        container(
1837            text(Renderer::ICED_LOGO)
1838                .line_height(1.0)
1839                .size(text_size)
1840                .font(Renderer::ICON_FONT)
1841                .color(Color::WHITE)
1842        )
1843        .padding(text_size * 0.15)
1844        .style(move |_| container::Style {
1845            background: Some(
1846                gradient::Linear::new(Radians::PI / 4.0)
1847                    .add_stop(0.0, color!(0x0033ff))
1848                    .add_stop(1.0, color!(0x1177ff))
1849                    .into()
1850            ),
1851            border: border::rounded(border::radius(text_size * 0.4)),
1852            ..container::Style::default()
1853        }),
1854        text("iced").size(text_size).font(Font::MONOSPACE)
1855    ]
1856    .spacing(text_size.0 / 3.0)
1857    .align_y(Alignment::Center)
1858    .into()
1859}
1860
1861/// Creates a new [`Canvas`].
1862///
1863/// Canvases can be leveraged to draw interactive 2D graphics.
1864///
1865/// [`Canvas`]: crate::Canvas
1866///
1867/// # Example: Drawing a Simple Circle
1868/// ```no_run
1869/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1870/// # pub type State = ();
1871/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1872/// #
1873/// use iced::mouse;
1874/// use iced::widget::canvas;
1875/// use iced::{Color, Rectangle, Renderer, Theme};
1876///
1877/// // First, we define the data we need for drawing
1878/// #[derive(Debug)]
1879/// struct Circle {
1880///     radius: f32,
1881/// }
1882///
1883/// // Then, we implement the `Program` trait
1884/// impl<Message> canvas::Program<Message> for Circle {
1885///     // No internal state
1886///     type State = ();
1887///
1888///     fn draw(
1889///         &self,
1890///         _state: &(),
1891///         renderer: &Renderer,
1892///         _theme: &Theme,
1893///         bounds: Rectangle,
1894///         _cursor: mouse::Cursor
1895///     ) -> Vec<canvas::Geometry> {
1896///         // We prepare a new `Frame`
1897///         let mut frame = canvas::Frame::new(renderer, bounds.size());
1898///
1899///         // We create a `Path` representing a simple circle
1900///         let circle = canvas::Path::circle(frame.center(), self.radius);
1901///
1902///         // And fill it with some color
1903///         frame.fill(&circle, Color::BLACK);
1904///
1905///         // Then, we produce the geometry
1906///         vec![frame.into_geometry()]
1907///     }
1908/// }
1909///
1910/// // Finally, we simply use our `Circle` to create the `Canvas`!
1911/// fn view<'a, Message: 'a>(_state: &'a State) -> Element<'a, Message> {
1912///     canvas(Circle { radius: 50.0 }).into()
1913/// }
1914/// ```
1915#[cfg(feature = "canvas")]
1916pub fn canvas<P, Message, Theme, Renderer>(program: P) -> crate::Canvas<P, Message, Theme, Renderer>
1917where
1918    Renderer: crate::graphics::geometry::Renderer,
1919    P: crate::canvas::Program<Message, Theme, Renderer>,
1920{
1921    crate::Canvas::new(program)
1922}
1923
1924/// Creates a new [`QRCode`] widget from the given [`Data`].
1925///
1926/// QR codes display information in a type of two-dimensional matrix barcode.
1927///
1928/// [`QRCode`]: crate::QRCode
1929/// [`Data`]: crate::qr_code::Data
1930///
1931/// # Example
1932/// ```no_run
1933/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1934/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
1935/// #
1936/// use iced::widget::qr_code;
1937///
1938/// struct State {
1939///    data: qr_code::Data,
1940/// }
1941///
1942/// #[derive(Debug, Clone)]
1943/// enum Message {
1944///     // ...
1945/// }
1946///
1947/// fn view(state: &State) -> Element<'_, Message> {
1948///     qr_code(&state.data).into()
1949/// }
1950/// ```
1951#[cfg(feature = "qr_code")]
1952pub fn qr_code<'a, Theme>(data: &'a crate::qr_code::Data) -> crate::QRCode<'a, Theme>
1953where
1954    Theme: crate::qr_code::Catalog + 'a,
1955{
1956    crate::QRCode::new(data)
1957}
1958
1959/// Creates a new [`Shader`].
1960///
1961/// [`Shader`]: crate::Shader
1962#[cfg(feature = "wgpu")]
1963pub fn shader<Message, P>(program: P) -> crate::Shader<Message, P>
1964where
1965    P: crate::shader::Program<Message>,
1966{
1967    crate::Shader::new(program)
1968}
1969
1970/// Creates a new [`MouseArea`].
1971pub fn mouse_area<'a, Message, Theme, Renderer>(
1972    widget: impl Into<Element<'a, Message, Theme, Renderer>>,
1973) -> MouseArea<'a, Message, Theme, Renderer>
1974where
1975    Renderer: core::Renderer,
1976{
1977    MouseArea::new(widget)
1978}
1979
1980/// A widget that applies any `Theme` to its contents.
1981pub fn themer<'a, Message, Theme, Renderer>(
1982    theme: Option<Theme>,
1983    content: impl Into<Element<'a, Message, Theme, Renderer>>,
1984) -> Themer<'a, Message, Theme, Renderer>
1985where
1986    Theme: theme::Base,
1987    Renderer: core::Renderer,
1988{
1989    Themer::new(theme, content)
1990}
1991
1992/// Creates a [`PaneGrid`] with the given [`pane_grid::State`] and view function.
1993///
1994/// Pane grids let your users split regions of your application and organize layout dynamically.
1995///
1996/// # Example
1997/// ```no_run
1998/// # mod iced { pub mod widget { pub use iced_widget::*; } pub use iced_widget::Renderer; pub use iced_widget::core::*; }
1999/// # pub type Element<'a, Message> = iced_widget::core::Element<'a, Message, iced_widget::Theme, iced_widget::Renderer>;
2000/// #
2001/// use iced::widget::{pane_grid, text};
2002///
2003/// struct State {
2004///     panes: pane_grid::State<Pane>,
2005/// }
2006///
2007/// enum Pane {
2008///     SomePane,
2009///     AnotherKindOfPane,
2010/// }
2011///
2012/// enum Message {
2013///     PaneDragged(pane_grid::DragEvent),
2014///     PaneResized(pane_grid::ResizeEvent),
2015/// }
2016///
2017/// fn view(state: &State) -> Element<'_, Message> {
2018///     pane_grid(&state.panes, |pane, state, is_maximized| {
2019///         pane_grid::Content::new(match state {
2020///             Pane::SomePane => text("This is some pane"),
2021///             Pane::AnotherKindOfPane => text("This is another kind of pane"),
2022///         })
2023///     })
2024///     .on_drag(Message::PaneDragged)
2025///     .on_resize(10, Message::PaneResized)
2026///     .into()
2027/// }
2028/// ```
2029pub fn pane_grid<'a, T, Message, Theme, Renderer>(
2030    state: &'a pane_grid::State<T>,
2031    view: impl Fn(pane_grid::Pane, &'a T, bool) -> pane_grid::Content<'a, Message, Theme, Renderer>,
2032) -> PaneGrid<'a, Message, Theme, Renderer>
2033where
2034    Theme: pane_grid::Catalog,
2035    Renderer: core::Renderer,
2036{
2037    PaneGrid::new(state, view)
2038}
2039
2040/// Creates a new [`Float`] widget with the given content.
2041pub fn float<'a, Message, Theme, Renderer>(
2042    content: impl Into<Element<'a, Message, Theme, Renderer>>,
2043) -> Float<'a, Message, Theme, Renderer>
2044where
2045    Theme: float::Catalog,
2046    Renderer: core::Renderer,
2047{
2048    Float::new(content)
2049}
2050
2051/// Creates a new [`Responsive`] widget with a closure that produces its
2052/// contents.
2053///
2054/// The `view` closure will receive the maximum available space for
2055/// the [`Responsive`] during layout. You can use this [`Size`] to
2056/// conditionally build the contents.
2057pub fn responsive<'a, Message, Theme, Renderer>(
2058    f: impl Fn(Size) -> Element<'a, Message, Theme, Renderer> + 'a,
2059) -> Responsive<'a, Message, Theme, Renderer>
2060where
2061    Renderer: core::Renderer,
2062{
2063    Responsive::new(f)
2064}