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