From 8655bb27ace7a4c4efd992d4d9957b1eca2eb654 Mon Sep 17 00:00:00 2001 From: Ioannis Skottis Date: Fri, 27 Jan 2023 17:20:39 +0000 Subject: [PATCH 1/9] Add foreground function to Container widget and WidgetExt --- druid/src/widget/container.rs | 53 ++++++++++++++++++++++++++++++++++ druid/src/widget/widget_ext.rs | 15 ++++++++-- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/druid/src/widget/container.rs b/druid/src/widget/container.rs index 36acd1705..b557fd9d7 100644 --- a/druid/src/widget/container.rs +++ b/druid/src/widget/container.rs @@ -30,6 +30,7 @@ struct BorderStyle { /// A widget that provides simple visual styling options to a child. pub struct Container { background: Option>, + foreground: Option>, border: Option, corner_radius: KeyOrValue, @@ -41,6 +42,7 @@ impl Container { pub fn new(child: impl Widget + 'static) -> Self { Self { background: None, + foreground: None, border: None, corner_radius: 0.0.into(), child: WidgetPod::new(child).boxed(), @@ -77,6 +79,36 @@ impl Container { self.background = None; } + /// Builder-style method for setting the foreground for this widget. + /// + /// This can be passed anything which can be represented by a [`BackgroundBrush`]; + /// notably, it can be any [`Color`], a [`Key`] resolvable in the [`Env`], + /// any gradient, or a fully custom [`Painter`] widget. + /// + /// [`Key`]: crate::Key + /// [`Painter`]: super::Painter + pub fn foreground(mut self, brush: impl Into>) -> Self { + self.set_foreground(brush); + self + } + + /// Set the foreground for this widget. + /// + /// This can be passed anything which can be represented by a [`BackgroundBrush`]; + /// notably, it can be any [`Color`], a [`Key`] resolvable in the [`Env`], + /// any gradient, or a fully custom [`Painter`] widget. + /// + /// [`Key`]: crate::Key + /// [`Painter`]: super::Painter + pub fn set_foreground(&mut self, brush: impl Into>) { + self.foreground = Some(brush.into()); + } + + /// Clears foreground. + pub fn clear_foreground(&mut self) { + self.foreground = None; + } + /// Builder-style method for painting a border around the widget with a color and width. /// /// Arguments can be either concrete values, or a [`Key`] of the respective @@ -130,6 +162,11 @@ impl Container { self.background.is_some() } + #[cfg(test)] + pub(crate) fn foreground_is_some(&self) -> bool { + self.foreground.is_some() + } + #[cfg(test)] pub(crate) fn border_is_some(&self) -> bool { self.border.is_some() @@ -170,6 +207,11 @@ impl Widget for Container { ctx.request_paint(); } self.child.update(ctx, data, env); + if let Some(brush) = self.foreground.as_mut() { + trace_span!("update foreground").in_scope(|| { + brush.update(ctx, old_data, data, env); + }); + } } #[instrument(name = "Container", level = "trace", skip(self, ctx, bc, data, env))] @@ -228,6 +270,17 @@ impl Widget for Container { }; self.child.paint(ctx, data, env); + + if let Some(foreground) = self.foreground.as_mut() { + let panel = ctx.size().to_rounded_rect(corner_radius); + + trace_span!("paint foreground").in_scope(|| { + ctx.with_save(|ctx| { + ctx.clip(panel); + foreground.paint(ctx, data, env); + }); + }); + } } fn debug_state(&self, data: &T) -> DebugState { diff --git a/druid/src/widget/widget_ext.rs b/druid/src/widget/widget_ext.rs index 5d96de2d6..5df34f475 100644 --- a/druid/src/widget/widget_ext.rs +++ b/druid/src/widget/widget_ext.rs @@ -115,6 +115,13 @@ pub trait WidgetExt: Widget + Sized + 'static { Container::new(self).background(brush) } + /// Wrap this widget in a [`Container`] with the provided `foreground`. + /// + /// See [`Container::background`] for more information. + fn foreground(self, brush: impl Into>) -> Container { + Container::new(self).foreground(brush) + } + /// Wrap this widget in a [`Container`] with the given border. /// /// Arguments can be either concrete values, or a [`Key`] of the respective @@ -303,16 +310,20 @@ mod tests { let widget = Slider::new() .background(Color::BLACK) .align_left() - .border(Color::BLACK, 1.0); + .border(Color::BLACK, 1.0) + .foreground(Color::WHITE); assert!(widget.border_is_some()); assert!(!widget.background_is_some()); + assert!(!widget.foreground_is_some()); // this should be Container let widget = Slider::new() .background(Color::BLACK) - .border(Color::BLACK, 1.0); + .border(Color::BLACK, 1.0) + .foreground(Color::WHITE); assert!(widget.background_is_some()); assert!(widget.border_is_some()); + assert!(!widget.foreground_is_some()); } #[test] From b02429d957651f65eb75b04d98a6131426c2b7ab Mon Sep 17 00:00:00 2001 From: John Date: Fri, 27 Jan 2023 17:46:33 +0000 Subject: [PATCH 2/9] Remove ! from test --- druid/src/widget/widget_ext.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/druid/src/widget/widget_ext.rs b/druid/src/widget/widget_ext.rs index 5df34f475..0b5c5b9bb 100644 --- a/druid/src/widget/widget_ext.rs +++ b/druid/src/widget/widget_ext.rs @@ -323,7 +323,7 @@ mod tests { .foreground(Color::WHITE); assert!(widget.background_is_some()); assert!(widget.border_is_some()); - assert!(!widget.foreground_is_some()); + assert!(widget.foreground_is_some()); } #[test] From 17ab88bdaf5e49df125562b42ec6d8a62d205ae0 Mon Sep 17 00:00:00 2001 From: John Date: Fri, 27 Jan 2023 18:33:28 +0000 Subject: [PATCH 3/9] Move update method --- druid/src/widget/container.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/druid/src/widget/container.rs b/druid/src/widget/container.rs index b557fd9d7..20573af69 100644 --- a/druid/src/widget/container.rs +++ b/druid/src/widget/container.rs @@ -195,6 +195,11 @@ impl Widget for Container { brush.update(ctx, old_data, data, env); }); } + if let Some(brush) = self.foreground.as_mut() { + trace_span!("update foreground").in_scope(|| { + brush.update(ctx, old_data, data, env); + }); + } if let Some(border) = &self.border { if ctx.env_key_changed(&border.width) { ctx.request_layout(); @@ -207,11 +212,6 @@ impl Widget for Container { ctx.request_paint(); } self.child.update(ctx, data, env); - if let Some(brush) = self.foreground.as_mut() { - trace_span!("update foreground").in_scope(|| { - brush.update(ctx, old_data, data, env); - }); - } } #[instrument(name = "Container", level = "trace", skip(self, ctx, bc, data, env))] From 13b277114faa6de4dd95faf1061ca4fa5fce7efe Mon Sep 17 00:00:00 2001 From: John Date: Fri, 27 Jan 2023 18:38:27 +0000 Subject: [PATCH 4/9] Update druid/src/widget/widget_ext.rs Co-authored-by: Kaur Kuut --- druid/src/widget/widget_ext.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/druid/src/widget/widget_ext.rs b/druid/src/widget/widget_ext.rs index 0b5c5b9bb..66c3b687b 100644 --- a/druid/src/widget/widget_ext.rs +++ b/druid/src/widget/widget_ext.rs @@ -115,9 +115,9 @@ pub trait WidgetExt: Widget + Sized + 'static { Container::new(self).background(brush) } - /// Wrap this widget in a [`Container`] with the provided `foreground`. + /// Wrap this widget in a [`Container`] with the provided foreground `brush`. /// - /// See [`Container::background`] for more information. + /// See [`Container::foreground`] for more information. fn foreground(self, brush: impl Into>) -> Container { Container::new(self).foreground(brush) } From b49052946152b84c92321b5e738f2f41970d7551 Mon Sep 17 00:00:00 2001 From: John Date: Sat, 28 Jan 2023 12:03:56 +0000 Subject: [PATCH 5/9] Move foreground() before align() --- druid/src/widget/widget_ext.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/druid/src/widget/widget_ext.rs b/druid/src/widget/widget_ext.rs index 66c3b687b..03362a0a1 100644 --- a/druid/src/widget/widget_ext.rs +++ b/druid/src/widget/widget_ext.rs @@ -309,9 +309,9 @@ mod tests { // this should be Container>> let widget = Slider::new() .background(Color::BLACK) + .foreground(Color::WHITE); .align_left() .border(Color::BLACK, 1.0) - .foreground(Color::WHITE); assert!(widget.border_is_some()); assert!(!widget.background_is_some()); assert!(!widget.foreground_is_some()); From e9b7f3863eed87b865f89fac160f20029ce136cd Mon Sep 17 00:00:00 2001 From: John Date: Sat, 28 Jan 2023 12:07:49 +0000 Subject: [PATCH 6/9] Move semicolon to correct position --- druid/src/widget/widget_ext.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/druid/src/widget/widget_ext.rs b/druid/src/widget/widget_ext.rs index 03362a0a1..bde8750ab 100644 --- a/druid/src/widget/widget_ext.rs +++ b/druid/src/widget/widget_ext.rs @@ -309,9 +309,9 @@ mod tests { // this should be Container>> let widget = Slider::new() .background(Color::BLACK) - .foreground(Color::WHITE); + .foreground(Color::WHITE) .align_left() - .border(Color::BLACK, 1.0) + .border(Color::BLACK, 1.0); assert!(widget.border_is_some()); assert!(!widget.background_is_some()); assert!(!widget.foreground_is_some()); From ea906b12eb4606902c593f2c462924610df2620a Mon Sep 17 00:00:00 2001 From: John Date: Thu, 2 Feb 2023 11:03:11 +0000 Subject: [PATCH 7/9] Add foreground entry to CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 507f2c333..f3fe51a11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ You can find its changes [documented below](#082---2023-01-27). ### Highlights ### Added +- `foreground`, `set_foreground`, and `clear_foreground` methods to `Container` and `WidgetExt::foreground` method for convenience. ([#2346] by [@giannissc]) ### Changed @@ -760,6 +761,7 @@ Last release without a changelog :( [@liias]: https://github.com/liias [@lzhoucs]: https://github.com/lzhoucs [@ratmice]: https://github.com/ratmice +[@giannissc]: https://github.com/giannissc [#599]: https://github.com/linebender/druid/pull/599 [#611]: https://github.com/linebender/druid/pull/611 @@ -1198,6 +1200,7 @@ Last release without a changelog :( [#2348]: https://github.com/linebender/druid/pull/2348 [#2351]: https://github.com/linebender/druid/pull/2351 [#2352]: https://github.com/linebender/druid/pull/2352 +[#2346]: https://github.com/linebender/druid/pull/2346 [Unreleased]: https://github.com/linebender/druid/compare/v0.8.2...master [0.8.2]: https://github.com/linebender/druid/compare/v0.8.1...v0.8.2 From 752e38c33d452dfd538478ef90511c2c49506dc5 Mon Sep 17 00:00:00 2001 From: John Date: Thu, 2 Feb 2023 11:44:21 +0000 Subject: [PATCH 8/9] Update docs --- druid/src/widget/widget_ext.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/druid/src/widget/widget_ext.rs b/druid/src/widget/widget_ext.rs index bde8750ab..0fcb23a7a 100644 --- a/druid/src/widget/widget_ext.rs +++ b/druid/src/widget/widget_ext.rs @@ -108,7 +108,7 @@ pub trait WidgetExt: Widget + Sized + 'static { SizedBox::new(self).expand_height() } - /// Wrap this widget in a [`Container`] with the provided `background`. + /// Wrap this widget in a [`Container`] with the provided background `brush`. /// /// See [`Container::background`] for more information. fn background(self, brush: impl Into>) -> Container { From 52b870bd6d075a867ac5c635f80ac773b82298a3 Mon Sep 17 00:00:00 2001 From: Kaur Kuut Date: Fri, 3 Feb 2023 00:10:52 +0200 Subject: [PATCH 9/9] Fix `CHANGELOG.md` spacing and ordering. --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3fe51a11..9534b3061 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ You can find its changes [documented below](#082---2023-01-27). ### Highlights ### Added + - `foreground`, `set_foreground`, and `clear_foreground` methods to `Container` and `WidgetExt::foreground` method for convenience. ([#2346] by [@giannissc]) ### Changed @@ -1196,11 +1197,11 @@ Last release without a changelog :( [#2340]: https://github.com/linebender/druid/pull/2340 [#2343]: https://github.com/linebender/druid/pull/2343 [#2345]: https://github.com/linebender/druid/pull/2345 +[#2346]: https://github.com/linebender/druid/pull/2346 [#2347]: https://github.com/linebender/druid/pull/2347 [#2348]: https://github.com/linebender/druid/pull/2348 [#2351]: https://github.com/linebender/druid/pull/2351 [#2352]: https://github.com/linebender/druid/pull/2352 -[#2346]: https://github.com/linebender/druid/pull/2346 [Unreleased]: https://github.com/linebender/druid/compare/v0.8.2...master [0.8.2]: https://github.com/linebender/druid/compare/v0.8.1...v0.8.2