Skip to main content

iced_widget/
helpers.rs

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