Skip to main content

iced_widget/
helpers.rs

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