Skip to content

Commit

Permalink
Add style property transitions
Browse files Browse the repository at this point in the history
  • Loading branch information
Zoxc committed Nov 5, 2023
1 parent d10a3c2 commit 1264f0f
Show file tree
Hide file tree
Showing 7 changed files with 376 additions and 110 deletions.
25 changes: 20 additions & 5 deletions examples/themes/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use floem::{
keyboard::{Key, NamedKey},
peniko::Color,
reactive::create_signal,
style::Style,
style::{Background, BorderColor, Style, TextColor, Transition},
style_class,
view::View,
views::{label, stack, text, Decorators},
Expand All @@ -20,6 +20,9 @@ fn app_view() -> impl View {
.border(1.0)
.border_color(Color::rgb8(109, 121, 135))
.hover(|s| s.background(Color::rgb8(170, 175, 187)))
.transition(TextColor, Transition::linear(0.06))
.transition(BorderColor, Transition::linear(0.06))
.transition(Background, Transition::linear(0.06))
.disabled(|s| {
s.background(Color::DARK_GRAY.with_alpha_factor(0.1))
.border_color(Color::BLACK.with_alpha_factor(0.2))
Expand All @@ -30,29 +33,40 @@ fn app_view() -> impl View {
.border_radius(5.0);
let blue_theme = Style::new()
.background(Color::rgb8(95, 102, 118))
.transition(Background, Transition::linear(0.1))
.transition(TextColor, Transition::linear(0.1))
.color(Color::WHITE)
.class(Button, move |_| blue_button)
.class(Label, |s| s.margin(4.0))
.class(Label, |s| {
s.margin(4.0).transition(TextColor, Transition::linear(0.1))
})
.font_size(12.0);

let green_button = Style::new()
.background(Color::rgb8(180, 188, 175))
.disabled(|s| {
s.background(Color::rgb8(180, 188, 175).with_alpha_factor(0.3))
.border_color(Color::rgb8(131, 145, 123).with_alpha_factor(0.3))
.color(Color::GRAY)
})
.active(|s| s.background(Color::rgb8(95, 105, 88)).color(Color::WHITE))
.color(Color::BLACK.with_alpha_factor(0.7))
.border(2.0)
.transition(TextColor, Transition::linear(0.3))
.transition(BorderColor, Transition::linear(0.3))
.transition(Background, Transition::linear(0.3))
.border_color(Color::rgb8(131, 145, 123))
.hover(|s| s.background(Color::rgb8(204, 209, 201)))
.padding(8.0)
.border_radius(8.0)
.margin(6.0);
let green_theme = Style::new()
.background(Color::rgb8(227, 231, 226))
.transition(Background, Transition::linear(0.5))
.class(Button, move |_| green_button)
.class(Label, |s| s.margin(4.0))
.class(Label, |s| {
s.margin(4.0).transition(TextColor, Transition::linear(0.5))
})
.class(Frame, |s| {
s.border(2.0)
.border_color(Color::rgb8(131, 145, 123).with_alpha_factor(0.2))
Expand All @@ -64,7 +78,7 @@ fn app_view() -> impl View {
.font_size(16.0);

let (counter, set_counter) = create_signal(0);
let (theme, set_theme) = create_signal(true);
let (theme, set_theme) = create_signal(false);
let view = stack((stack((
text("Toggle Theme")
.class(Button)
Expand Down Expand Up @@ -120,7 +134,8 @@ fn app_view() -> impl View {
.flex_col()
.items_center()
.justify_center()
});
})
.window_title(|| "Themes Example".to_string());

let id = view.id();
view.on_event(EventListener::KeyUp, move |e| {
Expand Down
33 changes: 31 additions & 2 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::{
collections::{HashMap, HashSet},
ops::{Deref, DerefMut},
rc::Rc,
time::Duration,
time::{Duration, Instant},
};

use floem_renderer::{
Expand All @@ -24,8 +24,10 @@ use crate::{
inspector::CaptureState,
menu::Menu,
pointer::PointerInputEvent,
prop_extracter,
responsive::{GridBreakpoints, ScreenSizeBp},
style::{
Background, BorderBottom, BorderColor, BorderLeft, BorderRadius, BorderRight, BorderTop,
BuiltinStyle, CursorStyle, DisplayProp, LayoutProps, Style, StyleClassRef, StyleProp,
StyleSelector, StyleSelectors,
},
Expand All @@ -47,6 +49,19 @@ pub(crate) struct MoveListener {
pub(crate) callback: Box<dyn Fn(Point)>,
}

prop_extracter! {
pub(crate) ViewStyleProps {
pub border_left: BorderLeft,
pub border_top: BorderTop,
pub border_right: BorderRight,
pub border_bottom: BorderBottom,
pub border_radius: BorderRadius,

pub border_color: BorderColor,
pub background: Background,
}
}

pub struct ViewState {
pub(crate) node: Node,
pub(crate) children_nodes: Vec<Node>,
Expand All @@ -58,6 +73,7 @@ pub struct ViewState {
pub(crate) viewport: Option<Rect>,
pub(crate) layout_rect: Rect,
pub(crate) layout_props: LayoutProps,
pub(crate) view_style_props: ViewStyleProps,
pub(crate) animation: Option<Animation>,
pub(crate) base_style: Option<Style>,
pub(crate) style: Style,
Expand All @@ -81,6 +97,7 @@ impl ViewState {
viewport: None,
layout_rect: Rect::ZERO,
layout_props: Default::default(),
view_style_props: Default::default(),

Check warning on line 100 in src/context.rs

View check run for this annotation

Codecov / codecov/patch

src/context.rs#L100

Added line #L100 was not covered by tests
request_layout: true,
request_style: true,
request_style_recursive: false,
Expand Down Expand Up @@ -199,6 +216,8 @@ pub struct AppState {
/// This keeps track of all views that have an animation,
/// regardless of the status of the animation
pub(crate) animated: HashSet<Id>,
/// This is a set of view which have active transition animations.
pub(crate) transitioning: HashSet<Id>,
pub(crate) cursor: Option<CursorStyle>,
pub(crate) last_cursor: CursorIcon,
pub(crate) keyboard_navigation: bool,
Expand Down Expand Up @@ -230,6 +249,7 @@ impl AppState {
taffy,
view_states: HashMap::new(),
animated: HashSet::new(),
transitioning: HashSet::new(),

Check warning on line 252 in src/context.rs

View check run for this annotation

Codecov / codecov/patch

src/context.rs#L252

Added line #L252 was not covered by tests
disabled: HashSet::new(),
keyboard_navigable: HashSet::new(),
draggable: HashSet::new(),
Expand Down Expand Up @@ -700,18 +720,22 @@ pub struct InteractionState {

pub struct StyleCx<'a> {
pub(crate) app_state: &'a mut AppState,
pub(crate) current_view: Id,
pub(crate) current: Rc<Style>,
pub(crate) direct: Style,
saved: Vec<Rc<Style>>,
pub(crate) now: Instant,
}

impl<'a> StyleCx<'a> {
pub(crate) fn new(app_state: &'a mut AppState) -> Self {
pub(crate) fn new(app_state: &'a mut AppState, root: Id) -> Self {

Check warning on line 731 in src/context.rs

View check run for this annotation

Codecov / codecov/patch

src/context.rs#L731

Added line #L731 was not covered by tests
Self {
app_state,
current_view: root,

Check warning on line 734 in src/context.rs

View check run for this annotation

Codecov / codecov/patch

src/context.rs#L734

Added line #L734 was not covered by tests
current: Default::default(),
direct: Default::default(),
saved: Default::default(),
now: Instant::now(),

Check warning on line 738 in src/context.rs

View check run for this annotation

Codecov / codecov/patch

src/context.rs#L738

Added line #L738 was not covered by tests
}
}

Expand All @@ -733,6 +757,11 @@ impl<'a> StyleCx<'a> {
(*self.current).clone().apply(self.direct.clone())
}

pub(crate) fn request_transition(&mut self) {
let id = self.current_view;
self.app_state_mut().transitioning.insert(id);
}

Check warning on line 763 in src/context.rs

View check run for this annotation

Codecov / codecov/patch

src/context.rs#L760-L763

Added lines #L760 - L763 were not covered by tests

pub fn app_state_mut(&mut self) -> &mut AppState {
self.app_state
}
Expand Down
109 changes: 67 additions & 42 deletions src/inspector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -468,60 +468,85 @@ fn selected_view(capture: &Rc<Capture>, selected: RwSignal<Option<Id>>) -> impl

let direct: HashSet<_> = view.direct_style.map.keys().copied().collect();

let mut styles = capture
let style = capture

Check warning on line 471 in src/inspector.rs

View check run for this annotation

Codecov / codecov/patch

src/inspector.rs#L471

Added line #L471 was not covered by tests
.state
.styles
.get(&view.id)
.cloned()
.unwrap_or_default()
.unwrap_or_default();

let mut style_list = style

Check warning on line 478 in src/inspector.rs

View check run for this annotation

Codecov / codecov/patch

src/inspector.rs#L476-L478

Added lines #L476 - L478 were not covered by tests
.map
.clone()

Check warning on line 480 in src/inspector.rs

View check run for this annotation

Codecov / codecov/patch

src/inspector.rs#L480

Added line #L480 was not covered by tests
.into_iter()
.map(|(p, v)| ((p, format!("{p:?}")), v))
.collect::<Vec<_>>();

styles.sort_unstable_by(|a, b| a.0 .1.cmp(&b.0 .1));
style_list.sort_unstable_by(|a, b| a.0 .1.cmp(&b.0 .1));

Check warning on line 485 in src/inspector.rs

View check run for this annotation

Codecov / codecov/patch

src/inspector.rs#L485

Added line #L485 was not covered by tests

let style_list = static_list(styles.into_iter().map(|((prop, name), value)| {
let name = name.strip_prefix("floem::style::").unwrap_or(&name);
let name: Box<dyn View> = if direct.contains(&prop) {
Box::new(text(name))
} else {
Box::new(stack((
text("Inherited").style(|s| {
let style_list =
static_list(style_list.into_iter().map(|((prop, name), value)| {
let name = name.strip_prefix("floem::style::").unwrap_or(&name);
let name: Box<dyn View> = if direct.contains(&prop) {
Box::new(text(name))

Check warning on line 491 in src/inspector.rs

View check run for this annotation

Codecov / codecov/patch

src/inspector.rs#L487-L491

Added lines #L487 - L491 were not covered by tests
} else {
Box::new(stack((
text("Inherited").style(|s| {
s.margin_right(5.0)
.background(Color::WHITE_SMOKE.with_alpha_factor(0.6))
.border(1.0)
.border_radius(5.0)
.border_color(Color::WHITE_SMOKE)
.padding(1.0)
.font_size(10.0)
.color(Color::BLACK.with_alpha_factor(0.4))
}),
text(name),
)))

Check warning on line 505 in src/inspector.rs

View check run for this annotation

Codecov / codecov/patch

src/inspector.rs#L493-L505

Added lines #L493 - L505 were not covered by tests
};
let mut v: Box<dyn View> = match value {
StyleMapValue::Val(v) => {
let v = &*v;
(prop.info.debug_view)(v)
.unwrap_or_else(|| Box::new(text((prop.info.debug_any)(v))))

Check warning on line 511 in src/inspector.rs

View check run for this annotation

Codecov / codecov/patch

src/inspector.rs#L507-L511

Added lines #L507 - L511 were not covered by tests
}
StyleMapValue::Unset => Box::new(text("Unset".to_owned())),

Check warning on line 513 in src/inspector.rs

View check run for this annotation

Codecov / codecov/patch

src/inspector.rs#L513

Added line #L513 was not covered by tests
};
if let Some(transition) = style.transitions.get(&prop).cloned() {
let transition = stack((
text("Transition").style(|s| {
s.margin_top(5.0)
.margin_right(5.0)
.background(Color::WHITE_SMOKE.with_alpha_factor(0.6))
.border(1.0)
.border_radius(5.0)
.border_color(Color::WHITE_SMOKE)
.padding(1.0)
.font_size(10.0)
.color(Color::BLACK.with_alpha_factor(0.4))
}),
text(format!("{transition:?}")),
))
.style(|s| s.items_center());
v = Box::new(stack((v, transition)).style(|s| s.flex_col()));
}
stack((
stack((name.style(|s| {

Check warning on line 534 in src/inspector.rs

View check run for this annotation

Codecov / codecov/patch

src/inspector.rs#L515-L534

Added lines #L515 - L534 were not covered by tests
s.margin_right(5.0)
.background(Color::WHITE_SMOKE.with_alpha_factor(0.6))
.border(1.0)
.border_radius(5.0)
.border_color(Color::WHITE_SMOKE)
.padding(1.0)
.font_size(10.0)
.color(Color::BLACK.with_alpha_factor(0.4))
.color(Color::BLACK.with_alpha_factor(0.6))
}),))
.style(|s| {
s.min_width(150.0).flex_direction(FlexDirection::RowReverse)

Check warning on line 539 in src/inspector.rs

View check run for this annotation

Codecov / codecov/patch

src/inspector.rs#L536-L539

Added lines #L536 - L539 were not covered by tests
}),
text(name),
)))
};
let v: Box<dyn View> = match value {
StyleMapValue::Val(v) => {
let v = &*v;
(prop.info.debug_view)(v)
.unwrap_or_else(|| Box::new(text((prop.info.debug_any)(v))))
}
StyleMapValue::Unset => Box::new(text("Unset".to_owned())),
};
stack((
stack((name.style(|s| {
s.margin_right(5.0)
.color(Color::BLACK.with_alpha_factor(0.6))
}),))
.style(|s| s.min_width(150.0).flex_direction(FlexDirection::RowReverse)),
v,
))
.style(|s| {
s.padding(5.0)
.hover(|s| s.background(Color::rgba8(228, 237, 216, 160)))
})
}))
.style(|s| s.flex_col().width_full());
v,
))
.style(|s| {
s.padding(5.0)
.items_center()
.hover(|s| s.background(Color::rgba8(228, 237, 216, 160)))
})
}))
.style(|s| s.flex_col().width_full());

Check warning on line 549 in src/inspector.rs

View check run for this annotation

Codecov / codecov/patch

src/inspector.rs#L541-L549

Added lines #L541 - L549 were not covered by tests

Box::new(
stack((
Expand Down
Loading

0 comments on commit 1264f0f

Please sign in to comment.