diff options
-rw-r--r-- | Applications/Spreadsheet/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Applications/Spreadsheet/Cell.cpp | 120 | ||||
-rw-r--r-- | Applications/Spreadsheet/Cell.h | 84 | ||||
-rw-r--r-- | Applications/Spreadsheet/Forward.h | 38 | ||||
-rw-r--r-- | Applications/Spreadsheet/JSIntegration.h | 4 | ||||
-rw-r--r-- | Applications/Spreadsheet/Spreadsheet.cpp | 64 | ||||
-rw-r--r-- | Applications/Spreadsheet/Spreadsheet.h | 82 | ||||
-rw-r--r-- | Applications/Spreadsheet/Workbook.h | 3 |
8 files changed, 250 insertions, 146 deletions
diff --git a/Applications/Spreadsheet/CMakeLists.txt b/Applications/Spreadsheet/CMakeLists.txt index 9eac41dc0f..5ec5efee9a 100644 --- a/Applications/Spreadsheet/CMakeLists.txt +++ b/Applications/Spreadsheet/CMakeLists.txt @@ -1,4 +1,5 @@ set(SOURCES + Cell.cpp CellSyntaxHighlighter.cpp HelpWindow.cpp JSIntegration.cpp diff --git a/Applications/Spreadsheet/Cell.cpp b/Applications/Spreadsheet/Cell.cpp new file mode 100644 index 0000000000..d44d02debf --- /dev/null +++ b/Applications/Spreadsheet/Cell.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2020, the SerenityOS developers. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "Cell.h" +#include "Spreadsheet.h" +#include <AK/StringBuilder.h> + +namespace Spreadsheet { + +void Cell::set_data(String new_data) +{ + if (data == new_data) + return; + + if (new_data.starts_with("=")) { + new_data = new_data.substring(1, new_data.length() - 1); + kind = Formula; + } else { + kind = LiteralString; + } + + data = move(new_data); + dirty = true; + evaluated_externally = false; +} + +void Cell::set_data(JS::Value new_data) +{ + dirty = true; + evaluated_externally = true; + + StringBuilder builder; + + builder.append(new_data.to_string_without_side_effects()); + data = builder.build(); + + evaluated_data = move(new_data); +} + +void Cell::update_data() +{ + TemporaryChange cell_change { sheet->current_evaluated_cell(), this }; + if (!dirty) + return; + + dirty = false; + if (kind == Formula) { + if (!evaluated_externally) + evaluated_data = sheet->evaluate(data, this); + } + + for (auto& ref : referencing_cells) { + if (ref) { + ref->dirty = true; + ref->update(); + } + } +} + +void Cell::update() +{ + sheet->update(*this); +} + +JS::Value Cell::js_data() +{ + if (dirty) + update(); + + if (kind == Formula) + return evaluated_data; + + return JS::js_string(sheet->interpreter(), data); +} + +String Cell::source() const +{ + StringBuilder builder; + if (kind == Formula) + builder.append('='); + builder.append(data); + return builder.to_string(); +} + +// FIXME: Find a better way to figure out dependencies +void Cell::reference_from(Cell* other) +{ + if (!other || other == this) + return; + + if (!referencing_cells.find([other](auto& ptr) { return ptr.ptr() == other; }).is_end()) + return; + + referencing_cells.append(other->make_weak_ptr()); +} + +} diff --git a/Applications/Spreadsheet/Cell.h b/Applications/Spreadsheet/Cell.h new file mode 100644 index 0000000000..6fed58f4b9 --- /dev/null +++ b/Applications/Spreadsheet/Cell.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2020, the SerenityOS developers. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "Forward.h" +#include "JSIntegration.h" +#include <AK/String.h> +#include <AK/Types.h> +#include <AK/WeakPtr.h> + +namespace Spreadsheet { + +struct Cell : public Weakable<Cell> { + Cell(String data, WeakPtr<Sheet> sheet) + : dirty(false) + , data(move(data)) + , kind(LiteralString) + , sheet(sheet) + { + } + + Cell(String source, JS::Value&& cell_value, WeakPtr<Sheet> sheet) + : dirty(false) + , data(move(source)) + , evaluated_data(move(cell_value)) + , kind(Formula) + , sheet(sheet) + { + } + + void reference_from(Cell*); + + void set_data(String new_data); + void set_data(JS::Value new_data); + + String source() const; + + JS::Value js_data(); + + void update(Badge<Sheet>) { update_data(); } + void update(); + + enum Kind { + LiteralString, + Formula, + }; + + bool dirty { false }; + bool evaluated_externally { false }; + String data; + JS::Value evaluated_data; + Kind kind { LiteralString }; + WeakPtr<Sheet> sheet; + Vector<WeakPtr<Cell>> referencing_cells; + +private: + void update_data(); +}; + +} diff --git a/Applications/Spreadsheet/Forward.h b/Applications/Spreadsheet/Forward.h new file mode 100644 index 0000000000..5bd5480025 --- /dev/null +++ b/Applications/Spreadsheet/Forward.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020, the SerenityOS developers. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +namespace Spreadsheet { + +struct Cell; +class Sheet; +struct Position; +class Workbook; +class WorkbookObject; +class SheetGlobalObject; + +} diff --git a/Applications/Spreadsheet/JSIntegration.h b/Applications/Spreadsheet/JSIntegration.h index bd3bd1e77f..ace3e3c823 100644 --- a/Applications/Spreadsheet/JSIntegration.h +++ b/Applications/Spreadsheet/JSIntegration.h @@ -26,14 +26,12 @@ #pragma once +#include "Forward.h" #include <LibJS/Forward.h> #include <LibJS/Runtime/GlobalObject.h> namespace Spreadsheet { -class Sheet; -class Workbook; - class SheetGlobalObject : public JS::GlobalObject { JS_OBJECT(SheetGlobalObject, JS::GlobalObject); diff --git a/Applications/Spreadsheet/Spreadsheet.cpp b/Applications/Spreadsheet/Spreadsheet.cpp index de8410d06d..fb250d177e 100644 --- a/Applications/Spreadsheet/Spreadsheet.cpp +++ b/Applications/Spreadsheet/Spreadsheet.cpp @@ -77,16 +77,15 @@ Sheet::Sheet(Workbook& workbook) } } } - } -JS::Interpreter& Sheet::interpreter() const +Sheet::~Sheet() { - return m_workbook.interpreter(); } -Sheet::~Sheet() +JS::Interpreter& Sheet::interpreter() const { + return m_workbook.interpreter(); } size_t Sheet::add_row() @@ -171,42 +170,6 @@ JS::Value Sheet::evaluate(const StringView& source, Cell* on_behalf_of) return value; } -void Cell::update_data() -{ - TemporaryChange cell_change { sheet->current_evaluated_cell(), this }; - if (!dirty) - return; - - dirty = false; - if (kind == Formula) { - if (!evaluated_externally) - evaluated_data = sheet->evaluate(data, this); - } - - for (auto& ref : referencing_cells) { - if (ref) { - ref->dirty = true; - ref->update(); - } - } -} - -void Cell::update() -{ - sheet->update(*this); -} - -JS::Value Cell::js_data() -{ - if (dirty) - update(); - - if (kind == Formula) - return evaluated_data; - - return JS::js_string(sheet->interpreter(), data); -} - Cell* Sheet::at(const StringView& name) { auto pos = parse_cell_name(name); @@ -238,27 +201,6 @@ Optional<Position> Sheet::parse_cell_name(const StringView& name) return Position { col, row.to_uint().value() }; } -String Cell::source() const -{ - StringBuilder builder; - if (kind == Formula) - builder.append('='); - builder.append(data); - return builder.to_string(); -} - -// FIXME: Find a better way to figure out dependencies -void Cell::reference_from(Cell* other) -{ - if (!other || other == this) - return; - - if (!referencing_cells.find([other](auto& ptr) { return ptr.ptr() == other; }).is_end()) - return; - - referencing_cells.append(other->make_weak_ptr()); -} - RefPtr<Sheet> Sheet::from_json(const JsonObject& object, Workbook& workbook) { auto sheet = adopt(*new Sheet(workbook)); diff --git a/Applications/Spreadsheet/Spreadsheet.h b/Applications/Spreadsheet/Spreadsheet.h index c711624ce4..3207398ec8 100644 --- a/Applications/Spreadsheet/Spreadsheet.h +++ b/Applications/Spreadsheet/Spreadsheet.h @@ -26,6 +26,8 @@ #pragma once +#include "Cell.h" +#include "Forward.h" #include <AK/HashMap.h> #include <AK/HashTable.h> #include <AK/String.h> @@ -39,9 +41,6 @@ namespace Spreadsheet { -class Workbook; -class SheetGlobalObject; - struct Position { String column; size_t row { 0 }; @@ -57,83 +56,6 @@ struct Position { } }; -class Sheet; - -struct Cell : public Weakable<Cell> { - Cell(String data, WeakPtr<Sheet> sheet) - : dirty(false) - , data(move(data)) - , kind(LiteralString) - , sheet(sheet) - { - } - - Cell(String source, JS::Value&& cell_value, WeakPtr<Sheet> sheet) - : dirty(false) - , data(move(source)) - , evaluated_data(move(cell_value)) - , kind(Formula) - , sheet(sheet) - { - } - - bool dirty { false }; - bool evaluated_externally { false }; - String data; - JS::Value evaluated_data; - - enum Kind { - LiteralString, - Formula, - } kind { LiteralString }; - - WeakPtr<Sheet> sheet; - Vector<WeakPtr<Cell>> referencing_cells; - - void reference_from(Cell*); - - void set_data(String new_data) - { - if (data == new_data) - return; - - if (new_data.starts_with("=")) { - new_data = new_data.substring(1, new_data.length() - 1); - kind = Formula; - } else { - kind = LiteralString; - } - - data = move(new_data); - dirty = true; - evaluated_externally = false; - } - - void set_data(JS::Value new_data) - { - dirty = true; - evaluated_externally = true; - - StringBuilder builder; - - builder.append("="); - builder.append(new_data.to_string_without_side_effects()); - data = builder.build(); - - evaluated_data = move(new_data); - } - - String source() const; - - JS::Value js_data(); - - void update(Badge<Sheet>) { update_data(); } - void update(); - -private: - void update_data(); -}; - class Sheet : public Core::Object { C_OBJECT(Sheet); diff --git a/Applications/Spreadsheet/Workbook.h b/Applications/Spreadsheet/Workbook.h index 54295fbe67..7c31db1f31 100644 --- a/Applications/Spreadsheet/Workbook.h +++ b/Applications/Spreadsheet/Workbook.h @@ -26,14 +26,13 @@ #pragma once +#include "Forward.h" #include "Spreadsheet.h" #include <AK/NonnullOwnPtrVector.h> #include <AK/Result.h> namespace Spreadsheet { -class WorkbookObject; - class Workbook { public: Workbook(NonnullRefPtrVector<Sheet>&& sheets); |