Implement cell context menu

This commit is contained in:
don-tnowe 2022-10-24 20:39:12 +03:00
parent 58b52af43a
commit 20ab0106df
11 changed files with 643 additions and 53 deletions

3
.gitignore vendored
View File

@ -16,3 +16,6 @@ mono_crash.*.json
# Editor Plugin persistent data # Editor Plugin persistent data
addons/resources_speadsheet_view/saved_state.json addons/resources_speadsheet_view/saved_state.json
# Tools used during development
addons/editor_icon_previewer/

View File

@ -31,6 +31,8 @@ Possible inputs:
- `Home/End` - Move cursor to start/end of cell - `Home/End` - Move cursor to start/end of cell
- `Ctrl + <move/erase> / Cmd + <move/erase>` - Move through / Erase whole word - `Ctrl + <move/erase> / Cmd + <move/erase>` - Move through / Erase whole word
- `Ctrl/Cmd + C/V` - Copy cells / Paste text into cells - `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 - `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. If clipboard contains as many lines as there are cells selected, each line is pasted into a separate cell.

View File

@ -2,6 +2,8 @@ tool
extends Control extends Control
signal grid_updated() signal grid_updated()
signal cells_selected(cells)
signal cells_context(cells)
export var table_header_scene : PackedScene export var table_header_scene : PackedScene
@ -390,6 +392,7 @@ func deselect_all_cells():
edited_cells.clear() edited_cells.clear()
edited_cells_text.clear() edited_cells_text.clear()
edit_cursor_positions.clear() edit_cursor_positions.clear()
emit_signal("cells_selected", [])
func deselect_cell(cell : Control): func deselect_cell(cell : Control):
@ -401,6 +404,8 @@ func deselect_cell(cell : Control):
if edited_cells_text.size() != 0: if edited_cells_text.size() != 0:
edited_cells_text.remove(idx) edited_cells_text.remove(idx)
edit_cursor_positions.remove(idx) edit_cursor_positions.remove(idx)
emit_signal("cells_selected", edited_cells)
func select_cell(cell : Control): func select_cell(cell : Control):
@ -411,6 +416,8 @@ func select_cell(cell : Control):
inspector_resource = rows[_get_cell_row(cell)].duplicate() inspector_resource = rows[_get_cell_row(cell)].duplicate()
editor_plugin.get_editor_interface().edit_resource(inspector_resource) editor_plugin.get_editor_interface().edit_resource(inspector_resource)
emit_signal("cells_selected", edited_cells)
func select_cells_to(cell : Control): func select_cells_to(cell : Control):
var column_index := _get_cell_column(cell) 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)) edited_cells_text.append(str(cur_cell.text))
edit_cursor_positions.append(cur_cell.text.length()) edit_cursor_positions.append(cur_cell.text.length())
emit_signal("cells_selected", edited_cells)
func select_column(column_index : int): func select_column(column_index : int):
deselect_all_cells() deselect_all_cells()
@ -509,6 +518,31 @@ func set_edited_cells_values(new_cell_values : Array):
_update_column_sizes() _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(): func _update_selected_cells_text():
if edited_cells_text.size() == 0: if edited_cells_text.size() == 0:
return return
@ -587,6 +621,9 @@ func _gui_input(event : InputEvent):
if event is InputEventMouseButton: if event is InputEventMouseButton:
_update_scroll() _update_scroll()
if event.button_index != BUTTON_LEFT: if event.button_index != BUTTON_LEFT:
if event.button_index == BUTTON_RIGHT:
emit_signal("cells_context", edited_cells)
return return
grab_focus() grab_focus()
@ -606,20 +643,21 @@ func _input(event : InputEvent):
return return
# Ctrl + Z (before, and instead of, committing the action!) # 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_CONTROL):
if Input.is_key_pressed(KEY_SHIFT): if event.scancode == KEY_Z:
editor_plugin.undo_redo.redo() if Input.is_key_pressed(KEY_SHIFT):
# Ctrl + z editor_plugin.undo_redo.redo()
else: # Ctrl + z
editor_plugin.undo_redo.undo() else:
editor_plugin.undo_redo.undo()
return
return
# This shortcut is used by Godot as well. # This shortcut is used by Godot as well.
if Input.is_key_pressed(KEY_CONTROL) and event.scancode == KEY_Y: if event.scancode == KEY_Y:
editor_plugin.undo_redo.redo() editor_plugin.undo_redo.redo()
return return
_key_specific_action(event) _key_specific_action(event)
grab_focus() 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) # Ctrl + C (so you can edit in a proper text editor instead of this wacky nonsense)
elif ctrl_pressed and event.scancode == KEY_C: elif ctrl_pressed and event.scancode == KEY_C:
TextEditingUtils.multi_copy(edited_cells_text) TextEditingUtils.multi_copy(edited_cells_text)
get_tree().set_input_as_handled()
# The following actions do not work on non-editable cells. # The following actions do not work on non-editable cells.
if !column_editors[column].is_text() or columns[column] == "resource_path": 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( set_edited_cells_values(TextEditingUtils.multi_paste(
edited_cells_text, edit_cursor_positions edited_cells_text, edit_cursor_positions
)) ))
get_tree().set_input_as_handled()
# ERASING # ERASING
elif event.scancode == KEY_BACKSPACE: elif event.scancode == KEY_BACKSPACE:
@ -759,7 +799,8 @@ func _try_convert(value, type):
func _get_edited_cells_resources() -> Array: func _get_edited_cells_resources() -> Array:
var arr := edited_cells.duplicate() var arr := []
arr.resize(edited_cells.size())
for i in arr.size(): for i in arr.size():
arr[i] = rows[_get_cell_row(edited_cells[i])] arr[i] = rows[_get_cell_row(edited_cells[i])]

View File

@ -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/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] [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/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/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/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] [sub_resource type="Image" id=3]
data = { data = {
@ -596,14 +597,16 @@ bbcode_text = "[center]Edit Resources as Spreadsheet[/center]
\"Welp, it is what it sounds like!\" \"Welp, it is what it sounds like!\"
Possible inputs: Possible inputs:
- [code]Ctrl + Click / Cmd + Click[/code] - Select multiple cells in one column - 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 - Shift + Click[/code] - Select all cells between A and B in one column
- [code]Left/Right[/code] - Move cursor along cell text - Left/Right[/code] - Move cursor along cell text
- [code]Backspace/Delete[/code] - Erase text Left / Right from cursor - Backspace/Delete[/code] - Erase text Left / Right from cursor
- [code]Home/End[/code] - Move cursor to start/end of cell - Home/End[/code] - Move cursor to start/end of cell
- [code]Ctrl + <move/erase> / Cmd + <move/erase>[/code] - Move through / Erase whole word - Ctrl + <move/erase> / Cmd + <move/erase>[/code] - Move through / Erase whole word
- [code]Ctrl/Cmd + C/V[/code] - Copy cells / Paste text into cells - Ctrl/Cmd + R - Rename resource
- [code]Ctrl/Cmd + (Shift) + Z[/code] - The Savior - 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. If clipboard contains as many lines as there are cells selected, each line is pasted into a separate cell.
Made by Don Tnowe. 2022. Made by Don Tnowe. 2022.
@ -615,14 +618,16 @@ text = "Edit Resources as Spreadsheet
\"Welp, it is what it sounds like!\" \"Welp, it is what it sounds like!\"
Possible inputs: Possible inputs:
- Ctrl + Click / Cmd + Click - Select multiple cells in one column - Ctrl + Click / Cmd + Click[/code] - Select multiple cells in one column
- Shift + Click - Select all cells between A and B in one column - Shift + Click[/code] - Select all cells between A and B in one column
- Left/Right - Move cursor along cell text - Left/Right[/code] - Move cursor along cell text
- Backspace/Delete - Erase text Left / Right from cursor - Backspace/Delete[/code] - Erase text Left / Right from cursor
- Home/End - Move cursor to start/end of cell - Home/End[/code] - Move cursor to start/end of cell
- Ctrl + <move/erase> / Cmd + <move/erase> - Move through / Erase whole word - Ctrl + <move/erase> / Cmd + <move/erase>[/code] - Move through / Erase whole word
- Ctrl/Cmd + C/V - Copy cells / Paste text into cells - Ctrl/Cmd + R - Rename resource
- Ctrl/Cmd + (Shift) + Z - The Savior - 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. If clipboard contains as many lines as there are cells selected, each line is pasted into a separate cell.
Made by Don Tnowe. 2022. Made by Don Tnowe. 2022.
@ -741,6 +746,11 @@ margin_bottom = 150.0
pressed = true pressed = true
text = "Enable" 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="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="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"] [connection signal="pressed" from="HeaderContentSplit/VBoxContainer/HBoxContainer2/Settings" to="Control/Settings" method="popup_centered"]

View File

@ -19,6 +19,18 @@ func save_entries(all_entries : Array, indices : Array):
func create_resource(entry) -> Resource: func create_resource(entry) -> Resource:
return Resource.new() 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: func import_from_path(folderpath : String, insert_func : FuncRef, sort_by : String, sort_reverse : bool = false) -> Array:
return [] return []

View File

@ -39,6 +39,20 @@ func create_resource(entry) -> Resource:
return entry 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: func import_from_path(path : String, insert_func : FuncRef, sort_by : String, sort_reverse : bool = false) -> Array:
import_data = load(path) import_data = load(path)
var file = File.new() var file = File.new()

View File

@ -19,6 +19,38 @@ func create_resource(entry) -> Resource:
return entry 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: func import_from_path(folderpath : String, insert_func : FuncRef, sort_by : String, sort_reverse : bool = false) -> Array:
var rows := [] var rows := []
var dir := Directory.new() var dir := Directory.new()

View File

@ -10,7 +10,7 @@
pause_mode = 2 pause_mode = 2
visible = true visible = true
margin_right = 493.0 margin_right = 493.0
margin_bottom = 294.0 margin_bottom = 351.0
popup_exclusive = true popup_exclusive = true
window_title = "Import/Export As Text" window_title = "Import/Export As Text"
script = ExtResource( 1 ) script = ExtResource( 1 )
@ -20,6 +20,7 @@ formats_import = [ ExtResource( 3 ) ]
[node name="TabContainer" type="TabContainer" parent="."] [node name="TabContainer" type="TabContainer" parent="."]
anchor_right = 1.0 anchor_right = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0
margin_bottom = 15.0
tab_align = 0 tab_align = 0
use_hidden_tabs_for_min_size = true use_hidden_tabs_for_min_size = true
@ -33,7 +34,7 @@ margin_bottom = -4.0
[node name="MarginContainer" type="MarginContainer" parent="TabContainer/Import"] [node name="MarginContainer" type="MarginContainer" parent="TabContainer/Import"]
margin_right = 485.0 margin_right = 485.0
margin_bottom = 234.0 margin_bottom = 306.0
size_flags_vertical = 3 size_flags_vertical = 3
custom_constants/margin_right = 4 custom_constants/margin_right = 4
custom_constants/margin_top = 4 custom_constants/margin_top = 4
@ -44,17 +45,17 @@ custom_constants/margin_bottom = 0
margin_left = 4.0 margin_left = 4.0
margin_top = 4.0 margin_top = 4.0
margin_right = 481.0 margin_right = 481.0
margin_bottom = 234.0 margin_bottom = 306.0
scroll_horizontal_enabled = false scroll_horizontal_enabled = false
[node name="VBoxContainer" type="VBoxContainer" parent="TabContainer/Import/MarginContainer/ScrollContainer"] [node name="VBoxContainer" type="VBoxContainer" parent="TabContainer/Import/MarginContainer/ScrollContainer"]
margin_right = 477.0 margin_right = 477.0
margin_bottom = 76.0 margin_bottom = 132.0
size_flags_horizontal = 3 size_flags_horizontal = 3
[node name="GridContainer" type="GridContainer" parent="TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer"] [node name="GridContainer" type="GridContainer" parent="TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer"]
margin_right = 477.0 margin_right = 477.0
margin_bottom = 76.0 margin_bottom = 132.0
columns = 2 columns = 2
[node name="Label" type="Label" parent="TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer/GridContainer"] [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_right = 477.0
margin_bottom = 76.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"] [node name="HBoxContainer" type="HBoxContainer" parent="TabContainer/Import"]
margin_top = 238.0 margin_top = 310.0
margin_right = 485.0 margin_right = 485.0
margin_bottom = 258.0 margin_bottom = 330.0
alignment = 1 alignment = 1
[node name="Ok2" type="Button" parent="TabContainer/Import/HBoxContainer"] [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"] [node name="Info" type="Label" parent="TabContainer/Export"]
margin_right = 485.0 margin_right = 485.0
margin_bottom = 65.0 margin_bottom = 99.0
size_flags_vertical = 0 size_flags_vertical = 0
text = "The currently edited folder will be exported into the selected file. text = "The currently edited folder will be exported into the selected file.
@ -139,14 +202,14 @@ Hidden columns will NOT be exported."
autowrap = true autowrap = true
[node name="HSeparator" type="HSeparator" parent="TabContainer/Export"] [node name="HSeparator" type="HSeparator" parent="TabContainer/Export"]
margin_top = 69.0 margin_top = 103.0
margin_right = 485.0 margin_right = 485.0
margin_bottom = 73.0 margin_bottom = 107.0
[node name="HBoxContainer2" type="HBoxContainer" parent="TabContainer/Export"] [node name="HBoxContainer2" type="HBoxContainer" parent="TabContainer/Export"]
margin_top = 77.0 margin_top = 111.0
margin_right = 485.0 margin_right = 485.0
margin_bottom = 101.0 margin_bottom = 135.0
alignment = 1 alignment = 1
[node name="Label2" type="Label" parent="TabContainer/Export/HBoxContainer2"] [node name="Label2" type="Label" parent="TabContainer/Export/HBoxContainer2"]
@ -188,26 +251,94 @@ margin_bottom = 24.0
text = "With space after" text = "With space after"
[node name="HBoxContainer3" type="HBoxContainer" parent="TabContainer/Export"] [node name="HBoxContainer3" type="HBoxContainer" parent="TabContainer/Export"]
margin_top = 105.0 margin_top = 139.0
margin_right = 485.0 margin_right = 485.0
margin_bottom = 129.0 margin_bottom = 163.0
[node name="CheckBox" type="CheckBox" parent="TabContainer/Export/HBoxContainer3"] [node name="CheckBox" type="CheckBox" parent="TabContainer/Export/HBoxContainer3"]
margin_right = 246.0 margin_right = 281.0
margin_bottom = 24.0 margin_bottom = 24.0
pressed = true pressed = true
text = "First row contains property names (CSV)" text = "First row contains property names (CSV)"
[node name="Control" type="Control" parent="TabContainer/Export"] [node name="GridContainer" type="GridContainer" parent="TabContainer/Export"]
margin_top = 133.0 margin_top = 167.0
margin_right = 485.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 size_flags_vertical = 3
[node name="HBoxContainer" type="HBoxContainer" parent="TabContainer/Export"] [node name="HBoxContainer" type="HBoxContainer" parent="TabContainer/Export"]
margin_top = 238.0 margin_top = 310.0
margin_right = 485.0 margin_right = 485.0
margin_bottom = 258.0 margin_bottom = 330.0
alignment = 1 alignment = 1
[node name="Button" type="Button" parent="TabContainer/Export/HBoxContainer"] [node name="Button" type="Button" parent="TabContainer/Export/HBoxContainer"]

View File

@ -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()

View File

@ -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"]

View File

@ -106,7 +106,7 @@ config/name="Addon: Resources as Sheets"
[editor_plugins] [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] [rendering]