Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding added controller widget #1485

Merged
merged 12 commits into from
Jan 8, 2021
62 changes: 62 additions & 0 deletions druid/src/widget/added.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// 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.

//! A [`Controller`] widget that responds to [`LifeCycle::WidgetAdded`] event.
//!
//! [`Controller`]: crate::widget::Controller
//! [`LifeCycle::WidgetAdded`]: crate::LifeCycle::WidgetAdded

use crate::widget::Controller;
use crate::{Data, Env, LifeCycleCtx, Widget};

/// This [`Controller`] widget responds to [`LifeCycle::WidgetAdded`] event
arthmis marked this conversation as resolved.
Show resolved Hide resolved
/// with the provided closure. Pass this and a child widget to [`ControllerHost`]
/// to respond to the event when the child widget is added to the widget tree.
/// This is also available, for convenience, as an `on_added` method
/// via [`WidgetExt`].
///
/// [`Controller`]: crate::widget::Controller
/// [`ControllerHost`]: crate::widget::ControllerHost
/// [`WidgetExt`]: crate::widget::WidgetExt
/// [`LifeCycle::WidgetAdded`]: crate::LifeCycle::WidgetAdded
pub struct Added<T, W> {
/// A closure that will be invoked when the child widget is added
/// to the widget tree
action: Box<dyn Fn(&mut W, &mut LifeCycleCtx, &T, &Env)>,
}

impl<T: Data, W: Widget<T>> Added<T, W> {
/// Create a new [`Controller`] widget to respond to widget added to tree event.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Splitting hairs, maybe, but a Controller isn't a widget (the ControllerHost is).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I was following the Click widget example. I don't remember if that's a full widget or a Controller type. So most of the docs I've written is paraphrasing Click's docs. I was trying to be consistent with that.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know what would be preferred here. I'm leaving it as is. I think calling it a Controller widget is appropriate. Anything else might be too verbose. I guess you can just call it controller like, "Create a new controller to respond to widget added to tree event".

pub fn new(action: impl Fn(&mut W, &mut LifeCycleCtx, &T, &Env) + 'static) -> Self {
Self {
action: Box::new(action),
}
}
}

impl<T: Data, W: Widget<T>> Controller<T, W> for Added<T, W> {
fn lifecycle(
&mut self,
child: &mut W,
ctx: &mut LifeCycleCtx,
event: &crate::LifeCycle,
data: &T,
env: &Env,
) {
if let crate::LifeCycle::WidgetAdded = event {
(self.action)(child, ctx, data, env);
}
child.lifecycle(ctx, event, data, env)
}
}
2 changes: 2 additions & 0 deletions druid/src/widget/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

//! Common widgets.

mod added;
mod align;
mod button;
mod checkbox;
Expand Down Expand Up @@ -55,6 +56,7 @@ mod widget;
mod widget_ext;

pub use self::image::Image;
pub use added::Added;
pub use align::Align;
pub use button::Button;
pub use checkbox::Checkbox;
Expand Down
21 changes: 19 additions & 2 deletions druid/src/widget/widget_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@

use super::invalidation::DebugInvalidation;
use super::{
Align, BackgroundBrush, Click, Container, Controller, ControllerHost, EnvScope,
Added, Align, BackgroundBrush, Click, Container, Controller, ControllerHost, EnvScope,
IdentityWrapper, LensWrap, Padding, Parse, SizedBox, WidgetId,
};
use crate::{Color, Data, Env, EventCtx, Insets, KeyOrValue, Lens, UnitPoint, Widget};
use crate::{
Color, Data, Env, EventCtx, Insets, KeyOrValue, Lens, LifeCycleCtx, UnitPoint, Widget,
};

/// A trait that provides extra methods for combining `Widget`s.
pub trait WidgetExt<T: Data>: Widget<T> + Sized + 'static {
Expand Down Expand Up @@ -159,6 +161,21 @@ pub trait WidgetExt<T: Data>: Widget<T> + Sized + 'static {
ControllerHost::new(self, controller)
}

/// Provide a closure that will be called when this widget is added to the widget tree.
///
/// You can use this to perform any initial setup.
///
/// This is equivalent to handling the [`LifeCycle::WidgetAdded`] event in a
/// custom [`Controller`].
///
/// [`LifeCycle::WidgetAdded`]: crate::LifeCycle::WidgetAdded
fn on_added<W: Widget<T>>(
self,
f: impl Fn(&mut W, &mut LifeCycleCtx, &T, &Env) + 'static,
) -> ControllerHost<Self, Added<T, W>> {
ControllerHost::new(self, Added::new(f))
}
arthmis marked this conversation as resolved.
Show resolved Hide resolved

/// Control the events of this widget with a [`Click`] widget. The closure
/// provided will be called when the widget is clicked with the left mouse
/// button.
Expand Down