iced_widget/
helpers.rs

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