iced_widget/
helpers.rs

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