@@ -24,7 +24,7 @@ use crate::piet::{
2424use crate :: {
2525 BoxConstraints , Color , Command , Data , Env , Event , EventCtx , InternalEvent , InternalLifeCycle ,
2626 LayoutCtx , LifeCycle , LifeCycleCtx , PaintCtx , Region , Target , TimerToken , UpdateCtx , Widget ,
27- WidgetId , WindowId ,
27+ WidgetId , WindowHandle , WindowId ,
2828} ;
2929
3030/// Our queue type
@@ -188,23 +188,53 @@ impl<T, W: Widget<T>> WidgetPod<T, W> {
188188 self . state . id
189189 }
190190
191- /// Set layout rectangle .
191+ /// Set the layout [`Rect`] .
192192 ///
193- /// Intended to be called on child widget in container's `layout`
194- /// implementation.
193+ /// A container widget should call the [`Widget::layout`] method on its children in
194+ /// its own [`Widget::layout`] implementation, then possibly modify the returned [`Size`], and
195+ /// finally call this `set_layout_rect` method on the child to set the final layout [`Rect`].
196+ ///
197+ /// The child will receive the [`LifeCycle::Size`] event informing them of the final [`Size`].
198+ ///
199+ /// [`Widget::layout`]: trait.Widget.html#tymethod.layout
200+ /// [`Rect`]: struct.Rect.html
201+ /// [`Size`]: struct.Size.html
202+ /// [`LifeCycle::Size`]: enum.LifeCycle.html#variant.Size
195203 pub fn set_layout_rect ( & mut self , ctx : & mut LayoutCtx , data : & T , env : & Env , layout_rect : Rect ) {
204+ let mut needs_merge = false ;
205+
206+ let old_size = self . state . layout_rect . map ( |r| r. size ( ) ) ;
207+ let new_size = layout_rect. size ( ) ;
208+
196209 self . state . layout_rect = Some ( layout_rect) ;
197210
211+ if old_size. is_none ( ) || old_size. unwrap ( ) != new_size {
212+ let mut child_ctx = LifeCycleCtx {
213+ command_queue : ctx. command_queue ,
214+ base_state : & mut self . state ,
215+ window_id : ctx. window_id ,
216+ window : ctx. window ,
217+ } ;
218+ let size_event = LifeCycle :: Size ( new_size) ;
219+ self . inner . lifecycle ( & mut child_ctx, & size_event, data, env) ;
220+ needs_merge = true ;
221+ }
222+
198223 if WidgetPod :: set_hot_state (
199224 & mut self . inner ,
200225 ctx. command_queue ,
201226 & mut self . state ,
202227 ctx. window_id ,
228+ ctx. window ,
203229 layout_rect,
204230 ctx. mouse_pos ,
205231 data,
206232 env,
207233 ) {
234+ needs_merge = true ;
235+ }
236+
237+ if needs_merge {
208238 ctx. base_state . merge_up ( & self . state ) ;
209239 }
210240 }
@@ -215,9 +245,12 @@ impl<T, W: Widget<T>> WidgetPod<T, W> {
215245 self . layout_rect ( )
216246 }
217247
218- /// The layout rectangle .
248+ /// Returns the layout [`Rect`] .
219249 ///
220- /// This will be same value as set by `set_layout_rect`.
250+ /// This will be the same [`Rect`] that was set by [`set_layout_rect`].
251+ ///
252+ /// [`Rect`]: struct.Rect.html
253+ /// [`set_layout_rect`]: #method.set_layout_rect
221254 pub fn layout_rect ( & self ) -> Rect {
222255 self . state . layout_rect . unwrap_or_default ( )
223256 }
@@ -303,6 +336,7 @@ impl<T, W: Widget<T>> WidgetPod<T, W> {
303336 command_queue : & mut CommandQueue ,
304337 child_state : & mut BaseState ,
305338 window_id : WindowId ,
339+ window : & WindowHandle ,
306340 rect : Rect ,
307341 mouse_pos : Option < Point > ,
308342 data : & T ,
@@ -319,6 +353,7 @@ impl<T, W: Widget<T>> WidgetPod<T, W> {
319353 command_queue,
320354 base_state : child_state,
321355 window_id,
356+ window,
322357 } ;
323358 child. lifecycle ( & mut child_ctx, & hot_changed_event, data, env) ;
324359 // if hot changes and we're showing widget ids, always repaint
@@ -484,6 +519,7 @@ impl<T: Data, W: Widget<T>> WidgetPod<T, W> {
484519 command_queue : ctx. command_queue ,
485520 base_state : & mut self . state ,
486521 window_id : ctx. window_id ,
522+ window : ctx. window ,
487523 text_factory : ctx. text_factory ,
488524 mouse_pos : child_mouse_pos,
489525 } ;
@@ -569,6 +605,7 @@ impl<T: Data, W: Widget<T>> WidgetPod<T, W> {
569605 child_ctx. command_queue ,
570606 child_ctx. base_state ,
571607 child_ctx. window_id ,
608+ child_ctx. window ,
572609 rect,
573610 None ,
574611 data,
@@ -616,6 +653,7 @@ impl<T: Data, W: Widget<T>> WidgetPod<T, W> {
616653 child_ctx. command_queue ,
617654 child_ctx. base_state ,
618655 child_ctx. window_id ,
656+ child_ctx. window ,
619657 rect,
620658 Some ( mouse_event. pos ) ,
621659 data,
@@ -632,6 +670,7 @@ impl<T: Data, W: Widget<T>> WidgetPod<T, W> {
632670 child_ctx. command_queue ,
633671 child_ctx. base_state ,
634672 child_ctx. window_id ,
673+ child_ctx. window ,
635674 rect,
636675 Some ( mouse_event. pos ) ,
637676 data,
@@ -648,6 +687,7 @@ impl<T: Data, W: Widget<T>> WidgetPod<T, W> {
648687 child_ctx. command_queue ,
649688 child_ctx. base_state ,
650689 child_ctx. window_id ,
690+ child_ctx. window ,
651691 rect,
652692 Some ( mouse_event. pos ) ,
653693 data,
@@ -658,6 +698,23 @@ impl<T: Data, W: Widget<T>> WidgetPod<T, W> {
658698 mouse_event. pos -= rect. origin ( ) . to_vec2 ( ) ;
659699 Event :: MouseMove ( mouse_event)
660700 }
701+ Event :: Wheel ( mouse_event) => {
702+ WidgetPod :: set_hot_state (
703+ & mut self . inner ,
704+ child_ctx. command_queue ,
705+ child_ctx. base_state ,
706+ child_ctx. window_id ,
707+ child_ctx. window ,
708+ rect,
709+ Some ( mouse_event. pos ) ,
710+ data,
711+ env,
712+ ) ;
713+ recurse = had_active || child_ctx. base_state . is_hot ;
714+ let mut mouse_event = mouse_event. clone ( ) ;
715+ mouse_event. pos -= rect. origin ( ) . to_vec2 ( ) ;
716+ Event :: Wheel ( mouse_event)
717+ }
661718 Event :: KeyDown ( e) => {
662719 recurse = child_ctx. has_focus ( ) ;
663720 Event :: KeyDown ( * e)
@@ -670,12 +727,6 @@ impl<T: Data, W: Widget<T>> WidgetPod<T, W> {
670727 recurse = child_ctx. has_focus ( ) ;
671728 Event :: Paste ( e. clone ( ) )
672729 }
673- Event :: Wheel ( wheel_event) => {
674- recurse = had_active || child_ctx. base_state . is_hot ;
675- let mut wheel_event = wheel_event. clone ( ) ;
676- wheel_event. pos -= rect. origin ( ) . to_vec2 ( ) ;
677- Event :: Wheel ( wheel_event)
678- }
679730 Event :: Zoom ( zoom) => {
680731 recurse = had_active || child_ctx. base_state . is_hot ;
681732 Event :: Zoom ( * zoom)
@@ -780,6 +831,11 @@ impl<T: Data, W: Widget<T>> WidgetPod<T, W> {
780831
781832 true
782833 }
834+ LifeCycle :: Size ( _) => {
835+ // We are a descendant of a widget that received the Size event.
836+ // This event was meant only for our parent, so don't recurse.
837+ false
838+ }
783839 //NOTE: this is not sent here, but from the special set_hot_state method
784840 LifeCycle :: HotChanged ( _) => false ,
785841 LifeCycle :: FocusChanged ( _) => {
@@ -793,6 +849,7 @@ impl<T: Data, W: Widget<T>> WidgetPod<T, W> {
793849 command_queue : ctx. command_queue ,
794850 base_state : & mut self . state ,
795851 window_id : ctx. window_id ,
852+ window : ctx. window ,
796853 } ;
797854
798855 if recurse {
@@ -959,6 +1016,7 @@ mod tests {
9591016 command_queue : & mut command_queue,
9601017 base_state : & mut state,
9611018 window_id : WindowId :: next ( ) ,
1019+ window : & WindowHandle :: default ( ) ,
9621020 } ;
9631021
9641022 let env = Env :: default ( ) ;
0 commit comments