iced_widget/
helpers.rs

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