Skip to main content

iced_widget/
helpers.rs

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