diff options
author | AnotherTest <ali.mpfard@gmail.com> | 2020-12-28 18:33:45 +0330 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-12-29 00:58:43 +0100 |
commit | f17874ecd23363221c2ae8da34e1ca006165b924 (patch) | |
tree | cb96a759fd0daa2537ccf21dd99f8b9290539965 | |
parent | cdf87d22044ccb2b87191d73827bc8f2c6f6a51a (diff) | |
download | serenity-f17874ecd23363221c2ae8da34e1ca006165b924.zip |
Spreadsheet: Add a 'contents' getter/setter to Position
This makes it possible to change the cells' contents programmatically!
-rw-r--r-- | Applications/Spreadsheet/JSIntegration.cpp | 82 | ||||
-rw-r--r-- | Applications/Spreadsheet/JSIntegration.h | 2 | ||||
-rw-r--r-- | Base/res/js/Spreadsheet/runtime.js | 14 |
3 files changed, 96 insertions, 2 deletions
diff --git a/Applications/Spreadsheet/JSIntegration.cpp b/Applications/Spreadsheet/JSIntegration.cpp index f027ceb870..9c0ccfb8ab 100644 --- a/Applications/Spreadsheet/JSIntegration.cpp +++ b/Applications/Spreadsheet/JSIntegration.cpp @@ -81,6 +81,8 @@ bool SheetGlobalObject::put(const JS::PropertyName& name, JS::Value value, JS::V void SheetGlobalObject::initialize() { GlobalObject::initialize(); + define_native_function("get_real_cell_contents", get_real_cell_contents, 1); + define_native_function("set_real_cell_contents", set_real_cell_contents, 2); define_native_function("parse_cell_name", parse_cell_name, 1); define_native_function("current_cell_position", current_cell_position, 0); define_native_function("column_arithmetic", column_arithmetic, 2); @@ -97,6 +99,86 @@ void SheetGlobalObject::visit_edges(Visitor& visitor) } } +JS_DEFINE_NATIVE_FUNCTION(SheetGlobalObject::get_real_cell_contents) +{ + auto* this_object = vm.this_value(global_object).to_object(global_object); + if (!this_object) + return JS::js_null(); + + if (StringView("SheetGlobalObject") != this_object->class_name()) { + vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, "SheetGlobalObject"); + return {}; + } + + auto sheet_object = static_cast<SheetGlobalObject*>(this_object); + + if (vm.argument_count() != 1) { + vm.throw_exception<JS::TypeError>(global_object, "Expected exactly one argument to get_real_cell_contents()"); + return {}; + } + + auto name_value = vm.argument(0); + if (!name_value.is_string()) { + vm.throw_exception<JS::TypeError>(global_object, "Expected a String argument to get_real_cell_contents()"); + return {}; + } + auto position = Sheet::parse_cell_name(name_value.as_string().string()); + if (!position.has_value()) { + vm.throw_exception<JS::TypeError>(global_object, "Invalid cell name"); + return {}; + } + + const auto* cell = sheet_object->m_sheet.at(position.value()); + if (!cell) + return JS::js_undefined(); + + if (cell->kind() == Spreadsheet::Cell::Kind::Formula) + return JS::js_string(vm.heap(), String::formatted("={}", cell->data())); + + return JS::js_string(vm.heap(), cell->data()); +} + +JS_DEFINE_NATIVE_FUNCTION(SheetGlobalObject::set_real_cell_contents) +{ + auto* this_object = vm.this_value(global_object).to_object(global_object); + if (!this_object) + return JS::js_null(); + + if (StringView("SheetGlobalObject") != this_object->class_name()) { + vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, "SheetGlobalObject"); + return {}; + } + + auto sheet_object = static_cast<SheetGlobalObject*>(this_object); + + if (vm.argument_count() != 2) { + vm.throw_exception<JS::TypeError>(global_object, "Expected exactly two arguments to set_real_cell_contents()"); + return {}; + } + + auto name_value = vm.argument(0); + if (!name_value.is_string()) { + vm.throw_exception<JS::TypeError>(global_object, "Expected the first argument of set_real_cell_contents() to be a String"); + return {}; + } + auto position = Sheet::parse_cell_name(name_value.as_string().string()); + if (!position.has_value()) { + vm.throw_exception<JS::TypeError>(global_object, "Invalid cell name"); + return {}; + } + + auto new_contents_value = vm.argument(1); + if (!new_contents_value.is_string()) { + vm.throw_exception<JS::TypeError>(global_object, "Expected the second argument of set_real_cell_contents() to be a String"); + return {}; + } + + auto& cell = sheet_object->m_sheet.ensure(position.value()); + auto& new_contents = new_contents_value.as_string().string(); + cell.set_data(new_contents); + return JS::js_null(); +} + JS_DEFINE_NATIVE_FUNCTION(SheetGlobalObject::parse_cell_name) { if (vm.argument_count() != 1) { diff --git a/Applications/Spreadsheet/JSIntegration.h b/Applications/Spreadsheet/JSIntegration.h index 4ad289e61f..2aeece9a6b 100644 --- a/Applications/Spreadsheet/JSIntegration.h +++ b/Applications/Spreadsheet/JSIntegration.h @@ -44,6 +44,8 @@ public: virtual bool put(const JS::PropertyName&, JS::Value value, JS::Value receiver = {}) override; virtual void initialize() override; + JS_DECLARE_NATIVE_FUNCTION(get_real_cell_contents); + JS_DECLARE_NATIVE_FUNCTION(set_real_cell_contents); JS_DECLARE_NATIVE_FUNCTION(parse_cell_name); JS_DECLARE_NATIVE_FUNCTION(current_cell_position); JS_DECLARE_NATIVE_FUNCTION(column_index); diff --git a/Base/res/js/Spreadsheet/runtime.js b/Base/res/js/Spreadsheet/runtime.js index 5f9cac58f7..688b8b7a04 100644 --- a/Base/res/js/Spreadsheet/runtime.js +++ b/Base/res/js/Spreadsheet/runtime.js @@ -7,6 +7,16 @@ class Position { this.name = `${column}${row}`; } + get contents() { + return this.sheet.get_real_cell_contents(this.name); + } + + set contents(value) { + value = `${value}`; + this.sheet.set_real_cell_contents(this.name, value); + return value; + } + static from_name(name) { let sheet = thisSheet; let obj = sheet.parse_cell_name(name); @@ -678,8 +688,8 @@ here.__documentation = JSON.stringify({ "- `with_row(row)`: Returns a Position with its column being this object's, and its row being the provided the value.\n" + "- `with_column(column)`: Similar to `with_row()`, but changes the column instead.\n" + "- `in_sheet(the_sheet)`: Returns a Position with the same column and row as this one, but with its sheet being `the_sheet`.\n" + - "- `value()`: Returns the value at the position which it represents, in the object's sheet (current sheet by default).\n\n" + - "**NOTE**: Currently only supports single-letter column names", + "- `value()`: Returns the value at the position which it represents, in the object's sheet (current sheet by default).\n" + + "- `contents`: An accessor for the real contents of the cell (i.e. the text as typed in the cell editor)\n", examples: { "here().up().value()": "Get the value of the cell above this one", "here().up().with_column('A')": |