151 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			GDScript
		
	
	
	
	
	
			
		
		
	
	
			151 lines
		
	
	
		
			3.8 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 last_selected_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)
 | |
| 			last_selected_file_path = file
 | |
| 
 | |
| 
 | |
| 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")
 | |
| 	if is_instance_valid(list):
 | |
| 		list.add_theme_stylebox_override("panel", get_theme_stylebox("panel", "Panel"))
 | |
| 
 | |
| 
 | |
| ### 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)
 |