Significant improvements to tree-handling.

* Don't manipulate selection in any way. Leave that to Godot, and I'll fix issues in the engine if needed.
* Unify speech rendering of tree rows. This results in more useful announcements of buttons and such when tree items receive focus.
* Only handle `ui_up` and `ui_down` to ensure that focus won't leave a tree when the top-most or bottom-most row is arrowed past.
* Add a bit of handling to strip out duplicate collapse/focus events generated by the remote `SceneTree` in an active game.
This commit is contained in:
Nolan Darilek 2020-06-06 12:05:59 -05:00
parent 123e475fed
commit 548199d647

View File

@ -331,54 +331,16 @@ func text_edit_input(event):
pass pass
func tree_item_render(): var _last_tree_item_tokens
var focused_tree_item = node.get_selected()
var tokens = PoolStringArray([])
for i in range(node.columns):
tokens.append(focused_tree_item.get_text(i))
if focused_tree_item.get_children():
if focused_tree_item.collapsed:
tokens.append("collapsed")
else:
tokens.append("expanded")
tokens.append("tree item")
if focused_tree_item.is_selected(0):
tokens.append("selected")
TTS.speak(tokens.join(": "), true)
func tree_item_deselect_all(item: TreeItem): func _tree_item_render():
for i in range(node.columns): if not node.has_focus():
item.deselect(i) return
func tree_deselect_all_but(target: TreeItem, tree: Tree):
var cur = tree.get_root()
while cur != null:
if cur != target:
tree_item_deselect_all(cur)
cur = tree.get_next_selected(cur)
var prev_selected_cell
var button_index
func tree_item_selected():
button_index = null
var cell = node.get_selected() var cell = node.get_selected()
if cell != prev_selected_cell:
if node.select_mode == Tree.SELECT_MULTI:
cell.select(0)
tree_deselect_all_but(cell, node)
if node.has_focus():
tree_item_render()
prev_selected_cell = cell
else:
var tokens = PoolStringArray([]) var tokens = PoolStringArray([])
for i in range(node.columns): for i in range(node.columns):
if cell.is_selected(i): if node.select_mode == Tree.SELECT_MULTI or cell.is_selected(i):
var title = node.get_column_title(i) var title = node.get_column_title(i)
if title: if title:
tokens.append(title) tokens.append(title)
@ -395,14 +357,31 @@ func tree_item_selected():
+ TTS.singular_or_plural(button_count, "button", "buttons") + TTS.singular_or_plural(button_count, "button", "buttons")
) )
) )
if cell.has_method("get_button_tooltip"):
var button_tooltip = cell.get_button_tooltip(i, button_index) var button_tooltip = cell.get_button_tooltip(i, button_index)
if button_tooltip: if button_tooltip:
tokens.append(button_tooltip) tokens.append(button_tooltip)
tokens.append("button") tokens.append("button")
if button_count > 1: if button_count > 1:
tokens.append("Use Home and End to switch focus.") tokens.append("Use Home and End to switch focus.")
if cell.get_children():
if cell.collapsed:
tokens.append("collapsed")
else:
tokens.append("expanded")
tokens.append("tree item")
if tokens != _last_tree_item_tokens:
TTS.speak(tokens.join(": "), true) TTS.speak(tokens.join(": "), true)
_last_tree_item_tokens = tokens
var prev_selected_cell
var button_index
func _tree_item_or_cell_selected():
button_index = null
_tree_item_render()
func tree_item_multi_selected(item, column, selected): func tree_item_multi_selected(item, column, selected):
@ -412,7 +391,9 @@ func tree_item_multi_selected(item, column, selected):
TTS.speak("unselected", true) TTS.speak("unselected", true)
func tree_input(event): func _tree_input(event):
if event.is_action_pressed("ui_up") or event.is_action_pressed("ui_down"):
node.accept_event()
var item = node.get_selected() var item = node.get_selected()
var column var column
if item: if item:
@ -431,7 +412,7 @@ func tree_input(event):
node.rect_global_position.y + area.position.y + area.size.y / 2 node.rect_global_position.y + area.position.y + area.size.y / 2
) )
node.get_tree().root.warp_mouse(position) node.get_tree().root.warp_mouse(position)
if item and column and button_index != null: if item and column != null and button_index != null:
if event.is_action_pressed("ui_accept"): if event.is_action_pressed("ui_accept"):
node.accept_event() node.accept_event()
return node.emit_signal("button_pressed", item, column, button_index + 1) return node.emit_signal("button_pressed", item, column, button_index + 1)
@ -457,18 +438,29 @@ func tree_input(event):
func tree_focused(): func tree_focused():
_last_tree_item_tokens = null
if node.get_selected(): if node.get_selected():
tree_item_render() _tree_item_render()
else: else:
TTS.speak("tree", true) TTS.speak("tree", true)
func tree_item_collapsed(item): var _was_collapsed
func _tree_item_collapsed(item):
if node.has_focus(): if node.has_focus():
var selected = false
for column in range(node.columns):
if item.is_selected(column):
selected = true
break
if selected and item.collapsed != _was_collapsed:
if item.collapsed: if item.collapsed:
TTS.speak("collapsed", true) TTS.speak("collapsed", true)
else: else:
TTS.speak("expanded", true) TTS.speak("expanded", true)
_was_collapsed = item.collapsed
func progress_bar_focused(): func progress_bar_focused():
@ -605,14 +597,7 @@ func gui_input(event):
elif node is TextEdit: elif node is TextEdit:
return text_edit_input(event) return text_edit_input(event)
elif node is Tree: elif node is Tree:
if ( return _tree_input(event)
event.is_action_pressed("ui_up")
or event.is_action_pressed("ui_down")
or event.is_action_pressed("ui_left")
or event.is_action_pressed("ui_right")
):
node.accept_event()
return tree_input(event)
elif node.is_class("EditorInspectorSection"): elif node.is_class("EditorInspectorSection"):
return editor_inspector_section_input(event) return editor_inspector_section_input(event)
@ -721,10 +706,10 @@ func _init(node):
elif node is TabContainer: elif node is TabContainer:
node.connect("tab_changed", self, "tab_container_tab_changed") node.connect("tab_changed", self, "tab_container_tab_changed")
elif node is Tree: elif node is Tree:
node.connect("item_collapsed", self, "tree_item_collapsed") node.connect("item_collapsed", self, "_tree_item_collapsed")
node.connect("multi_selected", self, "tree_item_multi_selected") node.connect("multi_selected", self, "tree_item_multi_selected")
if node.select_mode == Tree.SELECT_MULTI: if node.select_mode == Tree.SELECT_MULTI:
node.connect("cell_selected", self, "tree_item_selected") node.connect("cell_selected", self, "_tree_item_or_cell_selected")
else: else:
node.connect("item_selected", self, "tree_item_selected") node.connect("item_selected", self, "_tree_item_or_cell_selected")
node.connect("tree_exiting", self, "queue_free", [], Object.CONNECT_DEFERRED) node.connect("tree_exiting", self, "queue_free", [], Object.CONNECT_DEFERRED)