summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnotherTest <ali.mpfard@gmail.com>2020-12-22 12:52:59 +0330
committerAndreas Kling <kling@serenityos.org>2020-12-22 23:35:29 +0100
commit8f05e4e765b86d6f350886cdb81d1b3d0ffab085 (patch)
treee4c91f14e8165e079877da7eb00da8b058859b99
parentbfb25855cb208d855799906dd2121b3d122ca5ea (diff)
downloadserenity-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.h6
-rw-r--r--Applications/Spreadsheet/Spreadsheet.cpp19
-rw-r--r--Applications/Spreadsheet/Spreadsheet.h11
-rw-r--r--Applications/Spreadsheet/SpreadsheetModel.h1
-rw-r--r--Applications/Spreadsheet/SpreadsheetView.cpp4
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());