diff options
author | AnotherTest <ali.mpfard@gmail.com> | 2020-12-22 12:52:59 +0330 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-12-22 23:35:29 +0100 |
commit | 8f05e4e765b86d6f350886cdb81d1b3d0ffab085 (patch) | |
tree | e4c91f14e8165e079877da7eb00da8b058859b99 | |
parent | bfb25855cb208d855799906dd2121b3d122ca5ea (diff) | |
download | serenity-8f05e4e765b86d6f350886cdb81d1b3d0ffab085.zip |
Spreadsheet: Improve sheet update efficiency
There's no need to leave the cell dirty when not updating it, and
there's definitely no need to update the cells as we're selecting them.
This makes navigating a sheet and selecting cells significantly faster
as we no longer update unrelated cells just because they appear to have
a cyclic update dependency :^)
-rw-r--r-- | Applications/Spreadsheet/Cell.h | 6 | ||||
-rw-r--r-- | Applications/Spreadsheet/Spreadsheet.cpp | 19 | ||||
-rw-r--r-- | Applications/Spreadsheet/Spreadsheet.h | 11 | ||||
-rw-r--r-- | Applications/Spreadsheet/SpreadsheetModel.h | 1 | ||||
-rw-r--r-- | Applications/Spreadsheet/SpreadsheetView.cpp | 4 |
5 files changed, 35 insertions, 6 deletions
diff --git a/Applications/Spreadsheet/Cell.h b/Applications/Spreadsheet/Cell.h index 2487a43d4e..fef9031d5e 100644 --- a/Applications/Spreadsheet/Cell.h +++ b/Applications/Spreadsheet/Cell.h @@ -84,8 +84,10 @@ struct Cell : public Weakable<Cell> { const Position& position() const { return m_position; } void set_position(Position position, Badge<Sheet>) { - m_dirty = true; - m_position = move(position); + if (position != m_position) { + m_dirty = true; + m_position = move(position); + } } const Format& evaluated_formats() const { return m_evaluated_formats; } diff --git a/Applications/Spreadsheet/Spreadsheet.cpp b/Applications/Spreadsheet/Spreadsheet.cpp index cac5424d1f..4a9e57c2f2 100644 --- a/Applications/Spreadsheet/Spreadsheet.cpp +++ b/Applications/Spreadsheet/Spreadsheet.cpp @@ -154,12 +154,18 @@ String Sheet::add_column() void Sheet::update() { + if (m_should_ignore_updates) { + m_update_requested = true; + return; + } m_visited_cells_in_update.clear(); Vector<Cell*> cells_copy; // Grab a copy as updates might insert cells into the table. - for (auto& it : m_cells) - cells_copy.append(it.value); + for (auto& it : m_cells) { + if (it.value->dirty()) + cells_copy.append(it.value); + } for (auto& cell : cells_copy) update(*cell); @@ -169,10 +175,15 @@ void Sheet::update() void Sheet::update(Cell& cell) { + if (m_should_ignore_updates) { + m_update_requested = true; + return; + } if (cell.dirty()) { if (has_been_visited(&cell)) { - // This may be part of an cyclic reference chain - // just break the chain, but leave the cell dirty. + // This may be part of an cyclic reference chain, + // so just ignore it. + cell.clear_dirty(); return; } m_visited_cells_in_update.set(&cell); diff --git a/Applications/Spreadsheet/Spreadsheet.h b/Applications/Spreadsheet/Spreadsheet.h index ab9ecb62d8..f260f645be 100644 --- a/Applications/Spreadsheet/Spreadsheet.h +++ b/Applications/Spreadsheet/Spreadsheet.h @@ -117,6 +117,15 @@ public: void update(); void update(Cell&); + void disable_updates() { m_should_ignore_updates = true; } + void enable_updates() + { + m_should_ignore_updates = false; + if (m_update_requested) { + m_update_requested = false; + update(); + } + } struct ValueAndException { JS::Value value; @@ -154,6 +163,8 @@ private: Cell* m_current_cell_being_evaluated { nullptr }; HashTable<Cell*> m_visited_cells_in_update; + bool m_should_ignore_updates { false }; + bool m_update_requested { false }; }; } diff --git a/Applications/Spreadsheet/SpreadsheetModel.h b/Applications/Spreadsheet/SpreadsheetModel.h index 8926f6104b..14527d4c37 100644 --- a/Applications/Spreadsheet/SpreadsheetModel.h +++ b/Applications/Spreadsheet/SpreadsheetModel.h @@ -46,6 +46,7 @@ public: virtual void update() override; virtual bool is_column_sortable(int) const override { return false; } virtual StringView drag_data_type() const override { return "text/x-spreadsheet-data"; } + Sheet& sheet() { return *m_sheet; } private: explicit SheetModel(Sheet& sheet) diff --git a/Applications/Spreadsheet/SpreadsheetView.cpp b/Applications/Spreadsheet/SpreadsheetView.cpp index 9bb417f60f..9762f77578 100644 --- a/Applications/Spreadsheet/SpreadsheetView.cpp +++ b/Applications/Spreadsheet/SpreadsheetView.cpp @@ -86,6 +86,10 @@ void InfinitelyScrollableTableView::mousemove_event(GUI::MouseEvent& event) if (!index.is_valid()) return TableView::mousemove_event(event); + auto& sheet = static_cast<SheetModel&>(*model).sheet(); + sheet.disable_updates(); + ScopeGuard sheet_update_enabler { [&] { sheet.enable_updates(); } }; + auto holding_left_button = !!(event.buttons() & GUI::MouseButton::Left); auto rect = content_rect(index); auto distance = rect.center().absolute_relative_distance_to(event.position()); |