Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add style property transitions #143

Merged
merged 1 commit into from
Nov 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@
collections::{HashMap, HashSet},
ops::{Deref, DerefMut},
rc::Rc,
time::Duration,
time::{Duration, Instant},
};

use floem_renderer::{
Expand All @@ -24,8 +24,10 @@
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) 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(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 @@
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 @@
/// 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 @@
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 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 @@
(*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 @@

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