Skip to content

Commit

Permalink
Improve the fallback file dialog (#641)
Browse files Browse the repository at this point in the history
  • Loading branch information
MewPurPur authored Apr 8, 2024
1 parent a30236f commit 9f8dd1f
Show file tree
Hide file tree
Showing 41 changed files with 1,161 additions and 124 deletions.
11 changes: 7 additions & 4 deletions src/GlobalSettings.gd
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const default_config = {
"invert_zoom": false,
"wrap_mouse": false,
"use_ctrl_for_zoom": true,
"use_native_file_dialog": true,
},
}

Expand All @@ -73,10 +74,6 @@ var language: String:

var palettes: Array[ColorPalette] = []

# Input
var invert_zoom := false
var wrap_mouse := false
var use_ctrl_for_zoom := true

# Autoformat
var general_number_precision := 3
Expand Down Expand Up @@ -118,6 +115,12 @@ var basic_color_valid := Color("9f9")
var basic_color_error := Color("f99")
var basic_color_warning := Color("ff9")

# Other
var invert_zoom := false
var wrap_mouse := false
var use_ctrl_for_zoom := true
var use_native_file_dialog := true


func toggle_bool_setting(section: String, setting: String) -> void:
set(setting, !get(setting))
Expand Down
2 changes: 1 addition & 1 deletion src/HandlerGUI.gd
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ func add_overlay(overlay_menu: Node) -> void:
overlay_ref = OverlayRect.new()
get_tree().get_root().add_child(overlay_ref)
overlay_ref.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
overlay_ref.add_child(overlay_menu)
if overlay_menu is Control:
overlay_menu.set_anchors_and_offsets_preset(Control.PRESET_CENTER)
overlay_ref.add_child(overlay_menu)
overlay_menu.tree_exiting.connect(remove_overlay)
has_overlay = true
get_tree().paused = true
Expand Down
52 changes: 44 additions & 8 deletions src/SVG.gd
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
## The SVG text, and the native [TagSVG] representation.
extends Node

const GoodFileDialogType = preload("res://src/ui_parts/good_file_dialog.gd")

const AlertDialog := preload("res://src/ui_parts/alert_dialog.tscn")
const ImportWarningDialog = preload("res://src/ui_parts/import_warning_dialog.tscn")
const SVGFileDialog = preload("res://src/ui_parts/svg_file_dialog.tscn")
const GoodFileDialog = preload("res://src/ui_parts/good_file_dialog.tscn")
const ExportDialog = preload("res://src/ui_parts/export_dialog.tscn")

const default = '<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg"></svg>'
Expand Down Expand Up @@ -78,16 +80,22 @@ func _on_undo_redo() -> void:
func refresh() -> void:
SVG.root_tag.replace_self(SVG.root_tag.create_duplicate())


func is_native_preferred() -> bool:
return DisplayServer.has_feature(DisplayServer.FEATURE_NATIVE_DIALOG) and\
GlobalSettings.use_native_file_dialog

func open_import_dialog() -> void:
# Open it inside a native file dialog, or our custom one if it's not available.
if DisplayServer.has_feature(DisplayServer.FEATURE_NATIVE_DIALOG):
if is_native_preferred():
DisplayServer.file_dialog_show("Import a .svg file", Utils.get_last_dir(), "", false,
DisplayServer.FILE_DIALOG_MODE_OPEN_FILE, ["*.svg"], native_file_import)
elif OS.has_feature("web"):
HandlerGUI.web_load_svg()
else:
var svg_import_dialog := SVGFileDialog.instantiate()
svg_import_dialog.current_dir = Utils.get_last_dir()
var svg_import_dialog := GoodFileDialog.instantiate()
svg_import_dialog.setup(Utils.get_last_dir(), "",
GoodFileDialogType.FileMode.SELECT, "svg")
HandlerGUI.add_overlay(svg_import_dialog)
svg_import_dialog.file_selected.connect(apply_svg_from_path)

Expand All @@ -103,7 +111,7 @@ func open_export_dialog() -> void:
func open_save_dialog(extension: String, native_callable: Callable,
non_native_callable: Callable) -> void:
# Open it inside a native file dialog, or our custom one if it's not available.
if DisplayServer.has_feature(DisplayServer.FEATURE_NATIVE_DIALOG):
if is_native_preferred():
DisplayServer.file_dialog_show("Save the .%s file" % extension,
Utils.get_last_dir(),
Utils.get_file_name(GlobalSettings.save_data.current_file_path) + "." + extension,
Expand All @@ -112,9 +120,10 @@ non_native_callable: Callable) -> void:
elif OS.has_feature("web"):
HandlerGUI.web_save_svg()
else:
var svg_export_dialog := SVGFileDialog.instantiate()
svg_export_dialog.current_dir = Utils.get_last_dir()
svg_export_dialog.file_mode = FileDialog.FILE_MODE_SAVE_FILE
var svg_export_dialog := GoodFileDialog.instantiate()
svg_export_dialog.setup(Utils.get_last_dir(),
Utils.get_file_name(GlobalSettings.save_data.current_file_path),
GoodFileDialogType.FileMode.SAVE, extension)
HandlerGUI.add_overlay(svg_export_dialog)
svg_export_dialog.file_selected.connect(non_native_callable)

Expand Down Expand Up @@ -155,10 +164,37 @@ func apply_svg_from_path(path: String) -> int:
HandlerGUI.add_overlay(warning_panel)
return OK

func generate_image_from_tags(upscale_amount := 1.0) -> Image:
var export_svg := SVG.root_tag.create_duplicate()
if export_svg.attributes.viewBox.get_list().is_empty():
export_svg.attributes.viewBox.set_list([0, 0, export_svg.width, export_svg.height])
export_svg.attributes.width.set_num(export_svg.width * upscale_amount)
export_svg.attributes.height.set_num(export_svg.height * upscale_amount)
var img := Image.new()
img.load_svg_from_string(SVGParser.svg_to_text(export_svg))
img.fix_alpha_edges() # See godot issue 82579.
return img


func finish_import(svg_text: String, file_path: String) -> void:
GlobalSettings.modify_save_data("current_file_path", file_path)
apply_svg_text(svg_text)

func finish_export(file_path: String, extension: String, upscale_amount := 1.0) -> void:
if file_path.get_extension().is_empty():
file_path += "." + extension

GlobalSettings.modify_save_data("last_used_dir", file_path.get_base_dir())

match extension:
"png":
generate_image_from_tags(upscale_amount).save_png(file_path)
_:
# SVG / fallback.
GlobalSettings.modify_save_data("current_file_path", file_path)
save_svg_to_file(file_path)
HandlerGUI.remove_overlay()


func save_svg_to_file(path: String) -> void:
var FA := FileAccess.open(path, FileAccess.WRITE)
Expand Down
37 changes: 30 additions & 7 deletions src/ThemeGenerator.gd
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ static func generate_theme() -> void:
setup_button(theme)
setup_checkbox(theme)
setup_checkbutton(theme)
setup_filedialog(theme)
setup_itemlist(theme)
setup_lineedit(theme)
setup_scrollbar(theme)
setup_separator(theme)
Expand Down Expand Up @@ -132,7 +132,7 @@ static func setup_panelcontainer(theme: Theme) -> void:
overlay_stylebox.set_border_width_all(2)
overlay_stylebox.content_margin_left = 8.0
overlay_stylebox.content_margin_right = 10.0
overlay_stylebox.content_margin_top = 8.0
overlay_stylebox.content_margin_top = 6.0
overlay_stylebox.content_margin_bottom = 10.0
overlay_stylebox.bg_color = overlay_panel_inner_color
overlay_stylebox.border_color = overlay_panel_border_color
Expand Down Expand Up @@ -511,11 +511,34 @@ static func setup_checkbutton(theme: Theme) -> void:
theme.set_icon("checked", "CheckButton", icon("GuiToggleChecked"))
theme.set_icon("unchecked", "CheckButton", icon("GuiToggleUnchecked"))

static func setup_filedialog(theme: Theme) -> void:
theme.add_type("FileDialog")
theme.set_icon("parent_folder", "CheckButton", icon("FolderUp"))
theme.set_icon("reload", "CheckButton", icon("../Reload"))
theme.set_icon("toggle_hidden", "CheckButton", icon("../Visuals"))
static func setup_itemlist(theme: Theme) -> void:
theme.add_type("ItemList")
theme.set_color("font_color", "ItemList", Color(0.9, 0.9, 0.9))
theme.set_color("font_hovered", "ItemList", Color.WHITE)
theme.set_color("font_selected", "ItemList", Color.WHITE)
theme.set_color("guide_color", "ItemList", Color.TRANSPARENT)
#theme.set_constant("v_separation", "ItemList", 0)
theme.set_constant("icon_margin", "ItemList", 4)

var empty_stylebox := StyleBoxEmpty.new()
empty_stylebox.set_content_margin_all(1)
theme.set_stylebox("panel", "ItemList", empty_stylebox)
theme.set_stylebox("focus", "ItemList", empty_stylebox)
theme.set_stylebox("cursor", "ItemList", empty_stylebox)
theme.set_stylebox("cursor_unfocused", "ItemList", empty_stylebox)

var item_stylebox := StyleBoxFlat.new()
item_stylebox.set_corner_radius_all(3)
item_stylebox.set_content_margin_all(2)

var hover_item_stylebox := item_stylebox.duplicate()
hover_item_stylebox.bg_color = flat_button_color_hover
theme.set_stylebox("hovered", "ItemList", hover_item_stylebox)

var selected_item_stylebox := item_stylebox.duplicate()
selected_item_stylebox.bg_color = flat_button_color_pressed
theme.set_stylebox("selected", "ItemList", selected_item_stylebox)
theme.set_stylebox("selected_focus", "ItemList", selected_item_stylebox)

static func setup_lineedit(theme: Theme) -> void:
theme.add_type("LineEdit")
Expand Down
1 change: 1 addition & 0 deletions src/data_classes/SaveData.gd
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const GoodColorPicker = preload("res://src/ui_elements/good_color_picker.gd")
@export var color_picker_slider_mode := GoodColorPicker.SliderMode.RGB
@export var path_command_relative := false
@export var last_used_dir := ""
@export var file_dialog_show_hidden := false

signal current_file_path_changed
@export var current_file_path := "":
Expand Down
20 changes: 7 additions & 13 deletions src/ui_parts/alert_dialog.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -15,40 +15,34 @@ offset_right = 2.0
offset_bottom = 2.0
grow_horizontal = 2
grow_vertical = 2
theme_type_variation = &"OverlayPanel"
script = ExtResource("1_qntyo")

[node name="MarginContainer" type="MarginContainer" parent="."]
layout_mode = 2
theme_override_constants/margin_left = 8
theme_override_constants/margin_top = 6
theme_override_constants/margin_right = 8
theme_override_constants/margin_bottom = 8

[node name="MainContainer" type="VBoxContainer" parent="MarginContainer"]
[node name="MainContainer" type="VBoxContainer" parent="."]
unique_name_in_owner = true
layout_mode = 2
theme_override_constants/separation = 10

[node name="TextContainer" type="VBoxContainer" parent="MarginContainer/MainContainer"]
[node name="TextContainer" type="VBoxContainer" parent="MainContainer"]
layout_mode = 2

[node name="Title" type="Label" parent="MarginContainer/MainContainer/TextContainer"]
[node name="Title" type="Label" parent="MainContainer/TextContainer"]
layout_mode = 2
theme_override_fonts/font = ExtResource("1_3yrpq")
theme_override_font_sizes/font_size = 16
text = "Alert!"
horizontal_alignment = 1

[node name="Label" type="RichTextLabel" parent="MarginContainer/MainContainer/TextContainer"]
[node name="Label" type="RichTextLabel" parent="MainContainer/TextContainer"]
custom_minimum_size = Vector2(180, 0)
layout_mode = 2
theme_override_font_sizes/normal_font_size = 12
fit_content = true

[node name="OKButton" type="Button" parent="MarginContainer/MainContainer"]
[node name="OKButton" type="Button" parent="MainContainer"]
layout_mode = 2
size_flags_horizontal = 4
mouse_default_cursor_shape = 2
text = "OK"

[connection signal="pressed" from="MarginContainer/MainContainer/OKButton" to="." method="_on_ok_button_pressed"]
[connection signal="pressed" from="MainContainer/OKButton" to="." method="_on_ok_button_pressed"]
33 changes: 3 additions & 30 deletions src/ui_parts/export_dialog.gd
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
extends PanelContainer

const NumberEditType = preload("res://src/ui_elements/number_edit.gd")
const SVGFileDialog = preload("res://src/ui_parts/svg_file_dialog.tscn")

var upscale_amount := -1.0
var extension := ""
Expand Down Expand Up @@ -52,32 +51,17 @@ func _on_dropdown_value_changed(new_value: String) -> void:
func native_file_export(has_selected: bool, files: PackedStringArray,
_filter_idx: int) -> void:
if has_selected:
export(files[0])
SVG.finish_export(files[0], extension, upscale_amount)

func _on_ok_button_pressed() -> void:
if OS.has_feature("web"):
match extension:
"png":
HandlerGUI.web_save_png(create_image())
HandlerGUI.web_save_png(SVG.generate_image_from_tags())
_:
HandlerGUI.web_save_svg()
else:
SVG.open_save_dialog(extension, native_file_export, export)

func export(path: String) -> void:
if path.get_extension().is_empty():
path += "." + extension

GlobalSettings.modify_save_data("last_used_dir", path.get_base_dir())

match extension:
"png":
create_image().save_png(path)
_:
# SVG / fallback.
GlobalSettings.modify_save_data("current_file_path", path)
SVG.save_svg_to_file(path)
HandlerGUI.remove_overlay()
SVG.open_save_dialog(extension, native_file_export, SVG.finish_export.bind(extension))

func _on_cancel_button_pressed() -> void:
HandlerGUI.remove_overlay()
Expand All @@ -94,14 +78,3 @@ func update_final_scale() -> void:

func update_extension_configuration() -> void:
scale_container.visible = (extension == "png")

func create_image() -> Image:
var export_svg := SVG.root_tag.create_duplicate()
if export_svg.attributes.viewBox.get_list().is_empty():
export_svg.attributes.viewBox.set_list([0, 0, export_svg.width, export_svg.height])
export_svg.attributes.width.set_num(export_svg.width * upscale_amount)
export_svg.attributes.height.set_num(export_svg.height * upscale_amount)
var img := Image.new()
img.load_svg_from_string(SVGParser.svg_to_text(export_svg))
img.fix_alpha_edges() # See godot issue 82579.
return img
3 changes: 2 additions & 1 deletion src/ui_parts/export_dialog.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -108,17 +108,18 @@ theme_override_font_sizes/font_size = 10

[node name="ButtonContainer" type="HBoxContainer" parent="VBoxContainer"]
layout_mode = 2
theme_override_constants/separation = 12
alignment = 1

[node name="CancelButton" type="Button" parent="VBoxContainer/ButtonContainer"]
layout_mode = 2
size_flags_horizontal = 6
focus_mode = 0
mouse_default_cursor_shape = 2
text = "Cancel"

[node name="OKButton" type="Button" parent="VBoxContainer/ButtonContainer"]
layout_mode = 2
size_flags_horizontal = 6
focus_mode = 0
mouse_default_cursor_shape = 2
text = "Export"
Expand Down
Loading

0 comments on commit 9f8dd1f

Please sign in to comment.