Skip to content
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,7 @@ Last release without a changelog :(
[#1691]: https://github.com/linebender/druid/pull/1691
[#1693]: https://github.com/linebender/druid/pull/1693
[#1695]: https://github.com/linebender/druid/pull/1695
[#1696]: https://github.com/linebender/druid/pull/1696
[#1698]: https://github.com/linebender/druid/pull/1698
[#1702]: https://github.com/linebender/druid/pull/1702

Expand Down
42 changes: 41 additions & 1 deletion druid/examples/disabled.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,25 @@
use druid::widget::{Checkbox, CrossAxisAlignment, Flex, Label, Slider, Stepper, Switch, TextBox};
// Copyright 2020 The Druid Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! An example showing the effect of the disabled state on focus-chain and the widgets.
//! When the disabled checkbox is clicked only the widgets not marked as disabled should
//! respond. Pressing Tab should only focus widgets not marked as disabled. If a widget
//! is focused while getting disabled it should resign the focus.

use druid::widget::{
Button, Checkbox, CrossAxisAlignment, Flex, Label, Slider, Stepper, Switch, TextBox,
};
use druid::{AppLauncher, Data, Lens, LocalizedString, UnitPoint, Widget, WidgetExt, WindowDesc};

#[derive(Clone, Data, Lens)]
Expand Down Expand Up @@ -69,6 +90,25 @@ fn main_widget() -> impl Widget<AppData> {
.disabled_if(|data, _| data.disabled),
))
.with_default_spacer()
.with_child(
Flex::row()
.with_child(
Button::new("-")
.on_click(|_, data: &mut f64, _| *data -= 1.0)
.disabled_if(|data, _| *data < 1.0),
)
.with_default_spacer()
.with_child(Label::dynamic(|data: &f64, _| data.to_string()))
.with_default_spacer()
.with_child(
Button::new("+")
.on_click(|_, data: &mut f64, _| *data += 1.0)
.disabled_if(|data, _| *data > 9.0),
)
.lens(AppData::value)
.disabled_if(|data: &AppData, _| data.disabled),
)
.with_default_spacer()
.with_default_spacer()
.with_default_spacer()
.with_child(Checkbox::new("disabled").lens(AppData::disabled))
Expand Down
23 changes: 22 additions & 1 deletion druid/src/widget/disable_if.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,38 @@
// Copyright 2020 The Druid Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::{
BoxConstraints, Data, Env, Event, EventCtx, LayoutCtx, LifeCycle, LifeCycleCtx, PaintCtx,
Point, Size, UpdateCtx, Widget, WidgetPod,
};

/// A widget wrapper which disables the inner widget if the provided closure return true.
///
/// See [`is_disabled`] or [`set_disabled`] for more info about disabled state.
///
/// [`is_disabled`]: crate::EventCtx::is_disabled
/// [`set_disabled`]: crate::EventCtx::set_disabled
pub struct DisabledIf<T, W> {
inner: WidgetPod<T, W>,
disabled_if: Box<dyn Fn(&T, &Env) -> bool>,
}

impl<T: Data, W: Widget<T>> DisabledIf<T, W> {
/// Creates a new `DisabledIf` widget with the inner widget and the closure to decide if the
/// widget should be disabled.
/// widget should be [`disabled`].
///
/// [`disabled`]: crate::EventCtx::is_disabled
pub fn new(widget: W, disabled_if: impl Fn(&T, &Env) -> bool + 'static) -> Self {
DisabledIf {
inner: WidgetPod::new(widget),
Expand Down
10 changes: 5 additions & 5 deletions druid/src/widget/widget_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,13 +275,13 @@ pub trait WidgetExt<T: Data>: Widget<T> + Sized + 'static {
}

/// Wrap this widget in a [`DisabledIf`] widget.
/// The provided closure will determine if the widget is disabled.
///
/// See [`is_disabled`] or [`set_disabled`] for more info about the disabled state.
/// The provided closure will determine if the widget is disabled.
/// See [`is_disabled`] or [`set_disabled`] for more info about disabled state.
///
/// [`is_disabled`]: struct.EventCtx.html#method.is_disabled
/// [`set_disabled`]: struct.EventCtx.html#method.set_disabled
/// [`DisabledIf`]: widget/struct.DisabledIf.html
/// [`is_disabled`]: crate::EventCtx::is_disabled
/// [`set_disabled`]: crate::EventCtx::set_disabled
/// [`DisabledIf`]: crate::widget::DisabledIf
fn disabled_if(self, disabled_if: impl Fn(&T, &Env) -> bool + 'static) -> DisabledIf<T, Self> {
DisabledIf::new(self, disabled_if)
}
Expand Down