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/// 
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}