Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve the fallback file dialog #641

Merged
merged 1 commit into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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