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