mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 08:58:11 +00:00
Spreadsheet: Add a 'contents' getter/setter to Position
This makes it possible to change the cells' contents programmatically!
This commit is contained in:
parent
cdf87d2204
commit
f17874ecd2
3 changed files with 96 additions and 2 deletions
|
@ -81,6 +81,8 @@ bool SheetGlobalObject::put(const JS::PropertyName& name, JS::Value value, JS::V
|
||||||
void SheetGlobalObject::initialize()
|
void SheetGlobalObject::initialize()
|
||||||
{
|
{
|
||||||
GlobalObject::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("parse_cell_name", parse_cell_name, 1);
|
||||||
define_native_function("current_cell_position", current_cell_position, 0);
|
define_native_function("current_cell_position", current_cell_position, 0);
|
||||||
define_native_function("column_arithmetic", column_arithmetic, 2);
|
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)
|
JS_DEFINE_NATIVE_FUNCTION(SheetGlobalObject::parse_cell_name)
|
||||||
{
|
{
|
||||||
if (vm.argument_count() != 1) {
|
if (vm.argument_count() != 1) {
|
||||||
|
|
|
@ -44,6 +44,8 @@ public:
|
||||||
virtual bool put(const JS::PropertyName&, JS::Value value, JS::Value receiver = {}) override;
|
virtual bool put(const JS::PropertyName&, JS::Value value, JS::Value receiver = {}) override;
|
||||||
virtual void initialize() 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(parse_cell_name);
|
||||||
JS_DECLARE_NATIVE_FUNCTION(current_cell_position);
|
JS_DECLARE_NATIVE_FUNCTION(current_cell_position);
|
||||||
JS_DECLARE_NATIVE_FUNCTION(column_index);
|
JS_DECLARE_NATIVE_FUNCTION(column_index);
|
||||||
|
|
|
@ -7,6 +7,16 @@ class Position {
|
||||||
this.name = `${column}${row}`;
|
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) {
|
static from_name(name) {
|
||||||
let sheet = thisSheet;
|
let sheet = thisSheet;
|
||||||
let obj = sheet.parse_cell_name(name);
|
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_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" +
|
"- `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" +
|
"- `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" +
|
"- `value()`: Returns the value at the position which it represents, in the object's sheet (current sheet by default).\n" +
|
||||||
"**NOTE**: Currently only supports single-letter column names",
|
"- `contents`: An accessor for the real contents of the cell (i.e. the text as typed in the cell editor)\n",
|
||||||
examples: {
|
examples: {
|
||||||
"here().up().value()": "Get the value of the cell above this one",
|
"here().up().value()": "Get the value of the cell above this one",
|
||||||
"here().up().with_column('A')":
|
"here().up().with_column('A')":
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue