iced_widget/
helpers.rs

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