Struct druid::widget::ViewSwitcher

source ·
pub struct ViewSwitcher<T, U> { /* private fields */ }
Expand description

A widget that switches dynamically between multiple children.

Implementations§

source§

impl<T: Data, U: Data> ViewSwitcher<T, U>

source

pub fn new( child_picker: impl Fn(&T, &Env) -> U + 'static, child_builder: impl Fn(&U, &T, &Env) -> Box<dyn Widget<T>> + 'static ) -> Self

Create a new view switcher.

The child_picker closure is called every time the application data changes. If the value it returns is the same as the one it returned during the previous data change, nothing happens. If it returns a different value, then the child_builder closure is called with the new value.

The child_builder closure creates a new child widget based on the value passed to it.

Examples
use druid::{
    widget::{Label, ViewSwitcher},
    Data, Widget,
};

#[derive(Clone, PartialEq, Data)]
enum Foo {
    A,
    B,
    C,
}

fn ui() -> impl Widget<Foo> {
    ViewSwitcher::new(
        |data: &Foo, _env| data.clone(),
        |selector, _data, _env| match selector {
            Foo::A => Box::new(Label::new("A")),
            _ => Box::new(Label::new("Not A")),
        },
    )
}
Examples found in repository?
examples/slider.rs (lines 75-89)
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
fn build_root_widget() -> impl Widget<AppState> {
    let range = Flex::row()
        .with_child(Label::dynamic(|value: &(f64, f64), _| {
            format!("Value Range: {value:?}")
        }))
        .with_default_spacer()
        .with_child(
            RangeSlider::new()
                .with_range(0.0, 20.0)
                .with_step(1.0)
                .track_color(KeyOrValue::Concrete(Color::RED))
                .fix_width(250.0),
        )
        .lens(AppState::range);

    let value = Flex::row()
        .with_child(Label::dynamic(|value: &AppState, _| {
            format!("Value: {:?}", value.value)
        }))
        .with_default_spacer()
        .with_child(ViewSwitcher::new(
            |data: &AppState, _| data.range,
            |range, _, _| {
                Slider::new()
                    .with_range(range.0, range.1)
                    .track_color(KeyOrValue::Concrete(Color::RED))
                    .knob_style(KnobStyle::Wedge)
                    .axis(Axis::Vertical)
                    .with_step(0.25)
                    .annotated(1.0, 0.25)
                    .fix_height(250.0)
                    .lens(AppState::value)
                    .boxed()
            },
        ));

    // arrange the two widgets vertically, with some padding
    Flex::column()
        .with_child(range)
        .with_spacer(VERTICAL_WIDGET_SPACING)
        .with_child(value)
        .cross_axis_alignment(CrossAxisAlignment::End)
        .align_vertical(UnitPoint::RIGHT)
        .padding(20.0)
}
More examples
Hide additional examples
examples/tabs.rs (lines 159-162)
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
fn build_root_widget() -> impl Widget<AppState> {
    fn group<T: Data, W: Widget<T> + 'static>(text: &str, w: W) -> impl Widget<T> {
        Flex::column()
            .cross_axis_alignment(CrossAxisAlignment::Start)
            .with_child(
                Label::new(text)
                    .background(theme::PLACEHOLDER_COLOR)
                    .expand_width(),
            )
            .with_default_spacer()
            .with_child(w)
            .with_default_spacer()
            .border(Color::WHITE, 0.5)
    }

    let axis_picker = group(
        "Tab bar axis",
        RadioGroup::column(vec![
            ("Horizontal", Axis::Horizontal),
            ("Vertical", Axis::Vertical),
        ])
        .lens(TabConfig::axis),
    );

    let cross_picker = group(
        "Tab bar edge",
        RadioGroup::column(vec![
            ("Leading", TabsEdge::Leading),
            ("Trailing", TabsEdge::Trailing),
        ])
        .lens(TabConfig::edge),
    );

    let transit_picker = group(
        "Transition",
        RadioGroup::column(vec![
            ("Instant", TabsTransition::Instant),
            (
                "Slide",
                TabsTransition::Slide(Duration::from_millis(250).as_nanos() as u64),
            ),
        ])
        .lens(TabConfig::transition),
    );

    let sidebar = Flex::column()
        .main_axis_alignment(MainAxisAlignment::Start)
        .cross_axis_alignment(CrossAxisAlignment::Start)
        .with_child(axis_picker)
        .with_default_spacer()
        .with_child(cross_picker)
        .with_default_spacer()
        .with_child(transit_picker)
        .with_flex_spacer(1.)
        .fix_width(200.0)
        .lens(AppState::tab_config);

    let vs = ViewSwitcher::new(
        |app_s: &AppState, _| app_s.tab_config.clone(),
        |tc: &TabConfig, _, _| Box::new(build_tab_widget(tc)),
    );
    Flex::row().with_child(sidebar).with_flex_child(vs, 1.0)
}
examples/view_switcher.rs (lines 58-97)
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
fn make_ui() -> impl Widget<AppState> {
    let mut switcher_column = Flex::column();
    switcher_column.add_child(
        Label::new(|data: &u32, _env: &Env| format!("Current view: {data}"))
            .lens(AppState::current_view),
    );
    for i in 0..6 {
        switcher_column.add_spacer(80.);
        switcher_column.add_child(
            Button::new(format!("View {i}"))
                .on_click(move |_event, data: &mut u32, _env| {
                    *data = i;
                })
                .lens(AppState::current_view),
        );
    }

    let view_switcher = ViewSwitcher::new(
        |data: &AppState, _env| data.current_view,
        |selector, _data, _env| match selector {
            0 => Box::new(Label::new("Simple Label").center()),
            1 => Box::new(
                Button::new("Simple Button").on_click(|_event, _data, _env| {
                    println!("Simple button clicked!");
                }),
            ),
            2 => Box::new(
                Button::new("Another Simple Button").on_click(|_event, _data, _env| {
                    println!("Another simple button clicked!");
                }),
            ),
            3 => Box::new(
                Flex::column()
                    .with_flex_child(Label::new("Here is a label").center(), 1.0)
                    .with_flex_child(
                        Button::new("Button").on_click(|_event, _data, _env| {
                            println!("Complex button clicked!");
                        }),
                        1.0,
                    )
                    .with_flex_child(TextBox::new().lens(AppState::current_text), 1.0)
                    .with_flex_child(
                        Label::new(|data: &String, _env: &Env| format!("Value entered: {data}"))
                            .lens(AppState::current_text),
                        1.0,
                    ),
            ),
            4 => Box::new(
                Split::columns(
                    Label::new("Left split").center(),
                    Label::new("Right split").center(),
                )
                .draggable(true),
            ),
            _ => Box::new(Label::new("Unknown").center()),
        },
    );

    Flex::row()
        .with_child(switcher_column)
        .with_flex_child(view_switcher, 1.0)
}

Trait Implementations§

source§

impl<T: Data, U: Data> Widget<T> for ViewSwitcher<T, U>

source§

fn event( &mut self, ctx: &mut EventCtx<'_, '_>, event: &Event, data: &mut T, env: &Env )

Handle an event. Read more
source§

fn lifecycle( &mut self, ctx: &mut LifeCycleCtx<'_, '_>, event: &LifeCycle, data: &T, env: &Env )

Handle a life cycle notification. Read more
source§

fn update( &mut self, ctx: &mut UpdateCtx<'_, '_>, _old_data: &T, data: &T, env: &Env )

Update the widget’s appearance in response to a change in the app’s Data or Env. Read more
source§

fn layout( &mut self, ctx: &mut LayoutCtx<'_, '_>, bc: &BoxConstraints, data: &T, env: &Env ) -> Size

Compute layout. Read more
source§

fn paint(&mut self, ctx: &mut PaintCtx<'_, '_, '_>, data: &T, env: &Env)

Paint the widget appearance. Read more
source§

fn compute_max_intrinsic( &mut self, axis: Axis, ctx: &mut LayoutCtx<'_, '_>, bc: &BoxConstraints, data: &T, env: &Env ) -> f64

Computes max intrinsic/preferred dimension of a widget on the provided axis. Read more

Auto Trait Implementations§

§

impl<T, U> !RefUnwindSafe for ViewSwitcher<T, U>

§

impl<T, U> !Send for ViewSwitcher<T, U>

§

impl<T, U> !Sync for ViewSwitcher<T, U>

§

impl<T, U> Unpin for ViewSwitcher<T, U>where T: Unpin, U: Unpin,

§

impl<T, U> !UnwindSafe for ViewSwitcher<T, U>

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for Twhere U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T> RoundFrom<T> for T

§

fn round_from(x: T) -> T

Performs the conversion.
§

impl<T, U> RoundInto<U> for Twhere U: RoundFrom<T>,

§

fn round_into(self) -> U

Performs the conversion.
source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T, W> TestWidgetExt<T> for Wwhere T: Data, W: Widget<T> + 'static,

source§

fn record(self, recording: &Recording) -> Recorder<Self>

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more