mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 10:42:45 +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
	
	 AnotherTest
						AnotherTest