diff options
author | AnotherTest <ali.mpfard@gmail.com> | 2020-11-26 10:46:22 +0330 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-11-30 12:07:45 +0100 |
commit | f6ae4edbd230dab2dcc4e108f731f00f54627497 (patch) | |
tree | 8658d6764f2b2dc6d73d6ec30fbef6900837aa65 /Applications | |
parent | 71de8b748068d3c2a7adb2796b2ed60c17a46552 (diff) | |
download | serenity-f6ae4edbd230dab2dcc4e108f731f00f54627497.zip |
Spreadsheet: Implement infinite-scroll for rows
Every time the scrollbar reaches the end, we append 100 more rows
(seamlessly!).
As a result of defaulting to 100 rows, we can also save with the
smallest number of rows required.
This partially deals with #4170.
Diffstat (limited to 'Applications')
-rw-r--r-- | Applications/Spreadsheet/Spreadsheet.cpp | 31 | ||||
-rw-r--r-- | Applications/Spreadsheet/Spreadsheet.h | 6 | ||||
-rw-r--r-- | Applications/Spreadsheet/SpreadsheetModel.cpp | 1 | ||||
-rw-r--r-- | Applications/Spreadsheet/SpreadsheetView.cpp | 29 | ||||
-rw-r--r-- | Applications/Spreadsheet/SpreadsheetView.h | 13 |
5 files changed, 69 insertions, 11 deletions
diff --git a/Applications/Spreadsheet/Spreadsheet.cpp b/Applications/Spreadsheet/Spreadsheet.cpp index 6f419bcf16..006ce2eec5 100644 --- a/Applications/Spreadsheet/Spreadsheet.cpp +++ b/Applications/Spreadsheet/Spreadsheet.cpp @@ -49,10 +49,10 @@ Sheet::Sheet(const StringView& name, Workbook& workbook) { m_name = name; - for (size_t i = 0; i < 20; ++i) + for (size_t i = 0; i < default_row_count; ++i) add_row(); - for (size_t i = 0; i < 16; ++i) + for (size_t i = 0; i < default_column_count; ++i) add_column(); } @@ -318,7 +318,7 @@ void Sheet::copy_cells(Vector<Position> from, Vector<Position> to, Optional<Posi RefPtr<Sheet> Sheet::from_json(const JsonObject& object, Workbook& workbook) { auto sheet = adopt(*new Sheet(workbook)); - auto rows = object.get("rows").to_u32(20); + auto rows = object.get("rows").to_u32(default_row_count); auto columns = object.get("columns"); if (!columns.is_array()) return nullptr; @@ -326,7 +326,7 @@ RefPtr<Sheet> Sheet::from_json(const JsonObject& object, Workbook& workbook) sheet->set_name(name); - for (size_t i = 0; i < rows; ++i) + for (size_t i = 0; i < max(rows, (unsigned)Sheet::default_row_count); ++i) sheet->add_row(); // FIXME: Better error checking. @@ -421,6 +421,19 @@ RefPtr<Sheet> Sheet::from_json(const JsonObject& object, Workbook& workbook) return sheet; } +Position Sheet::written_data_bounds() const +{ + Position bound; + for (auto& entry : m_cells) { + if (entry.key.row > bound.row) + bound.row = entry.key.row; + if (entry.key.column > bound.column) + bound.column = entry.key.column; + } + + return bound; +} + JsonObject Sheet::to_json() const { JsonObject object; @@ -433,12 +446,14 @@ JsonObject Sheet::to_json() const obj.set("background_color", format.background_color.value().to_string()); }; + auto bottom_right = written_data_bounds(); + auto columns = JsonArray(); for (auto& column : m_columns) columns.append(column); object.set("columns", move(columns)); - object.set("rows", m_rows); + object.set("rows", bottom_right.row); JsonObject cells; for (auto& it : m_cells) { @@ -502,10 +517,12 @@ Vector<Vector<String>> Sheet::to_xsv() const { Vector<Vector<String>> data; + auto bottom_right = written_data_bounds(); + // First row = headers. data.append(m_columns); - for (size_t i = 0; i < m_rows; ++i) { + for (size_t i = 0; i <= bottom_right.row; ++i) { Vector<String> row; row.resize(m_columns.size()); for (size_t j = 0; j < m_columns.size(); ++j) { @@ -527,7 +544,7 @@ RefPtr<Sheet> Sheet::from_xsv(const Reader::XSV& xsv, Workbook& workbook) auto sheet = adopt(*new Sheet(workbook)); sheet->m_columns = cols; - for (size_t i = 0; i < rows; ++i) + for (size_t i = 0; i < max(rows, Sheet::default_row_count); ++i) sheet->add_row(); for (auto row : xsv) { diff --git a/Applications/Spreadsheet/Spreadsheet.h b/Applications/Spreadsheet/Spreadsheet.h index f9a2c5af2b..edc2c68d60 100644 --- a/Applications/Spreadsheet/Spreadsheet.h +++ b/Applications/Spreadsheet/Spreadsheet.h @@ -46,6 +46,9 @@ class Sheet : public Core::Object { C_OBJECT(Sheet); public: + constexpr static size_t default_row_count = 100; + constexpr static size_t default_column_count = 26; + ~Sheet(); static Optional<Position> parse_cell_name(const StringView&); @@ -124,6 +127,9 @@ public: void copy_cells(Vector<Position> from, Vector<Position> to, Optional<Position> resolve_relative_to = {}); + /// Gives the bottom-right corner of the smallest bounding box containing all the written data. + Position written_data_bounds() const; + private: explicit Sheet(Workbook&); explicit Sheet(const StringView& name, Workbook&); diff --git a/Applications/Spreadsheet/SpreadsheetModel.cpp b/Applications/Spreadsheet/SpreadsheetModel.cpp index 58ac126095..5cc55acf08 100644 --- a/Applications/Spreadsheet/SpreadsheetModel.cpp +++ b/Applications/Spreadsheet/SpreadsheetModel.cpp @@ -170,6 +170,7 @@ void SheetModel::set_data(const GUI::ModelIndex& index, const GUI::Variant& valu void SheetModel::update() { m_sheet->update(); + did_update(UpdateFlag::DontInvalidateIndexes); } } diff --git a/Applications/Spreadsheet/SpreadsheetView.cpp b/Applications/Spreadsheet/SpreadsheetView.cpp index dfb718182d..7361258cc0 100644 --- a/Applications/Spreadsheet/SpreadsheetView.cpp +++ b/Applications/Spreadsheet/SpreadsheetView.cpp @@ -35,6 +35,7 @@ #include <LibGUI/Menu.h> #include <LibGUI/ModelEditingDelegate.h> #include <LibGUI/Painter.h> +#include <LibGUI/ScrollBar.h> #include <LibGUI/TableView.h> #include <LibGfx/Palette.h> @@ -57,17 +58,40 @@ void SpreadsheetView::EditingDelegate::set_value(const GUI::Variant& value) StringModelEditingDelegate::set_value(""); } +void InfinitelyScrollableTableView::did_scroll() +{ + TableView::did_scroll(); + auto& vscrollbar = vertical_scrollbar(); + if (vscrollbar.is_visible() && vscrollbar.value() == vscrollbar.max()) { + if (on_reaching_vertical_end) + on_reaching_vertical_end(); + } +} + +void SpreadsheetView::update_with_model() +{ + m_table_view->model()->update(); + m_table_view->update(); +} + SpreadsheetView::SpreadsheetView(Sheet& sheet) : m_sheet(sheet) { set_layout<GUI::VerticalBoxLayout>().set_margins({ 2, 2, 2, 2 }); - m_table_view = add<GUI::TableView>(); + m_table_view = add<InfinitelyScrollableTableView>(); m_table_view->set_grid_style(GUI::TableView::GridStyle::Both); m_table_view->set_cursor_style(GUI::TableView::CursorStyle::Item); m_table_view->set_edit_triggers(GUI::AbstractView::EditTrigger::EditKeyPressed | GUI::AbstractView::AnyKeyPressed | GUI::AbstractView::DoubleClicked); m_table_view->set_tab_key_navigation_enabled(true); m_table_view->row_header().set_visible(true); m_table_view->set_model(SheetModel::create(*m_sheet)); + m_table_view->on_reaching_vertical_end = [&]() { + for (size_t i = 0; i < 100; ++i) { + auto index = m_sheet->add_row(); + m_table_view->set_column_painting_delegate(index, make<TableCellPainter>(*m_table_view)); + }; + update_with_model(); + }; set_focus_proxy(m_table_view); @@ -107,8 +131,7 @@ SpreadsheetView::SpreadsheetView(Sheet& sheet) if (on_selection_changed) { on_selection_changed(move(selected_positions)); - m_table_view->model()->update(); - m_table_view->update(); + update_with_model(); }; }; diff --git a/Applications/Spreadsheet/SpreadsheetView.h b/Applications/Spreadsheet/SpreadsheetView.h index 93a3c83acc..09bcb59251 100644 --- a/Applications/Spreadsheet/SpreadsheetView.h +++ b/Applications/Spreadsheet/SpreadsheetView.h @@ -79,6 +79,15 @@ private: } }; +class InfinitelyScrollableTableView : public GUI::TableView { + C_OBJECT(InfinitelyScrollableTableView) +public: + Function<void()> on_reaching_vertical_end; + +private: + virtual void did_scroll() override; +}; + class SpreadsheetView final : public GUI::Widget { C_OBJECT(SpreadsheetView); @@ -100,6 +109,8 @@ private: virtual void hide_event(GUI::HideEvent&) override; virtual void show_event(GUI::ShowEvent&) override; + void update_with_model(); + SpreadsheetView(Sheet&); class EditingDelegate final : public GUI::StringModelEditingDelegate { @@ -143,7 +154,7 @@ private: }; NonnullRefPtr<Sheet> m_sheet; - RefPtr<GUI::TableView> m_table_view; + RefPtr<InfinitelyScrollableTableView> m_table_view; RefPtr<GUI::Menu> m_cell_range_context_menu; }; |