From a3b58a0ba3f9db08a6232f6f9a0aa441b029920c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Sch=C3=BCtt?= Date: Fri, 5 Oct 2018 15:43:37 +0200 Subject: [PATCH] Improved layout constraint insertion performance Crashes with stack overflow in recursive push_iframe function - shouldn't happen, of course. --- src/display_list.rs | 22 ++++++++++++++++------ src/dom.rs | 5 +++++ src/ui_solver.rs | 10 +++++++--- src/widgets/table_view.rs | 4 ++-- 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/display_list.rs b/src/display_list.rs index 66f62c9e7..7b335b3b7 100644 --- a/src/display_list.rs +++ b/src/display_list.rs @@ -343,26 +343,38 @@ fn insert_constraints_into_solver<'a, T: Layout>( if changeset.is_some() { + println!("4!"); + // inefficient for now, but prevents memory leak dom_solver.clear_all_constraints(); + let mut constraints = Vec::new(); + for rect_idx in rectangles.linear_iter() { - let constraints = dom_solver.create_layout_constraints(rect_idx, &rectangles, &*ui_description.ui_descr_arena.borrow()); - dom_solver.insert_css_constraints_for_rect(&constraints); - dom_solver.push_added_constraints(rect_idx, constraints); + constraints.extend(dom_solver.create_layout_constraints(rect_idx, &rectangles, &*ui_description.ui_descr_arena.borrow())); } + println!("constraints: {:?}", constraints.len()); + + dom_solver.insert_css_constraints(&constraints); + + println!("5!"); + // If we push or pop constraints that means we also need to re-layout the window has_window_size_changed = true; } + println!("6!"); // TODO: early return based on changeset? // Recalculate the actual layout if has_window_size_changed { - dom_solver.update_window_size(&bounds_size); + dom_solver.update_window_size(&bounds_size); // unknown } + println!("7!"); dom_solver.update_layout_cache(); + println!("8!"); + println!("end of insert constraints into DOM!"); } @@ -648,8 +660,6 @@ fn push_iframe<'a, 'b, 'c, T: Layout>( referenced_mutable_content.ui_solver.insert_dom(new_dom_id, dom_solver); - // ui_description.ui_descr_arena.borrow().print_tree(|t| format!("{}", t)); // REMOVE - println!("push_iframe"); insert_constraints_into_solver( &ui_description, diff --git a/src/dom.rs b/src/dom.rs index 3b026689c..2cda01fee 100644 --- a/src/dom.rs +++ b/src/dom.rs @@ -860,6 +860,11 @@ impl Dom { pub fn push_default_callback_id(&mut self, on: On, id: DefaultCallbackId) { self.arena.borrow_mut()[self.head].data.default_callback_ids.insert(on, id); } + + /// Prints a debug formatted version of the DOM for easier debugging + pub fn debug_dump(&self) { + println!("{}", self.arena.borrow().print_tree(|t| format!("{}", t))); + } } pub type TagId = u64; diff --git a/src/ui_solver.rs b/src/ui_solver.rs index adf17a110..6b29cda66 100644 --- a/src/ui_solver.rs +++ b/src/ui_solver.rs @@ -146,14 +146,14 @@ impl DomSolver { changeset } - pub(crate) fn insert_css_constraints_for_rect(&mut self, constraints: &[Constraint]) { + pub(crate) fn insert_css_constraints(&mut self, constraints: &[Constraint]) { self.solver.add_constraints(constraints).unwrap(); } /// Notifies the solver that the window size has changed pub(crate) fn update_window_size(&mut self, window_size: &LogicalSize) { - self.solver.suggest_value(self.root_constraints.width_var, window_size.width).unwrap(); - self.solver.suggest_value(self.root_constraints.height_var, window_size.height).unwrap(); + println!("{:?}", self.solver.suggest_value(self.root_constraints.width_var, window_size.width)); + println!("{:?}", self.solver.suggest_value(self.root_constraints.height_var, window_size.height)); } pub(crate) fn update_layout_cache(&mut self) { @@ -190,6 +190,7 @@ impl DomSolver { self.edit_variable_cache.map.get(&dom_hash.data).and_then(|rect| Some(rect.1)) } + /// TODO: Make this an iterator, so we can avoid the unnecessary collections! pub(crate) fn create_layout_constraints<'a, T: Layout>( &self, rect_id: NodeId, @@ -205,12 +206,15 @@ impl DomSolver { } pub(crate) fn clear_all_constraints(&mut self) { + /* for entry in self.added_constraints.values() { for constraint in entry { self.solver.remove_constraint(constraint).unwrap(); } } self.added_constraints = BTreeMap::new(); + */ + self.solver.reset(); } pub(crate) fn get_window_constraints(&self) -> RootSizeConstraints { diff --git a/src/widgets/table_view.rs b/src/widgets/table_view.rs index 5b6f49982..d95ddbd2b 100644 --- a/src/widgets/table_view.rs +++ b/src/widgets/table_view.rs @@ -91,7 +91,7 @@ fn render_table(state: &mut TableViewState, info: WindowInfo, dime .with_class("__azul-native-table-column-name") .with_sibling( // Rows - "1", "2", "3" - (0..necessary_rows - 1) + (0..necessary_rows.saturating_sub(1)) .map(|row_idx| NodeData { node_type: NodeType::Label(format!("{}", row_idx + 1)), @@ -116,7 +116,7 @@ fn render_table(state: &mut TableViewState, info: WindowInfo, dime .with_class("__azul-native-table-column-name") .with_sibling( // Actual rows - if no content is given, they are simply empty - (0..necessary_rows - 1) + (0..necessary_rows.saturating_sub(1)) .map(|row_idx| NodeData { node_type: if let Some(data) = state.work_sheet.data.get(&col_idx).and_then(|col| col.get(&row_idx)) {