Skip to content

Commit

Permalink
xilem: Wire up all views with transforms
Browse files Browse the repository at this point in the history
  • Loading branch information
Philipp-M committed Dec 7, 2024
1 parent e73c9ce commit 4b4969e
Show file tree
Hide file tree
Showing 10 changed files with 156 additions and 18 deletions.
20 changes: 18 additions & 2 deletions xilem/src/view/checkbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
// SPDX-License-Identifier: Apache-2.0

use masonry::text::ArcStr;
use masonry::widget;
use masonry::{widget, Affine};

use crate::core::{DynMessage, Mut, ViewMarker};
use crate::{MessageResult, Pod, View, ViewCtx, ViewId};

use super::Transformable;

pub fn checkbox<F, State, Action>(
label: impl Into<ArcStr>,
checked: bool,
Expand All @@ -19,6 +21,7 @@ where
label: label.into(),
callback,
checked,
transform: Affine::IDENTITY,
}
}

Expand All @@ -27,6 +30,13 @@ pub struct Checkbox<F> {
label: ArcStr,
checked: bool,
callback: F,
transform: Affine,
}

impl<F> Transformable for Checkbox<F> {
fn transform_mut(&mut self) -> &mut Affine {
&mut self.transform
}
}

impl<F> ViewMarker for Checkbox<F> {}
Expand All @@ -39,7 +49,10 @@ where

fn build(&self, ctx: &mut ViewCtx) -> (Self::Element, Self::ViewState) {
ctx.with_leaf_action_widget(|ctx| {
ctx.new_pod(widget::Checkbox::new(self.checked, self.label.clone()))
ctx.new_pod_with_transform(
widget::Checkbox::new(self.checked, self.label.clone()),
self.transform,
)
})
}

Expand All @@ -50,6 +63,9 @@ where
_ctx: &mut ViewCtx,
mut element: Mut<Self::Element>,
) {
if prev.transform != self.transform {
element.set_transform(self.transform);
}
if prev.label != self.label {
widget::Checkbox::set_text(&mut element, self.label.clone());
}
Expand Down
18 changes: 16 additions & 2 deletions xilem/src/view/grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@
use std::marker::PhantomData;

use masonry::widget::{self, GridParams, WidgetMut};
use masonry::Widget;
use masonry::{Affine, Widget};

use crate::core::{
AppendVec, DynMessage, ElementSplice, MessageResult, Mut, SuperElement, View, ViewElement,
ViewId, ViewMarker, ViewSequence,
};
use crate::{Pod, ViewCtx, WidgetView};

use super::Transformable;

pub fn grid<State, Action, Seq: GridSequence<State, Action>>(
sequence: Seq,
width: i32,
Expand All @@ -23,6 +25,7 @@ pub fn grid<State, Action, Seq: GridSequence<State, Action>>(
phantom: PhantomData,
height,
width,
transform: Affine::IDENTITY,
}
}

Expand All @@ -32,6 +35,7 @@ pub struct Grid<Seq, State, Action = ()> {
spacing: f64,
width: i32,
height: i32,
transform: Affine,
/// Used to associate the State and Action in the call to `.grid()` with the State and Action
/// used in the View implementation, to allow inference to flow backwards, allowing State and
/// Action to be inferred properly
Expand All @@ -50,6 +54,12 @@ impl<Seq, State, Action> Grid<Seq, State, Action> {
}
}

impl<Seq, State, Action> Transformable for Grid<Seq, State, Action> {
fn transform_mut(&mut self) -> &mut Affine {
&mut self.transform
}
}

impl<Seq, State, Action> ViewMarker for Grid<Seq, State, Action> {}

impl<State, Action, Seq> View<State, Action, ViewCtx> for Grid<Seq, State, Action>
Expand All @@ -72,7 +82,8 @@ where
GridElement::Child(child, params) => widget.with_child_pod(child.inner, params),
}
}
(ctx.new_pod(widget), seq_state)
let pod = ctx.new_pod_with_transform(widget, self.transform);
(pod, seq_state)
}

fn rebuild(
Expand All @@ -82,6 +93,9 @@ where
ctx: &mut ViewCtx,
mut element: Mut<Self::Element>,
) {
if prev.transform != self.transform {
element.set_transform(self.transform);
}
if prev.height != self.height {
widget::Grid::set_height(&mut element, self.height);
}
Expand Down
18 changes: 17 additions & 1 deletion xilem/src/view/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
//! The bitmap image widget.
use masonry::widget::{self, ObjectFit};
use masonry::Affine;

use crate::core::{DynMessage, Mut, ViewMarker};
use crate::{MessageResult, Pod, View, ViewCtx, ViewId};

use super::Transformable;

/// Displays the bitmap `image`.
///
/// By default, the Image will scale to fit its box constraints ([`ObjectFit::Fill`]).
Expand All @@ -25,6 +28,7 @@ pub fn image(image: &vello::peniko::Image) -> Image {
// easier than documenting that cloning is cheap.
image: image.clone(),
object_fit: ObjectFit::default(),
transform: Affine::IDENTITY,
}
}

Expand All @@ -35,6 +39,7 @@ pub fn image(image: &vello::peniko::Image) -> Image {
pub struct Image {
image: vello::peniko::Image,
object_fit: ObjectFit,
transform: Affine,
}

impl Image {
Expand All @@ -45,13 +50,21 @@ impl Image {
}
}

impl Transformable for Image {
fn transform_mut(&mut self) -> &mut Affine {
&mut self.transform
}
}

impl ViewMarker for Image {}
impl<State, Action> View<State, Action, ViewCtx> for Image {
type Element = Pod<widget::Image>;
type ViewState = ();

fn build(&self, ctx: &mut ViewCtx) -> (Self::Element, Self::ViewState) {
(ctx.new_pod(widget::Image::new(self.image.clone())), ())
let pod =
ctx.new_pod_with_transform(widget::Image::new(self.image.clone()), self.transform);
(pod, ())
}

fn rebuild(
Expand All @@ -61,6 +74,9 @@ impl<State, Action> View<State, Action, ViewCtx> for Image {
_: &mut ViewCtx,
mut element: Mut<Self::Element>,
) {
if prev.transform != self.transform {
element.set_transform(self.transform);
}
if prev.object_fit != self.object_fit {
widget::Image::set_fit_mode(&mut element, self.object_fit);
}
Expand Down
18 changes: 16 additions & 2 deletions xilem/src/view/label.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@

use masonry::parley::FontStack;
use masonry::text::{ArcStr, StyleProperty};
use masonry::widget;
use masonry::{widget, Affine};
use vello::peniko::Brush;

use crate::core::{DynMessage, Mut, ViewMarker};
use crate::{Color, MessageResult, Pod, TextAlignment, TextWeight, View, ViewCtx, ViewId};

use super::Transformable;

pub fn label(label: impl Into<ArcStr>) -> Label {
Label {
label: label.into(),
Expand All @@ -17,6 +19,7 @@ pub fn label(label: impl Into<ArcStr>) -> Label {
text_size: masonry::theme::TEXT_SIZE_NORMAL,
weight: TextWeight::NORMAL,
font: FontStack::List(std::borrow::Cow::Borrowed(&[])),
transform: Affine::IDENTITY,
}
}

Expand All @@ -30,6 +33,7 @@ pub struct Label {
pub(in crate::view) text_size: f32,
pub(in crate::view) weight: TextWeight,
pub(in crate::view) font: FontStack<'static>, // TODO: add more attributes of `masonry::widget::Label`
pub(in crate::view) transform: Affine,
}

impl Label {
Expand Down Expand Up @@ -65,19 +69,26 @@ impl Label {
}
}

impl Transformable for Label {
fn transform_mut(&mut self) -> &mut Affine {
&mut self.transform
}
}

impl ViewMarker for Label {}
impl<State, Action> View<State, Action, ViewCtx> for Label {
type Element = Pod<widget::Label>;
type ViewState = ();

fn build(&self, ctx: &mut ViewCtx) -> (Self::Element, Self::ViewState) {
let widget_pod = ctx.new_pod(
let widget_pod = ctx.new_pod_with_transform(
widget::Label::new(self.label.clone())
.with_brush(self.text_brush.clone())
.with_alignment(self.alignment)
.with_style(StyleProperty::FontSize(self.text_size))
.with_style(StyleProperty::FontWeight(self.weight))
.with_style(StyleProperty::FontStack(self.font.clone())),
self.transform,
);
(widget_pod, ())
}
Expand All @@ -89,6 +100,9 @@ impl<State, Action> View<State, Action, ViewCtx> for Label {
_ctx: &mut ViewCtx,
mut element: Mut<Self::Element>,
) {
if prev.transform != self.transform {
element.set_transform(self.transform);
}
if prev.label != self.label {
widget::Label::set_text(&mut element, self.label.clone());
}
Expand Down
23 changes: 20 additions & 3 deletions xilem/src/view/progress_bar.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
// Copyright 2024 the Xilem Authors
// SPDX-License-Identifier: Apache-2.0

use masonry::widget;
use masonry::{widget, Affine};

use crate::core::{DynMessage, Mut, ViewMarker};
use crate::{MessageResult, Pod, View, ViewCtx, ViewId};

use super::Transformable;

pub fn progress_bar(progress: Option<f64>) -> ProgressBar {
ProgressBar { progress }
ProgressBar {
progress,
transform: Affine::IDENTITY,
}
}

pub struct ProgressBar {
progress: Option<f64>,
transform: Affine,
}

impl Transformable for ProgressBar {
fn transform_mut(&mut self) -> &mut Affine {
&mut self.transform
}
}

impl ViewMarker for ProgressBar {}
Expand All @@ -20,7 +32,9 @@ impl<State, Action> View<State, Action, ViewCtx> for ProgressBar {
type ViewState = ();

fn build(&self, ctx: &mut ViewCtx) -> (Self::Element, Self::ViewState) {
ctx.with_leaf_action_widget(|ctx| ctx.new_pod(widget::ProgressBar::new(self.progress)))
ctx.with_leaf_action_widget(|ctx| {
ctx.new_pod_with_transform(widget::ProgressBar::new(self.progress), self.transform)
})
}

fn rebuild(
Expand All @@ -30,6 +44,9 @@ impl<State, Action> View<State, Action, ViewCtx> for ProgressBar {
_ctx: &mut ViewCtx,
mut element: Mut<Self::Element>,
) {
if prev.transform != self.transform {
element.set_transform(self.transform);
}
if prev.progress != self.progress {
widget::ProgressBar::set_progress(&mut element, self.progress);
}
Expand Down
14 changes: 14 additions & 0 deletions xilem/src/view/prose.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,22 @@

use masonry::text::{ArcStr, StyleProperty};
use masonry::widget::{self, LineBreaking};
use masonry::Affine;
use vello::peniko::Brush;

use crate::core::{DynMessage, Mut, ViewMarker};
use crate::{Color, MessageResult, Pod, TextAlignment, View, ViewCtx, ViewId};

use super::Transformable;

pub fn prose(content: impl Into<ArcStr>) -> Prose {
Prose {
content: content.into(),
text_brush: Color::WHITE.into(),
alignment: TextAlignment::default(),
text_size: masonry::theme::TEXT_SIZE_NORMAL,
line_break_mode: LineBreaking::WordWrap,
transform: Affine::IDENTITY,
}
}

Expand All @@ -36,6 +40,7 @@ pub struct Prose {
alignment: TextAlignment,
text_size: f32,
line_break_mode: LineBreaking,
transform: Affine,
// TODO: disabled: bool,
// TODO: add more attributes of `masonry::widget::Prose`
}
Expand Down Expand Up @@ -67,6 +72,12 @@ fn line_break_clips(linebreaking: LineBreaking) -> bool {
matches!(linebreaking, LineBreaking::Clip | LineBreaking::WordWrap)
}

impl Transformable for Prose {
fn transform_mut(&mut self) -> &mut Affine {
&mut self.transform
}
}

impl ViewMarker for Prose {}
impl<State, Action> View<State, Action, ViewCtx> for Prose {
type Element = Pod<widget::Prose>;
Expand All @@ -92,6 +103,9 @@ impl<State, Action> View<State, Action, ViewCtx> for Prose {
_ctx: &mut ViewCtx,
mut element: Mut<Self::Element>,
) {
if prev.transform != self.transform {
element.set_transform(self.transform);
}
let mut text_area = widget::Prose::text_mut(&mut element);
if prev.content != self.content {
widget::TextArea::reset_text(&mut text_area, &self.content);
Expand Down
Loading

0 comments on commit 4b4969e

Please sign in to comment.