diff --git a/Scenes/file_dialog.tscn b/Scenes/file_dialog.tscn index 5ed5673..565699a 100644 --- a/Scenes/file_dialog.tscn +++ b/Scenes/file_dialog.tscn @@ -24,4 +24,5 @@ offset_bottom = 603.0 grow_horizontal = 2 grow_vertical = 0 theme = ExtResource("1_w7vsw") +bbcode_enabled = true autowrap_mode = 0 diff --git a/Scripts/file_dialog.gd b/Scripts/file_dialog.gd index f927fe1..8576660 100644 --- a/Scripts/file_dialog.gd +++ b/Scripts/file_dialog.gd @@ -8,14 +8,25 @@ extends RichTextLabel var selected_index: int = 0 var dir: DirAccess var dirs: Array[String] +var bbcode_dirs: Array[String] +var shortened_dirs: Array[String] var files: Array[String] +var query: String = "" +var search_limit: int = 1000 +var current_dirs_count: int = 0 +var handled: bool +var erased: bool +var max_coincidence: Array = [] +var coincidence: Array = [] + var zoom: Vector2; var active: bool = false; signal ui_close func change_dir(path) -> void: + query = "" if !dir: dir = DirAccess.open(path) #dir.include_hidden = true # WARNING: this will heavily affect performance if de-commented @@ -23,8 +34,19 @@ func change_dir(path) -> void: dirs = [".."]; dirs.append_array(dir.get_directories()) dirs.append_array(dir.get_files()) + + shortened_dirs = [] + for dir_ in dirs: + if len(dir_) > 30: + dir_ = dir_.left(30) + "..." + dir_.right(3) + shortened_dirs.append(dir_) + + bbcode_dirs = [] + bbcode_dirs.append_array(dirs) - files.append_array(dir.get_files()); + current_dirs_count = len(dirs) + + files.append_array(dir.get_files()) zoom = %Cam.to_zoom(code.get_longest_line(dirs).length()) @@ -42,15 +64,44 @@ func _input(event: InputEvent) -> void: if !(event is InputEventKey): return var key_event = event as InputEventKey + bbcode_dirs = [] + bbcode_dirs.append_array(dirs) if !(key_event.is_pressed()): return; + handled = true if key_event.keycode == KEY_UP: selected_index = max(0, selected_index - 1) elif key_event.keycode == KEY_DOWN: - selected_index = min(dirs.size() - 1, selected_index + 1) + selected_index = min(len(dirs) - 1, selected_index + 1) elif key_event.keycode == KEY_ENTER: handle_enter_key() + else: + handled = false + + erased = false + if current_dirs_count <= search_limit and !handled: + if key_event.keycode == KEY_BACKSPACE: + erased = true + if len(query) > 0: + query = query.substr(0, len(query) - 1) + elif key_event.as_text() == 'Alt+R': + erased = true + query = "" + if len(key_event.as_text()) == 1: + query += key_event.as_text().to_lower() + elif key_event.keycode == KEY_PERIOD: + query += "." + + max_coincidence = [] + + if len(query) > 0: + for i in range(1, len(dirs)): + coincidence = fuzzy_search(shortened_dirs[i].to_lower(), query) + bbcode_dirs[i] = make_bold(shortened_dirs[i], coincidence) + if is_closer(max_coincidence, coincidence): + max_coincidence = coincidence + if not handled: selected_index = i update_ui() @@ -59,16 +110,18 @@ func update_ui() -> void: show_items() func show_items() -> void: - for i in range(dirs.size()): - show_item(dirs[i]) + for i in range(len(bbcode_dirs)): + show_item(i) -func show_item(item: String) -> void: +func show_item(index: int) -> void: + var item = dirs[index] + var bbcode_item = bbcode_dirs[index] if is_selected(item): push_bgcolor(LuaSingleton.gui.selection_color) else: push_bgcolor(Color(0, 0, 0, 0)) # Reset background color if not selected - var is_dir = dir.get_directories().find(item) != -1; + var is_dir = dir.get_directories().find(item) != -1 if item == "..": push_color(LuaSingleton.gui.font_color) @@ -85,19 +138,17 @@ func show_item(item: String) -> void: pop() - var filename = item.split(".")[0]; + var filename = bbcode_item.split(".")[0] - if is_dir: filename = item + if is_dir: filename = bbcode_item - if filename.length() > 30: - filename = filename.left(30) + "..." + filename.right(3) - if item == "..": - add_text(" %s\n" % [ item ]) + if bbcode_item == "..": + append_text(" %s\n" % [ bbcode_item ]) elif is_dir or !item.contains("."): - add_text(" %s\n" % [ filename ] ) + append_text(" %s\n" % [ filename ]) else: - add_text(" %s.%s\n" % [ filename, item.split(".")[1] ] ) + append_text(" %s.%s\n" % [ filename, bbcode_item.split(".")[1] ]) if active: %Cam.focus_on(Vector2(gp().x, global_position.y + (selected_index * 23)), zoom) @@ -111,7 +162,7 @@ func is_selected(item: String) -> bool: return (is_dir_item and is_dir_current) func handle_enter_key() -> void: - if selected_index > dirs.size(): return + if selected_index > len(dirs): return # ^^ this happens when the cursor was at, i.e., pos. 6, but arr is only has 4 entries var item = dirs[selected_index]; @@ -136,6 +187,43 @@ func handle_enter_key() -> void: change_dir(item) update_ui() +func make_bold(string: String, indexes: Array) -> String: + var new_string: String = "" + + for i in range(len(string)): + if i in indexes: new_string += "[b]" + string[i] + "[/b]" + else: new_string += string[i] + + return new_string + +func fuzzy_search(string: String, substring: String) -> Array: + if len(string) < len(substring): return [] + + var indexes: Array = [] + var pos: int = -1 + + for letter in substring: + while pos < len(substring) - 1: + pos += 1 + if string[pos] == letter: + indexes.append(pos) + break + + return indexes if len(indexes) == len(query) else [] + +# Compares 2 fuzzy Arrays and returns if 'new' Array is closer to query than 'old' +func is_closer(old: Array, new: Array) -> bool: + if len(old) == 0: return true + if len(new) == 0: return false + + if old == new: return false + + for i in range(len(old)): + if old[i] > new[i]: return true + elif old[i] < new[i]: return false + + return false + # global_position is slightly off, so we customize it a little. func gp() -> Vector2: var vec = global_position;