From 20ab0106df110dd664b28117e78341cf01062175 Mon Sep 17 00:00:00 2001 From: don-tnowe <67479453+don-tnowe@users.noreply.github.com> Date: Mon, 24 Oct 2022 20:39:12 +0300 Subject: [PATCH] Implement cell context menu --- .gitignore | 3 + README.md | 2 + .../resources_speadsheet_view/editor_view.gd | 69 +++++-- .../editor_view.tscn | 44 +++-- .../import_export/formats_edit/edit_base.gd | 14 +- .../import_export/formats_edit/edit_csv.gd | 14 ++ .../import_export/formats_edit/edit_tres.gd | 32 +++ .../import_export/import_export_dialog.tscn | 171 ++++++++++++++-- .../selection_actions.gd | 163 ++++++++++++++++ .../selection_actions.tscn | 182 ++++++++++++++++++ project.godot | 2 +- 11 files changed, 643 insertions(+), 53 deletions(-) create mode 100644 addons/resources_speadsheet_view/selection_actions.gd create mode 100644 addons/resources_speadsheet_view/selection_actions.tscn diff --git a/.gitignore b/.gitignore index 4cccccd..a3d9ebd 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,6 @@ mono_crash.*.json # Editor Plugin persistent data addons/resources_speadsheet_view/saved_state.json + +# Tools used during development +addons/editor_icon_previewer/ diff --git a/README.md b/README.md index 80f884f..82228ec 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,8 @@ Possible inputs: - `Home/End` - Move cursor to start/end of cell - `Ctrl + / Cmd + ` - Move through / Erase whole word - `Ctrl/Cmd + C/V` - Copy cells / Paste text into cells +- `Ctrl/Cmd + R` - Rename resource +- `Ctrl/Cmd + D` - Duplicate selected rows - `Ctrl/Cmd + (Shift) + Z` - The Savior If clipboard contains as many lines as there are cells selected, each line is pasted into a separate cell. diff --git a/addons/resources_speadsheet_view/editor_view.gd b/addons/resources_speadsheet_view/editor_view.gd index 39ef978..a9ad8ea 100644 --- a/addons/resources_speadsheet_view/editor_view.gd +++ b/addons/resources_speadsheet_view/editor_view.gd @@ -2,6 +2,8 @@ tool extends Control signal grid_updated() +signal cells_selected(cells) +signal cells_context(cells) export var table_header_scene : PackedScene @@ -390,6 +392,7 @@ func deselect_all_cells(): edited_cells.clear() edited_cells_text.clear() edit_cursor_positions.clear() + emit_signal("cells_selected", []) func deselect_cell(cell : Control): @@ -401,6 +404,8 @@ func deselect_cell(cell : Control): if edited_cells_text.size() != 0: edited_cells_text.remove(idx) edit_cursor_positions.remove(idx) + + emit_signal("cells_selected", edited_cells) func select_cell(cell : Control): @@ -411,6 +416,8 @@ func select_cell(cell : Control): inspector_resource = rows[_get_cell_row(cell)].duplicate() editor_plugin.get_editor_interface().edit_resource(inspector_resource) + emit_signal("cells_selected", edited_cells) + func select_cells_to(cell : Control): var column_index := _get_cell_column(cell) @@ -437,6 +444,8 @@ func select_cells_to(cell : Control): edited_cells_text.append(str(cur_cell.text)) edit_cursor_positions.append(cur_cell.text.length()) + emit_signal("cells_selected", edited_cells) + func select_column(column_index : int): deselect_all_cells() @@ -509,6 +518,31 @@ func set_edited_cells_values(new_cell_values : Array): _update_column_sizes() +func rename_row(row, new_name): + if !has_row_names(): return + + io.rename_row(row, new_name) + refresh() + + +func duplicate_selected_rows(new_name : String): + io.duplicate_rows(_get_edited_cells_resources(), new_name) + refresh() + + +func delete_selected_rows(): + io.delete_rows(_get_edited_cells_resources()) + refresh() + + +func has_row_names(): + return io.has_row_names() + + +func get_last_selected_row(): + return rows[_get_cell_row(edited_cells[-1])] + + func _update_selected_cells_text(): if edited_cells_text.size() == 0: return @@ -587,6 +621,9 @@ func _gui_input(event : InputEvent): if event is InputEventMouseButton: _update_scroll() if event.button_index != BUTTON_LEFT: + if event.button_index == BUTTON_RIGHT: + emit_signal("cells_context", edited_cells) + return grab_focus() @@ -606,20 +643,21 @@ func _input(event : InputEvent): return # Ctrl + Z (before, and instead of, committing the action!) - if Input.is_key_pressed(KEY_CONTROL) and event.scancode == KEY_Z: - if Input.is_key_pressed(KEY_SHIFT): - editor_plugin.undo_redo.redo() - # Ctrl + z - else: - editor_plugin.undo_redo.undo() - - return + if Input.is_key_pressed(KEY_CONTROL): + if event.scancode == KEY_Z: + if Input.is_key_pressed(KEY_SHIFT): + editor_plugin.undo_redo.redo() + # Ctrl + z + else: + editor_plugin.undo_redo.undo() + + return - # This shortcut is used by Godot as well. - if Input.is_key_pressed(KEY_CONTROL) and event.scancode == KEY_Y: - editor_plugin.undo_redo.redo() - return - + # This shortcut is used by Godot as well. + if event.scancode == KEY_Y: + editor_plugin.undo_redo.redo() + return + _key_specific_action(event) grab_focus() @@ -670,6 +708,7 @@ func _key_specific_action(event : InputEvent): # Ctrl + C (so you can edit in a proper text editor instead of this wacky nonsense) elif ctrl_pressed and event.scancode == KEY_C: TextEditingUtils.multi_copy(edited_cells_text) + get_tree().set_input_as_handled() # The following actions do not work on non-editable cells. if !column_editors[column].is_text() or columns[column] == "resource_path": @@ -680,6 +719,7 @@ func _key_specific_action(event : InputEvent): set_edited_cells_values(TextEditingUtils.multi_paste( edited_cells_text, edit_cursor_positions )) + get_tree().set_input_as_handled() # ERASING elif event.scancode == KEY_BACKSPACE: @@ -759,7 +799,8 @@ func _try_convert(value, type): func _get_edited_cells_resources() -> Array: - var arr := edited_cells.duplicate() + var arr := [] + arr.resize(edited_cells.size()) for i in arr.size(): arr[i] = rows[_get_cell_row(edited_cells[i])] diff --git a/addons/resources_speadsheet_view/editor_view.tscn b/addons/resources_speadsheet_view/editor_view.tscn index 6152df9..ed3cb67 100644 --- a/addons/resources_speadsheet_view/editor_view.tscn +++ b/addons/resources_speadsheet_view/editor_view.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=21 format=2] +[gd_scene load_steps=22 format=2] [ext_resource path="res://addons/resources_speadsheet_view/editor_view.gd" type="Script" id=1] [ext_resource path="res://addons/resources_speadsheet_view/typed_cells/cell_editor_string.gd" type="Script" id=2] @@ -18,6 +18,7 @@ [ext_resource path="res://addons/resources_speadsheet_view/typed_editors/dock_enum_array.tscn" type="PackedScene" id=16] [ext_resource path="res://addons/resources_speadsheet_view/table_pages.gd" type="Script" id=17] [ext_resource path="res://addons/resources_speadsheet_view/import_export/import_export_dialog.tscn" type="PackedScene" id=18] +[ext_resource path="res://addons/resources_speadsheet_view/selection_actions.tscn" type="PackedScene" id=19] [sub_resource type="Image" id=3] data = { @@ -596,14 +597,16 @@ bbcode_text = "[center]Edit Resources as Spreadsheet[/center] \"Welp, it is what it sounds like!\" Possible inputs: -- [code]Ctrl + Click / Cmd + Click[/code] - Select multiple cells in one column -- [code]Shift + Click[/code] - Select all cells between A and B in one column -- [code]Left/Right[/code] - Move cursor along cell text -- [code]Backspace/Delete[/code] - Erase text Left / Right from cursor -- [code]Home/End[/code] - Move cursor to start/end of cell -- [code]Ctrl + / Cmd + [/code] - Move through / Erase whole word -- [code]Ctrl/Cmd + C/V[/code] - Copy cells / Paste text into cells -- [code]Ctrl/Cmd + (Shift) + Z[/code] - The Savior +- Ctrl + Click / Cmd + Click[/code] - Select multiple cells in one column +- Shift + Click[/code] - Select all cells between A and B in one column +- Left/Right[/code] - Move cursor along cell text +- Backspace/Delete[/code] - Erase text Left / Right from cursor +- Home/End[/code] - Move cursor to start/end of cell +- Ctrl + / Cmd + [/code] - Move through / Erase whole word +- Ctrl/Cmd + R - Rename resource +- Ctrl/Cmd + D - Duplicate selected rows +- Ctrl/Cmd + C/V[/code] - Copy cells / Paste text into cells +- Ctrl/Cmd + (Shift) + Z[/code] - The Savior If clipboard contains as many lines as there are cells selected, each line is pasted into a separate cell. Made by Don Tnowe. 2022. @@ -615,14 +618,16 @@ text = "Edit Resources as Spreadsheet \"Welp, it is what it sounds like!\" Possible inputs: -- Ctrl + Click / Cmd + Click - Select multiple cells in one column -- Shift + Click - Select all cells between A and B in one column -- Left/Right - Move cursor along cell text -- Backspace/Delete - Erase text Left / Right from cursor -- Home/End - Move cursor to start/end of cell -- Ctrl + / Cmd + - Move through / Erase whole word -- Ctrl/Cmd + C/V - Copy cells / Paste text into cells -- Ctrl/Cmd + (Shift) + Z - The Savior +- Ctrl + Click / Cmd + Click[/code] - Select multiple cells in one column +- Shift + Click[/code] - Select all cells between A and B in one column +- Left/Right[/code] - Move cursor along cell text +- Backspace/Delete[/code] - Erase text Left / Right from cursor +- Home/End[/code] - Move cursor to start/end of cell +- Ctrl + / Cmd + [/code] - Move through / Erase whole word +- Ctrl/Cmd + R - Rename resource +- Ctrl/Cmd + D - Duplicate selected rows +- Ctrl/Cmd + C/V[/code] - Copy cells / Paste text into cells +- Ctrl/Cmd + (Shift) + Z[/code] - The Savior If clipboard contains as many lines as there are cells selected, each line is pasted into a separate cell. Made by Don Tnowe. 2022. @@ -741,6 +746,11 @@ margin_bottom = 150.0 pressed = true text = "Enable" +[node name="SelectionActions" parent="Control" instance=ExtResource( 19 )] +visible = false + +[connection signal="cells_context" from="." to="Control/SelectionActions" method="_on_grid_cells_context"] +[connection signal="cells_selected" from="." to="Control/SelectionActions" method="_on_grid_cells_selected"] [connection signal="grid_updated" from="." to="HeaderContentSplit/VBoxContainer/Pages" method="_on_Control_grid_updated"] [connection signal="about_to_show" from="HeaderContentSplit/VBoxContainer/HBoxContainer2/VisibleCols" to="." method="_on_VisibleCols_about_to_show"] [connection signal="pressed" from="HeaderContentSplit/VBoxContainer/HBoxContainer2/Settings" to="Control/Settings" method="popup_centered"] diff --git a/addons/resources_speadsheet_view/import_export/formats_edit/edit_base.gd b/addons/resources_speadsheet_view/import_export/formats_edit/edit_base.gd index 28420c1..c010d54 100644 --- a/addons/resources_speadsheet_view/import_export/formats_edit/edit_base.gd +++ b/addons/resources_speadsheet_view/import_export/formats_edit/edit_base.gd @@ -19,6 +19,18 @@ func save_entries(all_entries : Array, indices : Array): func create_resource(entry) -> Resource: return Resource.new() -## Override to define +## Override to define duplication behaviour. `name_input` should be a suffix if multiple entries, and full name if one. +func duplicate_rows(rows : Array, name_input : String): + pass + +## Override to define removal behaviour. +func delete_rows(rows : Array): + pass + +## Override with `return true` if `resource_name` is defined. +func has_row_names(): + return false + +## Override to define import behaviour. Must return the `rows` value for the editor view. func import_from_path(folderpath : String, insert_func : FuncRef, sort_by : String, sort_reverse : bool = false) -> Array: return [] diff --git a/addons/resources_speadsheet_view/import_export/formats_edit/edit_csv.gd b/addons/resources_speadsheet_view/import_export/formats_edit/edit_csv.gd index 4e11de7..227e7fe 100644 --- a/addons/resources_speadsheet_view/import_export/formats_edit/edit_csv.gd +++ b/addons/resources_speadsheet_view/import_export/formats_edit/edit_csv.gd @@ -39,6 +39,20 @@ func create_resource(entry) -> Resource: return entry +func duplicate_rows(rows : Array, name_input : String): + # Not today (TODO) + pass + + +func delete_rows(rows): + pass + + +func has_row_names(): + return false + + + func import_from_path(path : String, insert_func : FuncRef, sort_by : String, sort_reverse : bool = false) -> Array: import_data = load(path) var file = File.new() diff --git a/addons/resources_speadsheet_view/import_export/formats_edit/edit_tres.gd b/addons/resources_speadsheet_view/import_export/formats_edit/edit_tres.gd index 5c09f68..28ed7d0 100644 --- a/addons/resources_speadsheet_view/import_export/formats_edit/edit_tres.gd +++ b/addons/resources_speadsheet_view/import_export/formats_edit/edit_tres.gd @@ -19,6 +19,38 @@ func create_resource(entry) -> Resource: return entry +func duplicate_rows(rows : Array, name_input : String): + if rows.size() == 1: + var new_row = rows[0].duplicate() + new_row.resource_path = rows[0].resource_path.get_base_dir() + "/" + name_input + ".tres" + ResourceSaver.save(new_row.resource_path, new_row) + return + + var new_row + for x in rows: + new_row = x.duplicate() + new_row.resource_path = x.resource_path.get_basename() + name_input + ".tres" + ResourceSaver.save(new_row.resource_path, new_row) + + +func rename_row(row, new_name : String): + var dir = Directory.new() + var new_row = row + dir.remove(row.resource_path) + new_row.resource_path = row.resource_path.get_base_dir() + "/" + new_name + ".tres" + ResourceSaver.save(new_row.resource_path, new_row) + + +func delete_rows(rows): + var dir = Directory.new() + for x in rows: + dir.remove(x.resource_path) + + +func has_row_names(): + return true + + func import_from_path(folderpath : String, insert_func : FuncRef, sort_by : String, sort_reverse : bool = false) -> Array: var rows := [] var dir := Directory.new() diff --git a/addons/resources_speadsheet_view/import_export/import_export_dialog.tscn b/addons/resources_speadsheet_view/import_export/import_export_dialog.tscn index 87b2504..4e8885c 100644 --- a/addons/resources_speadsheet_view/import_export/import_export_dialog.tscn +++ b/addons/resources_speadsheet_view/import_export/import_export_dialog.tscn @@ -10,7 +10,7 @@ pause_mode = 2 visible = true margin_right = 493.0 -margin_bottom = 294.0 +margin_bottom = 351.0 popup_exclusive = true window_title = "Import/Export As Text" script = ExtResource( 1 ) @@ -20,6 +20,7 @@ formats_import = [ ExtResource( 3 ) ] [node name="TabContainer" type="TabContainer" parent="."] anchor_right = 1.0 anchor_bottom = 1.0 +margin_bottom = 15.0 tab_align = 0 use_hidden_tabs_for_min_size = true @@ -33,7 +34,7 @@ margin_bottom = -4.0 [node name="MarginContainer" type="MarginContainer" parent="TabContainer/Import"] margin_right = 485.0 -margin_bottom = 234.0 +margin_bottom = 306.0 size_flags_vertical = 3 custom_constants/margin_right = 4 custom_constants/margin_top = 4 @@ -44,17 +45,17 @@ custom_constants/margin_bottom = 0 margin_left = 4.0 margin_top = 4.0 margin_right = 481.0 -margin_bottom = 234.0 +margin_bottom = 306.0 scroll_horizontal_enabled = false [node name="VBoxContainer" type="VBoxContainer" parent="TabContainer/Import/MarginContainer/ScrollContainer"] margin_right = 477.0 -margin_bottom = 76.0 +margin_bottom = 132.0 size_flags_horizontal = 3 [node name="GridContainer" type="GridContainer" parent="TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer"] margin_right = 477.0 -margin_bottom = 76.0 +margin_bottom = 132.0 columns = 2 [node name="Label" type="Label" parent="TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer/GridContainer"] @@ -94,10 +95,72 @@ margin_top = 52.0 margin_right = 477.0 margin_bottom = 76.0 +[node name="Label4" type="Label" parent="TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer/GridContainer"] +margin_top = 83.0 +margin_right = 246.0 +margin_bottom = 97.0 +text = "Boolean True/False" + +[node name="HBoxContainer" type="HBoxContainer" parent="TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer/GridContainer"] +margin_left = 250.0 +margin_top = 80.0 +margin_right = 477.0 +margin_bottom = 100.0 + +[node name="Case" type="OptionButton" parent="TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer/GridContainer/HBoxContainer"] +margin_right = 148.0 +margin_bottom = 20.0 +size_flags_horizontal = 3 +text = "Caps Every Word" +clip_text = true +items = [ "all lower", null, false, 0, null, "caps Except First", null, false, 1, null, "Caps Every Word", null, false, 2, null, "ALL CAPS", null, false, 3, null ] +selected = 2 + +[node name="Separator" type="OptionButton" parent="TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer/GridContainer/HBoxContainer"] +margin_left = 152.0 +margin_right = 227.0 +margin_bottom = 20.0 +size_flags_horizontal = 3 +size_flags_stretch_ratio = 0.5 +text = "Space \" \"" +clip_text = true +items = [ "Space \" \"", null, false, 0, null, "Underscore \"_\"", null, false, 1, null, "Kebab \"-\"", null, false, 2, null ] +selected = 0 + +[node name="Label3" type="Label" parent="TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer/GridContainer"] +margin_top = 109.0 +margin_right = 246.0 +margin_bottom = 123.0 +text = "Enum word case/separator" + +[node name="HBoxContainer2" type="HBoxContainer" parent="TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer/GridContainer"] +margin_left = 250.0 +margin_top = 104.0 +margin_right = 477.0 +margin_bottom = 128.0 + +[node name="True" type="LineEdit" parent="TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer/GridContainer/HBoxContainer2"] +margin_right = 111.0 +margin_bottom = 24.0 +size_flags_horizontal = 3 +text = "Yes" + +[node name="False" type="LineEdit" parent="TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer/GridContainer/HBoxContainer2"] +margin_left = 115.0 +margin_right = 227.0 +margin_bottom = 24.0 +size_flags_horizontal = 3 +text = "No" + +[node name="Control2" type="Control" parent="TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer/GridContainer"] +margin_top = 132.0 +margin_right = 246.0 +margin_bottom = 132.0 + [node name="HBoxContainer" type="HBoxContainer" parent="TabContainer/Import"] -margin_top = 238.0 +margin_top = 310.0 margin_right = 485.0 -margin_bottom = 258.0 +margin_bottom = 330.0 alignment = 1 [node name="Ok2" type="Button" parent="TabContainer/Import/HBoxContainer"] @@ -129,7 +192,7 @@ margin_bottom = -4.0 [node name="Info" type="Label" parent="TabContainer/Export"] margin_right = 485.0 -margin_bottom = 65.0 +margin_bottom = 99.0 size_flags_vertical = 0 text = "The currently edited folder will be exported into the selected file. @@ -139,14 +202,14 @@ Hidden columns will NOT be exported." autowrap = true [node name="HSeparator" type="HSeparator" parent="TabContainer/Export"] -margin_top = 69.0 +margin_top = 103.0 margin_right = 485.0 -margin_bottom = 73.0 +margin_bottom = 107.0 [node name="HBoxContainer2" type="HBoxContainer" parent="TabContainer/Export"] -margin_top = 77.0 +margin_top = 111.0 margin_right = 485.0 -margin_bottom = 101.0 +margin_bottom = 135.0 alignment = 1 [node name="Label2" type="Label" parent="TabContainer/Export/HBoxContainer2"] @@ -188,26 +251,94 @@ margin_bottom = 24.0 text = "With space after" [node name="HBoxContainer3" type="HBoxContainer" parent="TabContainer/Export"] -margin_top = 105.0 +margin_top = 139.0 margin_right = 485.0 -margin_bottom = 129.0 +margin_bottom = 163.0 [node name="CheckBox" type="CheckBox" parent="TabContainer/Export/HBoxContainer3"] -margin_right = 246.0 +margin_right = 281.0 margin_bottom = 24.0 pressed = true text = "First row contains property names (CSV)" -[node name="Control" type="Control" parent="TabContainer/Export"] -margin_top = 133.0 +[node name="GridContainer" type="GridContainer" parent="TabContainer/Export"] +margin_top = 167.0 margin_right = 485.0 -margin_bottom = 234.0 +margin_bottom = 215.0 +columns = 2 + +[node name="Label4" type="Label" parent="TabContainer/Export/GridContainer"] +margin_top = 3.0 +margin_right = 241.0 +margin_bottom = 17.0 +size_flags_horizontal = 3 +text = "Boolean True/False" + +[node name="HBoxContainer" type="HBoxContainer" parent="TabContainer/Export/GridContainer"] +margin_left = 245.0 +margin_right = 485.0 +margin_bottom = 20.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="Case" type="OptionButton" parent="TabContainer/Export/GridContainer/HBoxContainer"] +margin_right = 157.0 +margin_bottom = 20.0 +size_flags_horizontal = 3 +text = "Caps Every Word" +clip_text = true +items = [ "all lower", null, false, 0, null, "caps Except First", null, false, 1, null, "Caps Every Word", null, false, 2, null, "ALL CAPS", null, false, 3, null ] +selected = 2 + +[node name="Separator" type="OptionButton" parent="TabContainer/Export/GridContainer/HBoxContainer"] +margin_left = 161.0 +margin_right = 240.0 +margin_bottom = 20.0 +size_flags_horizontal = 3 +size_flags_stretch_ratio = 0.5 +text = "Space \" \"" +clip_text = true +items = [ "Space \" \"", null, false, 0, null, "Underscore \"_\"", null, false, 1, null, "Kebab \"-\"", null, false, 2, null ] +selected = 0 + +[node name="Label3" type="Label" parent="TabContainer/Export/GridContainer"] +margin_top = 29.0 +margin_right = 241.0 +margin_bottom = 43.0 +size_flags_horizontal = 3 +text = "Enum word case/separator" + +[node name="HBoxContainer2" type="HBoxContainer" parent="TabContainer/Export/GridContainer"] +margin_left = 245.0 +margin_top = 24.0 +margin_right = 485.0 +margin_bottom = 48.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="True" type="LineEdit" parent="TabContainer/Export/GridContainer/HBoxContainer2"] +margin_right = 118.0 +margin_bottom = 24.0 +size_flags_horizontal = 3 +text = "Yes" + +[node name="False" type="LineEdit" parent="TabContainer/Export/GridContainer/HBoxContainer2"] +margin_left = 122.0 +margin_right = 240.0 +margin_bottom = 24.0 +size_flags_horizontal = 3 +text = "No" + +[node name="Control" type="Control" parent="TabContainer/Export"] +margin_top = 219.0 +margin_right = 485.0 +margin_bottom = 306.0 size_flags_vertical = 3 [node name="HBoxContainer" type="HBoxContainer" parent="TabContainer/Export"] -margin_top = 238.0 +margin_top = 310.0 margin_right = 485.0 -margin_bottom = 258.0 +margin_bottom = 330.0 alignment = 1 [node name="Button" type="Button" parent="TabContainer/Export/HBoxContainer"] diff --git a/addons/resources_speadsheet_view/selection_actions.gd b/addons/resources_speadsheet_view/selection_actions.gd new file mode 100644 index 0000000..b94cd8b --- /dev/null +++ b/addons/resources_speadsheet_view/selection_actions.gd @@ -0,0 +1,163 @@ +tool +extends MarginContainer + +enum { + EDITBOX_DUPLICATE = 1, + EDITBOX_RENAME, + EDITBOX_DELETE, +} + +export var editor_view := NodePath("../..") + +onready var editbox_node := $"Control/ColorRect/Popup" +onready var editbox_label := editbox_node.get_node("Panel/VBoxContainer/Label") +onready var editbox_input := editbox_node.get_node("Panel/VBoxContainer/LineEdit") + +var cell : Control +var editbox_action : int + + +func _ready(): + editbox_input.get_node("../..").add_stylebox_override( + "panel", + get_stylebox("Content", "EditorStyles") + ) + + +func _on_grid_cells_context(cells): + open(cells) + + +func _on_grid_cells_selected(cells): + open(cells) + + +func open(cells): + if cells.size() == 0: + hide() + cell = null + return + + cell = cells[-1] + rect_global_position = Vector2( + cell.rect_global_position.x + cell.rect_size.x, + cell.rect_global_position.y + ) + rect_size = Vector2.ZERO + show() + $"Control2/Label".text = str(cells.size()) + (" Cells" if cells.size() % 10 != 1 else " Cell") + $"GridContainer/Rename".visible = get_node(editor_view).has_row_names() + # TODO: remove this when dupes implemented for CSV. + $"GridContainer/Duplicate".visible = get_node(editor_view).has_row_names() + $"GridContainer/Delete".visible = get_node(editor_view).has_row_names() + + +func _unhandled_input(event): + if !is_visible_in_tree(): return + if event is InputEventKey: + if Input.is_key_pressed(KEY_CONTROL): + # Dupe + if event.scancode == KEY_D: + _on_Duplicate_pressed() + return + + # Rename + if event.scancode == KEY_R: + _on_Rename_pressed() + return + + if event is InputEventMouseButton && event.is_pressed(): + hide() + + +func _input(event): + if cell == null: return + rect_global_position = Vector2( + cell.rect_global_position.x + cell.rect_size.x, + cell.rect_global_position.y + ) + + +func _on_Duplicate_pressed(): + _show_editbox(EDITBOX_DUPLICATE) + + +func _on_CbCopy_pressed(): + TextEditingUtils.multi_copy(get_node(editor_view).edited_cells_text) + + +func _on_CbPaste_pressed(): + get_node(editor_view).set_edited_cells_values( + TextEditingUtils.multi_paste( + get_node(editor_view).edited_cells_text, + get_node(editor_view).edit_cursor_positions + ) + ) + + +func _on_Rename_pressed(): + _show_editbox(EDITBOX_RENAME) + + +func _on_Delete_pressed(): + _show_editbox(EDITBOX_DELETE) + + +func _show_editbox(action): + var node_editor_view = get_node(editor_view) + editbox_action = action + match(action): + EDITBOX_DUPLICATE: + if !node_editor_view.has_row_names(): + _on_editbox_accepted() + return + + if node_editor_view.edited_cells.size() == 1: + editbox_label.text = "Input new row's name..." + editbox_input.text = node_editor_view.get_last_selected_row()\ + .resource_path.get_file().get_basename() + + else: + editbox_label.text = "Input suffix to append to names..." + editbox_input.text = "" + + EDITBOX_RENAME: + editbox_label.text = "Input new name for row..." + editbox_input.text = node_editor_view.get_last_selected_row()\ + .resource_path.get_file().get_basename() + + EDITBOX_DELETE: + editbox_label.text = "Really delete selected rows? (Irreversible!!!)" + editbox_input.text = node_editor_view.get_last_selected_row()\ + .resource_path.get_file().get_basename() + + editbox_input.grab_focus() + editbox_input.caret_position = 999999999 + editbox_node.show() + $"Control/ColorRect".show() + $"Control/ColorRect".set_as_toplevel(true) + $"Control/ColorRect".rect_size = get_viewport_rect().size * 4.0 + editbox_node.rect_global_position = ( + rect_global_position + + rect_size * 0.5 + - editbox_node.get_child(0).rect_size * 0.5 + ) + + +func _on_editbox_closed(): + editbox_node.hide() + $"Control/ColorRect".hide() + + +func _on_editbox_accepted(): + match(editbox_action): + EDITBOX_DUPLICATE: + get_node(editor_view).duplicate_selected_rows(editbox_input.text) + + EDITBOX_RENAME: + get_node(editor_view).rename_row(get_node(editor_view).get_last_selected_row(), editbox_input.text) + + EDITBOX_DELETE: + get_node(editor_view).delete_selected_rows() + + _on_editbox_closed() diff --git a/addons/resources_speadsheet_view/selection_actions.tscn b/addons/resources_speadsheet_view/selection_actions.tscn new file mode 100644 index 0000000..55f579e --- /dev/null +++ b/addons/resources_speadsheet_view/selection_actions.tscn @@ -0,0 +1,182 @@ +[gd_scene load_steps=5 format=2] + +[ext_resource path="res://addons/resources_speadsheet_view/editor_icon_button.gd" type="Script" id=1] +[ext_resource path="res://addons/resources_speadsheet_view/selection_actions.gd" type="Script" id=2] + +[sub_resource type="Image" id=3] +data = { +"data": PoolByteArray( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), +"format": "LumAlpha8", +"height": 16, +"mipmaps": false, +"width": 16 +} + +[sub_resource type="ImageTexture" id=2] +flags = 4 +flags = 4 +image = SubResource( 3 ) +size = Vector2( 16, 16 ) + +[node name="SelectionActions" type="MarginContainer"] +margin_right = 84.0 +margin_bottom = 44.0 +mouse_filter = 2 +size_flags_horizontal = 9 +script = ExtResource( 2 ) + +[node name="Control2" type="Control" parent="."] +margin_right = 84.0 +margin_bottom = 44.0 +mouse_filter = 2 + +[node name="ColorRect" type="ColorRect" parent="Control2"] +show_behind_parent = true +margin_left = -2.0 +margin_top = -18.0 +margin_bottom = 2.0 + +[node name="ColorRect2" type="ColorRect" parent="Control2"] +show_behind_parent = true +anchor_bottom = 1.0 +margin_left = -2.0 + +[node name="Label" type="Label" parent="Control2"] +margin_left = 2.0 +margin_top = -16.0 +margin_right = 50.0 +margin_bottom = -2.0 +text = "Actions" + +[node name="ColorRect3" type="Panel" parent="Control2/Label"] +show_behind_parent = true +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = -2.0 +margin_top = -2.0 +margin_bottom = 2.0 +mouse_filter = 2 + +[node name="GridContainer" type="GridContainer" parent="."] +margin_right = 84.0 +margin_bottom = 44.0 +mouse_filter = 2 +size_flags_horizontal = 9 +size_flags_vertical = 9 +custom_constants/vseparation = 0 +custom_constants/hseparation = 0 +columns = 3 + +[node name="Duplicate" type="Button" parent="GridContainer"] +margin_right = 28.0 +margin_bottom = 22.0 +hint_tooltip = "Duplicate Selected Rows (Ctrl+D)" +icon = SubResource( 2 ) +script = ExtResource( 1 ) +icon_name = "Duplicate" + +[node name="CbCopy" type="Button" parent="GridContainer"] +margin_left = 28.0 +margin_right = 56.0 +margin_bottom = 22.0 +hint_tooltip = "Copy to Clipboard (Ctrl+C)" +icon = SubResource( 2 ) +script = ExtResource( 1 ) +icon_name = "ActionCopy" + +[node name="CbPaste" type="Button" parent="GridContainer"] +margin_left = 56.0 +margin_right = 84.0 +margin_bottom = 22.0 +hint_tooltip = "Paste Clipboard (Ctrl+V)" +icon = SubResource( 2 ) +script = ExtResource( 1 ) +icon_name = "ActionPaste" + +[node name="Rename" type="Button" parent="GridContainer"] +margin_top = 22.0 +margin_right = 28.0 +margin_bottom = 44.0 +hint_tooltip = "Rename Selected Rows (Ctrl+R)" +icon = SubResource( 2 ) +script = ExtResource( 1 ) +icon_name = "Edit" + +[node name="Delete" type="Button" parent="GridContainer"] +margin_left = 28.0 +margin_top = 22.0 +margin_right = 56.0 +margin_bottom = 44.0 +hint_tooltip = "DELETE Selected Rows" +icon = SubResource( 2 ) +script = ExtResource( 1 ) +icon_name = "Remove" + +[node name="Control" type="Control" parent="."] +margin_right = 84.0 +margin_bottom = 44.0 +mouse_filter = 2 + +[node name="ColorRect" type="ColorRect" parent="Control"] +visible = false +anchor_right = 1.0 +anchor_bottom = 1.0 +color = Color( 0, 0, 0, 0.498039 ) + +[node name="Popup" type="Popup" parent="Control/ColorRect"] +visible = true +margin_left = 42.0 +margin_top = 22.0 +margin_right = 42.0 +margin_bottom = 22.0 +mouse_filter = 2 +popup_exclusive = true + +[node name="Panel" type="PanelContainer" parent="Control/ColorRect/Popup"] +margin_right = 14.0 +margin_bottom = 14.0 +rect_min_size = Vector2( 192, 0 ) +mouse_filter = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="Control/ColorRect/Popup/Panel"] +margin_left = 7.0 +margin_top = 7.0 +margin_right = 185.0 +margin_bottom = 73.0 +mouse_filter = 2 + +[node name="Label" type="Label" parent="Control/ColorRect/Popup/Panel/VBoxContainer"] +margin_right = 178.0 +margin_bottom = 14.0 +text = "Input new name..." + +[node name="LineEdit" type="LineEdit" parent="Control/ColorRect/Popup/Panel/VBoxContainer"] +margin_top = 18.0 +margin_right = 178.0 +margin_bottom = 42.0 + +[node name="HBoxContainer" type="HBoxContainer" parent="Control/ColorRect/Popup/Panel/VBoxContainer"] +margin_top = 46.0 +margin_right = 178.0 +margin_bottom = 66.0 +alignment = 1 + +[node name="Button" type="Button" parent="Control/ColorRect/Popup/Panel/VBoxContainer/HBoxContainer"] +margin_left = 44.0 +margin_right = 75.0 +margin_bottom = 20.0 +text = "OK" + +[node name="Button2" type="Button" parent="Control/ColorRect/Popup/Panel/VBoxContainer/HBoxContainer"] +margin_left = 79.0 +margin_right = 133.0 +margin_bottom = 20.0 +text = "Cancel" + +[connection signal="pressed" from="GridContainer/Duplicate" to="." method="_on_Duplicate_pressed"] +[connection signal="pressed" from="GridContainer/CbCopy" to="." method="_on_CbCopy_pressed"] +[connection signal="pressed" from="GridContainer/CbPaste" to="." method="_on_CbPaste_pressed"] +[connection signal="pressed" from="GridContainer/Rename" to="." method="_on_Rename_pressed"] +[connection signal="pressed" from="GridContainer/Delete" to="." method="_on_Delete_pressed"] +[connection signal="pressed" from="Control/ColorRect/Popup/Panel/VBoxContainer/HBoxContainer/Button" to="." method="_on_editbox_accepted"] +[connection signal="pressed" from="Control/ColorRect/Popup/Panel/VBoxContainer/HBoxContainer/Button2" to="." method="_on_editbox_closed"] diff --git a/project.godot b/project.godot index c25adcb..2700eb6 100644 --- a/project.godot +++ b/project.godot @@ -106,7 +106,7 @@ config/name="Addon: Resources as Sheets" [editor_plugins] -enabled=PoolStringArray( "res://addons/resources_speadsheet_view/plugin.cfg" ) +enabled=PoolStringArray( "res://addons/editor_icon_previewer/plugin.cfg", "res://addons/resources_speadsheet_view/plugin.cfg" ) [rendering]