Skip to main content

iced_widget/
helpers.rs

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