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