From 8f942f441eb4b33b2fcb23cce0272aea4083ee2c Mon Sep 17 00:00:00 2001 From: Iceflower Date: Fri, 5 Jan 2024 22:19:57 +0100 Subject: [PATCH] [icon_explorer] Update icon explorer --- .../internal/scripts/collection.gd | 26 +++- .../internal/scripts/collection_mdi.gd | 21 ++- addons/icon_explorer/internal/scripts/io.gd | 17 +++ addons/icon_explorer/internal/ui/explorer.gd | 47 ------- .../icon_explorer/internal/ui/explorer.tscn | 69 ---------- .../icon_viewer.gd => explorer/explorer.gd} | 53 ++++++-- .../internal/ui/explorer/explorer.tscn | 120 ++++++++++++++++++ .../filter_options.gd | 0 .../internal/ui/explorer/option_popup.gd | 6 + .../internal/ui/explorer_dialog.gd | 8 -- .../internal/ui/explorer_dialog.tscn | 8 +- .../internal/ui/icon_viewer/icon_viewer.tscn | 67 ---------- .../internal/ui/options/collection_card.gd | 41 ------ .../internal/ui/options/collection_card.tscn | 69 ---------- .../internal/ui/options/options.gd | 82 ++++++++++-- .../internal/ui/options/options.tscn | 45 +++++-- 16 files changed, 330 insertions(+), 349 deletions(-) create mode 100644 addons/icon_explorer/internal/scripts/io.gd delete mode 100644 addons/icon_explorer/internal/ui/explorer.gd delete mode 100644 addons/icon_explorer/internal/ui/explorer.tscn rename addons/icon_explorer/internal/ui/{icon_viewer/icon_viewer.gd => explorer/explorer.gd} (62%) create mode 100644 addons/icon_explorer/internal/ui/explorer/explorer.tscn rename addons/icon_explorer/internal/ui/{icon_viewer => explorer}/filter_options.gd (100%) create mode 100644 addons/icon_explorer/internal/ui/explorer/option_popup.gd delete mode 100644 addons/icon_explorer/internal/ui/icon_viewer/icon_viewer.tscn delete mode 100644 addons/icon_explorer/internal/ui/options/collection_card.gd delete mode 100644 addons/icon_explorer/internal/ui/options/collection_card.tscn diff --git a/addons/icon_explorer/internal/scripts/collection.gd b/addons/icon_explorer/internal/scripts/collection.gd index 3fe1cb8..3d22f33 100644 --- a/addons/icon_explorer/internal/scripts/collection.gd +++ b/addons/icon_explorer/internal/scripts/collection.gd @@ -1,11 +1,15 @@ extends RefCounted +const Io := preload("res://addons/icon_explorer/internal/scripts/io.gd") const Icon := preload("res://addons/icon_explorer/internal/scripts/icon.gd") enum Id { MATERIAL_DESIGN, } +signal install_finished(status: Error) +signal remove_finished(status: Error) + var id: Id var name: String var version: String @@ -14,20 +18,32 @@ var license: String var license_text: String var web: String +var __remove_thread: Thread + # VIRTUAL func load() -> Array[Icon]: assert(false, "virtual function") return [] # VIRTUAL -func add(version: String) -> bool: +func install(http: HTTPRequest, version: String) -> void: assert(false, "virtual function") - return false # VIRTUAL -func remove() -> bool: - assert(false, "virtual function") - return false +func remove() -> void: + if self.__remove_thread != null && self.__remove_thread.is_alive(): + return + if self.__remove_thread != null: + self.__remove_thread.wait_to_finish() + + self.__remove_thread = Thread.new() + self.__remove_thread.start(self.__remove) + +func __remove() -> void: + if Io.rrm_dir(self.directory()): + self.remove_finished.emit(Error.OK) + else: + self.remove_finished.emit(Error.FAILED) # VIRTUAL func icon_directory() -> String: diff --git a/addons/icon_explorer/internal/scripts/collection_mdi.gd b/addons/icon_explorer/internal/scripts/collection_mdi.gd index 626fff6..bf8bd31 100644 --- a/addons/icon_explorer/internal/scripts/collection_mdi.gd +++ b/addons/icon_explorer/internal/scripts/collection_mdi.gd @@ -50,14 +50,23 @@ func load() -> Array[Icon]: return icons # OVERRIDE -func add(version: String) -> bool: - assert(false, "virtual function") - return false +func install(http: HTTPRequest, version: String) -> void: + if !http.request_completed.is_connected(self._on_request_completed): + http.request_completed.connect(_on_request_completed) + + self.install_finished.emit(Error.FAILED) + +func _on_request_completed(result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray) -> void: + if result != HTTPRequest.RESULT_SUCCESS: + self.install_finished.emit(Error.FAILED) + return + + + self.install_finished.emit(Error.OK) # OVERRIDE -func remove() -> bool: - assert(false, "virtual function") - return false +func remove() -> void: + super.remove() # OVERRIDE func icon_directory() -> String: diff --git a/addons/icon_explorer/internal/scripts/io.gd b/addons/icon_explorer/internal/scripts/io.gd new file mode 100644 index 0000000..043137b --- /dev/null +++ b/addons/icon_explorer/internal/scripts/io.gd @@ -0,0 +1,17 @@ +static func rrm_dir(dir_path: String) -> bool: + var dir: DirAccess = DirAccess.open(dir_path) + if !dir: + return false + + dir.list_dir_begin() + var file_name: String = dir.get_next() + while file_name != "": + if dir.current_is_dir(): + if !rrm_dir(dir_path.path_join(file_name)): + return false + else: + if dir.remove(file_name) != Error.OK: + return false + file_name = dir.get_next() + DirAccess.remove_absolute(dir_path) + return true diff --git a/addons/icon_explorer/internal/ui/explorer.gd b/addons/icon_explorer/internal/ui/explorer.gd deleted file mode 100644 index ccb614e..0000000 --- a/addons/icon_explorer/internal/ui/explorer.gd +++ /dev/null @@ -1,47 +0,0 @@ -#@tool -extends MarginContainer - -const IconDatabase := preload("res://addons/icon_explorer/internal/scripts/icon_database.gd") -const IconViewer := preload("res://addons/icon_explorer/internal/ui/icon_viewer/icon_viewer.gd") -const Options := preload("res://addons/icon_explorer/internal/ui/options/options.gd") - -@export var _icon_viewer_path: NodePath -@onready var _icon_viewer: IconViewer = self.get_node(self._icon_viewer_path) -@export var _options_path: NodePath -@onready var _options: Options = self.get_node(self._options_path) - -@export var _tab_bar: TabBar -@export var _tab_container: TabContainer - -@export var _status_panel: PanelContainer -@export var _status_bar: ProgressBar - -var _db: IconDatabase = IconDatabase.new() - -func _ready() -> void: - self._tab_bar.tab_changed.connect(self._on_tab_changed) - - if !self._db.is_loaded(): - # load in main thread: https://github.com/godotengine/godot/issues/86796 - #self.set_process(true) - self._status_panel.visible = true - self._db._load() - # remove next lines if loading threaded - self._icon_viewer.set_db(self._db) - self._options.set_db(self._db) - self._status_panel.visible = false - -func _process(_delta: float) -> void: - return - if self._db.is_loaded(): - self.set_process(false) - self._status_panel.visible = false - self._icon_viewer.set_db(self._db) - self._options.set_db(self._db) - return - - self._status_panel.visible = true - self._status_bar.value = self._db.load_progress() - -func _on_tab_changed(idx: int) -> void: - self._tab_container.current_tab = idx diff --git a/addons/icon_explorer/internal/ui/explorer.tscn b/addons/icon_explorer/internal/ui/explorer.tscn deleted file mode 100644 index cb8c13d..0000000 --- a/addons/icon_explorer/internal/ui/explorer.tscn +++ /dev/null @@ -1,69 +0,0 @@ -[gd_scene load_steps=4 format=3 uid="uid://c331kma8mx8wd"] - -[ext_resource type="Script" path="res://addons/icon_explorer/internal/ui/explorer.gd" id="1_mubw4"] -[ext_resource type="PackedScene" uid="uid://dnxwdqwt2eqfi" path="res://addons/icon_explorer/internal/ui/icon_viewer/icon_viewer.tscn" id="2_swfou"] -[ext_resource type="PackedScene" uid="uid://bfmh2kaf2qbrx" path="res://addons/icon_explorer/internal/ui/options/options.tscn" id="3_f2ugw"] - -[node name="explorer" type="MarginContainer" node_paths=PackedStringArray("_tab_bar", "_tab_container", "_status_panel", "_status_bar")] -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 -theme_override_constants/margin_left = 0 -theme_override_constants/margin_top = 0 -theme_override_constants/margin_right = 0 -theme_override_constants/margin_bottom = 0 -script = ExtResource("1_mubw4") -_icon_viewer_path = NodePath("v_box_container/tab_container/icon_viewer") -_options_path = NodePath("v_box_container/tab_container/options") -_tab_bar = NodePath("v_box_container/h_box_container/tab_bar") -_tab_container = NodePath("v_box_container/tab_container") -_status_panel = NodePath("v_box_container/h_box_container/status") -_status_bar = NodePath("v_box_container/h_box_container/status/progress_bar") - -[node name="v_box_container" type="VBoxContainer" parent="."] -layout_mode = 2 -theme_override_constants/separation = 0 - -[node name="h_box_container" type="HBoxContainer" parent="v_box_container"] -layout_mode = 2 - -[node name="tab_bar" type="TabBar" parent="v_box_container/h_box_container"] -layout_mode = 2 -size_flags_horizontal = 0 -tab_count = 2 -clip_tabs = false -tab_0/title = "Icons" -tab_1/title = "Options" - -[node name="status" type="PanelContainer" parent="v_box_container/h_box_container"] -visible = false -layout_mode = 2 -size_flags_horizontal = 3 - -[node name="progress_bar" type="ProgressBar" parent="v_box_container/h_box_container/status"] -custom_minimum_size = Vector2(0, 32) -layout_mode = 2 -size_flags_vertical = 4 -value = 50.0 -show_percentage = false - -[node name="label" type="Label" parent="v_box_container/h_box_container/status"] -layout_mode = 2 -size_flags_horizontal = 4 -text = "Loading..." - -[node name="tab_container" type="TabContainer" parent="v_box_container"] -layout_mode = 2 -size_flags_vertical = 3 -tabs_visible = false - -[node name="icon_viewer" parent="v_box_container/tab_container" instance=ExtResource("2_swfou")] -layout_mode = 2 - -[node name="options" parent="v_box_container/tab_container" instance=ExtResource("3_f2ugw")] -visible = false -layout_mode = 2 diff --git a/addons/icon_explorer/internal/ui/icon_viewer/icon_viewer.gd b/addons/icon_explorer/internal/ui/explorer/explorer.gd similarity index 62% rename from addons/icon_explorer/internal/ui/icon_viewer/icon_viewer.gd rename to addons/icon_explorer/internal/ui/explorer/explorer.gd index f899f4e..cc82213 100644 --- a/addons/icon_explorer/internal/ui/icon_viewer/icon_viewer.gd +++ b/addons/icon_explorer/internal/ui/explorer/explorer.gd @@ -2,39 +2,67 @@ extends VBoxContainer const Collection := preload("res://addons/icon_explorer/internal/scripts/collection.gd") -const FilterOptions := preload("res://addons/icon_explorer/internal/ui/icon_viewer/filter_options.gd") +const FilterOptions := preload("res://addons/icon_explorer/internal/ui/explorer/filter_options.gd") const Icon := preload("res://addons/icon_explorer/internal/scripts/icon.gd") const IconDatabase := preload("res://addons/icon_explorer/internal/scripts/icon_database.gd") const DetailPanel := preload("res://addons/icon_explorer/internal/ui/detail_panel/detail_panel.gd") +const Options := preload("res://addons/icon_explorer/internal/ui/options/options.gd") + @export var _filter_icon: TextureRect @export var _filter: LineEdit @export var _filter_options_path: NodePath @onready var _filter_options: FilterOptions = self.get_node(self._filter_options_path) @export var _icon_list: ItemList +@export var _options_button: Button +@export var _options_popup: Window +@export var _options_path: NodePath +@onready var _options: Options = self.get_node(self._options_path) + +@export var _status_bar: ProgressBar @export var _detail_panel_path: NodePath @onready var _detail_panel: DetailPanel = self.get_node(self._detail_panel_path) -var _db: IconDatabase: - set = set_db +var _db: IconDatabase = IconDatabase.new() + +func _ready() -> void: + self.get_viewport().gui_embed_subwindows = false + self._filter_icon.texture = self.get_theme_icon("Search", "EditorIcons") + self._filter_options.icon = self.get_theme_icon("AnimationFilter", "EditorIcons") + self._filter_options.options_changed.connect(self.update) + self._icon_list.item_selected.connect(self._on_icon_selected) + self._filter.text_changed.connect(self._on_filter_changed) + self._options_button.icon = self.get_theme_icon("Tools", "EditorIcons") + self._options_button.pressed.connect(self._on_option_pressed) -func set_db(new_db: IconDatabase) -> void: - _db = new_db + # load in main thread: https://github.com/godotengine/godot/issues/86796 + # self._db.load() + # self.set_process(true) + self._db._load() + self._status_bar.value = 100.0 var filter_popup: PopupMenu = self._filter_options.get_popup() for coll: Collection in self._db.installed_collections(): filter_popup.add_check_item(coll.name, int(coll.id)) for idx: int in range(filter_popup.item_count): filter_popup.set_item_checked(idx, true) + self._options.db = self._db self.update() -func _ready() -> void: - self._filter_icon.texture = self.get_theme_icon("Search", "EditorIcons") - self._filter_options.icon = self.get_theme_icon("AnimationFilter", "EditorIcons") - self._filter_options.options_changed.connect(self.update) - self._icon_list.item_selected.connect(self._on_icon_selected) - self._filter.text_changed.connect(self._on_filter_changed) +func _process(_delta: float) -> void: + return + if self._db.is_loaded(): + self.set_process(false) + var filter_popup: PopupMenu = self._filter_options.get_popup() + for coll: Collection in self._db.installed_collections(): + filter_popup.add_check_item(coll.name, int(coll.id)) + for idx: int in range(filter_popup.item_count): + filter_popup.set_item_checked(idx, true) + self.update() + return + + self._status_bar.value = self._db.load_progress() func clear() -> void: self._icon_list.clear() @@ -56,3 +84,6 @@ func _on_icon_selected(idx: int) -> void: func _on_filter_changed(text: String) -> void: self.update(text) + +func _on_option_pressed() -> void: + self._options_popup.popup_centered_ratio(0.35) diff --git a/addons/icon_explorer/internal/ui/explorer/explorer.tscn b/addons/icon_explorer/internal/ui/explorer/explorer.tscn new file mode 100644 index 0000000..debad83 --- /dev/null +++ b/addons/icon_explorer/internal/ui/explorer/explorer.tscn @@ -0,0 +1,120 @@ +[gd_scene load_steps=7 format=3 uid="uid://dnxwdqwt2eqfi"] + +[ext_resource type="Script" path="res://addons/icon_explorer/internal/ui/explorer/explorer.gd" id="1_2oqmk"] +[ext_resource type="Script" path="res://addons/icon_explorer/internal/ui/explorer/filter_options.gd" id="2_dkuya"] +[ext_resource type="PackedScene" uid="uid://c3s1t8hiu6xll" path="res://addons/icon_explorer/internal/ui/detail_panel/detail_panel.tscn" id="3_w4j77"] +[ext_resource type="Script" path="res://addons/icon_explorer/internal/ui/explorer/option_popup.gd" id="4_03l1v"] +[ext_resource type="PackedScene" uid="uid://bfmh2kaf2qbrx" path="res://addons/icon_explorer/internal/ui/options/options.tscn" id="5_wngaf"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_gnh63"] + +[node name="explorer" type="PanelContainer"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +scale = Vector2(0.989719, 1.05388) + +[node name="explorer" type="MarginContainer" parent="."] +layout_mode = 2 +theme_override_constants/margin_left = 4 +theme_override_constants/margin_top = 4 +theme_override_constants/margin_right = 4 +theme_override_constants/margin_bottom = 4 + +[node name="icon_viewer" type="VBoxContainer" parent="explorer" node_paths=PackedStringArray("_filter_icon", "_filter", "_icon_list", "_options_button", "_options_popup", "_status_bar")] +layout_mode = 2 +script = ExtResource("1_2oqmk") +_filter_icon = NodePath("toolbar/filter_icon") +_filter = NodePath("toolbar/filter") +_filter_options_path = NodePath("toolbar/filter_options") +_icon_list = NodePath("HSplitContainer/ScrollContainer/icons") +_options_button = NodePath("toolbar/options") +_options_popup = NodePath("option_popup") +_options_path = NodePath("option_popup/panel_container/margin_container/options") +_status_bar = NodePath("progress_bar") +_detail_panel_path = NodePath("HSplitContainer/detail_panel") + +[node name="toolbar" type="HBoxContainer" parent="explorer/icon_viewer"] +layout_mode = 2 + +[node name="filter_icon" type="TextureRect" parent="explorer/icon_viewer/toolbar"] +layout_mode = 2 +stretch_mode = 5 + +[node name="filter" type="LineEdit" parent="explorer/icon_viewer/toolbar"] +layout_mode = 2 +size_flags_horizontal = 3 +auto_translate = false +localize_numeral_system = false +placeholder_text = "search icons..." +clear_button_enabled = true + +[node name="filter_options" type="MenuButton" parent="explorer/icon_viewer/toolbar"] +layout_mode = 2 +script = ExtResource("2_dkuya") + +[node name="options" type="Button" parent="explorer/icon_viewer/toolbar"] +layout_mode = 2 +flat = true + +[node name="progress_bar" type="ProgressBar" parent="explorer/icon_viewer"] +visible = false +layout_mode = 2 +size_flags_vertical = 1 +show_percentage = false + +[node name="HSplitContainer" type="HSplitContainer" parent="explorer/icon_viewer"] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="ScrollContainer" type="ScrollContainer" parent="explorer/icon_viewer/HSplitContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +horizontal_scroll_mode = 3 + +[node name="icons" type="ItemList" parent="explorer/icon_viewer/HSplitContainer/ScrollContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_styles/focus = SubResource("StyleBoxEmpty_gnh63") +allow_search = false +max_text_lines = 3 +auto_height = true +max_columns = 0 +same_column_width = true +fixed_column_width = 128 +icon_mode = 0 +fixed_icon_size = Vector2i(64, 64) + +[node name="detail_panel" parent="explorer/icon_viewer/HSplitContainer" instance=ExtResource("3_w4j77")] +layout_mode = 2 +size_flags_vertical = 3 +size_flags_stretch_ratio = 0.35 + +[node name="option_popup" type="Window" parent="explorer/icon_viewer"] +visible = false +wrap_controls = true +transient = true +exclusive = true +script = ExtResource("4_03l1v") + +[node name="panel_container" type="PanelContainer" parent="explorer/icon_viewer/option_popup"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="margin_container" type="MarginContainer" parent="explorer/icon_viewer/option_popup/panel_container"] +layout_mode = 2 +theme_override_constants/margin_left = 4 +theme_override_constants/margin_top = 4 +theme_override_constants/margin_right = 4 +theme_override_constants/margin_bottom = 4 + +[node name="options" parent="explorer/icon_viewer/option_popup/panel_container/margin_container" instance=ExtResource("5_wngaf")] +layout_mode = 2 diff --git a/addons/icon_explorer/internal/ui/icon_viewer/filter_options.gd b/addons/icon_explorer/internal/ui/explorer/filter_options.gd similarity index 100% rename from addons/icon_explorer/internal/ui/icon_viewer/filter_options.gd rename to addons/icon_explorer/internal/ui/explorer/filter_options.gd diff --git a/addons/icon_explorer/internal/ui/explorer/option_popup.gd b/addons/icon_explorer/internal/ui/explorer/option_popup.gd new file mode 100644 index 0000000..1dbd77e --- /dev/null +++ b/addons/icon_explorer/internal/ui/explorer/option_popup.gd @@ -0,0 +1,6 @@ +#@tool +extends Window + +func _notification(what: int) -> void: + if (what == NOTIFICATION_WM_CLOSE_REQUEST): + self.hide() diff --git a/addons/icon_explorer/internal/ui/explorer_dialog.gd b/addons/icon_explorer/internal/ui/explorer_dialog.gd index 92d3355..1dbd77e 100644 --- a/addons/icon_explorer/internal/ui/explorer_dialog.gd +++ b/addons/icon_explorer/internal/ui/explorer_dialog.gd @@ -1,14 +1,6 @@ #@tool extends Window -const Explorer := preload("res://addons/icon_explorer/internal/ui/explorer.gd") - -@export_node_path("MarginContainer") var _explorer_path -@onready var _explorer: Explorer = self.get_node(self._explorer_path) - func _notification(what: int) -> void: if (what == NOTIFICATION_WM_CLOSE_REQUEST): self.hide() - -func _on_about_to_popup() -> void: - pass diff --git a/addons/icon_explorer/internal/ui/explorer_dialog.tscn b/addons/icon_explorer/internal/ui/explorer_dialog.tscn index ec8d832..c4f54f1 100644 --- a/addons/icon_explorer/internal/ui/explorer_dialog.tscn +++ b/addons/icon_explorer/internal/ui/explorer_dialog.tscn @@ -1,18 +1,18 @@ [gd_scene load_steps=3 format=3 uid="uid://dyfr78rcugqaa"] [ext_resource type="Script" path="res://addons/icon_explorer/internal/ui/explorer_dialog.gd" id="1_yupxp"] -[ext_resource type="PackedScene" uid="uid://c331kma8mx8wd" path="res://addons/icon_explorer/internal/ui/explorer.tscn" id="2_kva7t"] +[ext_resource type="PackedScene" uid="uid://dnxwdqwt2eqfi" path="res://addons/icon_explorer/internal/ui/explorer/explorer.tscn" id="2_3tinl"] [node name="explorer_dialog" type="Window"] disable_3d = true title = "Icon Explorer" -position = Vector2i(0, 36) +position = Vector2i(210, 133) size = Vector2i(1920, 1080) +visible = false wrap_controls = true transient = true script = ExtResource("1_yupxp") -_explorer_path = NodePath("") -[node name="explorer" parent="." instance=ExtResource("2_kva7t")] +[node name="explorer" parent="." instance=ExtResource("2_3tinl")] [connection signal="about_to_popup" from="." to="." method="_on_about_to_popup"] diff --git a/addons/icon_explorer/internal/ui/icon_viewer/icon_viewer.tscn b/addons/icon_explorer/internal/ui/icon_viewer/icon_viewer.tscn deleted file mode 100644 index 4c40c0e..0000000 --- a/addons/icon_explorer/internal/ui/icon_viewer/icon_viewer.tscn +++ /dev/null @@ -1,67 +0,0 @@ -[gd_scene load_steps=5 format=3 uid="uid://dnxwdqwt2eqfi"] - -[ext_resource type="Script" path="res://addons/icon_explorer/internal/ui/icon_viewer/icon_viewer.gd" id="1_bs3yl"] -[ext_resource type="Script" path="res://addons/icon_explorer/internal/ui/icon_viewer/filter_options.gd" id="2_x4k8m"] -[ext_resource type="PackedScene" uid="uid://c3s1t8hiu6xll" path="res://addons/icon_explorer/internal/ui/detail_panel/detail_panel.tscn" id="3_vgev5"] - -[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_gnh63"] - -[node name="icon_viewer" type="VBoxContainer" node_paths=PackedStringArray("_filter_icon", "_filter", "_icon_list")] -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -script = ExtResource("1_bs3yl") -_filter_icon = NodePath("toolbar/filter_icon") -_filter = NodePath("toolbar/filter") -_filter_options_path = NodePath("toolbar/filter_options") -_icon_list = NodePath("HSplitContainer/ScrollContainer/icons") -_detail_panel_path = NodePath("HSplitContainer/detail_panel") - -[node name="toolbar" type="HBoxContainer" parent="."] -layout_mode = 2 - -[node name="filter_icon" type="TextureRect" parent="toolbar"] -layout_mode = 2 -stretch_mode = 5 - -[node name="filter" type="LineEdit" parent="toolbar"] -layout_mode = 2 -size_flags_horizontal = 3 -auto_translate = false -localize_numeral_system = false -placeholder_text = "search icons..." -clear_button_enabled = true - -[node name="filter_options" type="MenuButton" parent="toolbar"] -layout_mode = 2 -script = ExtResource("2_x4k8m") - -[node name="HSplitContainer" type="HSplitContainer" parent="."] -layout_mode = 2 -size_flags_vertical = 3 - -[node name="ScrollContainer" type="ScrollContainer" parent="HSplitContainer"] -layout_mode = 2 -size_flags_horizontal = 3 -horizontal_scroll_mode = 3 - -[node name="icons" type="ItemList" parent="HSplitContainer/ScrollContainer"] -layout_mode = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 -theme_override_styles/focus = SubResource("StyleBoxEmpty_gnh63") -allow_search = false -max_text_lines = 3 -auto_height = true -max_columns = 0 -same_column_width = true -fixed_column_width = 128 -icon_mode = 0 -fixed_icon_size = Vector2i(64, 64) - -[node name="detail_panel" parent="HSplitContainer" instance=ExtResource("3_vgev5")] -layout_mode = 2 -size_flags_vertical = 3 -size_flags_stretch_ratio = 0.35 diff --git a/addons/icon_explorer/internal/ui/options/collection_card.gd b/addons/icon_explorer/internal/ui/options/collection_card.gd deleted file mode 100644 index 6beba4c..0000000 --- a/addons/icon_explorer/internal/ui/options/collection_card.gd +++ /dev/null @@ -1,41 +0,0 @@ -#@tool -extends MarginContainer - -const Collection := preload("res://addons/icon_explorer/internal/scripts/collection.gd") - -signal add_pressed() -signal remove_pressed() -signal open_directory_pressed() - -@export var _add_button: Button -@export var _remove_button: Button -@export var _open_directory_button: Button - -@export var _available: TextureRect -@export var _name: Label -@export var _version: Label - -func _ready() -> void: - self._available.texture = self.get_theme_icon("ImportCheck", "EditorIcons") - self._add_button.icon = self.get_theme_icon("AssetLib", "EditorIcons") - self._add_button.pressed.connect(self._on_add_button_pressed) - self._remove_button.icon = self.get_theme_icon("Remove", "EditorIcons") - self._remove_button.pressed.connect(self._on_remove_button_pressed) - self._open_directory_button.icon = self.get_theme_icon("Filesystem", "EditorIcons") - self._open_directory_button.pressed.connect(self._on_open_directory_button_pressed) - -func _on_add_button_pressed() -> void: - self.add_pressed.emit() - -func _on_remove_button_pressed() -> void: - self.remove_pressed.emit() - -func _on_open_directory_button_pressed() -> void: - self.open_directory_pressed.emit() - -func display(coll: Collection) -> void: - self._available.visible = coll.is_installed() - self._name.text = coll.name - self._version.text = coll.version - self._open_directory_button.disabled = !coll.is_installed() - self._remove_button.disabled = !coll.is_installed() diff --git a/addons/icon_explorer/internal/ui/options/collection_card.tscn b/addons/icon_explorer/internal/ui/options/collection_card.tscn deleted file mode 100644 index 0e53ac7..0000000 --- a/addons/icon_explorer/internal/ui/options/collection_card.tscn +++ /dev/null @@ -1,69 +0,0 @@ -[gd_scene load_steps=3 format=3 uid="uid://1vgw5tppe11y"] - -[ext_resource type="Script" path="res://addons/icon_explorer/internal/ui/options/collection_card.gd" id="1_n3lnl"] -[ext_resource type="Texture2D" uid="uid://bu0slf2fkpkac" path="res://icon.svg" id="2_gn4uh"] - -[node name="panel_container" type="PanelContainer" node_paths=PackedStringArray("_add_button", "_remove_button", "_open_directory_button", "_available", "_name", "_version")] -anchors_preset = 8 -anchor_left = 0.5 -anchor_top = 0.5 -anchor_right = 0.5 -anchor_bottom = 0.5 -offset_left = -80.0 -offset_top = -117.5 -offset_right = 80.0 -offset_bottom = 117.5 -grow_horizontal = 2 -grow_vertical = 2 -script = ExtResource("1_n3lnl") -_add_button = NodePath("collection_card/v_box_container/h_box_container/add") -_remove_button = NodePath("collection_card/v_box_container/h_box_container/remove") -_open_directory_button = NodePath("collection_card/v_box_container/h_box_container/open_directory") -_available = NodePath("collection_card/v_box_container/h_box_container2/available") -_name = NodePath("collection_card/v_box_container/h_box_container2/name") -_version = NodePath("collection_card/v_box_container/version") - -[node name="collection_card" type="MarginContainer" parent="."] -layout_mode = 2 -theme_override_constants/margin_left = 16 -theme_override_constants/margin_top = 16 -theme_override_constants/margin_right = 16 -theme_override_constants/margin_bottom = 16 - -[node name="v_box_container" type="VBoxContainer" parent="collection_card"] -layout_mode = 2 -theme_override_constants/separation = 7 - -[node name="texture_rect" type="TextureRect" parent="collection_card/v_box_container"] -layout_mode = 2 -texture = ExtResource("2_gn4uh") -stretch_mode = 5 - -[node name="h_box_container2" type="HBoxContainer" parent="collection_card/v_box_container"] -layout_mode = 2 - -[node name="available" type="TextureRect" parent="collection_card/v_box_container/h_box_container2"] -layout_mode = 2 -stretch_mode = 5 - -[node name="name" type="Label" parent="collection_card/v_box_container/h_box_container2"] -layout_mode = 2 -size_flags_horizontal = 3 -text = "" - -[node name="version" type="Label" parent="collection_card/v_box_container"] -layout_mode = 2 -text = "" - -[node name="h_box_container" type="HBoxContainer" parent="collection_card/v_box_container"] -layout_mode = 2 -size_flags_horizontal = 4 - -[node name="add" type="Button" parent="collection_card/v_box_container/h_box_container"] -layout_mode = 2 - -[node name="remove" type="Button" parent="collection_card/v_box_container/h_box_container"] -layout_mode = 2 - -[node name="open_directory" type="Button" parent="collection_card/v_box_container/h_box_container"] -layout_mode = 2 diff --git a/addons/icon_explorer/internal/ui/options/options.gd b/addons/icon_explorer/internal/ui/options/options.gd index 52c8e5d..0847bf7 100644 --- a/addons/icon_explorer/internal/ui/options/options.gd +++ b/addons/icon_explorer/internal/ui/options/options.gd @@ -1,48 +1,102 @@ #@tool -extends VBoxContainer +extends Control const IconDatabase := preload("res://addons/icon_explorer/internal/scripts/icon_database.gd") const Collection := preload("res://addons/icon_explorer/internal/scripts/collection.gd") -const CollectionCard := preload("res://addons/icon_explorer/internal/ui/options/collection_card.gd") enum BUTTON_ID { INSTALL, REMOVE, - OPEN_DIR + OPEN_DIR, + WEB } @export var _collection_tree: Tree - +@export var _http_request: HTTPRequest var db: IconDatabase: set = set_db +var _progress_texture: AnimatedTexture +var _processing: Array[Collection.Id] = [] + func set_db(db_: IconDatabase) -> void: db = db_ - self._update() + for coll: Collection in self.db.collections(): + coll.install_finished.connect(self._on_processing_finished.bind(coll.id)) + coll.remove_finished.connect(self._on_processing_finished.bind(coll.id)) + self.update() + +func _init() -> void: + self._progress_texture = _gen_progress_texture() + func _ready() -> void: + self._collection_tree.columns = 6 + self._collection_tree.set_column_title(0, "Installed") self._collection_tree.set_column_title(1, "Name") self._collection_tree.set_column_title(2, "Version") + self._collection_tree.set_column_title(3, "License") + self._collection_tree.set_column_title(4, "Web") + self._collection_tree.set_column_title(5, "Actions") self._collection_tree.set_column_expand(0, false) self._collection_tree.set_column_expand(1, true) - self._collection_tree.set_column_expand(2, false) - self._collection_tree.set_column_expand(3, false) + self._collection_tree.set_column_expand(2, true) + self._collection_tree.set_column_expand(3, true) self._collection_tree.set_column_expand(4, false) self._collection_tree.set_column_expand(5, false) + self._collection_tree.button_clicked.connect(self._on_button_clicked) -func _update() -> void: +func update() -> void: self._collection_tree.clear() self._collection_tree.create_item() for coll: Collection in self.db.collections(): var item: TreeItem = self._collection_tree.create_item() item.set_text(1, coll.name) item.set_text(2, coll.version) + item.set_text(3, coll.license) item.set_text_alignment(0, HORIZONTAL_ALIGNMENT_CENTER) + item.set_text_alignment(4, HORIZONTAL_ALIGNMENT_CENTER) + item.add_button(4, self.get_theme_icon("ExternalLink", "EditorIcons"), BUTTON_ID.WEB, false, "Open in Browser") + var is_processed: bool = self._processing.has(coll.id) + if is_processed: + item.set_icon(0, self._progress_texture) + elif coll.is_installed(): + item.set_icon(0, self.get_theme_icon("StatusSuccess", "EditorIcons")) + else: + item.set_icon(0, self.get_theme_icon("Node", "EditorIcons")) + if coll.is_installed(): - item.set_icon(0, self.get_theme_icon("ImportCheck", "EditorIcons")) - item.add_button(3, self.get_theme_icon("AssetLib", "EditorIcons"), BUTTON_ID.INSTALL, false, "Update") + item.add_button(5, self.get_theme_icon("Reload", "EditorIcons"), BUTTON_ID.INSTALL, is_processed, "Update") else: - item.set_icon(0, self.get_theme_icon("ImportCheck", "EditorIcons")) - item.add_button(3, self.get_theme_icon("Add", "EditorIcons"), BUTTON_ID.INSTALL, false, "Install") - item.add_button(4, self.get_theme_icon("Remove", "EditorIcons"), BUTTON_ID.REMOVE, !coll.is_installed(), "Remove") - item.add_button(5, self.get_theme_icon("Filesystem", "EditorIcons"), BUTTON_ID.OPEN_DIR, !coll.is_installed(), "Show in File Explorer") + item.add_button(5, self.get_theme_icon("AssetLib", "EditorIcons"), BUTTON_ID.INSTALL, is_processed, "Install") + item.add_button(5, self.get_theme_icon("Remove", "EditorIcons"), BUTTON_ID.REMOVE, is_processed || !coll.is_installed(), "Remove") + item.add_button(5, self.get_theme_icon("Filesystem", "EditorIcons"), BUTTON_ID.OPEN_DIR, is_processed || !coll.is_installed(), "Show in File Explorer") + +func _gen_progress_texture() -> AnimatedTexture: + var anim: AnimatedTexture = AnimatedTexture.new() + anim.frames = 8 + for idx: int in range(8): + anim.set_frame_texture(idx, self.get_theme_icon("Progress"+str(idx + 1), "EditorIcons")) + anim.set_frame_duration(idx, 0.2) + return anim + +func _on_button_clicked(item: TreeItem, _column: int, id: int, _mouse_button_index: int) -> void: + var idx: int= item.get_index() + match id: + BUTTON_ID.INSTALL: + self._processing.append(self.db.collections()[idx].id) + self.update() + self.db.collections()[idx].install(self._http_request, "") + BUTTON_ID.REMOVE: + self.db.collections()[idx].remove() + self.update() + BUTTON_ID.OPEN_DIR: + OS.shell_show_in_file_manager(self.db.collections()[idx].icon_directory()) + BUTTON_ID.WEB: + OS.shell_open(self.db.collections()[idx].web) + +func _on_processing_finished(status: Error, id: Collection.Id) -> void: + print(id) + self._processing.erase(id) + print("cb") + self.update() diff --git a/addons/icon_explorer/internal/ui/options/options.tscn b/addons/icon_explorer/internal/ui/options/options.tscn index a1fdb0c..a9014eb 100644 --- a/addons/icon_explorer/internal/ui/options/options.tscn +++ b/addons/icon_explorer/internal/ui/options/options.tscn @@ -2,28 +2,57 @@ [ext_resource type="Script" path="res://addons/icon_explorer/internal/ui/options/options.gd" id="1_hdn86"] -[node name="options" type="VBoxContainer" node_paths=PackedStringArray("_collection_tree")] +[node name="control" type="Control" node_paths=PackedStringArray("_collection_tree", "_http_request")] +layout_mode = 3 anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 script = ExtResource("1_hdn86") -_collection_tree = NodePath("scroll_container/tree") +_collection_tree = NodePath("options/options/tree") +_http_request = NodePath("http_request") -[node name="label" type="Label" parent="."] -layout_mode = 2 -text = "Collections" +[node name="http_request" type="HTTPRequest" parent="."] +timeout = 20.0 + +[node name="options" type="ScrollContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 -[node name="scroll_container" type="ScrollContainer" parent="."] +[node name="options" type="VBoxContainer" parent="options"] layout_mode = 2 +size_flags_horizontal = 3 size_flags_vertical = 3 -[node name="tree" type="Tree" parent="scroll_container"] +[node name="save_title" type="Label" parent="options/options"] +visible = false +layout_mode = 2 +text = "Save file automatically to folder" + +[node name="panel_container2" type="PanelContainer" parent="options/options"] +visible = false +layout_mode = 2 + +[node name="grid_container" type="GridContainer" parent="options/options/panel_container2"] +layout_mode = 2 +columns = 2 + +[node name="panel_container" type="PanelContainer" parent="options/options"] +layout_mode = 2 + +[node name="collections_title" type="Label" parent="options/options/panel_container"] +layout_mode = 2 +text = "Collections" + +[node name="tree" type="Tree" parent="options/options"] layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 3 -columns = 6 column_titles_visible = true allow_search = false hide_folding = true