forked from woofmeow/straywild
337 lines
11 KiB
GDScript
337 lines
11 KiB
GDScript
extends SceneTree
|
|
|
|
const FileDialogControllerNavigationType = preload(
|
|
"res://ui/file_dialog_controller_navigation.gd"
|
|
)
|
|
const InterfaceFontControllerType = preload(
|
|
"res://ui/interface_font_controller.gd"
|
|
)
|
|
const OnScreenKeyboardType = preload("res://ui/on_screen_keyboard.gd")
|
|
|
|
|
|
func _initialize() -> void:
|
|
call_deferred("_run")
|
|
|
|
|
|
func _run() -> void:
|
|
root.size = Vector2i(1280, 720)
|
|
var dialog := FileDialog.new()
|
|
dialog.file_mode = FileDialog.FILE_MODE_OPEN_DIR
|
|
dialog.access = FileDialog.ACCESS_FILESYSTEM
|
|
dialog.use_native_dialog = false
|
|
root.add_child(dialog)
|
|
dialog.current_dir = "/tmp"
|
|
dialog.popup_centered(Vector2i(900, 540))
|
|
for _frame: int in 3:
|
|
await process_frame
|
|
FileDialogControllerNavigationType.configure(dialog)
|
|
await process_frame
|
|
|
|
var root_scope: Window = (
|
|
FileDialogControllerNavigationType.active_scope(dialog)
|
|
)
|
|
assert(root_scope == dialog)
|
|
var root_controls: Array[Control] = (
|
|
FileDialogControllerNavigationType.interactive_controls(root_scope)
|
|
)
|
|
var directory_list: ItemList
|
|
var parent_button: Button
|
|
var create_folder_button: Button
|
|
var path_edit: LineEdit
|
|
var drive_button: MenuButton
|
|
var refresh_button: Button
|
|
var favorite_button: Button
|
|
var hidden_button: Button
|
|
var grid_button: Button
|
|
var list_button: Button
|
|
var filter_button: Button
|
|
var sort_button: MenuButton
|
|
var cancel_button: Button
|
|
var select_button: Button
|
|
for control: Control in root_controls:
|
|
if (
|
|
control is ItemList
|
|
and control.accessibility_name == "Directories & Files:"
|
|
):
|
|
directory_list = control as ItemList
|
|
if control is LineEdit and control.accessibility_name == "Path:":
|
|
path_edit = control as LineEdit
|
|
var button := control as Button
|
|
if button != null:
|
|
parent_button = (
|
|
button
|
|
if button.tooltip_text == "Go to parent folder."
|
|
else parent_button
|
|
)
|
|
create_folder_button = (
|
|
button
|
|
if button.tooltip_text == "Create a new folder."
|
|
else create_folder_button
|
|
)
|
|
refresh_button = (
|
|
button
|
|
if button.tooltip_text == "Refresh files."
|
|
else refresh_button
|
|
)
|
|
favorite_button = (
|
|
button
|
|
if button.tooltip_text == "(Un)favorite current folder."
|
|
else favorite_button
|
|
)
|
|
hidden_button = (
|
|
button
|
|
if button.tooltip_text == (
|
|
"Toggle the visibility of hidden files."
|
|
)
|
|
else hidden_button
|
|
)
|
|
grid_button = (
|
|
button
|
|
if button.tooltip_text == (
|
|
"View items as a grid of thumbnails."
|
|
)
|
|
else grid_button
|
|
)
|
|
list_button = (
|
|
button
|
|
if button.tooltip_text == "View items as a list."
|
|
else list_button
|
|
)
|
|
filter_button = (
|
|
button
|
|
if button.tooltip_text == (
|
|
"Toggle the visibility of the filter for file names."
|
|
)
|
|
else filter_button
|
|
)
|
|
cancel_button = button if button.text == "Cancel" else cancel_button
|
|
select_button = (
|
|
button
|
|
if button.text == "Select Current Folder"
|
|
else select_button
|
|
)
|
|
var menu := control as MenuButton
|
|
if menu != null:
|
|
drive_button = menu if menu.accessibility_name == "Drive" else drive_button
|
|
sort_button = (
|
|
menu if menu.tooltip_text == "Sort files" else sort_button
|
|
)
|
|
assert(directory_list != null)
|
|
assert(parent_button != null)
|
|
assert(path_edit != null)
|
|
assert(create_folder_button != null)
|
|
assert(drive_button != null)
|
|
assert(refresh_button != null)
|
|
assert(favorite_button != null)
|
|
assert(hidden_button != null)
|
|
assert(grid_button != null)
|
|
assert(list_button != null)
|
|
assert(filter_button != null)
|
|
assert(sort_button != null)
|
|
assert(cancel_button != null)
|
|
assert(select_button != null)
|
|
assert(dialog.gui_get_focus_owner() == directory_list)
|
|
_assert_neighbor(path_edit, &"focus_neighbor_left", parent_button)
|
|
_assert_neighbor(path_edit, &"focus_neighbor_right", drive_button)
|
|
_assert_neighbor(drive_button, &"focus_neighbor_left", path_edit)
|
|
_assert_neighbor(refresh_button, &"focus_neighbor_left", drive_button)
|
|
_assert_neighbor(favorite_button, &"focus_neighbor_left", refresh_button)
|
|
_assert_neighbor(
|
|
create_folder_button, &"focus_neighbor_left", favorite_button
|
|
)
|
|
_assert_neighbor(hidden_button, &"focus_neighbor_right", grid_button)
|
|
_assert_neighbor(grid_button, &"focus_neighbor_right", list_button)
|
|
_assert_neighbor(list_button, &"focus_neighbor_right", filter_button)
|
|
_assert_neighbor(filter_button, &"focus_neighbor_right", sort_button)
|
|
_assert_neighbor(sort_button, &"focus_neighbor_top", create_folder_button)
|
|
_assert_neighbor(
|
|
create_folder_button, &"focus_neighbor_bottom", sort_button
|
|
)
|
|
_assert_neighbor(directory_list, &"focus_neighbor_top", hidden_button)
|
|
_assert_neighbor(directory_list, &"focus_neighbor_bottom", select_button)
|
|
_assert_neighbor(cancel_button, &"focus_neighbor_right", select_button)
|
|
_assert_neighbor(select_button, &"focus_neighbor_left", cancel_button)
|
|
assert(favorite_button.accessibility_name == "favorite current folder")
|
|
assert(create_folder_button.accessibility_name == "new folder")
|
|
assert(filter_button.accessibility_name == "filter file names")
|
|
_assert_directionally_reachable(directory_list, root_controls)
|
|
directory_list.clear()
|
|
directory_list.add_item("test folder")
|
|
directory_list.select(0)
|
|
directory_list.grab_focus()
|
|
assert(
|
|
FileDialogControllerNavigationType.move_from_item_list(
|
|
directory_list, Vector2.UP
|
|
)
|
|
)
|
|
assert(dialog.gui_get_focus_owner() == hidden_button)
|
|
directory_list.grab_focus()
|
|
assert(
|
|
FileDialogControllerNavigationType.move_from_item_list(
|
|
directory_list, Vector2.DOWN
|
|
)
|
|
)
|
|
assert(dialog.gui_get_focus_owner() == select_button)
|
|
assert(FileDialogControllerNavigationType.activate_control(sort_button))
|
|
await process_frame
|
|
assert(sort_button.get_popup().visible)
|
|
sort_button.get_popup().hide()
|
|
await process_frame
|
|
|
|
create_folder_button.pressed.emit()
|
|
for _frame: int in 3:
|
|
await process_frame
|
|
FileDialogControllerNavigationType.configure(dialog)
|
|
await process_frame
|
|
var folder_scope: Window = (
|
|
FileDialogControllerNavigationType.active_scope(dialog)
|
|
)
|
|
assert(folder_scope != null and folder_scope != dialog)
|
|
var folder_controls: Array[Control] = (
|
|
FileDialogControllerNavigationType.interactive_controls(folder_scope)
|
|
)
|
|
var folder_name_edit: LineEdit
|
|
var folder_cancel: Button
|
|
var folder_ok: Button
|
|
for control: Control in folder_controls:
|
|
if control is LineEdit:
|
|
folder_name_edit = control as LineEdit
|
|
var button := control as Button
|
|
if button != null and button.text == "Cancel":
|
|
folder_cancel = button
|
|
if button != null and button.text == "OK":
|
|
folder_ok = button
|
|
assert(folder_name_edit != null)
|
|
assert(folder_cancel != null)
|
|
assert(folder_ok != null)
|
|
assert(folder_scope.gui_get_focus_owner() == folder_name_edit)
|
|
_assert_directionally_reachable(folder_name_edit, folder_controls)
|
|
|
|
var keyboard := OnScreenKeyboardType.new()
|
|
root.add_child(keyboard)
|
|
keyboard.set_enabled(true)
|
|
folder_name_edit.grab_focus()
|
|
assert(keyboard.request_for_control(folder_name_edit))
|
|
assert(keyboard.is_open())
|
|
assert(keyboard.get_parent() == folder_scope)
|
|
keyboard.call("_close_keyboard", true)
|
|
|
|
var main_source: String = FileAccess.get_file_as_string(
|
|
"res://main/main.gd"
|
|
)
|
|
assert(main_source.contains("picker_scope != _data_folder_dialog"))
|
|
assert(main_source.contains("picker_scope.hide()"))
|
|
assert(main_source.contains("is_controller_text_entry_open()"))
|
|
|
|
dialog.queue_free()
|
|
keyboard.queue_free()
|
|
await process_frame
|
|
await _validate_compact_dialog()
|
|
print("File dialog controller navigation validation: PASS")
|
|
quit()
|
|
|
|
|
|
func _validate_compact_dialog() -> void:
|
|
root.size = Vector2i(640, 480)
|
|
var font_controller := InterfaceFontControllerType.new()
|
|
root.add_child(font_controller)
|
|
var keyboard := OnScreenKeyboardType.new()
|
|
root.add_child(keyboard)
|
|
await process_frame
|
|
keyboard.set_enabled(false)
|
|
font_controller.set_controller_text_entry_request(
|
|
Callable(keyboard, "request_for_control"),
|
|
Callable(keyboard, "is_open"),
|
|
)
|
|
var dialog := FileDialog.new()
|
|
dialog.file_mode = FileDialog.FILE_MODE_OPEN_DIR
|
|
dialog.access = FileDialog.ACCESS_FILESYSTEM
|
|
dialog.use_native_dialog = false
|
|
root.add_child(dialog)
|
|
dialog.current_dir = "/tmp"
|
|
font_controller.popup_file_dialog(dialog)
|
|
for _frame: int in 4:
|
|
await process_frame
|
|
assert(dialog.size.x <= 616 and dialog.size.y <= 456)
|
|
var scope: Window = FileDialogControllerNavigationType.active_scope(dialog)
|
|
var controls: Array[Control] = (
|
|
FileDialogControllerNavigationType.interactive_controls(scope)
|
|
)
|
|
var directory_list: ItemList
|
|
var path_edit: LineEdit
|
|
var select_button: Button
|
|
for control: Control in controls:
|
|
if (
|
|
control is ItemList
|
|
and control.accessibility_name == "Directories & Files:"
|
|
):
|
|
directory_list = control as ItemList
|
|
if control is LineEdit and control.accessibility_name == "Path:":
|
|
path_edit = control as LineEdit
|
|
if control is Button and (control as Button).text == (
|
|
"Select Current Folder"
|
|
):
|
|
select_button = control as Button
|
|
assert(directory_list != null)
|
|
assert(path_edit != null)
|
|
assert(select_button != null)
|
|
_assert_directionally_reachable(directory_list, controls)
|
|
directory_list.clear()
|
|
directory_list.add_item("test folder")
|
|
directory_list.select(0)
|
|
directory_list.grab_focus()
|
|
var down_event := InputEventJoypadButton.new()
|
|
down_event.button_index = JOY_BUTTON_DPAD_DOWN
|
|
down_event.pressed = true
|
|
font_controller.call("_input", down_event)
|
|
assert(scope.gui_get_focus_owner() == select_button)
|
|
path_edit.grab_focus()
|
|
var accept_event := InputEventJoypadButton.new()
|
|
accept_event.button_index = JOY_BUTTON_A
|
|
accept_event.pressed = true
|
|
font_controller.call("_input", accept_event)
|
|
assert(keyboard.is_open())
|
|
keyboard.call("_close_keyboard", true)
|
|
dialog.queue_free()
|
|
font_controller.queue_free()
|
|
keyboard.queue_free()
|
|
await process_frame
|
|
|
|
|
|
func _assert_directionally_reachable(
|
|
start: Control,
|
|
controls: Array[Control],
|
|
) -> void:
|
|
var expected: Dictionary[int, bool] = {}
|
|
for control: Control in controls:
|
|
expected[control.get_instance_id()] = true
|
|
var visited: Dictionary[int, bool] = {start.get_instance_id(): true}
|
|
var pending: Array[Control] = [start]
|
|
while not pending.is_empty():
|
|
var current: Control = pending.pop_front()
|
|
for path: NodePath in [
|
|
current.focus_neighbor_left,
|
|
current.focus_neighbor_right,
|
|
current.focus_neighbor_top,
|
|
current.focus_neighbor_bottom,
|
|
]:
|
|
var neighbor := current.get_node_or_null(path) as Control
|
|
if (
|
|
neighbor == null
|
|
or not expected.has(neighbor.get_instance_id())
|
|
or visited.has(neighbor.get_instance_id())
|
|
):
|
|
continue
|
|
visited[neighbor.get_instance_id()] = true
|
|
pending.append(neighbor)
|
|
assert(visited.size() == expected.size())
|
|
|
|
|
|
func _assert_neighbor(
|
|
origin: Control,
|
|
property_name: StringName,
|
|
expected: Control,
|
|
) -> void:
|
|
var neighbor_path: NodePath = origin.get(property_name)
|
|
var neighbor := origin.get_node_or_null(neighbor_path) as Control
|
|
assert(neighbor == expected)
|