From e3390dfe100dc4d40b0f1f6239459e6b5318c080 Mon Sep 17 00:00:00 2001 From: jrmoulton Date: Mon, 9 Sep 2024 17:43:16 -0600 Subject: [PATCH] fix transition layout --- src/context.rs | 93 +++++++++++++++-------------------------------- src/view_state.rs | 53 ++++++++++++++++++++++++--- 2 files changed, 78 insertions(+), 68 deletions(-) diff --git a/src/context.rs b/src/context.rs index 4a06a92d..ec1fcceb 100644 --- a/src/context.rs +++ b/src/context.rs @@ -7,7 +7,6 @@ use std::{ rc::Rc, sync::Arc, }; -use taffy::Display; #[cfg(not(target_arch = "wasm32"))] use std::time::{Duration, Instant}; @@ -742,70 +741,38 @@ impl<'a> ComputeLayoutCx<'a> { pub fn compute_view_layout(&mut self, id: ViewId) -> Option { let view_state = id.state(); - { - let mut view_state_ref = view_state.borrow_mut(); - let is_hidden_state = view_state_ref.is_hidden_state; - let style_has_hidden = view_state_ref.combined_style.get(DisplayProp) == Display::None; - - match is_hidden_state { - IsHiddenState::Visble(dis) if style_has_hidden => { - // view state isn't yet marked as hidden but the style is, meaning that this is the first time that this view is hidden, - // need to check for animations - drop(view_state_ref); - let count = animations_recursive_on_remove(id, Scope::current()); - let mut view_state_ref = view_state.borrow_mut(); - view_state_ref.num_waiting_animations = count; - - if count > 0 { - // set the combined style to display - view_state_ref - .combined_style - .apply_mut(Style::new().display(dis)); - view_state_ref.is_hidden_state = IsHiddenState::AnimatingOut(dis); - } else { - // hidden and no animations active - view_state_ref.layout_rect = Rect::ZERO; - view_state_ref.is_hidden_state = IsHiddenState::Hidden; - return None; - } - } - IsHiddenState::AnimatingOut(dis) => { - if !style_has_hidden { - // finished hiding before animations finished - let display = view_state_ref.combined_style.get(DisplayProp); - view_state_ref.is_hidden_state = IsHiddenState::Visble(display); - } else if view_state_ref.num_waiting_animations == 0 { - // animations finished, set state to hidden - view_state_ref.is_hidden_state = IsHiddenState::Hidden; - view_state_ref.layout_rect = Rect::ZERO; - drop(view_state_ref); - id.request_layout(); - return None; - } else { - // while still animating, keep the same display mode - view_state_ref - .combined_style - .apply_mut(Style::new().display(dis)); - } - } - IsHiddenState::Hidden => { - drop(view_state_ref); - if !id.style_has_hidden() { - // view state was marked as hidden but style is now not, transition to visible - animations_recursive_on_create(id); - let mut view_state_ref = view_state.borrow_mut(); - let display = view_state_ref.combined_style.get(DisplayProp); - view_state_ref.is_hidden_state = IsHiddenState::Visble(display); - } else { - // style is hidden, view state has hidden - view_state.borrow_mut().layout_rect = Rect::ZERO; - return None; - } - } - _ => {} - }; + let mut is_hidden_state = view_state.borrow().is_hidden_state; + let display = view_state.borrow().combined_style.get(DisplayProp); + let request_layout = is_hidden_state.transition( + display, + || { + let count = animations_recursive_on_remove(id, Scope::current()); + view_state.borrow_mut().num_waiting_animations = count; + count > 0 + }, + || { + animations_recursive_on_create(id); + }, + || view_state.borrow().num_waiting_animations, + ); + if request_layout { + id.request_layout(); } + view_state.borrow_mut().is_hidden_state = is_hidden_state; + if is_hidden_state == IsHiddenState::Hidden { + view_state.borrow_mut().layout_rect = Rect::ZERO; + return None; + } + + let modified = view_state + .borrow() + .combined_style + .clone() + .apply_opt(is_hidden_state.get_display(), Style::display); + + view_state.borrow_mut().combined_style = modified; + self.save(); let layout = id.get_layout().unwrap_or_default(); diff --git a/src/view_state.rs b/src/view_state.rs index 7417e262..3c237a06 100644 --- a/src/view_state.rs +++ b/src/view_state.rs @@ -84,19 +84,62 @@ bitflags! { } } -#[derive(Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum IsHiddenState { - Visble(taffy::style::Display), + Visible(taffy::style::Display), AnimatingOut(taffy::style::Display), Hidden, + None, } impl IsHiddenState { pub(crate) fn get_display(&self) -> Option { match self { - IsHiddenState::Visble(dis) | IsHiddenState::AnimatingOut(dis) => Some(*dis), - IsHiddenState::Hidden => None, + IsHiddenState::AnimatingOut(dis) => Some(*dis), + _ => None, } } + + // returns true if the view should request layout + pub(crate) fn transition( + &mut self, + display: taffy::Display, + remove_animations: impl FnOnce() -> bool, + add_animations: impl FnOnce(), + num_waiting_anim: impl FnOnce() -> u16, + ) -> bool { + let hide = display == taffy::Display::None; + let mut request_layout = false; + *self = match self { + Self::None if hide => Self::Hidden, + Self::None if !hide => Self::Visible(display), + Self::Visible(dis) if !hide => Self::Visible(*dis), + Self::Visible(dis) if hide => { + let active_animations = remove_animations(); + if active_animations { + // request_layout = true; + Self::AnimatingOut(*dis) + } else { + Self::Hidden + } + } + Self::AnimatingOut(_) if !hide => Self::Visible(display), + Self::AnimatingOut(dis) if hide => { + if num_waiting_anim() == 0 { + request_layout = true; + Self::Hidden + } else { + Self::AnimatingOut(*dis) + } + } + Self::Hidden if hide => Self::Hidden, + Self::Hidden if !hide => { + add_animations(); + Self::Visible(display) + } + _ => unreachable!(), + }; + request_layout + } } /// View state stores internal state associated with a view which is owned and managed by Floem. @@ -154,7 +197,7 @@ impl ViewState { cleanup_listener: None, last_pointer_down: None, window_origin: Point::ZERO, - is_hidden_state: IsHiddenState::Visble(taffy::Display::Flex), + is_hidden_state: IsHiddenState::None, num_waiting_animations: 0, debug_name: Default::default(), }