diff --git a/Classes/GroupListMetadata.gd b/Classes/GroupListMetadata.gd new file mode 100644 index 0000000..2d43896 --- /dev/null +++ b/Classes/GroupListMetadata.gd @@ -0,0 +1,5 @@ +extends Resource +class_name GroupListMetadata + +@export var order: Array[String] +@export var uncollapsed_groups: Array[String] diff --git a/Classes/GroupMetadata.gd b/Classes/GroupMetadata.gd new file mode 100644 index 0000000..a44de86 --- /dev/null +++ b/Classes/GroupMetadata.gd @@ -0,0 +1,6 @@ +extends Resource +class_name GroupMetadata + +@export var icon_path: String +@export var description: String +@export var installs: Array[InstallMetadata] diff --git a/Classes/InstallMetadata.gd b/Classes/InstallMetadata.gd new file mode 100644 index 0000000..f933dad --- /dev/null +++ b/Classes/InstallMetadata.gd @@ -0,0 +1,7 @@ +extends Resource +class_name InstallMetadata + +@export var name: String +@export var icon_path: String +@export var binary_path: String +@export var local_overrides: Dictionary diff --git a/UI/Components/GroupMenu.gd b/UI/Components/GroupMenu.gd new file mode 100644 index 0000000..b1ecdc1 --- /dev/null +++ b/UI/Components/GroupMenu.gd @@ -0,0 +1,96 @@ +extends VBoxContainer + +@onready var collapse_button: Button = %CollapseButton +@onready var header_icon: TextureRect = %HeaderIcon +@onready var header_text_label: Label = %HeaderTextLabel +@onready var header_custom_control_container: HBoxContainer = %HeaderCustomControlContainer +@onready var child_container: VBoxContainer = %ChildContainer +@onready var add_install_button_container: CenterContainer = %AddInstallButtonContainer +@onready var add_install_button: Button = %AddInstallButton + +@onready var edit_text_button: Button = %EditTextButton +@onready var delete_group_button: Button = %DeleteGroupButton + +@onready var header_container: HBoxContainer = %HeaderContainer + +signal add_install_button_pressed + +signal delete_button_pressed +signal header_text_changed(new_text: String) + + +func _ready() -> void: + collapse_button.pressed.connect( + func(): + var b := collapse_button + set_children_visible(b.button_pressed) + ) + + add_install_button.pressed.connect(func(): add_install_button_pressed.emit()) + + edit_text_button.pressed.connect(setup_rename) + delete_group_button.pressed.connect(func(): delete_button_pressed.emit()) + + +func add(item) -> void: + pass + + +func free_item(at_idx: int) -> void: + child_container.get_child(at_idx).queue_free() + + +func clear() -> void: + child_container.get_children().map( + func(child: Node): + child.queue_free() + ) + + +func set_text(text: String) -> void: + header_text_label.text = text + + +func set_icon(icon: Texture2D) -> void: + header_icon.texture = icon + + +func set_icon_visible(p_visible: bool) -> void: + header_icon.visible = p_visible + + +func set_children_visible(p_visible: bool) -> void: + collapse_button.text = "v" if p_visible else ">" + child_container.visible = p_visible + add_install_button_container.visible = p_visible + + +func add_custom(control: Control) -> void: + header_custom_control_container.add_child(control) + + +func setup_rename() -> void: + header_text_label.visible = false + var l := RenameLineEdit.new(header_text_label.text) + l.size_flags_horizontal = header_text_label.size_flags_horizontal + + edit_text_button.disabled = true + + header_container.add_child(l) + header_container.move_child(l, 2) + + var reenable = func(): + header_text_label.visible = true + edit_text_button.disabled = false + + l.canceled.connect(reenable) + + l.text_submitted.connect( + func(new_text: String): + header_text_label.text = new_text + header_text_changed.emit(new_text) + + reenable.call() + ) + + l.grab_focus() diff --git a/UI/Components/GroupMenu.tscn b/UI/Components/GroupMenu.tscn new file mode 100644 index 0000000..e2d9e91 --- /dev/null +++ b/UI/Components/GroupMenu.tscn @@ -0,0 +1,70 @@ +[gd_scene load_steps=3 format=3 uid="uid://bh1nf1xrowlpv"] + +[ext_resource type="Script" path="res://UI/Components/GroupMenu.gd" id="1_h3o1w"] +[ext_resource type="Texture2D" uid="uid://de57eeeobflp4" path="res://icon.svg" id="2_crg6a"] + +[node name="GroupMenu" type="VBoxContainer"] +offset_right = 169.0 +offset_bottom = 71.0 +script = ExtResource("1_h3o1w") + +[node name="HSeparator" type="HSeparator" parent="."] +layout_mode = 2 + +[node name="HeaderContainer" type="HBoxContainer" parent="."] +unique_name_in_owner = true +layout_mode = 2 + +[node name="CollapseButton" type="Button" parent="HeaderContainer"] +unique_name_in_owner = true +custom_minimum_size = Vector2(32, 32) +layout_mode = 2 +toggle_mode = true +button_pressed = true +text = "v" +flat = true + +[node name="HeaderIcon" type="TextureRect" parent="HeaderContainer"] +unique_name_in_owner = true +visible = false +layout_mode = 2 +texture = ExtResource("2_crg6a") +expand_mode = 2 + +[node name="HeaderTextLabel" type="Label" parent="HeaderContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 1 +text = "header text" +vertical_alignment = 1 + +[node name="HeaderCustomControlContainer" type="HBoxContainer" parent="HeaderContainer"] +unique_name_in_owner = true +layout_mode = 2 + +[node name="EditTextButton" type="Button" parent="HeaderContainer/HeaderCustomControlContainer"] +unique_name_in_owner = true +layout_mode = 2 +text = "E" + +[node name="DeleteGroupButton" type="Button" parent="HeaderContainer/HeaderCustomControlContainer"] +unique_name_in_owner = true +layout_mode = 2 +text = "X" + +[node name="ChildContainer" type="VBoxContainer" parent="."] +unique_name_in_owner = true +layout_mode = 2 + +[node name="HSeparator2" type="HSeparator" parent="."] +layout_mode = 2 + +[node name="AddInstallButtonContainer" type="CenterContainer" parent="."] +unique_name_in_owner = true +layout_mode = 2 + +[node name="AddInstallButton" type="Button" parent="AddInstallButtonContainer"] +unique_name_in_owner = true +layout_mode = 2 +text = "New Install" diff --git a/UI/Components/RenameLineEdit.gd b/UI/Components/RenameLineEdit.gd new file mode 100644 index 0000000..d075871 --- /dev/null +++ b/UI/Components/RenameLineEdit.gd @@ -0,0 +1,27 @@ +extends LineEdit +class_name RenameLineEdit + +signal canceled + + +func _init(initial_text: String) -> void: + set_text(initial_text) + select_all() + clear_button_enabled = true + + text_submitted.connect(queue_free.unbind(1)) + + +# delete self if clicked outside +func _input(event: InputEvent) -> void: + if event is InputEventMouseButton && !(event as InputEventMouseButton).pressed: + if !get_global_rect().has_point((event as InputEventMouseButton).global_position): + canceled.emit() + queue_free() + + +# delete self if pressed escape +func _gui_input(event: InputEvent) -> void: + if event.is_action_pressed("ui_cancel"): + canceled.emit() + queue_free() diff --git a/UI/Main/GroupsView.tscn b/UI/Main/GroupsView.tscn new file mode 100644 index 0000000..81174fa --- /dev/null +++ b/UI/Main/GroupsView.tscn @@ -0,0 +1,32 @@ +[gd_scene format=3 uid="uid://bf464y0q4l67h"] + +[node name="GroupsView" type="VBoxContainer"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Label" type="Label" parent="."] +layout_mode = 2 +text = "Groups" +vertical_alignment = 1 + +[node name="PanelContainer" type="PanelContainer" parent="."] +custom_minimum_size = Vector2(0, 320) +layout_mode = 2 + +[node name="ScrollContainer" type="ScrollContainer" parent="PanelContainer"] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="GroupMenusContainer" type="VBoxContainer" parent="PanelContainer/ScrollContainer"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="CenterContainer" type="CenterContainer" parent="."] +layout_mode = 2 + +[node name="NewGroupButton" type="Button" parent="CenterContainer"] +layout_mode = 2 +text = "New Group"