Skip to content

Commit

Permalink
Merge pull request #1351 from andrewhickman/master
Browse files Browse the repository at this point in the history
Propagate events to hidden widgets in `Either`
  • Loading branch information
luleyleo committed Oct 31, 2020
2 parents 5a127c3 + 9acc014 commit a30b1ef
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 70 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ You can find its changes [documented below](#060---2020-06-01).
- Widgets can specify a baseline, flex rows can align baselines ([#1295] by [@cmyr])
- `TextBox::with_text_color` and `TextBox::set_text_color` ([#1320] by [@cmyr])
- `Checkbox::set_text` to update the label. ([#1346] by [@finnerale])
- `Event::should_propagate_to_hidden` and `Lifecycle::should_propagate_to_hidden` to determine whether an event should be sent to hidden widgets (e.g. in `Tabs` or `Either`). ([#1351] by [@andrewhickman])

### Changed

Expand Down Expand Up @@ -114,6 +115,7 @@ You can find its changes [documented below](#060---2020-06-01).
- Fix `widget::Either` using the wrong paint insets ([#1299] by [@andrewhickman])
- Various fixes to cross-platform menus ([#1306] by [@raphlinus])
- Improve Windows 7 DXGI compatibility ([#1311] by [@raphlinus])
- Fixed `Either` not passing events to its hidden child correctly. ([#1351] by [@andrewhickman])
- Don't drop events while showing file dialogs ([#1302], [#1328] by [@jneem])

### Visual
Expand Down Expand Up @@ -520,6 +522,7 @@ Last release without a changelog :(
[#1326]: https://github.com/linebender/druid/pull/1326
[#1328]: https://github.com/linebender/druid/pull/1328
[#1346]: https://github.com/linebender/druid/pull/1346
[#1351]: https://github.com/linebender/druid/pull/1351

[Unreleased]: https://github.com/linebender/druid/compare/v0.6.0...master
[0.6.0]: https://github.com/linebender/druid/compare/v0.5.0...v0.6.0
Expand Down
22 changes: 7 additions & 15 deletions druid/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -550,21 +550,13 @@ impl<T: Data, W: Widget<T>> WidgetPod<T, W> {
}

// log if we seem not to be laid out when we should be
if self.state.layout_rect.is_none() {
match event {
Event::Internal(_) => (),
Event::Timer(_) => (),
Event::WindowConnected => (),
Event::WindowSize(_) => (),
_ => {
log::warn!(
"Widget '{}' received an event ({:?}) without having been laid out. \
This likely indicates a missed call to set_layout_rect.",
self.inner.type_name(),
event,
);
}
}
if self.state.layout_rect.is_none() && !event.should_propagate_to_hidden() {
log::warn!(
"Widget '{}' received an event ({:?}) without having been laid out. \
This likely indicates a missed call to set_layout_rect.",
self.inner.type_name(),
event,
);
}

// TODO: factor as much logic as possible into monomorphic functions.
Expand Down
32 changes: 32 additions & 0 deletions druid/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,38 @@ impl Event {
_ => Some(self.clone()),
}
}

/// Whether this event should be sent to widgets which are currently not visible
/// (for example the hidden tabs in a tabs widget).
pub fn should_propagate_to_hidden(&self) -> bool {
match self {
Event::WindowConnected
| Event::WindowSize(_)
| Event::Timer(_)
| Event::AnimFrame(_)
| Event::Command(_)
| Event::Internal(_) => true,
Event::MouseDown(_)
| Event::MouseUp(_)
| Event::MouseMove(_)
| Event::Wheel(_)
| Event::KeyDown(_)
| Event::KeyUp(_)
| Event::Paste(_)
| Event::Zoom(_) => false,
}
}
}

impl LifeCycle {
/// Whether this event should be sent to widgets which are currently not visible
/// (for example the hidden tabs in a tabs widget).
pub fn should_propagate_to_hidden(&self) -> bool {
match self {
LifeCycle::WidgetAdded | LifeCycle::Internal(_) => true,
LifeCycle::Size(_) | LifeCycle::HotChanged(_) | LifeCycle::FocusChanged(_) => false,
}
}
}

#[cfg(test)]
Expand Down
50 changes: 25 additions & 25 deletions druid/src/widget/either.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,25 @@ impl<T> Either<T> {

impl<T: Data> Widget<T> for Either<T> {
fn event(&mut self, ctx: &mut EventCtx, event: &Event, data: &mut T, env: &Env) {
if self.current {
self.true_branch.event(ctx, event, data, env)
if event.should_propagate_to_hidden() {
self.true_branch.event(ctx, event, data, env);
self.false_branch.event(ctx, event, data, env);
} else {
self.false_branch.event(ctx, event, data, env)
self.current_widget().event(ctx, event, data, env)
}
}

fn lifecycle(&mut self, ctx: &mut LifeCycleCtx, event: &LifeCycle, data: &T, env: &Env) {
if let LifeCycle::WidgetAdded = event {
self.current = (self.closure)(data, env);
}
self.true_branch.lifecycle(ctx, event, data, env);
self.false_branch.lifecycle(ctx, event, data, env);

if event.should_propagate_to_hidden() {
self.true_branch.lifecycle(ctx, event, data, env);
self.false_branch.lifecycle(ctx, event, data, env);
} else {
self.current_widget().lifecycle(ctx, event, data, env)
}
}

fn update(&mut self, ctx: &mut UpdateCtx, _old_data: &T, data: &T, env: &Env) {
Expand All @@ -67,34 +73,28 @@ impl<T: Data> Widget<T> for Either<T> {
self.current = current;
ctx.request_layout();
}
if self.current {
self.true_branch.update(ctx, data, env);
} else {
self.false_branch.update(ctx, data, env);
}
self.current_widget().update(ctx, data, env)
}

fn layout(&mut self, ctx: &mut LayoutCtx, bc: &BoxConstraints, data: &T, env: &Env) -> Size {
if self.current {
let size = self.true_branch.layout(ctx, bc, data, env);
self.true_branch
.set_layout_rect(ctx, data, env, size.to_rect());
ctx.set_paint_insets(self.true_branch.paint_insets());
size
} else {
let size = self.false_branch.layout(ctx, bc, data, env);
self.false_branch
.set_layout_rect(ctx, data, env, size.to_rect());
ctx.set_paint_insets(self.false_branch.paint_insets());
size
}
let current_widget = self.current_widget();
let size = current_widget.layout(ctx, bc, data, env);
current_widget.set_layout_rect(ctx, data, env, size.to_rect());
ctx.set_paint_insets(current_widget.paint_insets());
size
}

fn paint(&mut self, ctx: &mut PaintCtx, data: &T, env: &Env) {
self.current_widget().paint(ctx, data, env)
}
}

impl<T> Either<T> {
fn current_widget(&mut self) -> &mut WidgetPod<T, Box<dyn Widget<T>>> {
if self.current {
self.true_branch.paint_raw(ctx, data, env);
&mut self.true_branch
} else {
self.false_branch.paint_raw(ctx, data, env);
&mut self.false_branch
}
}
}
32 changes: 2 additions & 30 deletions druid/src/widget/tabs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -550,37 +550,9 @@ impl<TP: TabsPolicy> TabsBody<TP> {
}
}

/// Possibly should be moved to Event
fn hidden_should_receive_event(evt: &Event) -> bool {
match evt {
Event::WindowConnected
| Event::WindowSize(_)
| Event::Timer(_)
| Event::AnimFrame(_)
| Event::Command(_)
| Event::Internal(_) => true,
Event::MouseDown(_)
| Event::MouseUp(_)
| Event::MouseMove(_)
| Event::Wheel(_)
| Event::KeyDown(_)
| Event::KeyUp(_)
| Event::Paste(_)
| Event::Zoom(_) => false,
}
}

/// Possibly should be moved to Lifecycle.
fn hidden_should_receive_lifecycle(lc: &LifeCycle) -> bool {
match lc {
LifeCycle::WidgetAdded | LifeCycle::Internal(_) => true,
LifeCycle::Size(_) | LifeCycle::HotChanged(_) | LifeCycle::FocusChanged(_) => false,
}
}

impl<TP: TabsPolicy> Widget<TabsState<TP>> for TabsBody<TP> {
fn event(&mut self, ctx: &mut EventCtx, event: &Event, data: &mut TabsState<TP>, env: &Env) {
if hidden_should_receive_event(event) {
if event.should_propagate_to_hidden() {
for child in self.child_pods() {
child.event(ctx, event, &mut data.inner, env);
}
Expand Down Expand Up @@ -612,7 +584,7 @@ impl<TP: TabsPolicy> Widget<TabsState<TP>> for TabsBody<TP> {
ctx.request_layout();
}

if hidden_should_receive_lifecycle(event) {
if event.should_propagate_to_hidden() {
for child in self.child_pods() {
child.lifecycle(ctx, event, &data.inner, env);
}
Expand Down

0 comments on commit a30b1ef

Please sign in to comment.