Skip to content

Commit

Permalink
refactor(core): 💡 separate the BoxDecoration into distinct widgets …
Browse files Browse the repository at this point in the history
…for border, background, and radius.
  • Loading branch information
M-Adoo authored and wjian23 committed Jan 15, 2025
1 parent 9b9a9ed commit 588dcd2
Show file tree
Hide file tree
Showing 35 changed files with 334 additions and 229 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ Please only add new entries below the [Unreleased](#unreleased---releasedate) he
- **macros**: Added the `part_reader!` macro to generate a partial reader from a reference of a reader. (#688 @M-Adoo)
- **macros**: The `simple_declare` now supports the `stateless` meta attribute, `#[simple_declare(stateless)]`. (#688 @M-Adoo)

### Changed

- **widgets**: Replace `BoxDecoration` with three separate widgets: `BorderWidget`, `RadiusWidget`, and `Background`. (#691 @M-Adoo)

### Fixed

- **Core**: `PartData` allows the use of a reference to create a write reference, which is unsafe. Introduce `PartRef` and `PartMut` to replace it. (#690 @M-Adoo)
Expand All @@ -44,6 +48,7 @@ Please only add new entries below the [Unreleased](#unreleased---releasedate) he
### Breading

- **core**: Removed `PartData`. (#690 @M-Adoo)
- **core**: Removed `BoxDecoration`. (#691 @M-Adoo)

## [0.4.0-alpha.22] - 2025-01-08

Expand Down
56 changes: 40 additions & 16 deletions core/src/builtin_widgets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ mod foreground;
mod padding;
pub use foreground::*;
pub use padding::*;
mod box_decoration;
pub use box_decoration::*;
mod scrollable;
pub use scrollable::*;
mod transform_widget;
Expand Down Expand Up @@ -82,6 +80,12 @@ mod tooltips;
pub use tooltips::*;
mod providers;
pub use providers::*;
mod border;
pub use border::*;
mod radius;
pub use radius::*;
mod background;
pub use background::*;

use crate::prelude::*;

Expand Down Expand Up @@ -120,7 +124,9 @@ pub struct FatObj<T> {
padding: Option<State<Padding>>,
fitted_box: Option<State<FittedBox>>,
constrained_box: Option<State<ConstrainedBox>>,
box_decoration: Option<State<BoxDecoration>>,
radius: Option<State<RadiusWidget>>,
border: Option<State<BorderWidget>>,
background: Option<State<Background>>,
foreground: Option<State<Foreground>>,
scrollable: Option<State<ScrollableWidget>>,
layout_box: Option<State<LayoutBox>>,
Expand Down Expand Up @@ -168,7 +174,9 @@ impl<T> FatObj<T> {
mix_builtin: self.mix_builtin,
request_focus: self.request_focus,
fitted_box: self.fitted_box,
box_decoration: self.box_decoration,
border: self.border,
radius: self.radius,
background: self.background,
foreground: self.foreground,
padding: self.padding,
layout_box: self.layout_box,
Expand Down Expand Up @@ -198,7 +206,9 @@ impl<T> FatObj<T> {
&& self.mix_builtin.is_none()
&& self.request_focus.is_none()
&& self.fitted_box.is_none()
&& self.box_decoration.is_none()
&& self.border.is_none()
&& self.radius.is_none()
&& self.background.is_none()
&& self.foreground.is_none()
&& self.padding.is_none()
&& self.layout_box.is_none()
Expand Down Expand Up @@ -297,11 +307,21 @@ impl<T> FatObj<T> {
.get_or_insert_with(|| State::value(<_>::default()))
}

/// Returns the `State<BoxDecoration>` widget from the FatObj. If it doesn't
/// exist, a new one will be created.
pub fn get_box_decoration_widget(&mut self) -> &State<BoxDecoration> {
pub fn get_border_widget(&mut self) -> &State<BorderWidget> {
self
.border
.get_or_insert_with(|| State::value(<_>::default()))
}

pub fn get_radius_widget(&mut self) -> &State<RadiusWidget> {
self
.radius
.get_or_insert_with(|| State::value(<_>::default()))
}

pub fn get_background_widget(&mut self) -> &State<Background> {
self
.box_decoration
.background
.get_or_insert_with(|| State::value(<_>::default()))
}

Expand Down Expand Up @@ -808,8 +828,8 @@ impl<T> FatObj<T> {
}

/// Initializes the background of the widget.
pub fn background<const M: usize>(self, v: impl DeclareInto<Option<Brush>, M>) -> Self {
self.declare_builtin_init(v, Self::get_box_decoration_widget, |m, v| m.background = v)
pub fn background<const M: usize>(self, v: impl DeclareInto<Brush, M>) -> Self {
self.declare_builtin_init(v, Self::get_background_widget, |m, v| m.background = v)
}

/// Initializes the foreground of the widget.
Expand All @@ -818,13 +838,13 @@ impl<T> FatObj<T> {
}

/// Initializes the border of the widget.
pub fn border<const M: usize>(self, v: impl DeclareInto<Option<Border>, M>) -> Self {
self.declare_builtin_init(v, Self::get_box_decoration_widget, |m, v| m.border = v)
pub fn border<const M: usize>(self, v: impl DeclareInto<Border, M>) -> Self {
self.declare_builtin_init(v, Self::get_border_widget, |m, v| m.border = v)
}

/// Initializes the border radius of the widget.
pub fn border_radius<const M: usize>(self, v: impl DeclareInto<Option<Radius>, M>) -> Self {
self.declare_builtin_init(v, Self::get_box_decoration_widget, |m, v| m.border_radius = v)
pub fn radius<const M: usize>(self, v: impl DeclareInto<Radius, M>) -> Self {
self.declare_builtin_init(v, Self::get_radius_widget, |m, v| m.radius = v)
}

/// Initializes the extra space within the widget.
Expand Down Expand Up @@ -1005,7 +1025,11 @@ impl<'a> FatObj<Widget<'a>> {
]);

compose_builtin_widgets!(
host + [track_id, padding, fitted_box, foreground, box_decoration, scrollable, layout_box]
host
+ [
track_id, padding, fitted_box, foreground, border, background, radius, scrollable,
layout_box
]
);
if let Some(providers) = self.providers {
host = Providers::new(providers).with_child(host);
Expand Down
43 changes: 43 additions & 0 deletions core/src/builtin_widgets/background.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use wrap_render::WrapRender;

use super::*;

/// A widget that utilizes the background brush to paint a background box based
/// on the layout size. If a `Radius` is provided, the corners of the box will
/// be rounded.
#[derive(Default, Clone)]
pub struct Background {
/// The background of the box.
pub background: Brush,
}

impl Declare for Background {
type Builder = FatObj<()>;
#[inline]
fn declarer() -> Self::Builder { FatObj::new(()) }
}

impl WrapRender for Background {
fn paint(&self, host: &dyn Render, ctx: &mut PaintingCtx) {
let size = ctx.box_size().unwrap();

if !size.is_empty() {
let rect = Rect::from_size(size);
let (provider_ctx, painter) = ctx.provider_ctx_and_painter();
let old_brush = painter.fill_brush().clone();

painter.set_fill_brush(self.background.clone());
if let Some(radius) = Provider::of::<Radius>(provider_ctx) {
painter.rect_round(&rect, &radius);
} else {
painter.rect(&rect);
}
painter.fill();

painter.set_fill_brush(old_brush);
}
host.paint(ctx);
}
}

impl_compose_child_for_wrap_render!(Background, DirtyPhase::Paint);
Loading

0 comments on commit 588dcd2

Please sign in to comment.