Skip to content

Commit 570ecf7

Browse files
committed
Add the LifeCycle::Size event.
1 parent 4eba61c commit 570ecf7

File tree

3 files changed

+51
-5
lines changed

3 files changed

+51
-5
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ This means that druid no longer requires cairo on macOS and uses Core Graphics i
4646
- `WidgetExt::debug_widget_id`, for displaying widget ids on hover. ([#876] by [@cmyr])
4747
- `im` feature, with `Data` support for the [`im` crate](https://docs.rs/im/) collections. ([#924] by [@cmyr])
4848
- `im::Vector` support for the `List` widget. ([#940] by [@xStrom])
49+
- `LifeCycle::Size` event to inform widgets that their size changed. ([#953] by [@xStrom])
4950

5051
### Changed
5152

@@ -194,6 +195,7 @@ This means that druid no longer requires cairo on macOS and uses Core Graphics i
194195
[#942]: https://github.com/xi-editor/druid/pull/942
195196
[#943]: https://github.com/xi-editor/druid/pull/943
196197
[#951]: https://github.com/xi-editor/druid/pull/951
198+
[#953]: https://github.com/xi-editor/druid/pull/953
197199

198200
## [0.5.0] - 2020-04-01
199201

druid/src/core.rs

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -188,13 +188,37 @@ 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+
};
217+
let size_event = LifeCycle::Size(new_size);
218+
self.inner.lifecycle(&mut child_ctx, &size_event, data, env);
219+
needs_merge = true;
220+
}
221+
198222
if WidgetPod::set_hot_state(
199223
&mut self.inner,
200224
ctx.command_queue,
@@ -205,6 +229,10 @@ impl<T, W: Widget<T>> WidgetPod<T, W> {
205229
data,
206230
env,
207231
) {
232+
needs_merge = true;
233+
}
234+
235+
if needs_merge {
208236
ctx.base_state.merge_up(&self.state);
209237
}
210238
}
@@ -215,9 +243,12 @@ impl<T, W: Widget<T>> WidgetPod<T, W> {
215243
self.layout_rect()
216244
}
217245

218-
/// The layout rectangle.
246+
/// Returns the layout [`Rect`].
247+
///
248+
/// This will be the same [`Rect`] that was set by [`set_layout_rect`].
219249
///
220-
/// This will be same value as set by `set_layout_rect`.
250+
/// [`Rect`]: struct.Rect.html
251+
/// [`set_layout_rect`]: #method.set_layout_rect
221252
pub fn layout_rect(&self) -> Rect {
222253
self.state.layout_rect.unwrap_or_default()
223254
}
@@ -790,6 +821,11 @@ impl<T: Data, W: Widget<T>> WidgetPod<T, W> {
790821

791822
true
792823
}
824+
LifeCycle::Size(_) => {
825+
// We are a descendant of a widget that received the Size event.
826+
// This event was meant only for our parent, so don't recurse.
827+
false
828+
}
793829
//NOTE: this is not sent here, but from the special set_hot_state method
794830
LifeCycle::HotChanged(_) => false,
795831
LifeCycle::FocusChanged(_) => {

druid/src/event.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,14 @@ pub enum LifeCycle {
178178
/// [`WidgetPod`]: struct.WidgetPod.html
179179
/// [`LifeCycleCtx::register_for_focus`]: struct.LifeCycleCtx.html#method.register_for_focus
180180
WidgetAdded,
181+
/// Called when the size of the widget changes.
182+
///
183+
/// The [`Size`] is derived from the [`Rect`] that was set with [`WidgetPod::set_layout_rect`].
184+
///
185+
/// [`Size`]: struct.Size.html
186+
/// [`Rect`]: struct.Rect.html
187+
/// [`WidgetPod::set_layout_rect`]: struct.WidgetPod.html#method.set_layout_rect
188+
Size(Size),
181189
/// Called at the beginning of a new animation frame.
182190
///
183191
/// On the first frame when transitioning from idle to animating, `interval`

0 commit comments

Comments
 (0)