147 lines
3.6 KiB
GDScript
147 lines
3.6 KiB
GDScript
@tool
|
|
extends VBoxContainer
|
|
|
|
|
|
signal file_selected(file_path: String)
|
|
signal file_popup_menu_requested(at_position: Vector2)
|
|
signal file_double_clicked(file_path: String)
|
|
signal file_middle_clicked(file_path: String)
|
|
|
|
|
|
const DialogueConstants = preload("../constants.gd")
|
|
|
|
const MODIFIED_SUFFIX = "(*)"
|
|
|
|
|
|
@export var icon: Texture2D
|
|
|
|
@onready var filter_edit: LineEdit = $FilterEdit
|
|
@onready var list: ItemList = $List
|
|
|
|
var file_map: Dictionary = {}
|
|
|
|
var current_file_path: String = ""
|
|
|
|
var files: PackedStringArray = []:
|
|
set(next_files):
|
|
files = next_files
|
|
files.sort()
|
|
update_file_map()
|
|
apply_filter()
|
|
get:
|
|
return files
|
|
|
|
var unsaved_files: Array[String] = []
|
|
|
|
var filter: String:
|
|
set(next_filter):
|
|
filter = next_filter
|
|
apply_filter()
|
|
get:
|
|
return filter
|
|
|
|
|
|
func _ready() -> void:
|
|
apply_theme()
|
|
|
|
filter_edit.placeholder_text = DialogueConstants.translate(&"files_list.filter")
|
|
|
|
|
|
func focus_filter() -> void:
|
|
filter_edit.grab_focus()
|
|
|
|
|
|
func select_file(file: String) -> void:
|
|
list.deselect_all()
|
|
for i in range(0, list.get_item_count()):
|
|
var item_text = list.get_item_text(i).replace(MODIFIED_SUFFIX, "")
|
|
if item_text == get_nice_file(file, item_text.count("/") + 1):
|
|
list.select(i)
|
|
|
|
|
|
func mark_file_as_unsaved(file: String, is_unsaved: bool) -> void:
|
|
if not file in unsaved_files and is_unsaved:
|
|
unsaved_files.append(file)
|
|
elif file in unsaved_files and not is_unsaved:
|
|
unsaved_files.erase(file)
|
|
apply_filter()
|
|
|
|
|
|
func update_file_map() -> void:
|
|
file_map = {}
|
|
for file in files:
|
|
var nice_file: String = get_nice_file(file)
|
|
|
|
# See if a value with just the file name is already in the map
|
|
for key in file_map.keys():
|
|
if file_map[key] == nice_file:
|
|
var bit_count = nice_file.count("/") + 2
|
|
|
|
var existing_nice_file = get_nice_file(key, bit_count)
|
|
nice_file = get_nice_file(file, bit_count)
|
|
|
|
while nice_file == existing_nice_file:
|
|
bit_count += 1
|
|
existing_nice_file = get_nice_file(key, bit_count)
|
|
nice_file = get_nice_file(file, bit_count)
|
|
|
|
file_map[key] = existing_nice_file
|
|
|
|
file_map[file] = nice_file
|
|
|
|
|
|
func get_nice_file(file_path: String, path_bit_count: int = 1) -> String:
|
|
var bits = file_path.replace("res://", "").replace(".dialogue", "").split("/")
|
|
bits = bits.slice(-path_bit_count)
|
|
return "/".join(bits)
|
|
|
|
|
|
func apply_filter() -> void:
|
|
list.clear()
|
|
for file in file_map.keys():
|
|
if filter == "" or filter.to_lower() in file.to_lower():
|
|
var nice_file = file_map[file]
|
|
if file in unsaved_files:
|
|
nice_file += MODIFIED_SUFFIX
|
|
var new_id := list.add_item(nice_file)
|
|
list.set_item_icon(new_id, icon)
|
|
|
|
select_file(current_file_path)
|
|
|
|
|
|
func apply_theme() -> void:
|
|
if is_instance_valid(filter_edit):
|
|
filter_edit.right_icon = get_theme_icon("Search", "EditorIcons")
|
|
|
|
|
|
### Signals
|
|
|
|
|
|
func _on_theme_changed() -> void:
|
|
apply_theme()
|
|
|
|
|
|
func _on_filter_edit_text_changed(new_text: String) -> void:
|
|
self.filter = new_text
|
|
|
|
|
|
func _on_list_item_clicked(index: int, at_position: Vector2, mouse_button_index: int) -> void:
|
|
var item_text = list.get_item_text(index).replace(MODIFIED_SUFFIX, "")
|
|
var file = file_map.find_key(item_text)
|
|
|
|
if mouse_button_index == MOUSE_BUTTON_LEFT or mouse_button_index == MOUSE_BUTTON_RIGHT:
|
|
select_file(file)
|
|
file_selected.emit(file)
|
|
if mouse_button_index == MOUSE_BUTTON_RIGHT:
|
|
file_popup_menu_requested.emit(at_position)
|
|
|
|
if mouse_button_index == MOUSE_BUTTON_MIDDLE:
|
|
file_middle_clicked.emit(file)
|
|
|
|
|
|
func _on_list_item_activated(index: int) -> void:
|
|
var item_text = list.get_item_text(index).replace(MODIFIED_SUFFIX, "")
|
|
var file = file_map.find_key(item_text)
|
|
select_file(file)
|
|
file_double_clicked.emit(file)
|