From ff0b075581cdf23bbcde28e9d24b40526555dc75 Mon Sep 17 00:00:00 2001 From: Zoxc Date: Fri, 3 Nov 2023 21:04:11 +0100 Subject: [PATCH] Make style changes which alter inherited style properties request layout for all children (#140) * Add an example with theme toggle using style classes * Make style changes which alter inherited style properties request layout for all children --- examples/themes/Cargo.toml | 7 ++ examples/themes/src/main.rs | 138 ++++++++++++++++++++++++++++++++++++ src/context.rs | 10 +++ src/style.rs | 8 ++- src/view.rs | 19 +++-- src/views/label.rs | 9 --- src/views/scroll.rs | 6 +- src/window_handle.rs | 16 ++++- 8 files changed, 191 insertions(+), 22 deletions(-) create mode 100644 examples/themes/Cargo.toml create mode 100644 examples/themes/src/main.rs diff --git a/examples/themes/Cargo.toml b/examples/themes/Cargo.toml new file mode 100644 index 00000000..5ce3f70f --- /dev/null +++ b/examples/themes/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "themes" +version = "0.1.0" +edition = "2021" + +[dependencies] +floem = { path = "../.." } diff --git a/examples/themes/src/main.rs b/examples/themes/src/main.rs new file mode 100644 index 00000000..31f78872 --- /dev/null +++ b/examples/themes/src/main.rs @@ -0,0 +1,138 @@ +use floem::{ + event::{Event, EventListener}, + keyboard::{Key, NamedKey}, + peniko::Color, + reactive::create_signal, + style::Style, + style_class, + view::View, + views::{label, stack, text, Decorators}, +}; + +style_class!(pub Button); +style_class!(pub Label); +style_class!(pub Frame); + +fn app_view() -> impl View { + let blue_button = Style::new() + .background(Color::rgb8(137, 145, 160)) + .color(Color::WHITE) + .border(1.0) + .border_color(Color::rgb8(109, 121, 135)) + .hover(|s| s.background(Color::rgb8(170, 175, 187))) + .disabled(|s| { + s.background(Color::DARK_GRAY.with_alpha_factor(0.1)) + .border_color(Color::BLACK.with_alpha_factor(0.2)) + }) + .active(|s| s.background(Color::BLACK.with_alpha_factor(0.4))) + .padding(5.0) + .margin(3.0) + .border_radius(5.0); + let blue_theme = Style::new() + .background(Color::rgb8(95, 102, 118)) + .color(Color::WHITE) + .class(Button, move |_| blue_button) + .class(Label, |s| s.margin(4.0)) + .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)) + }) + .active(|s| s.background(Color::rgb8(95, 105, 88)).color(Color::WHITE)) + .color(Color::BLACK.with_alpha_factor(0.7)) + .border(2.0) + .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)) + .class(Button, move |_| green_button) + .class(Label, |s| s.margin(4.0)) + .class(Frame, |s| { + s.border(2.0) + .border_color(Color::rgb8(131, 145, 123).with_alpha_factor(0.2)) + .border_radius(8.0) + .background(Color::WHITE.with_alpha_factor(0.1)) + .padding(12.0) + }) + .color(Color::BLACK.with_alpha_factor(0.5)) + .font_size(16.0); + + let (counter, set_counter) = create_signal(0); + let (theme, set_theme) = create_signal(true); + let view = stack((stack(( + text("Toggle Theme") + .class(Button) + .on_click({ + move |_| { + set_theme.update(|theme| *theme = !*theme); + true + } + }) + .keyboard_navigatable(), + stack(( + label(move || format!("Value: {}", counter.get())).class(Label), + text("Increment") + .class(Button) + .on_click({ + move |_| { + set_counter.update(|value| *value += 1); + true + } + }) + .keyboard_navigatable(), + text("Decrement") + .class(Button) + .on_click({ + move |_| { + set_counter.update(|value| *value -= 1); + true + } + }) + .keyboard_navigatable(), + text("Reset to 0") + .class(Button) + .on_click(move |_| { + println!("Reset counter pressed"); // will not fire if button is disabled + set_counter.update(|value| *value = 0); + true + }) + .disabled(move || counter.get() == 0) + .keyboard_navigatable(), + )) + .class(Frame) + .style(|s| s.items_center()), + )) + .style(|s| s.items_center()),)) + .style(move |_| { + if theme.get() { + blue_theme.clone() + } else { + green_theme.clone() + } + .width_full() + .height_full() + .flex_col() + .items_center() + .justify_center() + }); + + let id = view.id(); + view.on_event(EventListener::KeyUp, move |e| { + if let Event::KeyUp(e) = e { + if e.key.logical_key == Key::Named(NamedKey::F11) { + id.inspect(); + } + } + true + }) +} + +fn main() { + floem::launch(app_view); +} diff --git a/src/context.rs b/src/context.rs index 13d858b0..6a0d2100 100644 --- a/src/context.rs +++ b/src/context.rs @@ -51,6 +51,8 @@ pub struct ViewState { pub(crate) node: Node, pub(crate) children_nodes: Vec, pub(crate) request_layout: bool, + /// Layout is requested on all direct and indirect children. + pub(crate) request_layout_recursive: bool, pub(crate) has_style_selectors: StyleSelectors, pub(crate) viewport: Option, pub(crate) layout_rect: Rect, @@ -78,6 +80,7 @@ impl ViewState { layout_rect: Rect::ZERO, layout_props: Default::default(), request_layout: true, + request_layout_recursive: false, has_style_selectors: StyleSelectors::default(), animation: None, base_style: None, @@ -370,6 +373,13 @@ impl AppState { } } + /// Requests layout for a view and all direct and indirect children. + pub(crate) fn request_layout_recursive(&mut self, id: Id) { + let view = self.view_state(id); + view.request_layout_recursive = true; + self.request_layout(id); + } + pub fn request_layout(&mut self, id: Id) { let view = self.view_state(id); if view.request_layout { diff --git a/src/style.rs b/src/style.rs index 716efbce..644ca0e1 100644 --- a/src/style.rs +++ b/src/style.rs @@ -556,10 +556,12 @@ impl Style { } } - pub(crate) fn apply_only_inherited(this: &mut Rc