Refactored a lot of stuff.

Added property lists.
Renamed FileAdapter to FileSystemAdapter.
And more smaller stuff.
This commit is contained in:
Patrick 2021-08-18 22:03:39 +02:00
parent dc7dc48e9b
commit 18dd6d61fb
Signed by: mewin
GPG Key ID: CEDB412C39B5BC47
22 changed files with 954 additions and 36 deletions

149
images/folder_up.svg Normal file
View File

@ -0,0 +1,149 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="16"
height="16"
viewBox="0 0 4.2333333 4.2333335"
version="1.1"
id="svg8"
inkscape:version="1.1 (c4e8f9ed74, 2021-05-24)"
sodipodi:docname="folder_up.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs2">
<marker
style="overflow:visible;"
id="Arrow2Send"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Send"
inkscape:isstock="true">
<path
transform="scale(0.3) rotate(180) translate(-2.3,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;fill:context-stroke;stroke-width:0.62500000;stroke-linejoin:round;"
id="path1350" />
</marker>
<marker
style="overflow:visible;"
id="marker1919"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Lend"
inkscape:isstock="true">
<path
transform="scale(1.1) rotate(180) translate(1,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;fill:context-stroke;stroke-width:0.62500000;stroke-linejoin:round;"
id="path1917" />
</marker>
<marker
style="overflow:visible;"
id="Arrow2Lend"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Lend"
inkscape:isstock="true">
<path
transform="scale(1.1) rotate(180) translate(1,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;fill:context-stroke;stroke-width:0.62500000;stroke-linejoin:round;"
id="path1338" />
</marker>
<marker
style="overflow:visible;"
id="Arrow2Mend"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow2Mend"
inkscape:isstock="true">
<path
transform="scale(0.6) rotate(180) translate(0,0)"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
style="fill-rule:evenodd;fill:context-stroke;stroke-width:0.62500000;stroke-linejoin:round;"
id="path1344" />
</marker>
<marker
style="overflow:visible;"
id="Arrow1Send"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Send"
inkscape:isstock="true">
<path
transform="scale(0.2) rotate(180) translate(6,0)"
style="fill-rule:evenodd;fill:context-stroke;stroke:context-stroke;stroke-width:1.0pt;"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path1332" />
</marker>
<marker
style="overflow:visible;"
id="Arrow1Lend"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Lend"
inkscape:isstock="true">
<path
transform="scale(0.8) rotate(180) translate(12.5,0)"
style="fill-rule:evenodd;fill:context-stroke;stroke:context-stroke;stroke-width:1.0pt;"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path1320" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="45.254834"
inkscape:cx="7.1484076"
inkscape:cy="7.8776115"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1052"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:pagecheckerboard="true"
inkscape:snap-object-midpoints="false" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-292.76665)">
<path
style="fill:#f5fffc;fill-opacity:1;stroke:none;stroke-width:0.996038px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 0.38328226,296.66149 1.73338454,-3.55635 1.7333843,3.55635 z"
id="path3031"
sodipodi:nodetypes="cccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/folder_up.svg-097930bffb5edf2a0b4b16cb480291b4.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/de.mewin.gduibasics/images/folder_up.svg"
dest_files=[ "res://.import/folder_up.svg-097930bffb5edf2a0b4b16cb480291b4.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View File

@ -0,0 +1,44 @@
[gd_scene load_steps=4 format=2]
[ext_resource path="res://addons/de.mewin.gduibasics/scripts/types/misc/constraints/dynamic_grid_constraints.gd" type="Script" id=2]
[ext_resource path="res://addons/de.mewin.gduibasics/scenes/property_list/scripts/header.gd" type="Script" id=3]
[sub_resource type="StyleBoxFlat" id=1]
bg_color = Color( 0, 0, 0, 0.627451 )
corner_radius_top_left = 2
corner_radius_top_right = 2
corner_radius_bottom_right = 2
corner_radius_bottom_left = 2
[node name="header" type="PanelContainer"]
margin_right = 198.0
margin_bottom = 22.0
size_flags_horizontal = 3
custom_styles/panel = SubResource( 1 )
script = ExtResource( 3 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="header_info" type="HBoxContainer" parent="."]
margin_right = 198.0
margin_bottom = 22.0
alignment = 1
__meta__ = {
"_edit_use_anchors_": false
}
[node name="texture" type="TextureRect" parent="header_info"]
margin_left = 70.0
margin_right = 70.0
margin_bottom = 22.0
[node name="label" type="Label" parent="header_info"]
margin_left = 74.0
margin_right = 128.0
margin_bottom = 22.0
text = "Header"
[node name="constraints" type="Node" parent="."]
script = ExtResource( 2 )
colspan = 2

View File

@ -0,0 +1,21 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/de.mewin.gduibasics/scenes/property_list/scripts/property_label.gd" type="Script" id=1]
[node name="property_label" type="HBoxContainer"]
anchor_right = 1.0
anchor_bottom = 1.0
size_flags_horizontal = 3
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="texture" type="TextureRect" parent="."]
margin_bottom = 600.0
[node name="label" type="Label" parent="."]
margin_left = 4.0
margin_top = 289.0
margin_right = 12.0
margin_bottom = 311.0

View File

@ -0,0 +1,19 @@
extends Control
var label := "" setget _set_label, _get_label
var texture : Texture = null setget _set_texture, _get_texture
#####################
# setters & getters #
#####################
func _set_label(label_ : String) -> void:
$header_info/label.text = label_
func _get_label() -> String:
return $header_info/label.text
func _set_texture(texture_ : Texture) -> void:
$header_info/texture.texture = texture_
func _get_texture() -> Texture:
return $header_info/texture.texture

View File

@ -0,0 +1,19 @@
extends Control
var label := "" setget _set_label, _get_label
var texture : Texture = null setget _set_texture, _get_texture
#####################
# setters & getters #
#####################
func _set_label(label_ : String) -> void:
$label.text = label_
func _get_label() -> String:
return $label.text
func _set_texture(texture_ : Texture) -> void:
$texture.texture = texture_
func _get_texture() -> Texture:
return $texture.texture

View File

@ -39,6 +39,18 @@ static func new_item_sorted(tree : Tree, parent : TreeItem, key : String, meta_c
new_itm.set_metadata(meta_column, key)
return new_itm
static func find_tree_item_with_meta(root : TreeItem, value, column := 0) -> TreeItem:
if root == null:
return null
elif root.get_metadata(column) == value:
return root
else:
var itm := find_tree_item_with_meta(root.get_next(), value, column)
if itm != null:
return itm
itm = find_tree_item_with_meta(root.get_children(), value, column)
return itm
static func copy_size(target : Control, source : Control) -> void:
target.rect_min_size = source.rect_min_size
target.rect_size = source.rect_size

View File

@ -16,7 +16,7 @@ static func get_recent_places() -> Array:
return GDBSettings.get_value(GDBConstants.SETTING_RECENT_PLACES, [])
static func add_recent_place(place) -> void:
if place is UIB_FileAdapter.FileEntry:
if place is UIB_FilesystemAdapter.FileEntry:
add_recent_place(place._get_path())
return
@ -32,14 +32,14 @@ static func get_favourite_places() -> Array:
return GDBSettings.get_value(GDBConstants.SETTING_FAVOURITE_PLACES, [])
static func is_favourite_place(place) -> bool:
if place is UIB_FileAdapter.FileEntry:
if place is UIB_FilesystemAdapter.FileEntry:
return is_favourite_place(place._get_path())
assert(place is String)
return GDBSettings.array_has_value(GDBConstants.SETTING_FAVOURITE_PLACES, place)
static func add_favourite_place(place) -> void:
if place is UIB_FileAdapter.FileEntry:
if place is UIB_FilesystemAdapter.FileEntry:
add_favourite_place(place._get_path())
return
@ -52,7 +52,7 @@ static func add_favourite_place(place) -> void:
__get_state().emit_signal("favourite_places_changed")
static func remove_favourite_place(place) -> void:
if place is UIB_FileAdapter.FileEntry:
if place is UIB_FilesystemAdapter.FileEntry:
remove_favourite_place(place._get_path())
return

View File

@ -4,19 +4,51 @@ extends Container
class_name UIB_DynamicGridContainer
var __DEFAULT_CONSTRAINTS = UIB_DynamicGridConstraints.new()
const __META_CONSTRAINTS = "__uib_dynamic_grind_constraints__"
export(int, 1, 100) var columns := 1 setget _set_columns
#############
# overrides #
#############
func _notification(what):
if what == NOTIFICATION_SORT_CHILDREN:
__sort_children()
func __get_constraints(node : Node) -> UIB_DynamicGridConstraints:
################
# overridables #
################
func _get_constraints(node : Node) -> UIB_DynamicGridConstraints:
var constraints := get_existing_constraints(node)
return constraints if constraints else __DEFAULT_CONSTRAINTS
################
# public stuff #
################
static func get_existing_constraints(node : Node) -> UIB_DynamicGridConstraints:
if node.has_meta(__META_CONSTRAINTS):
return node.get_meta(__META_CONSTRAINTS).object
for child in node.get_children():
if child is UIB_DynamicGridConstraints:
return child
return __DEFAULT_CONSTRAINTS
return null
static func get_constraints(node : Node) -> UIB_DynamicGridConstraints:
var constraints := get_existing_constraints(node)
if constraints != null:
return constraints
if !node.has_meta(__META_CONSTRAINTS):
var wrapper := GDB_ReferenceWrapper.new()
wrapper.object = UIB_DynamicGridConstraints.new()
node.set_meta(__META_CONSTRAINTS, wrapper)
return node.get_meta(__META_CONSTRAINTS).object
#################
# private stuff #
#################
func __sort_children():
var column_widths := []
var column_expand := []
@ -32,7 +64,7 @@ func __sort_children():
for child in get_children():
if !child is Control || !child.visible:
continue
var constraints := __get_constraints(child)
var constraints := _get_constraints(child)
if col + constraints.colspan > columns:
col = 0
@ -67,7 +99,7 @@ func __sort_children():
var row_height := 0.0
col = 0
for child in row:
var constraints := __get_constraints(child)
var constraints := _get_constraints(child)
child.rect_position = pos
var width := 0.0
@ -88,7 +120,10 @@ func __sort_children():
pos.y += row_height
pos.x = 0.0
rect_min_size.y = pos.y
###########
# setters #
###########
func _set_columns(value : int):
if value != columns:
columns = value

View File

@ -0,0 +1,116 @@
extends Tree
class_name UIB_EntityTree
export(Array, String) var column_ids := [].duplicate()
export(Array, String) var column_titles := [].duplicate()
export(NodePath) var selected_entity_adapter := ""
onready var __selected_entity_adapter := get_node_or_null(selected_entity_adapter) as GDB_DataAdapter
#############
# overrides #
#############
func _ready():
create_item() # invisible root
hide_root = true
columns = column_ids.size()
select_mode = SELECT_ROW
set_column_titles_visible(true)
for col in range(min(columns, column_titles.size())):
set_column_title(col, column_titles[col])
connect("item_selected", self, "_on_item_selected")
if __selected_entity_adapter != null:
__selected_entity_adapter.connect("data_changed", self, "_on_selected_entity_adapter_data_changed")
################
# public stuff #
################
func add_entity(entity : Object) -> void:
if !GDB_Entity.is_valid_entity(entity):
printerr("UIB_EntityTree: attempted to add invalid entity")
return
var itm := create_item()
itm.set_metadata(0, entity)
var col := 0
for id in column_ids:
var prop : Object = entity.get_property_by_id(id)
if prop == null:
col += 1
continue
itm.set_text(col, GDB_Property.get_prop_value_as_string(prop))
col += 1
GDBUtility.try_connect(prop, "value_changed", self, "_on_property_value_changed", [entity, id])
func select_entity(entity : Object) -> void:
if entity == null:
return # TODO: unselect?
var itm := __item_from_entity(entity)
if itm == null:
return # TODO: unselect?
itm.select(0)
func get_selected_entity() -> Object:
var entities := get_selected_entities()
if !entities.empty():
return entities[0]
return null
func get_selected_entities() -> Array: # n/a yet
var entities := []
var itm := get_selected()
while itm != null:
var entity_ := __entity_from_item(itm)
if entity_ != null:
entities.append(entity_)
itm = get_next_selected(itm)
return entities
#################
# private stuff #
#################
func __entity_from_item(itm : TreeItem) -> Object:
return itm.get_metadata(0) as Object
func __item_from_entity(entity : Object) -> TreeItem:
return GDBUIUtility.find_tree_item_with_meta(get_root(), entity)
func __update_row(entity : Object, column := ""):
if column == "":
for col in column_ids:
if col != "":
__update_row(entity, col)
return
var itm := __item_from_entity(entity)
var col_idx := column_ids.find(column)
if itm == null || col_idx < 0:
return
var prop := entity.get_property_by_id(column) as Object
if prop == null:
return
itm.set_text(col_idx, GDB_Property.get_prop_value_as_string(prop))
############
# handlers #
############
func _on_item_selected() -> void:
if __selected_entity_adapter != null:
__selected_entity_adapter.data = get_selected_entity()
func _on_selected_entity_adapter_data_changed() -> void:
if __selected_entity_adapter.data != get_selected_entity():
select_entity(__selected_entity_adapter.data)
func _on_property_value_changed(entity : Object, property_id : String) -> void:
__update_row(entity, property_id)

View File

@ -46,7 +46,9 @@ class DetailsColumnType:
func _get_name() -> String:
return tr("Type")
func _get_value(entry) -> String:
if entry._is_folder():
if entry._is_link():
return tr("Link")
elif entry._is_folder():
return tr("Folder")
else:
return tr("File")
@ -82,7 +84,7 @@ class DetailsColumnModifiedTime:
return entry0._get_modified_time() < entry1._get_modified_time()
class __ParentFolderEntry:
extends UIB_FileAdapter.FileEntry
extends UIB_FilesystemAdapter.FileEntry
var real_entry
@ -99,11 +101,12 @@ const CHECKBOX_COLUMN_WIDTH = 25
export(ViewMode) var view_mode = ViewMode.DETAILS setget _set_view_mode
export(Checkable) var checkable = Checkable.NONE setget _set_checkable
export(NodePath) var folder_adapter := ""
export var allow_navigation := true
export var show_up_entry := true
var adapter : UIB_FileAdapter setget _set_adapter
var adapter : UIB_FilesystemAdapter setget _set_adapter
var filter : UIB_FileFilter setget _set_filter
var current_folder : UIB_FileAdapter.FileEntry setget _set_current_folder
var current_folder : UIB_FilesystemAdapter.FileEntry setget _set_current_folder
var details_columns := [
DetailsColumnName.new(),
DetailsColumnType.new(),
@ -113,13 +116,14 @@ var details_columns := [
var __special_columns := []
var __sort_column := 0
var __sort_reverse := false
onready var __folder_adapter := get_node_or_null(folder_adapter) as GDB_DataAdapter
func _ready():
hide_root = true
select_mode = Tree.SELECT_ROW
if adapter == null:
adapter = UIB_LocalFileAdapter.new()
adapter = UIB_LocalFilesystemAdapter.new()
if current_folder == null:
current_folder = adapter._get_root()
@ -129,6 +133,13 @@ func _ready():
connect("item_activated", self, "_on_item_activated")
connect("item_selected", self, "_on_item_selected")
connect("column_title_pressed", self, "_on_column_title_pressed")
if __folder_adapter != null:
__folder_adapter.connect("data_changed", self, "_on_folder_adapter_data_changed")
if __folder_adapter.data:
_set_current_folder(__folder_adapter.data)
else:
__folder_adapter.data = current_folder
#################
# private stuff #
@ -213,7 +224,7 @@ func _set_view_mode(value):
view_mode = value
__update_entries()
func _set_adapter(value : UIB_FileAdapter):
func _set_adapter(value : UIB_FilesystemAdapter):
if value != adapter:
adapter = value
__update_entries()
@ -223,11 +234,13 @@ func _set_filter(value : UIB_FileFilter):
filter = value
__update_entries()
func _set_current_folder(value : UIB_FileAdapter.FileEntry):
func _set_current_folder(value : UIB_FilesystemAdapter.FileEntry):
if value != current_folder:
current_folder = value
emit_signal("current_folder_changed")
__update_entries()
if __folder_adapter != null:
__folder_adapter.data = current_folder
func _set_checkable(value):
if value != checkable:
@ -272,6 +285,9 @@ func _on_column_title_pressed(idx : int):
__sort_reverse = false
__update_entries()
func _on_folder_adapter_data_changed() -> void:
_set_current_folder(__folder_adapter.data)
###########
# signals #
###########

View File

@ -0,0 +1,81 @@
extends ToolButton
class_name UIB_FolderDefaultButton
enum Type {
FOLDER_UP,
FAVOURITE
}
export(Type) var type := Type.FAVOURITE
export(NodePath) var folder_adapter := ""
export(Texture) var icon_active : Texture = null
var current_folder : UIB_FilesystemAdapter.FileEntry = null
onready var __folder_adapter := get_node_or_null(folder_adapter) as GDB_DataAdapter
onready var __icon_inactive = icon
#############
# overrides #
#############
func _ready() -> void:
if __folder_adapter == null:
printerr("This UIB_FolderDefaultButton is missing a folder_adapter, it will do nothing.")
disabled = true
return
if __folder_adapter.data:
__set_current_folder(__folder_adapter.data)
__update_disabled()
__folder_adapter.connect("data_changed", self, "_on_folder_adapter_data_changed")
GDBUX.connect_static("favourite_places_changed", self, "_on_favourite_places_changed")
func _pressed() -> void:
match type:
Type.FOLDER_UP:
__set_current_folder(current_folder._get_parent())
Type.FAVOURITE:
if GDBUX.is_favourite_place(current_folder):
GDBUX.remove_favourite_place(current_folder)
else:
GDBUX.add_favourite_place(current_folder)
#################
# private stuff #
#################
func __set_current_folder(value : UIB_FilesystemAdapter.FileEntry) -> void:
if value != current_folder:
current_folder = value
__folder_adapter.data = current_folder
__update_disabled()
__update_icon()
func __update_disabled() -> void:
if current_folder == null:
disabled = true
return
match type:
Type.FOLDER_UP:
disabled = (current_folder._get_parent() == null)
Type.FAVOURITE:
disabled = false
func __update_icon():
if type == Type.FAVOURITE:
if GDBUX.is_favourite_place(current_folder):
icon = icon_active
else:
icon = __icon_inactive
############
# handlers #
############
func _on_folder_adapter_data_changed() -> void:
__set_current_folder(__folder_adapter.data)
func _on_favourite_places_changed() -> void:
__update_icon()

View File

@ -2,9 +2,13 @@ extends LineEdit
class_name UIB_FolderEdit
export(NodePath) var folder_adapter := ""
var suggestion_popup := UIB_SuggestionPopup.new()
var adapter : UIB_FileAdapter
var current_folder : UIB_FileAdapter.FileEntry setget _set_current_folder
var adapter : UIB_FilesystemAdapter
var current_folder : UIB_FilesystemAdapter.FileEntry setget _set_current_folder
onready var __folder_adapter := get_node_or_null(folder_adapter) as GDB_DataAdapter
#############
# overrides #
@ -13,6 +17,16 @@ func _ready():
call_deferred("__setup")
connect("text_changed", self, "_on_text_changed")
connect("text_entered", self, "_on_text_entered")
if adapter == null:
adapter = UIB_LocalFilesystemAdapter.new()
if __folder_adapter:
__folder_adapter.connect("data_changed", self, "_on_folder_adapter_data_changed")
if __folder_adapter.data:
_set_current_folder(__folder_adapter.data)
else:
__folder_adapter.data = current_folder
#################
# private stuff #
@ -59,6 +73,8 @@ func _set_current_folder(value):
current_folder = value
text = current_folder._get_path()
emit_signal("current_folder_changed")
if __folder_adapter != null:
__folder_adapter.data = current_folder
############
# handlers #
@ -73,6 +89,9 @@ func _on_suggestion_accepted(suggestion):
__update_current_folder()
__update_suggestions()
func _on_folder_adapter_data_changed() -> void:
_set_current_folder(__folder_adapter.data)
###########
# signals #
###########

View File

@ -13,9 +13,9 @@ export(DefaultFolder) var default_folder = DefaultFolder.HOME
export(NodePath) var folder_up_action
export(NodePath) var folder_favourite_action
export var custom_default_folder := ""
var adapter : UIB_FileAdapter = UIB_LocalFileAdapter.new()
var adapter : UIB_FilesystemAdapter = UIB_LocalFilesystemAdapter.new()
var current_folder : UIB_FileAdapter.FileEntry setget set_current_folder
var current_folder : UIB_FilesystemAdapter.FileEntry setget set_current_folder
var __folder_up_action : UIB_SimpleAction
var __folder_favourite_action : UIB_SimpleAction
var __nodes := []

View File

@ -18,17 +18,16 @@ class __DefaultItem:
icon = icon_
label = label_
var __DEFAULT_ITEMS := [
__DefaultItem.new(GDBFsUtil.get_home_folder(), preload("res://addons/de.mewin.gduibasics/images/home32.svg"), tr("Home"))
]
export(Mode) var mode = Mode.DEFAULT setget _set_mode
export(Array, String) var places := [] setget _set_places
export(Array, Texture) var icons := []
export(Array, String) var names := []
export(NodePath) var folder_adapter := ""
var adapter : UIB_FileAdapter
var current_folder : UIB_FileAdapter.FileEntry setget _set_current_folder
var adapter : UIB_FilesystemAdapter
var current_folder : UIB_FilesystemAdapter.FileEntry setget _set_current_folder
onready var __folder_adapter := get_node_or_null(folder_adapter) as GDB_DataAdapter
#############
# overrides #
@ -36,6 +35,16 @@ var current_folder : UIB_FileAdapter.FileEntry setget _set_current_folder
func _ready():
call_deferred("__update_items")
if adapter == null:
adapter = UIB_LocalFilesystemAdapter.new()
if __folder_adapter:
__folder_adapter.connect("data_changed", self, "_on_folder_adapter_data_changed")
if __folder_adapter.data:
_set_current_folder(__folder_adapter.data)
else:
__folder_adapter.data = current_folder
connect("item_activated", self, "_on_item_activated")
GDBUX.connect_static("favourite_places_changed", self, "_on_favourite_places_changed")
@ -44,8 +53,6 @@ func _ready():
#################
func __update_items():
clear()
if !adapter:
return
match mode:
Mode.DEFAULT:
@ -54,7 +61,7 @@ func __update_items():
__add_custom_places()
func __add_default_places():
for default_place in __DEFAULT_ITEMS:
for default_place in __get_default_places():
var folder := adapter._get_file(default_place.place)
if !folder || !folder._is_folder():
continue
@ -75,7 +82,7 @@ func __add_custom_places():
var icon : Texture = icons[i] if i < icons.size() else null
__add_place(folder, icon, label)
func __add_place(folder : UIB_FileAdapter.FileEntry, icon : Texture, label := ""):
func __add_place(folder : UIB_FilesystemAdapter.FileEntry, icon : Texture, label := ""):
if !icon:
icon = preload("res://addons/de.mewin.gduibasics/images/folder32.svg")
if !label:
@ -89,6 +96,14 @@ func __select_current_folder():
if get_item_metadata(i)._get_path() == current_folder._get_path():
select(i)
func __get_default_places() -> Array:
var places := [
__DefaultItem.new(GDBFsUtil.get_home_folder(), preload("res://addons/de.mewin.gduibasics/images/home32.svg"), tr("Home"))
]
for special_folder in GDBFsUtil.get_special_folders():
places.append(__DefaultItem.new(special_folder.path, preload("res://addons/de.mewin.gduibasics/images/folder32.svg"), special_folder.name))
return places
###########
# setters #
###########
@ -106,6 +121,8 @@ func _set_current_folder(value):
if value != current_folder:
current_folder = value
emit_signal("current_folder_changed")
if __folder_adapter:
__folder_adapter.data = current_folder
############
# handlers #
@ -116,6 +133,10 @@ func _on_item_activated(idx):
func _on_favourite_places_changed():
if mode == Mode.DEFAULT:
__update_items()
func _on_folder_adapter_data_changed() -> void:
_set_current_folder(__folder_adapter.data)
###########
# signals #
###########

View File

@ -0,0 +1,51 @@
extends CheckBox
class_name UIB_PropertyCheckBox
var property : Object = null setget _set_property
#############
# overrides #
#############
func _pressed() -> void:
if property == null:
return
property.set_value(pressed)
#################
# private stuff #
#################
func __init_property() -> void:
text = __text_from_property()
pressed = property.get_value() if property != null else false
disabled = (property == null)
if property != null:
GDBUtility.try_connect(property, "value_changed", self, "_on_property_value_changed")
func __text_from_property() -> String:
if property == null:
return ""
return property.get_name()
###########
# setters #
###########
func _set_property(property_ : Object) -> void:
if property_ != null && (!GDB_Property.is_valid_property(property_) || property_.get_type() != TYPE_BOOL):
printerr("Attempting to set invalid property in UIB_PropertyCheckBox.")
return
if property_ != property:
if property:
GDBUtility.disconnect_all(property, self)
property = property_
__init_property()
############
# handlers #
############
func _on_property_value_changed() -> void:
var value = property.get_value()
if value != pressed:
pressed = value

View File

@ -0,0 +1,169 @@
extends UIB_DynamicGridContainer
class_name UIB_PropertyList
export(NodePath) var entity_adapter := ""
var entity : Object = null setget _set_entity
var _properties := [].duplicate()
var __controls_per_property := [].duplicate()
onready var __entity_adapter := get_node_or_null(entity_adapter) as GDB_DataAdapter
#############
# overrides #
#############
func _ready() -> void:
self.columns = 2
if __entity_adapter != null:
__entity_adapter.connect("data_changed", self, "_on_entity_adapter_data_changed")
################
# overridables #
################
func _make_controls(property : Object) -> Array:
match property.get_type():
GDB_Property.TYPE_HEADER:
return _make_header(property)
TYPE_INT, TYPE_REAL, TYPE_STRING:
return _make_controls_simple(property)
TYPE_BOOL:
return _make_controls_bool(property)
_:
return []
func _make_header(property : Object) -> Array:
assert(property.get_type() == GDB_Property.TYPE_HEADER)
var header := preload("res://addons/de.mewin.gduibasics/scenes/property_list/header.tscn").instance()
header.label = property.get_name()
header.texture = GDB_Property.get_prop_icon(property)
get_constraints(header).colspan = self.columns
return [header]
func _make_controls_simple(property : Object) -> Array:
var label := preload("res://addons/de.mewin.gduibasics/scenes/property_list/property_label.tscn").instance()
label.label = property.get_name()
label.texture = GDB_Property.get_prop_icon(property)
var edit := UIB_SimplePropertyEdit.new()
edit.property = property
edit.size_flags_horizontal |= SIZE_EXPAND
return [
label, edit
]
func _make_controls_bool(property : Object) -> Array:
var checkbox := UIB_PropertyCheckBox.new()
checkbox.property = property
checkbox.size_flags_horizontal |= SIZE_EXPAND
get_constraints(checkbox).colspan = self.columns
return [
checkbox
]
################
# public stuff #
################
func add_property(property : Object, insert_before := -1) -> void: # no type to allow ducktyping
if find_property(property) >= 0:
return
if !GDB_Property.is_valid_property(property):
printerr("Attempting to add invalid property object to property list: ", property)
return
var control_insert_index := -1
var insert_index : int
if insert_before < 0:
insert_index = _properties.size()
else:
insert_index = min(insert_index, _properties.size())
control_insert_index = __find_control_index_before(insert_index)
_properties.insert(insert_index, property)
# create controls
var controls := _make_controls(property)
__controls_per_property.insert(insert_index, controls)
for control in controls:
add_child(control)
if control_insert_index >= 0:
for control in controls:
move_child(control, control_insert_index)
control_insert_index += 1
emit_signal("property_added", insert_index)
func remove_property(property : Object) -> bool:
var index := find_property(property)
if index < 0:
return false
# remove actual property
GDBUtility.disconnect_all(property, self)
_properties.remove(index)
# remove controls
for control in __controls_per_property[index]:
control.queue_free()
__controls_per_property.remove(index)
emit_signal("property_removed", property)
return true
func find_property(property : Object) -> int:
return _properties.find(property)
func clear_properties() -> void:
_properties.clear()
__controls_per_property.clear()
for child in get_children():
child.queue_free()
#################
# private stuff #
#################
func __find_control_index_before(index : int) -> int:
if index >= __controls_per_property.size():
return -1
var controls : Array = __controls_per_property[index]
if controls.empty():
return __find_control_index_before(index + 1)
return controls[0].get_position_in_parent()
func __init_entity() -> void:
clear_properties()
if entity == null:
return
for property in entity.get_properties():
add_property(property)
###########
# setters #
###########
func _set_entity(entity_ : Object) -> void:
if entity_ != null && !GDB_Entity.is_valid_entity(entity_):
printerr("Attempting to set invalid entity in UIB_PropertyList.")
return
if entity_ != entity:
entity = entity_
if __entity_adapter != null:
__entity_adapter.data = entity
__init_entity()
############
# handlers #
############
func _on_entity_adapter_data_changed() -> void:
_set_entity(__entity_adapter.data)
###########
# signals #
###########
signal property_added(index)
signal property_removed(index)

View File

@ -6,6 +6,7 @@ class_name UIB_RecentPlacesList
# overrides #
#############
func _ready():
mode = Mode.CUSTOM
places = GDBSettings.get_value(GDBConstants.SETTING_RECENT_PLACES, [])
GDBSettings.connect_static("setting_changed", self, "_on_setting_changed")

View File

@ -0,0 +1,102 @@
extends LineEdit
class_name UIB_SimplePropertyEdit
var property : Object = null setget _set_property
var __caret_pos := 0
var __last_valid_text := ""
#############
# overrides #
#############
func _ready() -> void:
connect("text_changed", self, "_on_text_changed")
func _gui_input(event : InputEvent) -> void:
__caret_pos = caret_position
#################
# private stuff #
#################
func __init_property() -> void:
text = __text_from_property()
editable = (property != null)
__validate_text()
if property != null:
GDBUtility.try_connect(property, "value_changed", self, "_on_property_value_changed")
func __text_from_property() -> String:
if property == null:
return ""
match property.get_type():
TYPE_INT, TYPE_REAL:
return str(property.get_value())
TYPE_STRING:
return property.get_value()
_:
printerr("UIB_SimplePropertyEdit: unsupported property type: %s" % GDBUtility.type_name(property.get_type()))
return ""
func __text_to_property() -> bool:
if property == null:
return false
var value
match property.get_type():
TYPE_INT:
value = int(text)
TYPE_REAL:
value = float(text)
TYPE_STRING:
value = text
_:
printerr("UIB_SimplePropertyEdit: unsupported property type: %s" % GDBUtility.type_name(property.get_type()))
return false
if !GDB_Property.is_prop_value_valid(property, value):
return false
property.set_value(value)
return true
func __is_text_valid() -> bool:
if property == null:
return false
match property.get_type():
TYPE_INT:
return text == "" || text.is_valid_integer()
TYPE_REAL:
return text == "" || text.is_valid_float()
return true
func __validate_text() -> void:
if !__is_text_valid() || !__text_to_property():
# var old_caret := caret_position
text = __last_valid_text
caret_position = __caret_pos
else:
__last_valid_text = text
###########
# setters #
###########
func _set_property(property_ : Object) -> void:
if property_ != null && !GDB_Property.is_valid_property(property_):
printerr("Attempting to set invalid property in UIB_SimplePropertyEdit.")
return
if property_ != property:
if property:
GDBUtility.disconnect_all(property, self)
property = property_
__init_property()
############
# handlers #
############
func _on_text_changed(new_text : String) -> void:
__validate_text()
func _on_property_value_changed() -> void:
var new_text := __text_from_property()
if new_text != text:
text = new_text

View File

@ -1,6 +1,6 @@
extends Reference
class_name UIB_FileAdapter
class_name UIB_FilesystemAdapter
class FileEntry:
func _is_folder() -> bool:

View File

@ -1,11 +1,11 @@
extends UIB_FileAdapter
extends UIB_FilesystemAdapter
class_name UIB_LocalFileAdapter
class_name UIB_LocalFilesystemAdapter
var __dir = Directory.new()
class LocalFileEntry:
extends UIB_FileAdapter.FileEntry
extends UIB_FilesystemAdapter.FileEntry
var path : String
var is_link : bool
@ -30,6 +30,7 @@ class LocalFileEntry:
if !is_folder:
return []
var dir := Directory.new()
var file := File.new()
if dir.open(path + "/") != OK:
return []
if dir.list_dir_begin(true) != OK:
@ -59,7 +60,7 @@ class LocalFileEntry:
modified_time = __calc_modified_time()
return modified_time
func _get_parent() -> UIB_FileAdapter.FileEntry:
func _get_parent() -> UIB_FilesystemAdapter.FileEntry:
var parent_path := path.get_base_dir()
if parent_path && parent_path != path:
return LocalFileEntry.new(parent_path, false, true)
@ -97,7 +98,7 @@ func _get_file(path : String) -> FileEntry:
else:
return null
func _get_root() -> UIB_FileAdapter.FileEntry:
func _get_root() -> UIB_FilesystemAdapter.FileEntry:
return _get_file("/")
func _get_drives() -> Array:

View File

@ -0,0 +1,8 @@
[gd_resource type="StyleBoxFlat" format=2]
[resource]
bg_color = Color( 0, 0, 0, 0.627451 )
corner_radius_top_left = 2
corner_radius_top_right = 2
corner_radius_bottom_right = 2
corner_radius_bottom_left = 2