diff --git a/Applications/Spreadsheet/Cell.h b/Applications/Spreadsheet/Cell.h index 2487a43d4ea..fef9031d5e9 100644 --- a/Applications/Spreadsheet/Cell.h +++ b/Applications/Spreadsheet/Cell.h @@ -84,8 +84,10 @@ struct Cell : public Weakable { const Position& position() const { return m_position; } void set_position(Position position, Badge) { - 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 cac5424d1ff..4a9e57c2f22 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 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 ab9ecb62d8b..f260f645be4 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 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 8926f6104b0..14527d4c377 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 9bb417f60f5..9762f77578c 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(*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());