miggor-StreamGraph/graph_node_renderer/add_node_menu.gd
Lera Elvoé eeb509cae0 add node menu (#3)
we finally have a way to add nodes from a menu!! lets goooooooo

Reviewed-on: https://codeberg.org/Eroax/Re-DotDeck/pulls/3
Co-authored-by: Lera Elvoé <yagich@poto.cafe>
Co-committed-by: Lera Elvoé <yagich@poto.cafe>
2023-11-23 06:38:10 +00:00

306 lines
9 KiB
GDScript

extends MarginContainer
class_name AddNodeMenu
@onready var search_line_edit: LineEdit = %SearchLineEdit
@onready var scroll_content_container: VBoxContainer = %ScrollContentContainer
@onready var scroll_container: ScrollContainer = $VBoxContainer/ScrollContainer
var categories: Dictionary = {} # Dictionary[String, Category]
var collapsed_categories: Array[String]
signal node_selected(type: String)
func _ready() -> void:
search("")
func add_category(category_name: String) -> void:
var c := Category.new(category_name.capitalize())
categories[category_name] = c
scroll_content_container.add_child(c)
c.collapse_toggled.connect(_on_category_collapse_toggled.bind(category_name))
c.item_pressed.connect(
func(item: int):
node_selected.emit(c.get_item_metadata(item, "type"))
)
c.item_favorite_button_toggled.connect(
func(item: int, toggled: bool):
NodeDB.set_node_favorite(c.get_item_metadata(item, "type"), toggled)
)
func add_category_item(category: String, item: String, tooltip: String = "", favorite: bool = false) -> void:
var c: Category = categories[category]
c.add_item(item, tooltip, favorite)
func add_item(category: String, item: String, tooltip: String = "", favorite: bool = false) -> void:
if !categories.has(category):
add_category(category)
add_category_item(category, item, tooltip, favorite)
func get_category(category: String) -> Category:
return categories[category]
func focus_search_bar() -> void:
search_line_edit.select_all()
search_line_edit.grab_focus()
func search(text: String) -> void:
scroll_content_container.get_children().map(func(c: Node): c.queue_free())
categories.clear()
var search_results := SearchProvider.search(text)
if search_results.is_empty():
return
for nd in search_results:
add_item(nd.category, nd.name, nd.description, NodeDB.is_node_favorite(nd.type))
var c := get_category(nd.category)
c.set_item_metadata(c.get_item_count() - 1, "type", nd.type)
c.set_item_metadata(c.get_item_count() - 1, "node_descriptor", weakref(nd))
c.set_collapsed(nd.category in collapsed_categories)
get_category(categories.keys()[0]).highlight_item(0)
func _on_search_line_edit_gui_input(event: InputEvent) -> void:
if event.is_action_pressed("ui_down"):
var category: Category
for i: String in categories:
var c: Category = categories[i]
if c.get_highlighted_item() != -1:
category = c
break
var item := category.get_highlighted_item()
if item + 1 == category.get_item_count():
# reached the end of items in the current category
category.unhighlight_all()
var nc: Category
if category.get_index() + 1 == scroll_content_container.get_child_count():
# reached the end, get the first category
nc = scroll_content_container.get_child(0)
else:
# there is another category after this
nc = scroll_content_container.get_child(category.get_index() + 1)
nc.highlight_item(0)
scroll_container.ensure_control_visible(nc.get_child(0))
return
category.highlight_item(item + 1)
scroll_container.ensure_control_visible(category.get_child(item + 1))
if event.is_action_pressed("ui_up"):
var category: Category
for i: String in categories:
var c: Category = categories[i]
if c.get_highlighted_item() != -1:
category = c
break
var item := category.get_highlighted_item()
if item - 1 == -1:
# reached the beginning of items in the current category
category.unhighlight_all()
var nc: Category
if category.get_index() - 1 == -1:
# reached the beginning, get the last category
nc = scroll_content_container.get_child(scroll_content_container.get_child_count() - 1)
else:
# there is another category before this
nc = scroll_content_container.get_child(category.get_index() - 1)
nc.highlight_item(nc.get_item_count() - 1)
scroll_container.ensure_control_visible(nc.get_child(nc.get_item_count() - 1))
return
category.highlight_item(item - 1)
scroll_container.ensure_control_visible(category.get_child(item - 1))
func _on_search_line_edit_text_submitted(_new_text: String) -> void:
var category: Category
for i: String in categories:
var c: Category = categories[i]
if c.get_highlighted_item() != -1:
category = c
break
node_selected.emit(category.get_item_metadata(category.get_highlighted_item(), "type"))
func _on_category_collapse_toggled(collapsed: bool, category: String) -> void:
if collapsed:
collapsed_categories.append(category)
else:
collapsed_categories.erase(category)
class Category extends VBoxContainer:
const COLLAPSE_ICON := preload("res://graph_node_renderer/textures/collapse-icon.svg")
const COLLAPSE_ICON_COLLAPSED := preload("res://graph_node_renderer/textures/collapse-icon-collapsed.svg")
var collapse_button: Button
signal item_pressed(item: int)
signal item_favorite_button_toggled(item: int, toggled: bool)
signal collapse_toggled(collapsed: bool)
func _init(p_name: String) -> void:
collapse_button = Button.new()
collapse_button.alignment = HORIZONTAL_ALIGNMENT_LEFT
collapse_button.icon = COLLAPSE_ICON
collapse_button.toggle_mode = true
collapse_button.flat = true
collapse_button.size_flags_vertical = Control.SIZE_EXPAND_FILL
collapse_button.text = p_name
collapse_button.toggled.connect(
func(toggled: bool):
collapse_toggled.emit(toggled)
)
add_child(collapse_button, false, Node.INTERNAL_MODE_FRONT)
renamed.connect(func():
collapse_button.name = name
)
collapse_button.toggled.connect(set_collapsed)
func set_collapsed(collapsed: bool) -> void:
collapse_button.icon = COLLAPSE_ICON_COLLAPSED if collapsed else COLLAPSE_ICON
collapse_button.set_pressed_no_signal(collapsed)
for c: CategoryItem in get_children():
c.visible = !collapsed
func add_item(p_name: String, p_tooltip: String, p_favorite: bool = false) -> void:
var item := CategoryItem.new(p_name, p_tooltip, p_favorite)
item.favorite_toggled.connect(
func(toggled: bool):
item_favorite_button_toggled.emit(item.get_index(), toggled)
)
item.pressed.connect(
func():
item_pressed.emit(item.get_index())
)
add_child(item)
func set_item_metadata(item: int, key: StringName, metadata: Variant) -> void:
get_child(item).set_meta(key, metadata)
func get_item_metadata(item: int, key: StringName) -> Variant:
return get_child(item).get_meta(key)
func get_item_count() -> int:
return get_child_count()
func set_item_favorite(item:int, favorite: bool) -> void:
var _item := get_child(item) as CategoryItem
_item.set_favorite(favorite)
func is_item_favorite(item: int) -> bool:
var _item := get_child(item) as CategoryItem
return _item.is_favorite()
func highlight_item(item: int) -> void:
for c: CategoryItem in get_children():
c.set_highlighted(c.get_index() == item)
func unhighlight_all() -> void:
for c: CategoryItem in get_children():
c.set_highlighted(false)
func get_highlighted_item() -> int:
for c: CategoryItem in get_children():
if c.is_highlighted:
return c.get_index()
return -1
class CategoryItem extends HBoxContainer:
const FAVORITE_ICON := preload("res://graph_node_renderer/textures/favorite-icon.svg")
const NON_FAVORITE_ICON := preload("res://graph_node_renderer/textures/non-favorite-icon.svg")
const ITEM_MARGIN := 16
var highlighted_stylebox := StyleBoxFlat.new()
var is_highlighted: bool
var fav_button: Button
var name_button: Button
var panel: PanelContainer
signal pressed
signal favorite_toggled(toggled: bool)
func _init(p_name: String, p_tooltip: String, p_favorite: bool) -> void:
fav_button = Button.new()
fav_button.icon = FAVORITE_ICON if p_favorite else NON_FAVORITE_ICON
fav_button.toggle_mode = true
fav_button.set_pressed_no_signal(p_favorite)
fav_button.flat = true
fav_button.toggled.connect(
func(toggled: bool):
favorite_toggled.emit(toggled)
)
fav_button.toggled.connect(set_favorite)
name_button = Button.new()
name_button.size_flags_horizontal = Control.SIZE_EXPAND_FILL
name_button.text = p_name
name_button.flat = true
name_button.alignment = HORIZONTAL_ALIGNMENT_LEFT
name_button.tooltip_text = p_tooltip
name_button.pressed.connect(
func():
pressed.emit()
)
var mc := MarginContainer.new()
mc.add_theme_constant_override(&"margin_left", ITEM_MARGIN)
panel = PanelContainer.new()
panel.size_flags_horizontal = Control.SIZE_EXPAND_FILL
panel.add_theme_stylebox_override(&"panel", highlighted_stylebox)
highlighted_stylebox.bg_color = Color(0.0, 0.0, 0.0, 0.15)
panel.self_modulate = Color.TRANSPARENT
var inner_hb := HBoxContainer.new()
inner_hb.add_child(fav_button)
inner_hb.add_child(name_button)
panel.add_child(inner_hb)
add_child(mc)
add_child(panel)
func set_favorite(favorite: bool) -> void:
fav_button.icon = FAVORITE_ICON if favorite else NON_FAVORITE_ICON
fav_button.set_pressed_no_signal(favorite)
func is_favorite() -> bool:
return fav_button.icon == FAVORITE_ICON
func set_highlighted(highlighted: bool) -> void:
is_highlighted = highlighted
if highlighted:
panel.self_modulate = Color.WHITE
else:
panel.self_modulate = Color.TRANSPARENT