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