diff --git a/druid/src/widget/added.rs b/druid/src/widget/added.rs new file mode 100644 index 0000000000..32f81aba78 --- /dev/null +++ b/druid/src/widget/added.rs @@ -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 +/// 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 { + /// A closure that will be invoked when the child widget is added + /// to the widget tree + action: Box, +} + +impl> Added { + /// Create a new [`Controller`] widget 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> Controller for Added { + 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) + } +} diff --git a/druid/src/widget/mod.rs b/druid/src/widget/mod.rs index 62e50630ee..a00130b4e1 100644 --- a/druid/src/widget/mod.rs +++ b/druid/src/widget/mod.rs @@ -18,6 +18,7 @@ #[macro_use] mod widget_wrapper; +mod added; mod align; mod button; mod checkbox; @@ -59,6 +60,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; diff --git a/druid/src/widget/widget_ext.rs b/druid/src/widget/widget_ext.rs index ccf05b3a05..822a85aa6d 100644 --- a/druid/src/widget/widget_ext.rs +++ b/druid/src/widget/widget_ext.rs @@ -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: Widget + Sized + 'static { @@ -159,6 +161,21 @@ pub trait WidgetExt: Widget + 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( + self, + f: impl Fn(&mut Self, &mut LifeCycleCtx, &T, &Env) + 'static, + ) -> ControllerHost> { + ControllerHost::new(self, Added::new(f)) + } + /// 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.