diff --git a/app_info.json b/app_info.json
deleted file mode 100644
index 1b65971..0000000
--- a/app_info.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "project_founder_and_manager": "Anish Mishra",
- "authors": ["Anish Mishra (syntaxerror247)"],
- "donors": [],
- "anonymous_donors": 0,
- "golden_donors": [],
- "anonymous_golden_donors": 0,
- "diamond_donors": [],
- "anonymous_diamond_donors": 0,
- "past_donors": [],
- "past_anonymous_donors": 0,
- "past_golden_donors": [],
- "past_anonymous_golden_donors": 0,
- "past_diamond_donors": [],
- "past_anonymous_diamond_donors": 0
-}
diff --git a/app_info.toml b/app_info.toml
new file mode 100644
index 0000000..3db6f4f
--- /dev/null
+++ b/app_info.toml
@@ -0,0 +1,19 @@
+project_founder_and_manager = "Anish Mishra"
+authors = [
+ "Anish Mishra (syntaxerror247)"
+]
+
+donors = []
+anonymous_donors = 0
+golden_donors = []
+anonymous_golden_donors = 0
+
+diamond_donors = []
+anonymous_diamond_donors = 0
+
+past_donors = []
+past_anonymous_donors = 0
+past_golden_donors = []
+past_anonymous_golden_donors = 0
+past_diamond_donors = []
+past_anonymous_diamond_donors = 0
diff --git a/godot_only/scripts/tests.gd b/godot_only/scripts/tests.gd
index 35b7417..1ba6fb5 100644
--- a/godot_only/scripts/tests.gd
+++ b/godot_only/scripts/tests.gd
@@ -15,12 +15,12 @@ func _run() -> void:
for report_line in report:
print_rich(report_line)
-
func add_to_report(test_category: String, test: String, result: String,
expected: String) -> void:
report.append('%s: [b]"%s"[/b] returned [b]"%s"[/b], expected [b]"%s"[/b]' %\
[test_category, test, result, expected])
+
# This test is dependent on specifics of the Formatter and AttributePathdata classes.
# But its logic would likely not change enough in the future to make the tests obsolete.
# https://www.w3.org/TR/SVG11/paths.html#PathDataBNF
@@ -103,6 +103,6 @@ func transform_list_tests() -> void:
}
for test in tests:
- var result := AttributeTransformList.new("transform")._format(test, spacious_formatter)
+ var result := AttributeTransformList.new("transform").format(test, spacious_formatter)
if result != tests[test]:
add_to_report("Transform list parser", test, result, tests[test])
diff --git a/godot_only/scripts/update_translations.gd b/godot_only/scripts/update_translations.gd
index b4ac7cf..7aee587 100644
--- a/godot_only/scripts/update_translations.gd
+++ b/godot_only/scripts/update_translations.gd
@@ -38,7 +38,7 @@ func populate_delimiters() -> void:
for method in ["translate"]:
for quote in ["'", '"', '"""']:
delimiters["Translator." + method + "(" + quote] = quote + ")"
- for i in range(2, 8):
+ for i in range(2, 10):
delimiters["Translator." + method + "(\n" + "\t".repeat(i) + quote] = quote + ")"
var messages: Array[Message] = [Message.new("translation-credits", PackedStringArray())]
diff --git a/project.godot b/project.godot
index 84248c4..c3f9c33 100644
--- a/project.godot
+++ b/project.godot
@@ -36,7 +36,6 @@ HandlerGUI="*res://src/autoload/HandlerGUI.gd"
window/size/viewport_width=480
window/size/viewport_height=854
-window/energy_saving/keep_screen_on=false
window/handheld/orientation=6
mouse_cursor/tooltip_position_offset=Vector2(0, 10)
diff --git a/src/autoload/Configs.gd b/src/autoload/Configs.gd
index 086a2f5..94179df 100644
--- a/src/autoload/Configs.gd
+++ b/src/autoload/Configs.gd
@@ -96,22 +96,10 @@ func post_load() -> void:
sync_canvas_color()
sync_locale()
sync_max_fps()
+ sync_keep_screen_on()
sync_theme()
-func generate_highlighter() -> SVGHighlighter:
- var new_highlighter := SVGHighlighter.new()
- new_highlighter.symbol_color = Configs.savedata.highlighting_symbol_color
- new_highlighter.element_color = Configs.savedata.highlighting_element_color
- new_highlighter.attribute_color = Configs.savedata.highlighting_attribute_color
- new_highlighter.string_color = Configs.savedata.highlighting_string_color
- new_highlighter.comment_color = Configs.savedata.highlighting_comment_color
- new_highlighter.text_color = Configs.savedata.highlighting_text_color
- new_highlighter.cdata_color = Configs.savedata.highlighting_cdata_color
- new_highlighter.error_color = Configs.savedata.highlighting_error_color
- return new_highlighter
-
-
# Global effects from settings. Some of them should also be used on launch.
func sync_canvas_color() -> void:
@@ -130,6 +118,9 @@ func sync_vsync() -> void:
func sync_max_fps() -> void:
Engine.max_fps = savedata.max_fps
+func sync_keep_screen_on() -> void:
+ DisplayServer.screen_set_keep_on(savedata.keep_screen_on)
+
func sync_theme() -> void:
ThemeUtils.generate_and_apply_theme()
theme_changed.emit()
diff --git a/src/autoload/State.gd b/src/autoload/State.gd
index 52ffa70..263bf7f 100644
--- a/src/autoload/State.gd
+++ b/src/autoload/State.gd
@@ -756,11 +756,9 @@ func get_selection_context(popup_method: Callable, context: Utils.LayoutPart) ->
btn_arr.append(ContextPopup.create_shortcut_button("duplicate"))
var xnode := root_element.get_xnode(selected_xids[0])
- if selected_xids.size() == 1 and ((not xnode.is_element() and\
- xnode.get_type() != BasicXNode.NodeType.UNKNOWN) or (xnode.is_element() and\
- not xnode.possible_conversions.is_empty())):
- btn_arr.append(ContextPopup.create_button(
- Translator.translate("Convert To"),
+ if selected_xids.size() == 1 and (not xnode.is_element() or\
+ (xnode.is_element() and not xnode.possible_conversions.is_empty())):
+ btn_arr.append(ContextPopup.create_button(Translator.translate("Convert To"),
popup_convert_to_context.bind(popup_method), false,
load("res://assets/icons/Reload.svg")))
diff --git a/src/config_classes/Formatter.gd b/src/config_classes/Formatter.gd
index 8a0d0b3..12005a7 100644
--- a/src/config_classes/Formatter.gd
+++ b/src/config_classes/Formatter.gd
@@ -53,7 +53,6 @@ static func get_enum_value_text_map(property: String) -> Dictionary:
func get_setting_default(setting: String) -> Variant:
match setting:
- "xml_keep_unrecognized": return false
"xml_add_trailing_newline": return false
"xml_indentation_use_spaces": return false
"xml_indentation_spaces": return 2
@@ -115,12 +114,6 @@ func _init(new_preset := Preset.COMPACT) -> void:
xml_keep_comments = new_value
emit_changed()
-@export var xml_keep_unrecognized := false:
- set(new_value):
- if xml_keep_unrecognized != new_value:
- xml_keep_unrecognized = new_value
- emit_changed()
-
@export var xml_add_trailing_newline := false:
set(new_value):
if xml_add_trailing_newline != new_value:
@@ -245,3 +238,10 @@ const INDENTS_MAX = 16
if transform_list_remove_unnecessary_params != new_value:
transform_list_remove_unnecessary_params = new_value
emit_changed()
+
+
+func get_indent_string() -> String:
+ if xml_indentation_use_spaces:
+ return " ".repeat(xml_indentation_spaces)
+ else:
+ return "\t"
diff --git a/src/config_classes/SVGHighlighter.gd b/src/config_classes/SVGHighlighter.gd
index 1f2cfb6..7a7772e 100644
--- a/src/config_classes/SVGHighlighter.gd
+++ b/src/config_classes/SVGHighlighter.gd
@@ -20,6 +20,16 @@ var attribute_color := Color("bce0ff"):
unrecognized_attribute_color = Color(new_value, new_value.a * 0.7)
+func _init() -> void:
+ symbol_color = Configs.savedata.highlighting_symbol_color
+ element_color = Configs.savedata.highlighting_element_color
+ attribute_color = Configs.savedata.highlighting_attribute_color
+ string_color = Configs.savedata.highlighting_string_color
+ comment_color = Configs.savedata.highlighting_comment_color
+ text_color = Configs.savedata.highlighting_text_color
+ cdata_color = Configs.savedata.highlighting_cdata_color
+ error_color = Configs.savedata.highlighting_error_color
+
func _get_line_syntax_highlighting(line: int) -> Dictionary:
var svg_text := get_text_edit().get_line(line)
if svg_text.is_empty():
@@ -66,13 +76,13 @@ func _get_line_syntax_highlighting(line: int) -> Dictionary:
color_map[offset] = {"color": symbol_color}
break
else:
- if not expecting_attribute_name:
- color_map[offset] = {"color": error_color}
- return color_map
- else:
- expecting_end = false
+ if expecting_attribute_name and c != "=":
expecting_attribute_name = false
+ expecting_end = false
current_attribute_name += c
+ else:
+ color_map[offset] = {"color": error_color}
+ return color_map
elif not current_attribute_name.is_empty():
if c in " \t\n\r":
color_map[offset - current_attribute_name.length()] = {"color":
diff --git a/src/config_classes/SaveData.gd b/src/config_classes/SaveData.gd
index db66f2e..3d42ae7 100644
--- a/src/config_classes/SaveData.gd
+++ b/src/config_classes/SaveData.gd
@@ -20,7 +20,7 @@ func get_setting_default(setting: String) -> Variant:
"accent_color":
match theme_preset:
ThemePreset.DARK: return Color("3e8cfc")
- ThemePreset.LIGHT: return Color("0830a6ff")
+ ThemePreset.LIGHT: return Color("0031bf")
ThemePreset.BLACK: return Color("7c8dbf")
"highlighter_preset":
match theme_preset:
@@ -68,7 +68,7 @@ func get_setting_default(setting: String) -> Variant:
ThemePreset.LIGHT: return Color("b22")
"basic_color_warning":
match theme_preset:
- ThemePreset.DARK,ThemePreset.BLACK: return Color("ee5")
+ ThemePreset.DARK,ThemePreset.BLACK: return Color("ee6")
ThemePreset.LIGHT: return Color("991")
"handle_size": return 1.0 if OS.get_name() != "Android" else 2.0
"handle_inner_color": return Color("fff")
@@ -94,11 +94,12 @@ func get_setting_default(setting: String) -> Variant:
"invert_zoom": return false
"wraparound_panning": return false
"use_ctrl_for_zoom": return true
- "use_native_file_dialog": return true
- "use_filename_for_window_title": return true
"ui_scale": return ScalingApproach.AUTO
"vsync": return true
"max_fps": return 0
+ "keep_screen_on": return false
+ "use_native_file_dialog": return true
+ "use_filename_for_window_title": return true
return null
func reset_to_default() -> void:
@@ -106,9 +107,11 @@ func reset_to_default() -> void:
set(setting, get_setting_default(setting))
func reset_theme_items_to_default() -> void:
+ var old_highlighter_preset_value := highlighter_preset
for setting in theme_items:
set(setting, get_setting_default(setting))
- reset_highlighting_items_to_default()
+ if old_highlighter_preset_value != highlighter_preset:
+ reset_highlighting_items_to_default()
func reset_highlighting_items_to_default() -> void:
for setting in highlighting_items:
@@ -129,17 +132,6 @@ const theme_items: PackedStringArray = [
"basic_color_valid",
"basic_color_error",
"basic_color_warning",
- "handle_size",
- "handle_inner_color",
- "handle_color",
- "handle_hovered_color",
- "handle_selected_color",
- "handle_hovered_selected_color",
- "selection_rectangle_speed",
- "selection_rectangle_width",
- "selection_rectangle_dash_length",
- "selection_rectangle_color1",
- "selection_rectangle_color2",
"canvas_color",
"grid_color",
]
@@ -326,7 +318,7 @@ const CURRENT_VERSION = 1
emit_changed()
Configs.basic_colors_changed.emit()
-@export var basic_color_warning := Color("ee5"):
+@export var basic_color_warning := Color("ee6"):
set(new_value):
if basic_color_warning != new_value:
basic_color_warning = new_value
@@ -485,19 +477,6 @@ const MAX_SELECTION_RECTANGLE_DASH_LENGTH = 600.0
use_ctrl_for_zoom = new_value
emit_changed()
-@export var use_native_file_dialog := true:
- set(new_value):
- if use_native_file_dialog != new_value:
- use_native_file_dialog = new_value
- emit_changed()
-
-@export var use_filename_for_window_title := true:
- set(new_value):
- if use_filename_for_window_title != new_value:
- use_filename_for_window_title = new_value
- emit_changed()
- external_call(HandlerGUI.update_window_title)
-
enum ScalingApproach {AUTO, CONSTANT_075, CONSTANT_100, CONSTANT_125, CONSTANT_150,
CONSTANT_175, CONSTANT_200, CONSTANT_225, CONSTANT_250, CONSTANT_275, CONSTANT_300, CONSTANT_400, MAX}
@export var ui_scale := ScalingApproach.AUTO:
@@ -533,6 +512,26 @@ const MAX_FPS_MAX = 600
emit_changed()
external_call(Configs.sync_max_fps)
+@export var keep_screen_on := false:
+ set(new_value):
+ if keep_screen_on != new_value:
+ keep_screen_on = new_value
+ emit_changed()
+ external_call(Configs.sync_keep_screen_on)
+
+@export var use_native_file_dialog := true:
+ set(new_value):
+ if use_native_file_dialog != new_value:
+ use_native_file_dialog = new_value
+ emit_changed()
+
+@export var use_filename_for_window_title := true:
+ set(new_value):
+ if use_filename_for_window_title != new_value:
+ use_filename_for_window_title = new_value
+ emit_changed()
+ external_call(HandlerGUI.update_window_title)
+
# Session
diff --git a/src/config_classes/TabData.gd b/src/config_classes/TabData.gd
index 42efcec..167fec5 100644
--- a/src/config_classes/TabData.gd
+++ b/src/config_classes/TabData.gd
@@ -46,7 +46,7 @@ func set_svg_text(new_text: String) -> void:
if not is_instance_valid(undo_redo):
undo_redo = UndoRedoRef.new()
var old_value := _svg_text
- undo_redo.create_action("")
+ undo_redo.create_action()
undo_redo.add_do_property(self, "_svg_text", new_text)
undo_redo.add_undo_property(self, "_svg_text", old_value)
undo_redo.add_do_property(State, "svg_text", new_text)
diff --git a/src/data_classes/Attribute.gd b/src/data_classes/Attribute.gd
index b3d3ab6..eff3ce0 100644
--- a/src/data_classes/Attribute.gd
+++ b/src/data_classes/Attribute.gd
@@ -1,5 +1,6 @@
# Represents an attribute inside an element, i.e. .
# If the Attribute's data type is known, one of the inheriting classes should be used.
+# By default uses the editor formatter.
class_name Attribute
signal value_changed
@@ -13,7 +14,7 @@ func set_value(new_value: String) -> void:
# Formatting can be expensive, so do this cheap check first.
if new_value == _value:
return
- var proposed_new_value := format(new_value)
+ var proposed_new_value := format(new_value, Configs.savedata.editor_formatter)
if proposed_new_value != _value:
_value = proposed_new_value
_sync()
@@ -22,16 +23,13 @@ func set_value(new_value: String) -> void:
func get_value() -> String:
return _value
+func get_formatted_value(formatter: Formatter) -> String:
+ return format(_value, formatter)
+
func _sync() -> void:
pass
-func format(text: String) -> String:
- return _format(text, Configs.savedata.editor_formatter)
-
-func get_export_value() -> String:
- return _format(_value, Configs.savedata.export_formatter)
-
-func _format(text: String, _formatter: Formatter) -> String:
+func format(text: String, _formatter: Formatter) -> String:
return text
func _init(new_name: String, init_value := "") -> void:
diff --git a/src/data_classes/AttributeColor.gd b/src/data_classes/AttributeColor.gd
index 9dd3b14..b958e51 100644
--- a/src/data_classes/AttributeColor.gd
+++ b/src/data_classes/AttributeColor.gd
@@ -8,7 +8,7 @@ func set_value(new_value: String) -> void:
name in DB.attribute_color_url_allowed, name in DB.attribute_color_none_allowed,
name in DB.attribute_color_current_color_allowed) else "")
-func _format(text: String, formatter: Formatter) -> String:
+func format(text: String, formatter: Formatter) -> String:
text = text.strip_edges()
if text.is_empty() or text in ["none", "currentColor"]:
diff --git a/src/data_classes/AttributeList.gd b/src/data_classes/AttributeList.gd
index eb370f8..ccfbb06 100644
--- a/src/data_classes/AttributeList.gd
+++ b/src/data_classes/AttributeList.gd
@@ -6,7 +6,7 @@ var _list: PackedFloat64Array
func _sync() -> void:
_list = text_to_list(get_value())
-func _format(text: String, formatter: Formatter) -> String:
+func format(text: String, formatter: Formatter) -> String:
return list_to_text(text_to_list(text), formatter)
diff --git a/src/data_classes/AttributeNumeric.gd b/src/data_classes/AttributeNumeric.gd
index 1cc0066..8903ad5 100644
--- a/src/data_classes/AttributeNumeric.gd
+++ b/src/data_classes/AttributeNumeric.gd
@@ -20,7 +20,7 @@ func is_percentage() -> bool:
return _percentage
-func _format(text: String, formatter: Formatter) -> String:
+func format(text: String, formatter: Formatter) -> String:
var num := text_to_num(text)
if text_check_percentage(text):
return num_to_text(num * 100.0, formatter) + "%"
diff --git a/src/data_classes/AttributePathdata.gd b/src/data_classes/AttributePathdata.gd
index b65f6f6..72e4611 100644
--- a/src/data_classes/AttributePathdata.gd
+++ b/src/data_classes/AttributePathdata.gd
@@ -8,7 +8,7 @@ func _sync() -> void:
_commands = parse_pathdata(get_value())
parse_properties()
-func _format(text: String, formatter: Formatter) -> String:
+func format(text: String, formatter: Formatter) -> String:
return path_commands_to_text(parse_pathdata(text), formatter)
diff --git a/src/data_classes/AttributeTransformList.gd b/src/data_classes/AttributeTransformList.gd
index 77b65a1..5fe266b 100644
--- a/src/data_classes/AttributeTransformList.gd
+++ b/src/data_classes/AttributeTransformList.gd
@@ -11,7 +11,7 @@ func _sync() -> void:
func sync_after_transforms_change() -> void:
set_value(transform_list_to_text(_transform_list))
-func _format(text: String, formatter: Formatter) -> String:
+func format(text: String, formatter: Formatter) -> String:
return transform_list_to_text(text_to_transform_list(text), formatter)
func set_transform_list(new_transform_list: Array[Transform]) -> void:
diff --git a/src/data_classes/BasicXNode.gd b/src/data_classes/BasicXNode.gd
index 06f9857..f51b9f5 100644
--- a/src/data_classes/BasicXNode.gd
+++ b/src/data_classes/BasicXNode.gd
@@ -3,8 +3,8 @@ class_name BasicXNode extends XNode
signal text_changed # Any text change.
signal rendered_text_changed # Text changes that could affect the SVG.
-enum NodeType {COMMENT, TEXT, CDATA, UNKNOWN}
-var _type := NodeType.UNKNOWN
+enum NodeType {COMMENT, TEXT, CDATA}
+var _type: NodeType
var _text := ""
func set_text(new_text: String) -> void:
diff --git a/src/data_classes/ElementRoot.gd b/src/data_classes/ElementRoot.gd
index cd5734f..1bd2758 100644
--- a/src/data_classes/ElementRoot.gd
+++ b/src/data_classes/ElementRoot.gd
@@ -9,10 +9,10 @@ signal xnodes_moved_in_parent(parent_xid: PackedInt32Array, old_indices: Array[i
signal xnodes_moved_to(xids: Array[PackedInt32Array], location: PackedInt32Array)
signal xnode_layout_changed # Emitted together with any of the above four.
-@warning_ignore("unused_signal")
+@warning_ignore_start("unused_signal")
signal basic_xnode_text_changed(xid: PackedInt32Array)
-@warning_ignore("unused_signal")
signal basic_xnode_rendered_text_changed(xid: PackedInt32Array)
+@warning_ignore_restore("unused_signal")
func _init() -> void:
super()
@@ -196,8 +196,7 @@ func optimize(not_applied := false) -> bool:
if not xnode.is_element():
var basic_xnode: BasicXNode = xnode
var xids_to_remove: Array[PackedInt32Array] = []
- if basic_xnode.get_type() in [BasicXNode.NodeType.COMMENT,
- BasicXNode.NodeType.UNKNOWN]:
+ if basic_xnode.get_type() == BasicXNode.NodeType.COMMENT:
if not_applied:
return true
xids_to_remove.append(xnode.xid)
diff --git a/src/data_classes/NumberParser.gd b/src/data_classes/NumberParser.gd
index c4f75c7..8008f56 100644
--- a/src/data_classes/NumberParser.gd
+++ b/src/data_classes/NumberParser.gd
@@ -15,16 +15,19 @@ static func num_to_text(number: float, formatter: Formatter) -> String:
var e := 3
while numstr[-e - 1] == "0":
e += 1
- return String.num_int64(int(number / 10 ** e)) + "e" + String.num_int64(e)
- elif numstr.begins_with("0.00"):
- if not formatter.number_remove_leading_zero or numstr.begins_with("0.000"):
- var e := 2
- var r := 3 if numstr.begins_with("-") else 2
- while e + r < numstr.length() and numstr[e + r] == "0":
+ return numstr.left(-e) + "e" + String.num_uint64(e)
+ else:
+ var numstr_abs := numstr.trim_prefix("-")
+ # Leading zeros aren't removed yet.
+ if numstr_abs.begins_with("0.00") and\
+ (not formatter.number_remove_leading_zero or numstr_abs.begins_with("0.000")):
+ var is_num_negative := numstr.begins_with("-")
+ var e := 3
+ while e + 1 < numstr.length() and numstr_abs[e + 1] == "0":
e += 1
- var output := "-" if numstr.begins_with("-") else ""
- return output + String.num_int64(numstr.right(e + r - 1).to_int()) +\
- "e-" + String.num_int64(e + 1)
+
+ var output := "-" if is_num_negative else ""
+ return output + numstr_abs.right(-e - 1) + "e-" + String.num_uint64(e)
if formatter.number_remove_leading_zero and not is_zero_approx(fmod(number, 1)):
if numstr.begins_with("0"):
diff --git a/src/data_classes/SVGParser.gd b/src/data_classes/SVGParser.gd
index d14c187..c6c8811 100644
--- a/src/data_classes/SVGParser.gd
+++ b/src/data_classes/SVGParser.gd
@@ -41,35 +41,46 @@ custom_height: float, custom_viewbox: Rect2) -> String:
new_root_element.set_attribute("viewBox", ListParser.rect_to_list(custom_viewbox))
new_root_element.set_attribute("width", custom_width)
new_root_element.set_attribute("height", custom_height)
- var text := _xnode_to_editor_text(new_root_element)
+ var text := _xnode_to_text(new_root_element, Configs.savedata.editor_formatter)
text = text.left(maxi(text.find("/>"), text.find(""))) + ">"
for child_idx in root_element.get_child_count():
- text += _xnode_to_editor_text(
- root_element.get_xnode(PackedInt32Array([child_idx])), true)
+ text += _xnode_to_text(root_element.get_xnode(
+ PackedInt32Array([child_idx])), Configs.savedata.editor_formatter, true)
return text + ""
+
+static func root_children_to_text(root_element: ElementRoot, formatter: Formatter) -> String:
+ var text := ""
+ for child in root_element.get_children():
+ var new_text := _xnode_to_text(child, formatter)
+ var lines := new_text.split('\n')
+ for i in lines.size():
+ lines[i] = lines[i].trim_prefix(formatter.get_indent_string())
+ text += '\n'.join(lines)
+ return text.trim_suffix('\n')
+
static func root_to_editor_text(root_element: ElementRoot) -> String:
- var text := _xnode_to_editor_text(root_element).trim_suffix('\n')
- if Configs.savedata.editor_formatter.xml_add_trailing_newline:
- text += "\n"
- return text
+ return root_to_text(root_element, Configs.savedata.editor_formatter)
static func root_to_export_text(root_element: ElementRoot) -> String:
- var text := _xnode_to_export_text(root_element).trim_suffix('\n')
- if Configs.savedata.export_formatter.xml_add_trailing_newline:
+ return root_to_text(root_element, Configs.savedata.export_formatter)
+
+static func root_to_text(root_element: ElementRoot, formatter: Formatter) -> String:
+ var text := _xnode_to_text(root_element, formatter).trim_suffix('\n')
+ if formatter.xml_add_trailing_newline:
text += "\n"
return text
-static func _xnode_to_editor_text(xnode: XNode, make_attributes_absolute := false) -> String:
- var formatter := Configs.savedata.editor_formatter
+static func _xnode_to_text(xnode: XNode, formatter: Formatter,
+make_attributes_absolute := false) -> String:
var text := ""
if formatter.xml_pretty_formatting:
- if formatter.xml_indentation_use_spaces:
- text = ' '.repeat(xnode.xid.size() * formatter.xml_indentation_spaces)
- else:
- text = '\t'.repeat(xnode.xid.size())
+ text = formatter.get_indent_string().repeat(xnode.xid.size())
if not xnode.is_element():
+ if (not formatter.xml_keep_comments and xnode.get_type() == BasicXNode.NodeType.COMMENT):
+ return ""
+
match xnode.get_type():
BasicXNode.NodeType.COMMENT: text += "" % xnode.get_text()
BasicXNode.NodeType.CDATA: text += "" % xnode.get_text()
@@ -106,55 +117,7 @@ static func _xnode_to_editor_text(xnode: XNode, make_attributes_absolute := fals
text += '<' + element.name
for attribute: Attribute in attribute_array:
- var value := attribute.get_value()
-
- if not '"' in value:
- text += ' %s="%s"' % [attribute.name, value]
- else:
- text += " %s='%s'" % [attribute.name, value]
-
- if not element.has_children() and (formatter.xml_shorthand_tags ==\
- Formatter.ShorthandTags.ALWAYS or (formatter.xml_shorthand_tags ==\
- Formatter.ShorthandTags.ALL_EXCEPT_CONTAINERS and\
- not element.name in Formatter.container_elements)):
- text += ' />' if formatter.xml_shorthand_tags_space_out_slash else '/>'
- if formatter.xml_pretty_formatting:
- text += '\n'
- else:
- text += '>'
- if formatter.xml_pretty_formatting:
- text += '\n'
- for child in element.get_children():
- text += _xnode_to_editor_text(child, make_attributes_absolute)
- if formatter.xml_pretty_formatting:
- text += '\t'.repeat(element.xid.size())
- text += '%s>' % element.name
- if formatter.xml_pretty_formatting:
- text += '\n'
- return text
-
-static func _xnode_to_export_text(xnode: XNode) -> String:
- var formatter := Configs.savedata.export_formatter
- var text := ""
- if formatter.xml_pretty_formatting:
- if formatter.xml_indentation_use_spaces:
- text = ' '.repeat(xnode.xid.size() * formatter.xml_indentation_spaces)
- else:
- text = '\t'.repeat(xnode.xid.size())
-
- if not xnode.is_element():
- match xnode.get_type():
- BasicXNode.NodeType.COMMENT: text += "" % xnode.get_text()
- BasicXNode.NodeType.CDATA: text += "" % xnode.get_text()
- _: text += xnode.get_text()
- if formatter.xml_pretty_formatting:
- text += "\n"
- return text
-
- var element := xnode as Element
- text += '<' + element.name
- for attribute: Attribute in element.get_all_attributes():
- var value := attribute.get_export_value()
+ var value := attribute.get_formatted_value(formatter)
if not '"' in value:
text += ' %s="%s"' % [attribute.name, value]
@@ -173,9 +136,9 @@ static func _xnode_to_export_text(xnode: XNode) -> String:
if formatter.xml_pretty_formatting:
text += '\n'
for child in element.get_children():
- text += _xnode_to_export_text(child)
+ text += _xnode_to_text(child, formatter, make_attributes_absolute)
if formatter.xml_pretty_formatting:
- text += '\t'.repeat(element.xid.size())
+ text += formatter.get_indent_string().repeat(element.xid.size())
text += '%s>' % element.name
if formatter.xml_pretty_formatting:
text += '\n'
@@ -277,10 +240,6 @@ static func text_to_root(text: String) -> ParseResult:
XMLParser.NODE_CDATA:
unclosed_element_stack.back().insert_child(-1,
BasicXNode.new(BasicXNode.NodeType.CDATA, parser.get_node_name()))
- _:
- if Configs.savedata.editor_formatter.xml_keep_unrecognized:
- unclosed_element_stack.back().insert_child(-1,
- BasicXNode.new(BasicXNode.NodeType.UNKNOWN, parser.get_node_name()))
if not unclosed_element_stack.is_empty():
return ParseResult.new(ParseError.ERR_IMPROPER_NESTING)
diff --git a/src/shaders/animated_stroke.gdshader b/src/shaders/animated_stroke.gdshader
index 6e441a7..27c8d02 100644
--- a/src/shaders/animated_stroke.gdshader
+++ b/src/shaders/animated_stroke.gdshader
@@ -6,15 +6,41 @@ uniform float ant_width = 2.0;
uniform float ant_length = 10.0;
uniform float ant_speed = 30.0;
+varying float cos_skew;
+varying float max_rotation_factor;
+
+void vertex() {
+ // A bunch of hacks to deal with rotated or skewed drawing resulting in ants
+ // that are too long, fast, and sometimes wide.
+ vec2 col0 = MODEL_MATRIX[0].xy;
+ vec2 col1 = MODEL_MATRIX[1].xy;
+
+ float rotation = atan(col0.y, col0.x);
+ float det = col0.x * col1.y - col0.y * col1.x;
+
+ vec2 col0_norm = normalize(col0);
+ vec2 col1_norm = normalize(col1) * sign(det);
+
+ float dot_product = dot(col0_norm, col1_norm);
+ float skew = acos(clamp(dot_product, -1.0, 1.0)) - PI * 0.5;
+
+ cos_skew = cos(skew);
+ max_rotation_factor = max(abs(cos(rotation)), abs(sin(rotation)));
+}
+
void fragment() {
+ float corrected_length = ant_length * cos_skew * max_rotation_factor;
+ float corrected_speed = ant_speed * cos_skew * max_rotation_factor;
+ float corrected_width = ant_width * max_rotation_factor;
+
vec2 uv = UV;
vec2 fw = fwidth(uv);
- float adjusted_ant_width = min(ant_width, min(0.5 / fw.x, 0.5 / fw.y));
+ float adjusted_ant_width = min(corrected_width, min(0.5 / fw.x, 0.5 / fw.y)) + 0.15;
vec2 aw = fw * adjusted_ant_width;
-
+
vec2 cond = (sign(abs(uv - 0.5) - 0.5 + aw) + 1.0) * 0.5 * ceil(((sign(uv.yx - aw.yx) + 1.0) * 0.5 * (sign(uv - 0.5) * vec2(0.5, -0.5) + 0.5) * 0.5 + (sign(1.0 - aw.yx - uv.yx) + 1.0) * 0.5 * (sign(uv - 0.5) * vec2(-0.5, 0.5)+ 0.5) * 0.5));
float dir = dot(vec2(cond.y, -cond.x), sign(uv.yx - 0.5) * uv / aw);
- float ant_type = round(fract((dir * adjusted_ant_width + TIME * ant_speed) * 0.5 / ant_length));
+ float ant_type = round(fract((dir * adjusted_ant_width + TIME * corrected_speed) * 0.5 / corrected_length));
vec4 ant_color = mix(ant_color_1, ant_color_2, ant_type);
COLOR = (cond.x + cond.y) * ant_color;
}
diff --git a/src/shaders/animated_stroke_static.gdshader b/src/shaders/animated_stroke_static.gdshader
index 8b98f30..15bbe7d 100644
--- a/src/shaders/animated_stroke_static.gdshader
+++ b/src/shaders/animated_stroke_static.gdshader
@@ -7,15 +7,40 @@ uniform vec4 ant_color_2: source_color = vec4(0.0, 0.0, 0.0, 1.0);
uniform float ant_width = 2.0;
uniform float ant_length = 10.0;
+varying float cos_skew;
+varying float max_rotation_factor;
+
+void vertex() {
+ // A bunch of hacks to deal with rotated or skewed drawing resulting in ants
+ // that are too long, fast, and sometimes wide.
+ vec2 col0 = MODEL_MATRIX[0].xy;
+ vec2 col1 = MODEL_MATRIX[1].xy;
+
+ float rotation = atan(col0.y, col0.x);
+ float det = col0.x * col1.y - col0.y * col1.x;
+
+ vec2 col0_norm = normalize(col0);
+ vec2 col1_norm = normalize(col1) * sign(det);
+
+ float dot_product = dot(col0_norm, col1_norm);
+ float skew = acos(clamp(dot_product, -1.0, 1.0)) - PI * 0.5;
+
+ cos_skew = cos(skew);
+ max_rotation_factor = max(abs(cos(rotation)), abs(sin(rotation)));
+}
+
void fragment() {
+ float corrected_length = ant_length * cos_skew * max_rotation_factor;
+ float corrected_width = ant_width * max_rotation_factor;
+
vec2 uv = UV;
vec2 fw = fwidth(uv);
- float adjusted_ant_width = min(ant_width, min(0.5 / fw.x, 0.5 / fw.y));
+ float adjusted_ant_width = min(corrected_width, min(0.5 / fw.x, 0.5 / fw.y)) + 0.15;
vec2 aw = fw * adjusted_ant_width;
-
+
vec2 cond = (sign(abs(uv - 0.5) - 0.5 + aw) + 1.0) * 0.5 * ceil(((sign(uv.yx - aw.yx) + 1.0) * 0.5 * (sign(uv - 0.5) * vec2(0.5, -0.5) + 0.5) * 0.5 + (sign(1.0 - aw.yx - uv.yx) + 1.0) * 0.5 * (sign(uv - 0.5) * vec2(-0.5, 0.5)+ 0.5) * 0.5));
float dir = dot(vec2(cond.y, -cond.x), sign(uv.yx - 0.5) * uv / aw);
- float ant_type = round(fract((dir * adjusted_ant_width) * 0.5 / ant_length));
+ float ant_type = round(fract((dir * adjusted_ant_width) * 0.5 / corrected_length));
vec4 ant_color = mix(ant_color_1, ant_color_2, ant_type);
COLOR = (cond.x + cond.y) * ant_color;
}
diff --git a/src/ui_parts/about_menu.gd b/src/ui_parts/about_menu.gd
index 1fd3d9c..b17dfae 100644
--- a/src/ui_parts/about_menu.gd
+++ b/src/ui_parts/about_menu.gd
@@ -1,7 +1,5 @@
extends PanelContainer
-const app_info_json = preload("res://app_info.json")
-
@onready var close_button: Button = $VBoxContainer/CloseButton
@onready var translators_vbox: VBoxContainer = %TranslatorsVBox
@onready var developers_list: PanelGrid = %DevelopersList
@@ -31,10 +29,17 @@ func _ready() -> void:
tab_container.tab_changed.connect(_on_tab_changed)
_on_tab_changed(0)
+func _unhandled_input(event: InputEvent) -> void:
+ var tab_count := tab_container.get_tab_count()
+ if ShortcutUtils.is_action_pressed(event, "select_next_tab"):
+ tab_container.current_tab = (tab_container.current_tab + 1) % tab_count
+ elif ShortcutUtils.is_action_pressed(event, "select_previous_tab"):
+ tab_container.current_tab = (tab_container.current_tab + tab_count - 1) % tab_count
+
func _on_tab_changed(idx: int) -> void:
match idx:
0:
- var app_info: Dictionary = app_info_json.data
+ var app_info := get_app_info()
%ProjectFounderLabel.text = Translator.translate("Project Founder and Manager") +\
": " + app_info.project_founder_and_manager
@@ -64,11 +69,12 @@ func _on_tab_changed(idx: int) -> void:
list.items = credits
translators_vbox.add_child(list)
1:
+ var app_info := get_app_info()
+
%Donors/Label.text = Translator.translate("Donors")
%GoldenDonors/Label.text = Translator.translate("Golden donors")
%DiamondDonors/Label.text = Translator.translate("Diamond donors")
- var app_info: Dictionary = app_info_json.data
# Once the past donors lists start filling up, they will never unfill,
# so no need to bother with logic, we can just unhide it manually.
if app_info.donors.is_empty() and app_info.anonymous_donors == 0:
@@ -126,7 +132,7 @@ func _on_tab_changed(idx: int) -> void:
var godsvg_parts_label := Label.new()
godsvg_parts_label.text = "GodSVG components"
var godot_parts_label := Label.new()
- godot_parts_label.text = "Godot components"
+ godot_parts_label.text = "Godot Engine components"
var license_texts_label := Label.new()
license_texts_label.text = "Licenses"
for label: Label in [godsvg_parts_label, godot_parts_label, license_texts_label]:
@@ -244,3 +250,68 @@ func _on_tab_changed(idx: int) -> void:
license_text.text = licenses_dict[license_name]
license_vbox.add_child(license_text)
%LicenseTexts.add_child(license_vbox)
+
+
+# Just enough of a parser to handle app_data.toml
+func get_app_info() -> Dictionary[String, Variant]:
+ var toml_text := FileAccess.get_file_as_string("res://app_info.toml")
+ var lines := toml_text.split("\n", false)
+ var result: Dictionary[String, Variant]
+ var i := 0
+
+ while i < lines.size():
+ var line := lines[i].get_slice("#", 0).strip_edges()
+ if line.is_empty():
+ i += 1
+ continue
+
+ var parts := line.split("=", false, 2)
+ if parts.size() != 2:
+ i += 1
+ continue
+
+ var key := parts[0].strip_edges()
+ var raw_value := parts[1].strip_edges()
+
+ if raw_value.begins_with("["):
+ var array_text := ""
+ if raw_value.ends_with("]"):
+ array_text = raw_value.substr(1, raw_value.length() - 2)
+ else:
+ array_text = raw_value.right(-1)
+ while true:
+ i += 1
+ if i >= lines.size():
+ break
+ var next_line := lines[i].get_slice("#", 0).strip_edges()
+ if next_line.ends_with("]"):
+ array_text += " " + next_line.substr(0, next_line.length() - 1)
+ break
+ else:
+ array_text += " " + next_line
+
+ var elements := array_text.split(",", false)
+ var arr := []
+ for elem in elements:
+ var v := elem.strip_edges()
+ if (v.begins_with('"') and v.ends_with('"')) or\
+ (v.begins_with("'") and v.ends_with("'")):
+ arr.append(v.substr(1, v.length() - 2))
+ elif v.is_valid_int():
+ arr.append(v.to_int())
+ elif v.is_valid_float():
+ arr.append(v.to_float())
+ result[key] = arr
+
+ else:
+ if (raw_value.begins_with('"') and raw_value.ends_with('"')) or\
+ (raw_value.begins_with("'") and raw_value.ends_with("'")):
+ result[key] = raw_value.substr(1, raw_value.length() - 2)
+ elif raw_value.is_valid_int():
+ result[key] = raw_value.to_int()
+ elif raw_value.is_valid_float():
+ result[key] = raw_value.to_float()
+
+ i += 1
+
+ return result
diff --git a/src/ui_parts/code_editor.gd b/src/ui_parts/code_editor.gd
index e5e9ca2..4c5018b 100644
--- a/src/ui_parts/code_editor.gd
+++ b/src/ui_parts/code_editor.gd
@@ -7,8 +7,8 @@ extends VBoxContainer
@onready var options_button: Button = %MetaActions/OptionsButton
func _ready() -> void:
- Configs.theme_changed.connect(update_theme)
- update_theme()
+ Configs.theme_changed.connect(sync_theming)
+ sync_theming()
State.parsing_finished.connect(update_error)
Configs.highlighting_colors_changed.connect(update_syntax_highlighter)
update_syntax_highlighter()
@@ -26,15 +26,15 @@ func update_error(err_id: SVGParser.ParseError) -> void:
if err_id == SVGParser.ParseError.OK:
if error_bar.visible:
error_bar.hide()
- update_theme()
+ sync_theming()
else:
# When the error is shown, the code editor's theme is changed to match up.
if not error_bar.visible:
error_bar.show()
error_label.text = SVGParser.get_error_string(err_id)
- update_theme()
+ sync_theming()
-func update_theme() -> void:
+func sync_theming() -> void:
# Set up the code edit.
code_edit.begin_bulk_theme_override()
const CONST_ARR_1: PackedStringArray = ["normal", "focus", "hover"]
@@ -115,4 +115,4 @@ func _on_options_button_pressed() -> void:
func update_syntax_highlighter() -> void:
if is_instance_valid(code_edit):
- code_edit.syntax_highlighter = Configs.generate_highlighter()
+ code_edit.syntax_highlighter = SVGHighlighter.new()
diff --git a/src/ui_parts/display.gd b/src/ui_parts/display.gd
index 74ac961..7023102 100644
--- a/src/ui_parts/display.gd
+++ b/src/ui_parts/display.gd
@@ -19,10 +19,12 @@ var should_refresh_tabs := false
var reference_overlay := false
func _ready() -> void:
- Configs.language_changed.connect(update_translations)
+ Configs.language_changed.connect(sync_localization)
+ sync_localization()
Configs.snap_changed.connect(update_snap_config)
- Configs.theme_changed.connect(update_theme)
- Configs.tabs_changed.connect(set.bind("should_refresh_tabs" ,true))
+ update_snap_config()
+ Configs.theme_changed.connect(sync_theming)
+ sync_theming()
Configs.active_tab_changed.connect(sync_reference_image)
Configs.active_tab_reference_changed.connect(sync_reference_image)
sync_reference_image()
@@ -32,15 +34,13 @@ func _ready() -> void:
_on_overlay_reference_updated()
State.show_debug_changed.connect(_on_show_debug_changed)
_on_show_debug_changed()
- update_translations()
- update_theme()
- update_snap_config()
get_window().window_input.connect(_update_input_debug)
-func update_translations() -> void:
+
+func sync_localization() -> void:
%LeftMenu/Snapping/SnapNumberEdit.tooltip_text = Translator.translate("Snap size")
-func update_theme() -> void:
+func sync_theming() -> void:
var frame := StyleBoxFlat.new()
frame.draw_center = false
frame.set_content_margin_all(2.0)
diff --git a/src/ui_parts/display.tscn b/src/ui_parts/display.tscn
index 0cb3ce1..69163ee 100644
--- a/src/ui_parts/display.tscn
+++ b/src/ui_parts/display.tscn
@@ -8,13 +8,13 @@
[ext_resource type="Texture2D" uid="uid://dgoy38n5me7r0" path="res://assets/icons/Grid.svg" id="8_rll1m"]
[ext_resource type="PackedScene" uid="uid://oltvrf01xrxl" path="res://src/ui_widgets/zoom_menu.tscn" id="8_xtdmn"]
[ext_resource type="Script" uid="uid://b6pmlbnl76wmm" path="res://src/ui_parts/viewport.gd" id="9_4xrk7"]
+[ext_resource type="Script" uid="uid://cbajqkgudfvh0" path="res://src/ui_parts/viewport_container.gd" id="9_ryr8t"]
[ext_resource type="Texture2D" uid="uid://b7r171i82g3xl" path="res://assets/icons/Translate.svg" id="10_rll1m"]
[ext_resource type="Shader" uid="uid://i2y5pyhcgra2" path="res://src/shaders/zoom_shader.gdshader" id="10_x7ybk"]
[ext_resource type="Texture2D" uid="uid://c68og6bsqt0lb" path="res://assets/icons/backgrounds/Checkerboard.svg" id="11_1bm1s"]
[ext_resource type="Script" uid="uid://dtplje5mhdmrj" path="res://src/ui_parts/display_texture.gd" id="12_qi23s"]
[ext_resource type="Script" uid="uid://csqewpxr21ywy" path="res://src/ui_parts/handles_manager.gd" id="13_lwhwy"]
[ext_resource type="Texture2D" uid="uid://8x628rb2bnep" path="res://assets/icons/TabSwitcher.svg" id="14_ryr8t"]
-[ext_resource type="Script" uid="uid://cm5033meho5vr" path="res://src/ui_widgets/camera.gd" id="15_hevpa"]
[ext_resource type="Texture2D" uid="uid://d04w7h3k83w8u" path="res://assets/icons/element/svg.svg" id="15_kq8gf"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_kqplg"]
@@ -40,9 +40,11 @@ size_flags_vertical = 3
layout_mode = 2
[node name="ViewportContainer" type="SubViewportContainer" parent="ViewportPanel/VBoxContainer"]
+clip_contents = true
layout_mode = 2
size_flags_vertical = 3
stretch = true
+script = ExtResource("9_ryr8t")
[node name="Viewport" type="SubViewport" parent="ViewportPanel/VBoxContainer/ViewportContainer"]
unique_name_in_owner = true
@@ -86,12 +88,6 @@ anchors_preset = 0
mouse_filter = 1
script = ExtResource("13_lwhwy")
-[node name="Camera" type="Control" parent="ViewportPanel/VBoxContainer/ViewportContainer/Viewport"]
-layout_mode = 3
-anchors_preset = 0
-mouse_filter = 2
-script = ExtResource("15_hevpa")
-
[node name="Toolbar" type="PanelContainer" parent="ViewportPanel/VBoxContainer"]
layout_mode = 2
diff --git a/src/ui_parts/donate_menu.tscn b/src/ui_parts/donate_menu.tscn
index 3166555..8be6b65 100644
--- a/src/ui_parts/donate_menu.tscn
+++ b/src/ui_parts/donate_menu.tscn
@@ -28,7 +28,7 @@ theme_override_constants/separation = 4
[node name="TitleLabel" type="Label" parent="VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
-theme_override_font_sizes/font_size = 15
+theme_type_variation = &"TitleLabel"
horizontal_alignment = 1
[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer"]
diff --git a/src/ui_parts/export_menu.gd b/src/ui_parts/export_menu.gd
index 4472b43..cf7609a 100644
--- a/src/ui_parts/export_menu.gd
+++ b/src/ui_parts/export_menu.gd
@@ -83,21 +83,21 @@ func _on_export_button_pressed() -> void:
func _on_dropdown_value_changed(new_value: String) -> void:
var current_format := export_data.format
- undo_redo.create_action("")
+ undo_redo.create_action()
undo_redo.add_do_property(export_data, "format", new_value)
undo_redo.add_undo_property(export_data, "format", current_format)
undo_redo.commit_action()
func _on_lossless_check_box_toggled(toggled_on: bool) -> void:
var current_lossy := export_data.lossy
- undo_redo.create_action("")
+ undo_redo.create_action()
undo_redo.add_do_property(export_data, "lossy", not toggled_on)
undo_redo.add_undo_property(export_data, "lossy", current_lossy)
undo_redo.commit_action()
func _on_quality_value_changed(new_value: float) -> void:
var current_quality := export_data.quality
- undo_redo.create_action("")
+ undo_redo.create_action()
undo_redo.add_do_property(export_data, "quality", new_value / 100)
undo_redo.add_undo_property(export_data, "quality", current_quality)
undo_redo.commit_action()
@@ -106,7 +106,7 @@ func _on_scale_edit_value_changed(new_value: float) -> void:
if new_value == export_data.upscale_amount:
return
var current_upscale_amount := export_data.upscale_amount
- undo_redo.create_action("")
+ undo_redo.create_action()
undo_redo.add_do_property(export_data, "upscale_amount", new_value)
undo_redo.add_undo_property(export_data, "upscale_amount", current_upscale_amount)
undo_redo.commit_action()
@@ -115,7 +115,7 @@ func _on_width_edit_value_changed(new_value: float) -> void:
if roundi(dimensions.x * export_data.upscale_amount) == roundi(new_value):
return
var current_upscale_amount := export_data.upscale_amount
- undo_redo.create_action("")
+ undo_redo.create_action()
undo_redo.add_do_property(export_data, "upscale_amount", new_value / dimensions.x)
undo_redo.add_undo_property(export_data, "upscale_amount", current_upscale_amount)
undo_redo.commit_action()
@@ -124,7 +124,7 @@ func _on_height_edit_value_changed(new_value: float) -> void:
if roundi(dimensions.y * export_data.upscale_amount) == roundi(new_value):
return
var current_upscale_amount := export_data.upscale_amount
- undo_redo.create_action("")
+ undo_redo.create_action()
undo_redo.add_do_property(export_data, "upscale_amount", new_value / dimensions.y)
undo_redo.add_undo_property(export_data, "upscale_amount", current_upscale_amount)
undo_redo.commit_action()
diff --git a/src/ui_parts/good_file_dialog.tscn b/src/ui_parts/good_file_dialog.tscn
index 77c4c33..a340d42 100644
--- a/src/ui_parts/good_file_dialog.tscn
+++ b/src/ui_parts/good_file_dialog.tscn
@@ -21,7 +21,7 @@ theme_override_constants/separation = 8
[node name="TitleLabel" type="Label" parent="VBoxContainer"]
layout_mode = 2
-theme_override_font_sizes/font_size = 15
+theme_type_variation = &"TitleLabel"
horizontal_alignment = 1
[node name="TopBar" type="HBoxContainer" parent="VBoxContainer"]
diff --git a/src/ui_parts/handles_manager.gd b/src/ui_parts/handles_manager.gd
index 63fc6a0..38d0bce 100644
--- a/src/ui_parts/handles_manager.gd
+++ b/src/ui_parts/handles_manager.gd
@@ -798,7 +798,7 @@ func _unhandled_input(event: InputEvent) -> void:
event.button_mask == 0) or (event is InputEventMouseButton and\
(event.button_index in [MOUSE_BUTTON_LEFT, MOUSE_BUTTON_RIGHT]))):
var nearest_handle := find_nearest_handle(event.position / State.zoom +\
- get_parent().view.position)
+ get_parent().get_parent().camera_position)
if is_instance_valid(nearest_handle):
hovered_handle = nearest_handle
if hovered_handle is PathHandle:
@@ -910,7 +910,7 @@ func find_nearest_handle(event_pos: Vector2) -> Handle:
# Two 64-bit coordinates instead of a Vector2.
func get_event_pos(event: InputEvent) -> PackedFloat64Array:
- return apply_snap(event.position / State.zoom + get_parent().view.position)
+ return apply_snap(event.position / State.zoom + get_parent().get_parent().camera_position)
func apply_snap(pos: Vector2) -> PackedFloat64Array:
var precision_snap := 0.1 ** maxi(ceili(-log(1.0 / State.zoom) / log(10)), 0)
diff --git a/src/ui_parts/import_warning_menu.tscn b/src/ui_parts/import_warning_menu.tscn
index 2a6594d..065d76b 100644
--- a/src/ui_parts/import_warning_menu.tscn
+++ b/src/ui_parts/import_warning_menu.tscn
@@ -25,7 +25,7 @@ theme_override_constants/separation = 12
[node name="TitleLabel" type="Label" parent="VBoxContainer"]
layout_mode = 2
-theme_override_font_sizes/font_size = 15
+theme_type_variation = &"TitleLabel"
horizontal_alignment = 1
[node name="TextureContainer" type="HBoxContainer" parent="VBoxContainer"]
diff --git a/src/ui_parts/inspector.gd b/src/ui_parts/inspector.gd
index 85e6e54..f7d9a56 100644
--- a/src/ui_parts/inspector.gd
+++ b/src/ui_parts/inspector.gd
@@ -5,21 +5,22 @@ extends VTitledPanel
func _ready() -> void:
- Configs.theme_changed.connect(update_theme)
- Configs.language_changed.connect(update_translation)
- update_theme()
- update_translation()
+ Configs.theme_changed.connect(sync_theming)
+ Configs.language_changed.connect(sync_localization)
+ sync_theming()
+ sync_localization()
State.xnode_layout_changed.connect(full_rebuild)
State.svg_unknown_change.connect(full_rebuild)
full_rebuild()
add_button.pressed.connect(_on_add_button_pressed)
-func update_theme() -> void:
+
+func sync_theming() -> void:
color = Color.TRANSPARENT
border_color = ThemeUtils.subtle_panel_border_color
title_color = ThemeUtils.basic_panel_inner_color
-func update_translation() -> void:
+func sync_localization() -> void:
add_button.text = Translator.translate("Add element")
diff --git a/src/ui_parts/layout_popup.gd b/src/ui_parts/layout_popup.gd
index 1268656..b7bdc44 100644
--- a/src/ui_parts/layout_popup.gd
+++ b/src/ui_parts/layout_popup.gd
@@ -88,7 +88,7 @@ func _on_window_mouse_exited() -> void:
# Drawing
func _draw() -> void:
- get_theme_stylebox("panel", "PanelContainer").draw(ci, Rect2(Vector2.ZERO, get_size()))
+ get_theme_stylebox("panel", "PanelContainer").draw(ci, Rect2(Vector2.ZERO, size))
var half_width := size.x / 2.0 - PANEL_MARGIN
var right_rect := Rect2(size.x / 2.0, PANEL_MARGIN, half_width, half_width * 1.25)
diff --git a/src/ui_parts/settings_menu.gd b/src/ui_parts/settings_menu.gd
index 36f8c85..1a16f3d 100644
--- a/src/ui_parts/settings_menu.gd
+++ b/src/ui_parts/settings_menu.gd
@@ -1,45 +1,44 @@
extends PanelContainer
-const PaletteConfigWidgetScene = preload("res://src/ui_widgets/palette_config.tscn")
-const ShortcutConfigWidgetScene = preload("res://src/ui_widgets/setting_shortcut.tscn")
-const ShortcutShowcaseWidgetScene = preload("res://src/ui_widgets/presented_shortcut.tscn")
-const SettingFrameScene = preload("res://src/ui_widgets/setting_frame.tscn")
-const ProfileFrameScene = preload("res://src/ui_widgets/profile_frame.tscn")
-
-const plus_icon = preload("res://assets/icons/Plus.svg")
-const import_icon = preload("res://assets/icons/Import.svg")
-const reset_icon = preload("res://assets/icons/Reload.svg")
+const SettingsContentGeneric = preload("res://src/ui_widgets/settings_content_generic.tscn")
+const SettingsContentPalettes = preload("res://src/ui_widgets/settings_content_palettes.tscn")
+const SettingsContentShortcuts = preload("res://src/ui_widgets/settings_content_shortcuts.tscn")
@onready var lang_button: Button = $VBoxContainer/Language
@onready var scroll_container: ScrollContainer = %ScrollContainer
@onready var content_container: MarginContainer = %ScrollContainer/ContentContainer
@onready var tabs: VBoxContainer = %Tabs
@onready var close_button: Button = $VBoxContainer/CloseButton
-@onready var advice_panel: PanelContainer = $VBoxContainer/AdvicePanel
-@onready var advice_label: Label = $VBoxContainer/AdvicePanel/AdviceLabel
+@onready var preview_panel: PanelContainer = $VBoxContainer/PreviewPanel
+
+enum TabIndex {FORMATTING, PALETTES, SHORTCUTS, THEMING, TAB_BAR, OTHER}
+
+func get_tab_localized_name(tab_index: TabIndex) -> String:
+ match tab_index:
+ TabIndex.FORMATTING: return Translator.translate("Formatting")
+ TabIndex.PALETTES: return Translator.translate("Palettes")
+ TabIndex.SHORTCUTS: return Translator.translate("Shortcuts")
+ TabIndex.THEMING: return Translator.translate("Theming")
+ TabIndex.TAB_BAR: return Translator.translate("Tab bar")
+ TabIndex.OTHER: return Translator.translate("Other")
+ return ""
-var focused_tab := ""
-var current_setup_setting := ""
-var current_setup_resource: ConfigResource
-var setting_container: VBoxContainer
-var advice: Dictionary[String, String] = {}
+@warning_ignore("int_as_enum_without_match")
+var focused_tab_index := -1 as TabIndex
func _ready() -> void:
close_button.pressed.connect(queue_free)
- Configs.language_changed.connect(setup_everything)
-
change_orientation()
Configs.orientation_changed.connect(change_orientation)
scroll_container.get_v_scroll_bar().visibility_changed.connect(adjust_right_margin)
adjust_right_margin()
- update_language_button()
- update_close_button()
- setup_tabs()
- tabs.get_child(0).button_pressed = true
- Configs.theme_changed.connect(update_theme)
- update_theme()
+ Configs.theme_changed.connect(sync_theming)
+ sync_theming()
+ Configs.language_changed.connect(sync_localization)
+ sync_localization()
+ press_tab(0)
func change_orientation():
if Configs.current_orientation == Configs.orientation.PORTRAIT:
@@ -49,11 +48,27 @@ func change_orientation():
$VBoxContainer/BoxContainer.vertical = false
$VBoxContainer/BoxContainer/PanelContainer.size_flags_horizontal = SIZE_EXPAND_FILL
-func update_theme() -> void:
+func _unhandled_input(event: InputEvent) -> void:
+ var tab_count := TabIndex.size()
+ if ShortcutUtils.is_action_pressed(event, "select_next_tab"):
+ press_tab((focused_tab_index + 1) % tab_count)
+ elif ShortcutUtils.is_action_pressed(event, "select_previous_tab"):
+ press_tab((focused_tab_index + tab_count - 1) % tab_count)
+
+func press_tab(index: int) -> void:
+ tabs.get_child(index).button_pressed = true
+
+func sync_theming() -> void:
var stylebox := ThemeDB.get_default_theme().get_stylebox("panel", theme_type_variation).duplicate()
stylebox.content_margin_top += 4.0
add_theme_stylebox_override("panel", stylebox)
+func sync_localization() -> void:
+ close_button.text = Translator.translate("Close")
+ lang_button.text = Translator.translate("Language") + ": " +\
+ TranslationUtils.get_locale_string(TranslationServer.get_locale())
+ setup_tabs()
+
func adjust_right_margin() -> void:
var scrollbar := scroll_container.get_v_scroll_bar()
content_container.add_theme_constant_override("margin_right",
@@ -63,389 +78,63 @@ func setup_tabs() -> void:
for tab in tabs.get_children():
tab.queue_free()
var button_group := ButtonGroup.new()
- add_tab("formatting", Translator.translate("Formatting"), button_group)
- add_tab("palettes", Translator.translate("Palettes"), button_group)
- # Removing shortcuts tab as this is not really needed for mobile port.
- #add_tab("shortcuts", Translator.translate("Shortcuts"), button_group)
- add_tab("theming", Translator.translate("Theming"), button_group)
- add_tab("other", Translator.translate("Other"), button_group)
-
-func add_tab(tab_name: String, tab_text: String, button_group: ButtonGroup) -> void:
- var tab := Button.new()
- tab.text = tab_text
- tab.alignment = HORIZONTAL_ALIGNMENT_LEFT
- tab.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
- tab.toggle_mode = true
- tab.action_mode = BaseButton.ACTION_MODE_BUTTON_PRESS
- tab.focus_mode = Control.FOCUS_NONE
- tab.theme_type_variation = "SideTab"
- tab.toggled.connect(_on_tab_toggled.bind(tab_name))
- tab.button_group = button_group
- tab.button_pressed = (tab_name == focused_tab)
- tabs.add_child(tab)
-
-func setup_everything() -> void:
- update_language_button()
- setup_tabs()
- setup_content()
- update_close_button()
-
-func update_close_button() -> void:
- close_button.text = Translator.translate("Close")
-
-func _on_tab_toggled(toggled_on: bool, tab_name: String) -> void:
- if toggled_on and focused_tab != tab_name:
- focused_tab = tab_name
+ for tab_index in TabIndex.size():
+ if tab_index in [TabIndex.SHORTCUTS, TabIndex.TAB_BAR]:
+ continue
+ var tab := Button.new()
+ tab.text = get_tab_localized_name(tab_index)
+ tab.alignment = HORIZONTAL_ALIGNMENT_LEFT
+ tab.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
+ tab.toggle_mode = true
+ tab.action_mode = BaseButton.ACTION_MODE_BUTTON_PRESS
+ tab.focus_mode = Control.FOCUS_NONE
+ tab.theme_type_variation = "SideTab"
+ tab.toggled.connect(_on_tab_toggled.bind(tab_index))
+ tab.button_group = button_group
+ tab.button_pressed = (tab_index == focused_tab_index)
+ tabs.add_child(tab)
+
+
+func _on_tab_toggled(toggled_on: bool, tab_index: TabIndex) -> void:
+ if toggled_on and focused_tab_index != tab_index:
+ focused_tab_index = tab_index
setup_content()
-func setup_content(reset_scroll := true) -> void:
- if reset_scroll:
- scroll_container.scroll_vertical = 0
-
+func setup_content() -> void:
+ scroll_container.scroll_vertical = 0
for child in content_container.get_children():
child.queue_free()
- match focused_tab:
- "formatting":
- advice_panel.hide()
- var vbox := VBoxContainer.new()
- vbox.size_flags_horizontal = Control.SIZE_EXPAND_FILL
- vbox.add_theme_constant_override("separation", 6)
- content_container.add_child(vbox)
- var categories := HFlowContainer.new()
- categories.alignment = FlowContainer.ALIGNMENT_CENTER
- var button_group := ButtonGroup.new()
- for tab_idx in formatter_tab_names:
- var btn := Button.new()
- btn.toggle_mode = true
- btn.button_group = button_group
- btn.pressed.connect(show_formatter.bind(tab_idx))
- btn.text = get_translated_formatter_tab(tab_idx)
- btn.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
- btn.focus_mode = Control.FOCUS_NONE
- btn.action_mode = BaseButton.ACTION_MODE_BUTTON_PRESS
- categories.add_child(btn)
- vbox.add_child(categories)
- create_setting_container()
- vbox.add_child(setting_container)
- categories.get_child(0).button_pressed = true
- categories.get_child(0).pressed.emit()
- "palettes":
- advice_panel.hide()
- var vbox := VBoxContainer.new()
- vbox.size_flags_horizontal = Control.SIZE_EXPAND_FILL
- content_container.add_child(vbox)
- rebuild_palettes()
- #"shortcuts":
- #advice_panel.hide()
- #var vbox := VBoxContainer.new()
- #vbox.size_flags_horizontal = Control.SIZE_EXPAND_FILL
- #vbox.add_theme_constant_override("separation", 6)
- #content_container.add_child(vbox)
- #var categories := HFlowContainer.new()
- #var button_group := ButtonGroup.new()
- #for tab_idx in shortcut_tab_names:
- #var btn := Button.new()
- #btn.toggle_mode = true
- #btn.button_group = button_group
- #btn.pressed.connect(show_shortcuts.bind(tab_idx))
- #btn.text = get_translated_shortcut_tab(tab_idx)
- #btn.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
- #btn.focus_mode = Control.FOCUS_NONE
- #btn.action_mode = BaseButton.ACTION_MODE_BUTTON_PRESS
- #categories.add_child(btn)
- #vbox.add_child(categories)
- #var shortcuts := VBoxContainer.new()
- #shortcuts.add_theme_constant_override("separation", 3)
- #shortcuts.size_flags_horizontal = Control.SIZE_EXPAND_FILL
- #shortcuts.size_flags_vertical = Control.SIZE_EXPAND_FILL
- #vbox.add_child(shortcuts)
- #categories.get_child(0).button_pressed = true
- #categories.get_child(0).pressed.emit()
- "theming":
- advice_panel.hide()
- create_setting_container()
- content_container.add_child(setting_container)
-
- current_setup_resource = Configs.savedata
-
- current_setup_setting = "theme_preset"
- add_profile_picker(Translator.translate("Theme preset"),
- current_setup_resource.reset_theme_items_to_default,
- SaveData.ThemePreset.size(), SaveData.get_theme_preset_value_text_map(),
- current_setup_resource.is_theming_default)
-
- add_section(Translator.translate("Primary theme colors"))
- current_setup_setting = "base_color"
- add_color_edit(Translator.translate("Base color"), false)
- current_setup_setting = "accent_color"
- add_color_edit(Translator.translate("Accent color"), false)
-
- add_section(Translator.translate("SVG Text colors"))
- current_setup_setting = "highlighter_preset"
- add_profile_picker(Translator.translate("Highlighter preset"),
- current_setup_resource.reset_highlighting_items_to_default,
- SaveData.HighlighterPreset.size(),
- SaveData.get_highlighter_preset_value_text_map(),
- current_setup_resource.is_highlighting_default)
- current_setup_setting = "highlighting_symbol_color"
- add_color_edit(Translator.translate("Symbol color"))
- current_setup_setting = "highlighting_element_color"
- add_color_edit(Translator.translate("Element color"))
- current_setup_setting = "highlighting_attribute_color"
- add_color_edit(Translator.translate("Attribute color"))
- current_setup_setting = "highlighting_string_color"
- add_color_edit(Translator.translate("String color"))
- current_setup_setting = "highlighting_comment_color"
- add_color_edit(Translator.translate("Comment color"))
- current_setup_setting = "highlighting_text_color"
- add_color_edit(Translator.translate("Text color"))
- current_setup_setting = "highlighting_cdata_color"
- add_color_edit(Translator.translate("CDATA color"))
- current_setup_setting = "highlighting_error_color"
- add_color_edit(Translator.translate("Error color"))
-
- add_section(Translator.translate("Handles"))
- current_setup_setting = "handle_size"
- add_number_dropdown(Translator.translate("Size"),
- [0.75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.5, 3.0], false, false,
- SaveData.HANDLE_SIZE_MIN, SaveData.HANDLE_SIZE_MAX)
- current_setup_setting = "handle_inner_color"
- add_color_edit(Translator.translate("Inside color"), false)
- current_setup_setting = "handle_color"
- add_color_edit(Translator.translate("Normal color"), false)
- current_setup_setting = "handle_hovered_color"
- add_color_edit(Translator.translate("Hovered color"), false)
- current_setup_setting = "handle_selected_color"
- add_color_edit(Translator.translate("Selected color"), false)
- current_setup_setting = "handle_hovered_selected_color"
- add_color_edit(Translator.translate("Hovered selected color"), false)
-
- add_section(Translator.translate("Selection rectangle"))
- current_setup_setting = "selection_rectangle_speed"
- add_number_dropdown(Translator.translate("Speed"),
- [0.0, 10.0, 20.0, 30.0, 50.0, 80.0, 130.0], false, false,
- -SaveData.MAX_SELECTION_RECTANGLE_SPEED,
- SaveData.MAX_SELECTION_RECTANGLE_SPEED)
- current_setup_setting = "selection_rectangle_width"
- add_number_dropdown(Translator.translate("Width"),
- [1.0, 2.0, 3.0, 4.0], false, false, 1.0,
- SaveData.MAX_SELECTION_RECTANGLE_WIDTH)
- current_setup_setting = "selection_rectangle_dash_length"
- add_number_dropdown(Translator.translate("Dash length"),
- [5.0, 10.0, 15.0, 20.0], false, false, 1.0,
- SaveData.MAX_SELECTION_RECTANGLE_DASH_LENGTH)
- current_setup_setting = "selection_rectangle_color1"
- add_color_edit(Translator.translate("Color {index}").format({"index": "1"}))
- current_setup_setting = "selection_rectangle_color2"
- add_color_edit(Translator.translate("Color {index}").format({"index": "2"}))
-
- add_section(Translator.translate("Basic colors"))
- current_setup_setting = "canvas_color"
- add_color_edit(Translator.translate("Canvas color"), false)
- current_setup_setting = "grid_color"
- add_color_edit(Translator.translate("Grid color"), false)
- current_setup_setting = "basic_color_valid"
- add_color_edit(Translator.translate("Valid color"))
- current_setup_setting = "basic_color_error"
- add_color_edit(Translator.translate("Error color"))
- current_setup_setting = "basic_color_warning"
- add_color_edit(Translator.translate("Warning color"))
- "tab_bar":
- advice_panel.show()
- create_setting_container()
- content_container.add_child(setting_container)
- current_setup_resource = Configs.savedata
-
- add_section(Translator.translate("Input"))
- current_setup_setting = "tab_mmb_close"
- add_checkbox(Translator.translate("Close tabs with middle mouse button"))
- add_advice(Translator.translate("If turned on, clicking on a tab with the middle mouse button closes the tab. If turned off, it focuses the tab instead."))
- "other":
- advice_panel.show()
- create_setting_container()
- content_container.add_child(setting_container)
- current_setup_resource = Configs.savedata
-
- add_section(Translator.translate("Input"))
- current_setup_setting = "invert_zoom"
- add_checkbox(Translator.translate("Invert zoom direction"))
- add_advice(Translator.translate("Swaps the scroll directions for zooming in and zooming out."))
- current_setup_setting = "wraparound_panning"
- var wraparound_panning := add_checkbox(Translator.translate("Wrap-around panning"))
- add_advice(Translator.translate("Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning."))
- current_setup_setting = "use_ctrl_for_zoom"
- add_checkbox(Translator.translate("Use CTRL for zooming"))
- add_advice(Translator.translate("If turned on, scrolling pans the view. To zoom, hold CTRL while scrolling."))
-
- add_section(Translator.translate("Display"))
- # Prepare parameters for the UI scale setting.
- current_setup_setting = "ui_scale"
-
- var auto_scale: float = HandlerGUI.get_auto_ui_scale()
- var all_options := {
- SaveData.ScalingApproach.CONSTANT_100: 1.0,
- SaveData.ScalingApproach.CONSTANT_125: 1.25,
- SaveData.ScalingApproach.CONSTANT_150: 1.5,
- SaveData.ScalingApproach.CONSTANT_175: 1.75,
- SaveData.ScalingApproach.CONSTANT_200: 2.0,
- SaveData.ScalingApproach.CONSTANT_225: 2.25,
- SaveData.ScalingApproach.CONSTANT_250: 2.5,
- SaveData.ScalingApproach.CONSTANT_275: 2.75,
- SaveData.ScalingApproach.CONSTANT_300: 3.0
- }
- var dropdown_map := {
- SaveData.ScalingApproach.AUTO: "Auto (%d%%)" % int(auto_scale * 100),
- }
- for approach in all_options.keys():
- var value: float= all_options[approach]
- dropdown_map[approach] = "%d%%" % int(value * 100)
-
- add_dropdown(Translator.translate("UI scale"), dropdown_map.keys(), dropdown_map)
- add_advice(Translator.translate("Changes the scale factor for the interface."))
-
- current_setup_setting = "vsync"
- add_checkbox(Translator.translate("V-Sync"))
- add_advice(Translator.translate("Synchronizes graphics rendering with display refresh rate to prevent screen tearing artifacts. May increase input lag slightly."))
-
- current_setup_setting = "max_fps"
- add_fps_limit_dropdown(Translator.translate("Maximum FPS"))
- add_advice(Translator.translate("Determines the maximum number of frames per second."))
-
- add_section(Translator.translate("Miscellaneous"))
- current_setup_setting = "use_native_file_dialog"
- var use_native_file_dialog := add_checkbox(Translator.translate("Use native file dialog"))
- add_advice(Translator.translate("If turned on, uses your operating system's native file dialog. If turned off, uses GodSVG's built-in file dialog."))
- current_setup_setting = "use_filename_for_window_title"
- add_checkbox(Translator.translate("Sync window title to file name"))
- add_advice(Translator.translate("If turned off, the window title remains as \"GodSVG\" without including the current file."))
-
- # Disable mouse wrap if not available.
- if not DisplayServer.has_feature(DisplayServer.FEATURE_MOUSE_WARP):
- wraparound_panning.permanent_disable_checkbox(false)
- # Disable fallback file dialog on web, and native file dialog if not available.
- if OS.has_feature("web"):
- use_native_file_dialog.permanent_disable_checkbox(true)
- elif not DisplayServer.has_feature(DisplayServer.FEATURE_NATIVE_DIALOG_FILE):
- use_native_file_dialog.permanent_disable_checkbox(false)
-
+ match focused_tab_index:
+ TabIndex.FORMATTING:
+ preview_panel.show()
+ var current_content := SettingsContentGeneric.instantiate()
+ current_content.setup([Configs.savedata.editor_formatter,
+ Configs.savedata.export_formatter] as Array[ConfigResource], focused_tab_index)
+ content_container.add_child(current_content)
+ current_content.preview_changed.connect(set_preview)
+ TabIndex.PALETTES:
+ preview_panel.hide()
+ var current_content := SettingsContentPalettes.instantiate()
+ content_container.add_child(current_content)
+ TabIndex.SHORTCUTS:
+ preview_panel.hide()
+ var current_content := SettingsContentShortcuts.instantiate()
+ content_container.add_child(current_content)
+ TabIndex.THEMING, TabIndex.TAB_BAR, TabIndex.OTHER:
+ preview_panel.show()
+ var current_content := SettingsContentGeneric.instantiate()
+ current_content.setup([Configs.savedata] as Array[ConfigResource], focused_tab_index)
+ content_container.add_child(current_content)
+ current_content.preview_changed.connect(set_preview)
# Update hover.
HandlerGUI.throw_mouse_motion_event()
-func add_section(section_name: String) -> void:
- var vbox := VBoxContainer.new()
- vbox.add_theme_constant_override("separation", 0)
- var label := Label.new()
- label.add_theme_font_size_override("font_size", 15)
- label.theme_type_variation = "TitleLabel"
- label.text = section_name
- vbox.add_child(label)
- var spacer := Control.new()
- spacer.custom_minimum_size.y = 2
- vbox.add_child(spacer)
- setting_container.add_child(vbox)
-
-func add_profile_picker(text: String, application_callback: Callable, profile_count: int,
-value_text_map: Dictionary, disabled_check_callback: Callable) -> void:
- var bind := current_setup_setting
- var frame := ProfileFrameScene.instantiate()
- frame.setup_dropdown(range(profile_count), value_text_map)
- frame.getter = current_setup_resource.get.bind(bind)
- var resource_permanent_ref := current_setup_resource
- frame.setter = func(p: Variant) -> void:
- resource_permanent_ref.set(bind, p)
- frame.text = text
- frame.disabled_check_callback = disabled_check_callback
- frame.value_changed.connect.call_deferred(setup_content.bind(false))
- frame.defaults_applied.connect(application_callback)
- frame.defaults_applied.connect(setup_content.bind(false))
- add_frame(frame)
-
- resource_permanent_ref.changed_deferred.connect(frame.button_update_disabled)
- frame.tree_exited.connect(resource_permanent_ref.changed_deferred.disconnect.bind(
- frame.button_update_disabled), CONNECT_ONE_SHOT)
-
-
-func add_checkbox(text: String, dim_text := false) -> Control:
- var frame := SettingFrameScene.instantiate()
- frame.dim_text = dim_text
- frame.text = text
- setup_frame(frame)
- frame.setup_checkbox()
- add_frame(frame)
- # Some checkboxes need to update the dimness of the text of other settings.
- # There's nothing persistent in checkboxes, so it's safe to just rebuild the content
- # for them, specifically.
- frame.value_changed.connect(setup_content.bind(false))
- return frame
-
-# TODO Typed Dictionary wonkiness
-func add_dropdown(text: String, values: Array[Variant], value_text_map: Dictionary) -> Control: # Dictionary[Variant, String]
- var frame := SettingFrameScene.instantiate()
- frame.text = text
- setup_frame(frame)
- frame.setup_dropdown(values, value_text_map)
- add_frame(frame)
- return frame
-
-func add_number_dropdown(text: String, values: Array[float], is_integer := false,
-restricted := true, min_value := -INF, max_value := INF, dim_text := false) -> Control:
- var frame := SettingFrameScene.instantiate()
- frame.dim_text = dim_text
- frame.text = text
- setup_frame(frame)
- frame.setup_number_dropdown(values, is_integer, restricted, min_value, max_value)
- add_frame(frame)
- return frame
-
-func add_fps_limit_dropdown(text: String, dim_text := false) -> Control:
- var frame := SettingFrameScene.instantiate()
- frame.dim_text = dim_text
- frame.text = text
- setup_frame(frame)
- frame.setup_fps_limit_dropdown()
- add_frame(frame)
- return frame
-
-func add_color_edit(text: String, enable_alpha := true) -> Control:
- var frame := SettingFrameScene.instantiate()
- frame.text = text
- setup_frame(frame)
- frame.setup_color(enable_alpha)
- add_frame(frame)
- return frame
-
-func setup_frame(frame: Control) -> void:
- var bind := current_setup_setting
- frame.getter = current_setup_resource.get.bind(bind)
- frame.setter = func(p: Variant) -> void: current_setup_resource.set(bind, p)
- frame.default = current_setup_resource.get_setting_default(current_setup_setting)
- frame.mouse_entered.connect(show_advice.bind(current_setup_setting))
- frame.mouse_exited.connect(hide_advice.bind(current_setup_setting))
-
-func add_frame(frame: Control) -> void:
- if setting_container.get_child_count() > 0:
- setting_container.get_child(-1).add_child(frame)
- else:
- setting_container.add_child(frame)
-
-func add_advice(text: String) -> void:
- advice[current_setup_setting] = text
-
-
-func show_advice(setting: String) -> void:
- if advice.has(setting):
- advice_label.text = advice[setting]
- advice_label.remove_theme_font_size_override("font_size")
- var advice_font_size := get_theme_font_size("font_size", "Label")
- while advice_label.get_line_count() > 2:
- advice_font_size -= 1
- advice_label.add_theme_font_size_override("font_size", advice_font_size)
-
-func hide_advice(setting: String) -> void:
- if advice.has(setting) and advice_label.text == advice[setting]:
- advice_label.text = ""
+func set_preview(node: Control) -> void:
+ for child in preview_panel.get_children():
+ child.queue_free()
+ preview_panel.add_child(node)
func _on_language_pressed() -> void:
@@ -477,194 +166,3 @@ func _on_language_pressed() -> void:
func _on_language_chosen(locale: String) -> void:
Configs.savedata.language = locale
-
-func update_language_button() -> void:
- lang_button.text = Translator.translate("Language") + ": " +\
- TranslationUtils.get_locale_string(TranslationServer.get_locale())
-
-
-# Palette tab helpers.
-
-func _popup_xml_palette_options(palette_xml_button: Button) -> void:
- var btn_arr: Array[Button] = []
- btn_arr.append(ContextPopup.create_button(Translator.translate("Import XML"),
- add_imported_palette, false, load("res://assets/icons/Import.svg")))
- btn_arr.append(ContextPopup.create_button(Translator.translate("Paste XML"),
- add_pasted_palette, !Palette.is_valid_palette(Utils.get_clipboard_web_safe()),
- load("res://assets/icons/Paste.svg")))
-
- var context_popup := ContextPopup.new()
- context_popup.setup(btn_arr, true)
- HandlerGUI.popup_under_rect_center(context_popup, palette_xml_button.get_global_rect(),
- get_viewport())
-
-
-func add_empty_palette() -> void:
- _shared_add_palette_logic(Palette.new())
-
-func add_pasted_palette() -> void:
- _shared_add_palettes_logic(Palette.text_to_palettes(Utils.get_clipboard_web_safe()))
-
-func add_imported_palette() -> void:
- FileUtils.open_xml_import_dialog(_on_import_palette_finished)
-
-func _on_import_palette_finished(file_text: String) -> void:
- _shared_add_palettes_logic(Palette.text_to_palettes(file_text))
-
-func _shared_add_palettes_logic(palettes: Array[Palette]) -> void:
- if not palettes.is_empty():
- _shared_add_palette_logic(palettes[0])
-
-func _shared_add_palette_logic(palette: Palette) -> void:
- Configs.savedata.add_palette(palette)
- rebuild_palettes()
-
-
-func rebuild_palettes() -> void:
- var palette_container := content_container.get_child(-1)
- for palette_config in palette_container.get_children():
- palette_config.queue_free()
- for palette in Configs.savedata.get_palettes():
- var palette_config := PaletteConfigWidgetScene.instantiate()
- palette_container.add_child(palette_config)
- palette_config.assign_palette(palette)
- palette_config.layout_changed.connect(rebuild_palettes)
-
- # Add the buttons for adding a new palette.
- var spacer := Control.new()
- palette_container.add_child(spacer)
- var hbox := HBoxContainer.new()
- hbox.alignment = BoxContainer.ALIGNMENT_CENTER
- palette_container.add_child(hbox)
-
- var add_palette_button := Button.new()
- add_palette_button.theme_type_variation = "TranslucentButton"
- add_palette_button.icon = plus_icon
- add_palette_button.text = Translator.translate("New palette")
- add_palette_button.focus_mode = Control.FOCUS_NONE
- add_palette_button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
- add_palette_button.pressed.connect(add_empty_palette)
- hbox.add_child(add_palette_button)
-
- var xml_palette_button := Button.new()
- xml_palette_button.theme_type_variation = "TranslucentButton"
- xml_palette_button.icon = import_icon
- xml_palette_button.text = Translator.translate("New palette from XML")
- xml_palette_button.focus_mode = Control.FOCUS_NONE
- xml_palette_button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
- hbox.add_child(xml_palette_button)
- xml_palette_button.pressed.connect(_popup_xml_palette_options.bind(xml_palette_button))
-
-
-var shortcut_tab_names := PackedStringArray(["file", "edit", "view", "tool", "help"])
-var formatter_tab_names := PackedStringArray(["editor", "export"])
-
-func get_translated_formatter_tab(tab_idx: String) -> String:
- match tab_idx:
- "editor": return Translator.translate("Editor formatter")
- "export": return Translator.translate("Export formatter")
- return ""
-
-func get_translated_shortcut_tab(tab_idx: String) -> String:
- match tab_idx:
- "file": return Translator.translate("File")
- "edit": return Translator.translate("Edit")
- "view": return Translator.translate("View")
- "tool": return Translator.translate("Tool")
- "help": return Translator.translate("Help")
- return ""
-
-
-func show_formatter(category: String) -> void:
- for child in setting_container.get_children():
- child.queue_free()
-
- match category:
- "editor": current_setup_resource = Configs.savedata.editor_formatter
- "export": current_setup_resource = Configs.savedata.export_formatter
-
- current_setup_setting = "preset"
- add_profile_picker(Translator.translate("Preset"),
- current_setup_resource.reset_to_default, Formatter.Preset.size(),
- Formatter.get_preset_value_text_map(), current_setup_resource.is_everything_default)
-
- add_section("XML")
- current_setup_setting = "xml_keep_comments"
- add_checkbox(Translator.translate("Keep comments"))
- current_setup_setting = "xml_keep_unrecognized"
- add_checkbox(Translator.translate("Keep unrecognized XML structures"))
- current_setup_setting = "xml_add_trailing_newline"
- add_checkbox(Translator.translate("Add trailing newline"))
- current_setup_setting = "xml_shorthand_tags"
- add_dropdown(Translator.translate("Use shorthand tag syntax"),
- range(Formatter.ShorthandTags.size()),
- Formatter.get_shorthand_tags_value_text_map())
- current_setup_setting = "xml_shorthand_tags_space_out_slash"
- add_checkbox(Translator.translate("Space out the slash of shorthand tags"))
- current_setup_setting = "xml_pretty_formatting"
- add_checkbox(Translator.translate("Use pretty formatting"))
- current_setup_setting = "xml_indentation_use_spaces"
- add_checkbox(Translator.translate("Use spaces instead of tabs"),
- not current_setup_resource.xml_pretty_formatting)
- current_setup_setting = "xml_indentation_spaces"
- add_number_dropdown(Translator.translate("Number of indentation spaces"),
- [2, 3, 4, 6, 8], true, false, Formatter.INDENTS_MIN, Formatter.INDENTS_MAX,
- not (current_setup_resource.xml_pretty_formatting and\
- current_setup_resource.xml_indentation_use_spaces))
-
- add_section(Translator.translate("Numbers"))
- current_setup_setting = "number_remove_leading_zero"
- add_checkbox(Translator.translate("Remove leading zero"))
- current_setup_setting = "number_use_exponent_if_shorter"
- add_checkbox(Translator.translate("Use exponential when shorter"))
-
- add_section(Translator.translate("Colors"))
- current_setup_setting = "color_use_named_colors"
- add_dropdown(Translator.translate("Use named colors"),
- range(Formatter.NamedColorUse.size()),
- Formatter.get_named_color_use_value_text_map())
- current_setup_setting = "color_primary_syntax"
- add_dropdown(Translator.translate("Primary syntax"),
- range(Formatter.PrimaryColorSyntax.size()),
- Formatter.get_primary_color_syntax_value_text_map())
- current_setup_setting = "color_capital_hex"
- add_checkbox(Translator.translate("Capitalize hexadecimal letters"),
- current_setup_resource.color_primary_syntax == Formatter.PrimaryColorSyntax.RGB)
-
- add_section(Translator.translate("Pathdata"))
- current_setup_setting = "pathdata_compress_numbers"
- add_checkbox(Translator.translate("Compress numbers"))
- current_setup_setting = "pathdata_minimize_spacing"
- add_checkbox(Translator.translate("Minimize spacing"))
- current_setup_setting = "pathdata_remove_spacing_after_flags"
- add_checkbox(Translator.translate("Remove spacing after flags"))
- current_setup_setting = "pathdata_remove_consecutive_commands"
- add_checkbox(Translator.translate("Remove consecutive commands"))
-
- add_section(Translator.translate("Transform lists"))
- current_setup_setting = "transform_list_compress_numbers"
- add_checkbox(Translator.translate("Compress numbers"))
- current_setup_setting = "transform_list_minimize_spacing"
- add_checkbox(Translator.translate("Minimize spacing"))
- current_setup_setting = "transform_list_remove_unnecessary_params"
- add_checkbox(Translator.translate("Remove unnecessary parameters"))
-
-
-func show_shortcuts(category: String) -> void:
- var shortcuts_container := content_container.get_child(-1).get_child(-1)
- for child in shortcuts_container.get_children():
- child.queue_free()
-
- for action in ShortcutUtils.get_actions(category):
- var shortcut_config := ShortcutConfigWidgetScene.instantiate() if\
- ShortcutUtils.is_action_modifiable(action) else\
- ShortcutShowcaseWidgetScene.instantiate()
-
- shortcuts_container.add_child(shortcut_config)
- shortcut_config.label.text = TranslationUtils.get_action_description(action)
- shortcut_config.setup(action)
-
-func create_setting_container() -> void:
- setting_container = VBoxContainer.new()
- setting_container.add_theme_constant_override("separation", 6)
- setting_container.size_flags_horizontal = Control.SIZE_EXPAND_FILL
diff --git a/src/ui_parts/settings_menu.tscn b/src/ui_parts/settings_menu.tscn
index 05538c5..ba23d79 100644
--- a/src/ui_parts/settings_menu.tscn
+++ b/src/ui_parts/settings_menu.tscn
@@ -60,17 +60,11 @@ theme_override_constants/margin_top = 10
theme_override_constants/margin_right = 2
theme_override_constants/margin_bottom = 4
-[node name="AdvicePanel" type="PanelContainer" parent="VBoxContainer"]
-custom_minimum_size = Vector2(0, 45)
+[node name="PreviewPanel" type="PanelContainer" parent="VBoxContainer"]
+custom_minimum_size = Vector2(0, 48)
layout_mode = 2
theme_type_variation = &"TextBox"
-[node name="AdviceLabel" type="Label" parent="VBoxContainer/AdvicePanel"]
-layout_mode = 2
-size_flags_vertical = 1
-theme_override_constants/line_spacing = 2
-autowrap_mode = 3
-
[node name="CloseButton" type="Button" parent="VBoxContainer"]
layout_mode = 2
size_flags_horizontal = 4
diff --git a/src/ui_parts/tab_bar.gd b/src/ui_parts/tab_bar.gd
index c36f438..dd0fff8 100644
--- a/src/ui_parts/tab_bar.gd
+++ b/src/ui_parts/tab_bar.gd
@@ -401,6 +401,14 @@ func activate() -> void:
var add_rect := get_add_button_rect()
var add_button := Button.new()
add_button.theme_type_variation = "FlatButton"
+ add_button.begin_bulk_theme_override()
+ const CONST_ARR: PackedStringArray = ["hover", "pressed"]
+ for stylebox_theme in CONST_ARR:
+ var sb: StyleBoxFlat = add_button.get_theme_stylebox(stylebox_theme, "FlatButton").duplicate()
+ sb.corner_radius_bottom_left = 0
+ sb.corner_radius_bottom_right = 0
+ add_button.add_theme_stylebox_override(stylebox_theme, sb)
+ add_button.end_bulk_theme_override()
add_button.focus_mode = Control.FOCUS_NONE
add_button.position = add_rect.position
add_button.size = add_rect.size
diff --git a/src/ui_parts/top_app_bar.gd b/src/ui_parts/top_app_bar.gd
index 6f1b732..aa3dc16 100644
--- a/src/ui_parts/top_app_bar.gd
+++ b/src/ui_parts/top_app_bar.gd
@@ -8,23 +8,23 @@ const LayoutPopupScene = preload("res://src/ui_parts/layout_popup.tscn")
@onready var size_button: Button = $SizeButton
@onready var layout_button: Button = $LeftSide/LayoutButton
-func update_translation() -> void:
+func sync_localization() -> void:
layout_button.tooltip_text = Translator.translate("Layout")
func _ready() -> void:
State.svg_changed.connect(update_size_button)
update_size_button()
- Configs.theme_changed.connect(update_theme)
+ Configs.theme_changed.connect(sync_theming)
Configs.basic_colors_changed.connect(update_size_button_colors)
- update_theme()
- Configs.language_changed.connect(update_translation)
- update_translation()
+ sync_theming()
+ Configs.language_changed.connect(sync_localization)
+ sync_localization()
more_options.pressed.connect(_on_more_options_pressed)
size_button.pressed.connect(_on_size_button_pressed)
layout_button.pressed.connect(_on_layout_button_pressed)
-func update_theme() -> void:
+func sync_theming() -> void:
size_button.begin_bulk_theme_override()
const CONST_ARR: PackedStringArray = ["normal", "focus", "hover", "disabled"]
for theme_type in CONST_ARR:
diff --git a/src/ui_parts/update_menu.tscn b/src/ui_parts/update_menu.tscn
index 3fa8d29..08cf685 100644
--- a/src/ui_parts/update_menu.tscn
+++ b/src/ui_parts/update_menu.tscn
@@ -30,7 +30,7 @@ theme_override_constants/separation = 8
[node name="CurrentVersionLabel" type="Label" parent="VBoxContainer"]
layout_mode = 2
-theme_override_font_sizes/font_size = 15
+theme_type_variation = &"TitleLabel"
horizontal_alignment = 1
[node name="IncludePrereleases" type="CheckButton" parent="VBoxContainer"]
diff --git a/src/ui_parts/viewport.gd b/src/ui_parts/viewport.gd
index f164a84..a534979 100644
--- a/src/ui_parts/viewport.gd
+++ b/src/ui_parts/viewport.gd
@@ -1,7 +1,6 @@
extends SubViewport
const ZoomMenu = preload("res://src/ui_widgets/zoom_menu.gd")
-const Camera = preload("res://src/ui_widgets/camera.gd")
const HandlesManager = preload("res://src/ui_parts/handles_manager.gd")
const DisplayTexture = preload("res://src/ui_parts/display_texture.gd")
@@ -11,8 +10,13 @@ const ZOOM_RESET_BUFFER = 0.875
# Holds zoom position for Ctrl + MMB zooming.
var _zoom_to: Vector2
+var limit_left := 0.0
+var limit_right := 0.0
+var limit_top := 0.0
+var limit_bottom := 0.0
+
@onready var display: TextureRect = $Checkerboard
-@onready var view: Camera = $Camera
+@onready var view: SubViewportContainer = get_parent()
@onready var controls: HandlesManager = $Controls
@onready var display_texture: DisplayTexture = $Checkerboard/DisplayTexture
@onready var reference_texture: TextureRect = $ReferenceTexture
@@ -30,14 +34,14 @@ func _ready() -> void:
# Top left corner.
func set_view(new_position: Vector2) -> void:
var scaled_size := size / State.zoom
- view.unsnapped_position = new_position.clamp(Vector2(view.limit_left, view.limit_top),
- Vector2(view.limit_right, view.limit_bottom) - scaled_size)
+ view.camera_unsnapped_position = new_position.clamp(Vector2(limit_left, limit_top),
+ Vector2(limit_right, limit_bottom) - scaled_size)
- var stripped_left := maxf(view.unsnapped_position.x, 0.0)
- var stripped_top := maxf(view.unsnapped_position.y, 0.0)
- var stripped_right := minf(view.unsnapped_position.x + scaled_size.x,
+ var stripped_left := maxf(view.camera_unsnapped_position.x, 0.0)
+ var stripped_top := maxf(view.camera_unsnapped_position.y, 0.0)
+ var stripped_right := minf(view.camera_unsnapped_position.x + scaled_size.x,
State.root_element.width)
- var stripped_bottom := minf(view.unsnapped_position.y + scaled_size.y,
+ var stripped_bottom := minf(view.camera_unsnapped_position.y + scaled_size.y,
State.root_element.height)
display_texture.view_rect = Rect2(stripped_left, stripped_top,
stripped_right - stripped_left, stripped_bottom - stripped_top)
@@ -81,7 +85,7 @@ func _unhandled_input(event: InputEvent) -> void:
# Panning with LMB or MMB. This gives a reliable way to adjust the view
# without dragging the things on it.
else:
- set_view(view.unsnapped_position - (wrap_mouse(event.relative) if\
+ set_view(view.camera_unsnapped_position - (wrap_mouse(event.relative) if\
Configs.savedata.wraparound_panning else event.relative) / State.zoom)
elif event is InputEventPanGesture and not DisplayServer.get_name() == "Android":
@@ -90,7 +94,7 @@ func _unhandled_input(event: InputEvent) -> void:
zoom_menu.set_zoom(State.zoom * (1 + event.delta.y / 2))
# Panning with touch.
else:
- set_view(view.unsnapped_position + event.delta * 32 / State.zoom)
+ set_view(view.camera_unsnapped_position + event.delta * 32 / State.zoom)
# Zooming with touch.
elif event is InputEventMagnifyGesture:
zoom_menu.set_zoom(State.zoom * event.factor)
@@ -136,7 +140,7 @@ func _unhandled_input(event: InputEvent) -> void:
elif zoom_dir == -1:
zoom_menu.zoom_out(factor, mouse_offset)
- set_view(view.unsnapped_position + move_vec * factor / State.zoom * 32)
+ set_view(view.camera_unsnapped_position + move_vec * factor / State.zoom * 32)
else:
if not event.is_echo():
@@ -163,14 +167,14 @@ func adjust_view(offset := Vector2(0.5, 0.5)) -> void:
State.root_element.has_attribute("height") else 16384.0
var zoomed_size := BUFFER_VIEW_SPACE * size / State.zoom
- view.limit_left = -zoomed_size.x
- view.limit_right = zoomed_size.x + svg_w
- view.limit_top = -zoomed_size.y
- view.limit_bottom = zoomed_size.y + svg_h
+ limit_left = -zoomed_size.x
+ limit_right = zoomed_size.x + svg_w
+ limit_top = -zoomed_size.y
+ limit_bottom = zoomed_size.y + svg_h
- set_view(Vector2(lerpf(view.unsnapped_position.x, view.unsnapped_position.x +\
- old_size.x - size.x / State.zoom, offset.x), lerpf(view.unsnapped_position.y,
- view.unsnapped_position.y + old_size.y - size.y / State.zoom, offset.y)))
+ set_view(Vector2(lerpf(view.camera_unsnapped_position.x, view.camera_unsnapped_position.x +\
+ old_size.x - size.x / State.zoom, offset.x), lerpf(view.camera_unsnapped_position.y,
+ view.camera_unsnapped_position.y + old_size.y - size.y / State.zoom, offset.y)))
func _on_size_changed() -> void:
State.set_viewport_size(size)
diff --git a/src/ui_parts/viewport_container.gd b/src/ui_parts/viewport_container.gd
new file mode 100644
index 0000000..c9d2296
--- /dev/null
+++ b/src/ui_parts/viewport_container.gd
@@ -0,0 +1,130 @@
+extends SubViewportContainer
+
+const TICKS_INTERVAL = 4
+const TICK_DISTANCE = float(TICKS_INTERVAL)
+
+var ci := get_canvas_item()
+var grid_ci := RenderingServer.canvas_item_create()
+var grid_numbers_ci := RenderingServer.canvas_item_create()
+
+var camera_zoom: float
+var camera_position: Vector2
+var camera_unsnapped_position: Vector2
+
+
+func _ready() -> void:
+ Configs.grid_color_changed.connect(queue_redraw)
+ State.show_grid_changed.connect(update_show_grid)
+ update_show_grid()
+ RenderingServer.canvas_item_set_parent(grid_ci, ci)
+ RenderingServer.canvas_item_set_parent(grid_numbers_ci, ci)
+ State.svg_resized.connect(queue_redraw)
+ State.zoom_changed.connect(change_zoom)
+ State.zoom_changed.connect(queue_redraw)
+
+func exit_tree() -> void:
+ RenderingServer.free_rid(grid_numbers_ci)
+
+func change_zoom() -> void:
+ camera_zoom = State.zoom
+
+func update_show_grid() -> void:
+ RenderingServer.canvas_item_set_visible(grid_ci, State.show_grid)
+ RenderingServer.canvas_item_set_visible(grid_numbers_ci, State.show_grid)
+
+
+func update() -> void:
+ var new_position := camera_unsnapped_position.snapped(Vector2(1, 1) / camera_zoom)
+ if camera_position != new_position:
+ camera_position = new_position
+ State.view_changed.emit()
+
+ get_child(0).canvas_transform = Transform2D(0.0, Vector2(camera_zoom, camera_zoom),
+ 0.0, -camera_position * camera_zoom)
+ queue_redraw()
+
+
+# Don't ask me to explain this.
+func _draw() -> void:
+ RenderingServer.canvas_item_clear(grid_ci)
+ RenderingServer.canvas_item_clear(grid_numbers_ci)
+
+ var axis_line_color := Color(Configs.savedata.grid_color, 0.75)
+ var major_grid_color := Color(Configs.savedata.grid_color, 0.35)
+ var minor_grid_color := Color(Configs.savedata.grid_color, 0.15)
+
+ var grid_size := Vector2(State.viewport_size) / camera_zoom
+ RenderingServer.canvas_item_add_line(grid_ci, Vector2(-camera_position.x * camera_zoom, 0),
+ Vector2(-camera_position.x * camera_zoom, grid_size.y * camera_zoom), axis_line_color)
+ RenderingServer.canvas_item_add_line(grid_ci, Vector2(0, -camera_position.y * camera_zoom),
+ Vector2(grid_size.x * camera_zoom, -camera_position.y * camera_zoom), axis_line_color)
+
+ var major_points := PackedVector2Array()
+ var minor_points := PackedVector2Array()
+ var draw_minor_lines := (camera_zoom >= 8.0)
+ var mark_pixel_lines := (camera_zoom >= 128.0)
+ @warning_ignore("integer_division")
+ var rate := nearest_po2(roundi(maxf(128.0 / (TICKS_INTERVAL * camera_zoom), 2.0))) / 2
+
+ var i := fmod(-camera_position.x, 1.0)
+ var major_line_h_offset := fposmod(-camera_position.x, TICK_DISTANCE)
+ # Horizontal offset.
+ while i <= grid_size.x:
+ if major_line_h_offset != fposmod(i, TICK_DISTANCE):
+ if draw_minor_lines:
+ minor_points.append(Vector2(i * camera_zoom, 0))
+ minor_points.append(Vector2(i * camera_zoom, grid_size.y * camera_zoom))
+ if mark_pixel_lines:
+ ThemeUtils.regular_font.draw_string(grid_numbers_ci,
+ Vector2(i * camera_zoom + 4, 14), String.num_int64(floori(i + camera_position.x)),
+ HORIZONTAL_ALIGNMENT_LEFT, -1, 14, axis_line_color)
+ else:
+ var coord := snappedi(i + camera_position.x, TICKS_INTERVAL)
+ if int(coord / TICK_DISTANCE) % rate == 0:
+ major_points.append(Vector2(i * camera_zoom, 0))
+ major_points.append(Vector2(i * camera_zoom, grid_size.y * camera_zoom))
+ ThemeUtils.regular_font.draw_string(grid_numbers_ci,
+ Vector2(i * camera_zoom + 4, 14), String.num_int64(coord),
+ HORIZONTAL_ALIGNMENT_LEFT, -1, 14, axis_line_color)
+ elif coord % rate == 0:
+ minor_points.append(Vector2(i * camera_zoom, 0))
+ minor_points.append(Vector2(i * camera_zoom, grid_size.y * camera_zoom))
+ i += 1.0
+
+ i = fmod(-camera_position.y, 1.0)
+ var major_line_v_offset := fposmod(-camera_position.y, TICK_DISTANCE)
+ # Vertical offset.
+ while i < grid_size.y:
+ if major_line_v_offset != fposmod(i, TICK_DISTANCE):
+ if draw_minor_lines:
+ minor_points.append(Vector2(0, i * camera_zoom))
+ minor_points.append(Vector2(grid_size.x * camera_zoom, i * camera_zoom))
+ if mark_pixel_lines:
+ ThemeUtils.regular_font.draw_string(grid_numbers_ci,
+ Vector2(4, i * camera_zoom + 14), String.num_int64(floori(i + camera_position.y)),
+ HORIZONTAL_ALIGNMENT_LEFT, -1, 14, axis_line_color)
+ else:
+ var coord := snappedi(i + camera_position.y, TICKS_INTERVAL)
+ if int(coord / TICK_DISTANCE) % rate == 0:
+ major_points.append(Vector2(0, i * camera_zoom))
+ major_points.append(Vector2(grid_size.x * camera_zoom, i * camera_zoom))
+ ThemeUtils.regular_font.draw_string(grid_numbers_ci,
+ Vector2(4, i * camera_zoom + 14), String.num_int64(coord),
+ HORIZONTAL_ALIGNMENT_LEFT, -1, 14, axis_line_color)
+ elif coord % rate == 0:
+ minor_points.append(Vector2(0, i * camera_zoom))
+ minor_points.append(Vector2(grid_size.x * camera_zoom, i * camera_zoom))
+ i += 1.0
+
+ if not major_points.is_empty():
+ var pca := PackedColorArray()
+ @warning_ignore("integer_division")
+ pca.resize(major_points.size() / 2)
+ pca.fill(major_grid_color)
+ RenderingServer.canvas_item_add_multiline(grid_ci, major_points, pca)
+ if not minor_points.is_empty():
+ var pca := PackedColorArray()
+ @warning_ignore("integer_division")
+ pca.resize(minor_points.size() / 2)
+ pca.fill(minor_grid_color)
+ RenderingServer.canvas_item_add_multiline(grid_ci, minor_points, pca)
diff --git a/src/ui_parts/viewport_container.gd.uid b/src/ui_parts/viewport_container.gd.uid
new file mode 100644
index 0000000..c0ed287
--- /dev/null
+++ b/src/ui_parts/viewport_container.gd.uid
@@ -0,0 +1 @@
+uid://cbajqkgudfvh0
diff --git a/src/ui_widgets/BetterButton.gd b/src/ui_widgets/BetterButton.gd
index d3d6348..53878e6 100644
--- a/src/ui_widgets/BetterButton.gd
+++ b/src/ui_widgets/BetterButton.gd
@@ -26,9 +26,12 @@ func _unhandled_input(event: InputEvent) -> void:
return
if not just_pressed and ShortcutUtils.is_action_pressed(event, action):
+ begin_bulk_theme_override()
add_theme_color_override("icon_normal_color", get_theme_color("icon_pressed_color"))
add_theme_color_override("icon_hover_color", get_theme_color("icon_pressed_color"))
add_theme_stylebox_override("normal", get_theme_stylebox("pressed"))
+ add_theme_stylebox_override("hover", get_theme_stylebox("hover_pressed"))
+ end_bulk_theme_override()
if is_instance_valid(timer):
timer.timeout.disconnect(end_highlight)
timer = get_tree().create_timer(HIGHLIGHT_TIME)
@@ -38,4 +41,5 @@ func end_highlight() -> void:
remove_theme_color_override("icon_normal_color")
remove_theme_color_override("icon_hover_color")
remove_theme_stylebox_override("normal")
+ remove_theme_stylebox_override("hover")
timer = null
diff --git a/src/ui_widgets/BetterLineEdit.gd b/src/ui_widgets/BetterLineEdit.gd
index feb2996..c5c5b86 100644
--- a/src/ui_widgets/BetterLineEdit.gd
+++ b/src/ui_widgets/BetterLineEdit.gd
@@ -15,7 +15,7 @@ var _hovered := false
func _set(property: StringName, value: Variant) -> bool:
if property == &"editable" and editable != value:
editable = value
- update_theme()
+ sync_theming()
return true
return false
@@ -32,10 +32,10 @@ func _init() -> void:
mouse_exited.connect(_on_base_class_mouse_exited)
text_submitted.connect(release_focus.unbind(1))
original_selection_color = get_theme_color("selection_color")
- Configs.theme_changed.connect(update_theme)
- update_theme()
+ Configs.theme_changed.connect(sync_theming)
+ sync_theming()
-func update_theme() -> void:
+func sync_theming() -> void:
if editable:
add_theme_color_override("selection_color", original_selection_color)
else:
diff --git a/src/ui_widgets/BetterTextEdit.gd b/src/ui_widgets/BetterTextEdit.gd
index ad9a23f..d8abb55 100644
--- a/src/ui_widgets/BetterTextEdit.gd
+++ b/src/ui_widgets/BetterTextEdit.gd
@@ -2,6 +2,9 @@
class_name BetterTextEdit extends TextEdit
## A TextEdit with some improvements.
+@export var show_line_numbers := true
+var _line_gutter_needed_space: int
+
var _surface := RenderingServer.canvas_item_create()
var _timer := Timer.new()
@@ -32,6 +35,40 @@ func _ready() -> void:
focus_entered.connect(_on_base_class_focus_entered)
focus_exited.connect(_on_base_class_focus_exited)
caret_changed.connect(queue_redraw_caret)
+ # Add gutter for line numbers.
+ if show_line_numbers:
+ text_changed.connect(recalibrate_line_gutter)
+ text_set.connect(recalibrate_line_gutter)
+ recalibrate_line_gutter()
+
+func recalibrate_line_gutter() -> void:
+ if get_gutter_count() == 1:
+ remove_gutter(0)
+ add_gutter(0)
+ set_gutter_name(0, "line_numbers")
+ set_gutter_type(0, GUTTER_TYPE_CUSTOM)
+ set_gutter_custom_draw(0, _line_number_draw_callback)
+ set_gutter_clickable(0, false)
+ var max_digits := floori(log(get_line_count()) / log(10) + 1.0)
+ _line_gutter_needed_space = int(max_digits * get_theme_font("font").get_char_size(69,
+ get_theme_font_size("font_size")).x) + 11
+ set_gutter_width(0, _line_gutter_needed_space)
+
+func _line_number_draw_callback(line: int, _gutter: int, region: Rect2) -> void:
+ if not Rect2(Vector2.ZERO, size).intersects(region):
+ return
+
+ var line_number_text := String.num_int64(line + 1)
+ var font := get_theme_font("font")
+ var font_size := get_theme_font_size("font_size")
+
+ # Center vertically, align to the left of the gutter.
+ var text_pos := Vector2(-5,
+ region.get_center().y + font.get_ascent(font_size) - font.get_string_size(
+ line_number_text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).y / 2)
+ draw_string(font, text_pos, line_number_text, HORIZONTAL_ALIGNMENT_RIGHT,
+ _line_gutter_needed_space, font_size, ThemeUtils.dimmer_text_color)
+
func _exit_tree() -> void:
RenderingServer.free_rid(_surface)
@@ -60,24 +97,34 @@ func _redraw_caret() -> void:
if not has_focus():
return
- var char_size := ThemeUtils.mono_font.get_char_size(69,
- get_theme_font_size("font_size"))
+ var char_size := ThemeUtils.mono_font.get_char_size(69, get_theme_font_size("font_size"))
for caret in get_caret_count():
var caret_pos := Vector2.ZERO
var caret_column := get_caret_column(caret)
var caret_line := get_caret_line(caret)
if caret_column == 0:
- caret_pos = Vector2(get_theme_stylebox("normal").content_margin_left,
- get_rect_at_line_column(caret_line, caret_column).end.y) + Vector2(1, -2)
+ var rect := get_rect_at_line_column(caret_line, caret_column)
+ caret_pos = Vector2(rect.position.x + 1, rect.end.y - 2)
else:
var glyph_end := Vector2(get_rect_at_line_column(caret_line, caret_column).end)
- caret_pos = glyph_end + Vector2(1, -2)
- # Workaround for ligatures.
+ caret_pos = Vector2(glyph_end.x + 1, glyph_end.y - 2)
var line := get_line(caret_line)
- if caret_column < line.length() and line[caret_column] == '\t':
- caret_pos = caret_pos
- elif glyph_end.x > 0 and glyph_end.y > 0:
+ # Workaround for indent_wrapped_lines.
+ if get_line_wrap_index_at_column(caret_line, caret_column) >= 1:
+ var i := 0
+ while true:
+ var c := line[i]
+ if c == ' ':
+ caret_pos.x += char_size.x
+ elif c == '\t':
+ caret_pos.x += char_size.x * get_tab_size()
+ else:
+ break
+ i += 1
+ # Workaround for ligatures.
+ if (caret_column >= line.length() or line[caret_column] != '\t') and\
+ glyph_end.x > 0 and glyph_end.y > 0:
var chars_back := 0
while line.length() > caret_column + chars_back and glyph_end ==\
Vector2(get_rect_at_line_column(caret_line, caret_column + chars_back + 1).end):
@@ -116,6 +163,12 @@ func _on_base_class_mouse_exited() -> void:
func _draw() -> void:
if editable and _hovered and has_theme_stylebox("hover"):
draw_style_box(get_theme_stylebox("hover"), Rect2(Vector2.ZERO, size))
+
+ if get_gutter_count() == 1:
+ var col := ThemeUtils.subtle_text_color
+ col.a *= 0.4
+ draw_line(Vector2(_line_gutter_needed_space, 0),
+ Vector2(_line_gutter_needed_space, size.y), col)
func _input(event: InputEvent) -> void:
@@ -166,8 +219,10 @@ func _gui_input(event: InputEvent) -> void:
HandlerGUI.popup_under_pos(context_popup, vp.get_mouse_position(), vp)
accept_event()
var click_pos := get_line_column_at_pos(event.position)
- set_caret_line(click_pos.y, false)
- set_caret_column(click_pos.x, false)
+ if get_selection_at_line_column(click_pos.y, click_pos.x) == -1:
+ deselect()
+ set_caret_line(click_pos.y, false)
+ set_caret_column(click_pos.x, false)
else:
# Set these inputs as handled, so the default UndoRedo doesn't eat them.
if ShortcutUtils.is_action_pressed(event, "ui_redo"):
diff --git a/src/ui_widgets/PanelGrid.gd b/src/ui_widgets/PanelGrid.gd
index dbfe259..91f4d55 100644
--- a/src/ui_widgets/PanelGrid.gd
+++ b/src/ui_widgets/PanelGrid.gd
@@ -17,8 +17,8 @@ func _draw() -> void:
if item_count == 0:
return
- var inner_color := ThemeUtils.desaturated_color.lerp(ThemeUtils.extreme_theme_color, 0.75)
- var border_color := ThemeUtils.desaturated_color.lerp(ThemeUtils.extreme_theme_color, 0.55)
+ var inner_color := ThemeUtils.tab_container_panel_inner_color.lerp(ThemeUtils.desaturated_color, 0.35)
+ var border_color := ThemeUtils.tab_container_panel_inner_color.lerp(ThemeUtils.desaturated_color, 0.85)
var effective_columns := clampi(columns, 1, item_count)
var text_color := get_theme_color("font_color", "Label")
@@ -45,7 +45,7 @@ func _draw() -> void:
RenderingServer.canvas_item_add_rect(ci,
Rect2(pos_x, pos_y, box_width, box_height), inner_color)
if dim_last_item:
- text_color = ThemeUtils.dim_text_color
+ text_color = ThemeUtils.dimmer_text_color
# Sigh...
if is_zero_approx(pos_x):
@@ -53,7 +53,6 @@ func _draw() -> void:
else:
draw_rect(Rect2(pos_x, pos_y, box_width, box_height), border_color, false, 1.0)
-
text_font.draw_string(ci, Vector2(pos_x + side_spacing, pos_y + top_spacing +\
text_font_size), items[item_idx], HORIZONTAL_ALIGNMENT_LEFT, -1,
text_font_size, text_color)
diff --git a/src/ui_widgets/UndoRedoRef.gd b/src/ui_widgets/UndoRedoRef.gd
index 52318ef..f6da9f2 100644
--- a/src/ui_widgets/UndoRedoRef.gd
+++ b/src/ui_widgets/UndoRedoRef.gd
@@ -11,7 +11,7 @@ var _undo_redo := UndoRedo.new()
func _init() -> void:
_undo_redo.version_changed.connect(version_changed.emit)
-func create_action(name: String) -> void:
+func create_action(name := "") -> void:
_undo_redo.create_action(name)
func add_do_method(callable: Callable) -> void:
@@ -47,6 +47,9 @@ func has_undo() -> bool:
func has_redo() -> bool:
return _undo_redo.has_redo()
+func clear_history() -> void:
+ _undo_redo.clear_history()
+
func _notification(what: int) -> void:
if what == NOTIFICATION_PREDELETE:
if is_instance_valid(_undo_redo):
diff --git a/src/ui_widgets/basic_xnode_frame.gd b/src/ui_widgets/basic_xnode_frame.gd
index 141f04e..6bf6a35 100644
--- a/src/ui_widgets/basic_xnode_frame.gd
+++ b/src/ui_widgets/basic_xnode_frame.gd
@@ -175,7 +175,7 @@ func _draw() -> void:
drop_sb.draw_center = false
drop_sb.set_corner_radius_all(4)
- drop_sb.draw(surface, Rect2(Vector2.ZERO, get_size()))
+ drop_sb.draw(surface, Rect2(Vector2.ZERO, size))
func _on_title_bar_draw() -> void:
var xnode_icon := DB.get_xnode_icon(xnode.get_type())
@@ -184,17 +184,6 @@ func _on_title_bar_draw() -> void:
xnode_icon_size), false, ThemeUtils.tinted_contrast_color)
func _on_text_modified() -> void:
- # TODO figure out a way to make this work.
- #if text_edit.get_line_count() >= 3 or (text_edit.get_line_count() == 2 and\
- #text_edit.get_line_wrap_count(0) + text_edit.get_line_wrap_count(1) >= 1) or\
- #(text_edit.get_line_count() == 1 and text_edit.get_line_wrap_count(0) >= 2):
- #size.y = 36 + text_edit.get_line_height() * 2
- #elif text_edit.get_line_count() >= 2 or (text_edit.get_line_count() == 1 and\
- #text_edit.get_line_wrap_count(0) >= 1):
- #size.y = 36 + text_edit.get_line_height()
- #else:
- #size.y = 36
-
if xnode.check_text_validity(text_edit.text):
xnode.set_text(text_edit.text)
set_default_font_color()
diff --git a/src/ui_widgets/basic_xnode_frame.tscn b/src/ui_widgets/basic_xnode_frame.tscn
index 391f092..366b078 100644
--- a/src/ui_widgets/basic_xnode_frame.tscn
+++ b/src/ui_widgets/basic_xnode_frame.tscn
@@ -24,6 +24,7 @@ size_flags_horizontal = 0
mouse_filter = 2
[node name="TextEdit" type="TextEdit" parent="."]
-custom_minimum_size = Vector2(0, 28)
+custom_minimum_size = Vector2(0, 44)
layout_mode = 2
script = ExtResource("2_0i3q7")
+show_line_numbers = false
diff --git a/src/ui_widgets/camera.gd b/src/ui_widgets/camera.gd
deleted file mode 100644
index 92d61dd..0000000
--- a/src/ui_widgets/camera.gd
+++ /dev/null
@@ -1,133 +0,0 @@
-extends Control
-
-const TICKS_INTERVAL = 4
-const TICK_DISTANCE = float(TICKS_INTERVAL)
-
-var axis_line_color: Color
-var major_grid_color: Color
-var minor_grid_color: Color
-
-var limit_left := 0.0
-var limit_right := 0.0
-var limit_top := 0.0
-var limit_bottom := 0.0
-
-var zoom: float
-var ci := get_canvas_item()
-var surface := RenderingServer.canvas_item_create() # Used for drawing the numbers.
-
-var unsnapped_position: Vector2
-
-
-func _ready() -> void:
- Configs.grid_color_changed.connect(setup_grid_color)
- setup_grid_color()
- State.show_grid_changed.connect(update_show_grid)
- update_show_grid()
- RenderingServer.canvas_item_set_parent(surface, ci)
- State.svg_resized.connect(queue_redraw)
- State.zoom_changed.connect(change_zoom)
- State.zoom_changed.connect(queue_redraw)
-
-func exit_tree() -> void:
- RenderingServer.free_rid(surface)
-
-func change_zoom() -> void:
- zoom = State.zoom
-
-func update_show_grid() -> void:
- visible = State.show_grid
-
-
-func update() -> void:
- var new_position := unsnapped_position.snapped(Vector2(1, 1) / zoom)
- if position != new_position:
- Utils.set_control_position_fixed(self, new_position)
- State.view_changed.emit()
-
- get_viewport().canvas_transform = Transform2D(0.0, Vector2(zoom, zoom),
- 0.0, -position * zoom)
- queue_redraw()
-
-
-# Don't ask me to explain this.
-func _draw() -> void:
- var grid_size := Vector2(State.viewport_size) / zoom
- RenderingServer.canvas_item_add_line(ci,
- Vector2(-position.x, 0), Vector2(-position.x, grid_size.y), axis_line_color)
- RenderingServer.canvas_item_add_line(ci,
- Vector2(0, -position.y), Vector2(grid_size.x, -position.y), axis_line_color)
-
- var major_points := PackedVector2Array()
- var minor_points := PackedVector2Array()
- var draw_minor_lines := zoom >= 8.0
- var mark_pixel_lines := zoom >= 128.0
- @warning_ignore("integer_division")
- var rate := nearest_po2(roundi(maxf(128.0 / (TICKS_INTERVAL * zoom), 2.0))) / 2
-
- # The grid lines are always 1px wide, but the numbers need to be resized.
- RenderingServer.canvas_item_clear(surface)
- RenderingServer.canvas_item_set_transform(surface,
- Transform2D(0, Vector2(1, 1) / zoom, 0, Vector2.ZERO))
-
- var i := fmod(-position.x, 1.0)
- var major_line_h_offset := fposmod(-position.x, TICK_DISTANCE)
- # Horizontal offset.
- while i <= grid_size.x:
- if major_line_h_offset != fposmod(i, TICK_DISTANCE):
- if draw_minor_lines:
- minor_points.append(Vector2(i, 0))
- minor_points.append(Vector2(i, grid_size.y))
- if mark_pixel_lines:
- ThemeUtils.regular_font.draw_string(surface, Vector2(i * zoom + 4, 14),
- String.num_int64(floori(i + position.x)),
- HORIZONTAL_ALIGNMENT_LEFT, -1, 14, axis_line_color)
- else:
- var coord := snappedi(i + position.x, TICKS_INTERVAL)
- if int(coord / TICK_DISTANCE) % rate == 0:
- major_points.append(Vector2(i, 0))
- major_points.append(Vector2(i, grid_size.y))
- ThemeUtils.regular_font.draw_string(surface, Vector2(i * zoom + 4, 14),
- String.num_int64(coord), HORIZONTAL_ALIGNMENT_LEFT, -1, 14,
- axis_line_color)
- elif coord % rate == 0:
- minor_points.append(Vector2(i, 0))
- minor_points.append(Vector2(i, grid_size.y))
- i += 1.0
-
- i = fmod(-position.y, 1.0)
- var major_line_v_offset := fposmod(-position.y, TICK_DISTANCE)
- # Vertical offset.
- while i < grid_size.y:
- if major_line_v_offset != fposmod(i, TICK_DISTANCE):
- if draw_minor_lines:
- minor_points.append(Vector2(0, i))
- minor_points.append(Vector2(grid_size.x, i))
- if mark_pixel_lines:
- ThemeUtils.regular_font.draw_string(surface, Vector2(4, i * zoom + 14),
- String.num_int64(floori(i + position.y)),
- HORIZONTAL_ALIGNMENT_LEFT, -1, 14, axis_line_color)
- else:
- var coord := snappedi(i + position.y, TICKS_INTERVAL)
- if int(coord / TICK_DISTANCE) % rate == 0:
- major_points.append(Vector2(0, i))
- major_points.append(Vector2(grid_size.x, i))
- ThemeUtils.regular_font.draw_string(surface, Vector2(4, i * zoom + 14),
- String.num_int64(coord), HORIZONTAL_ALIGNMENT_LEFT, -1, 14,
- axis_line_color)
- elif coord % rate == 0:
- minor_points.append(Vector2(0, i))
- minor_points.append(Vector2(grid_size.x, i))
- i += 1.0
-
- if not major_points.is_empty():
- draw_multiline(major_points, major_grid_color)
- if not minor_points.is_empty():
- draw_multiline(minor_points, minor_grid_color)
-
-
-func setup_grid_color() -> void:
- axis_line_color = Color(Configs.savedata.grid_color, 0.75)
- major_grid_color = Color(Configs.savedata.grid_color, 0.35)
- minor_grid_color = Color(Configs.savedata.grid_color, 0.15)
- queue_redraw()
diff --git a/src/ui_widgets/camera.gd.uid b/src/ui_widgets/camera.gd.uid
deleted file mode 100644
index 74639c6..0000000
--- a/src/ui_widgets/camera.gd.uid
+++ /dev/null
@@ -1 +0,0 @@
-uid://cm5033meho5vr
diff --git a/src/ui_widgets/configure_color_popup.gd b/src/ui_widgets/configure_color_popup.gd
index 45c3b82..e2a7887 100644
--- a/src/ui_widgets/configure_color_popup.gd
+++ b/src/ui_widgets/configure_color_popup.gd
@@ -12,15 +12,15 @@ var palette: Palette
var idx: int
func _ready() -> void:
- Configs.language_changed.connect(update_translation)
+ Configs.language_changed.connect(sync_localization)
set_label_text(palette.get_color_name(idx))
color_edit.value = palette.get_color(idx)
- update_translation()
+ sync_localization()
color_name_edit.text_submitted.connect(_on_name_edit_text_submitted)
color_name_edit.text_change_canceled.connect(hide_name_edit)
-func update_translation() -> void:
+func sync_localization() -> void:
%LabelContainer/EditButton.tooltip_text =\
Translator.translate("Edit color name")
$ConfigureContainer/BottomContainer/DeleteButton.tooltip_text =\
diff --git a/src/ui_widgets/element_frame.gd b/src/ui_widgets/element_frame.gd
index 1de21b6..6a00f07 100644
--- a/src/ui_widgets/element_frame.gd
+++ b/src/ui_widgets/element_frame.gd
@@ -288,7 +288,7 @@ func _draw() -> void:
drop_sb.draw_center = false
drop_sb.set_corner_radius_all(4)
- drop_sb.draw(surface, Rect2(Vector2.ZERO, get_size()))
+ drop_sb.draw(surface, Rect2(Vector2.ZERO, size))
func _on_title_bar_draw() -> void:
var element_icon := DB.get_element_icon(element.name)
diff --git a/src/ui_widgets/flag_field.tscn b/src/ui_widgets/flag_field.tscn
index 6870de6..8abe4c5 100644
--- a/src/ui_widgets/flag_field.tscn
+++ b/src/ui_widgets/flag_field.tscn
@@ -24,9 +24,9 @@ content_margin_left = 5.0
content_margin_top = 0.0
content_margin_right = 5.0
content_margin_bottom = 0.0
-bg_color = Color(0.24323256, 0.42435676, 0.115875855, 0.4)
+bg_color = Color(0.34799996, 0.6, 0.16799997, 0.4)
border_width_bottom = 2
-border_color = Color(0.7655958, 0.9776526, 0.25387198, 1)
+border_color = Color(0.70019996, 0.9, 0.23399997, 1)
corner_radius_top_left = 3
corner_radius_top_right = 3
@@ -39,13 +39,14 @@ offset_bottom = 18.0
focus_mode = 0
mouse_filter = 1
mouse_default_cursor_shape = 2
-theme_override_colors/font_color = Color(1, 0.8456523, 0.8433526, 1)
-theme_override_colors/font_pressed_color = Color(0.6350836, 1, 0.5034966, 1)
+theme_override_colors/font_color = Color(1, 0.84705883, 0.84313726, 1)
+theme_override_colors/font_pressed_color = Color(0.70666665, 1, 0.6, 1)
theme_override_fonts/font = SubResource("FontVariation_46ud6")
theme_override_font_sizes/font_size = 14
theme_override_styles/normal = SubResource("StyleBoxFlat_oo47u")
theme_override_styles/pressed = SubResource("StyleBoxFlat_uepoa")
theme_override_styles/hover = SubResource("StyleBoxFlat_oo47u")
+theme_override_styles/hover_pressed = SubResource("StyleBoxFlat_uepoa")
theme_override_styles/disabled = SubResource("StyleBoxEmpty_kfgda")
toggle_mode = true
text = "0"
diff --git a/src/ui_widgets/good_color_picker.gd b/src/ui_widgets/good_color_picker.gd
index 51498b8..8259f72 100644
--- a/src/ui_widgets/good_color_picker.gd
+++ b/src/ui_widgets/good_color_picker.gd
@@ -89,7 +89,7 @@ func setup_color(new_color: String, default_color: Color) -> void:
update()
-func update_color_space_buttons() -> void:
+func sync_color_space_buttons() -> void:
for child in color_space_container.get_children():
child.queue_free()
@@ -140,8 +140,8 @@ func update_keyword_button() -> void:
keyword_button.show()
func _ready() -> void:
- Configs.theme_changed.connect(update_color_space_buttons)
- update_color_space_buttons()
+ Configs.theme_changed.connect(sync_color_space_buttons)
+ sync_color_space_buttons()
# Set up signals.
widgets_arr[0].gui_input.connect(parse_slider_input.bind(0, true))
widgets_arr[1].gui_input.connect(parse_slider_input.bind(1))
@@ -179,13 +179,16 @@ func _on_slider_mode_changed() -> void:
update()
+# If the change was continuous, like a color wheel adjustment, the backup color
+# should be used as it stores the color from before the operation.
func register_visual_change(new_color: Color, use_backup := true) -> void:
- if use_backup and new_color == backup_display_color:
- return
- elif not use_backup and new_color == display_color:
+ # Return early if the color didn't change. If the color is a keyword, all visual
+ # changes reset it to a normal color.
+ if not color in ["none", "currentColor"] and\
+ new_color == (backup_display_color if use_backup else display_color):
return
- undo_redo.create_action("")
+ undo_redo.create_action()
undo_redo.add_do_method(set_color.bind(hex(new_color), new_color))
if use_backup:
undo_redo.add_undo_method(set_color.bind(backup_color, backup_display_color))
@@ -195,13 +198,13 @@ func register_visual_change(new_color: Color, use_backup := true) -> void:
func set_color(new_color: String, new_display_color: Color) -> void:
- set_display_color(new_display_color)
if color == new_color:
- return
-
- color = new_color
- update()
- color_changed.emit(new_color)
+ set_display_color(new_display_color)
+ else:
+ display_color = new_display_color
+ color = new_color
+ update()
+ color_changed.emit(new_color)
func set_display_color(new_display_color: Color) -> void:
@@ -392,7 +395,7 @@ func _on_keyword_button_pressed() -> void:
get_viewport())
func set_to_keyword(keyword: String) -> void:
- undo_redo.create_action("")
+ undo_redo.create_action()
if color.strip_edges() == keyword:
undo_redo.add_do_method(set_color.bind(backup_color, backup_display_color))
undo_redo.add_undo_method(set_color.bind(color, display_color))
@@ -404,7 +407,7 @@ func set_to_keyword(keyword: String) -> void:
func _on_reset_color_button_pressed() -> void:
reset_color_button.disabled = true
- undo_redo.create_action("")
+ undo_redo.create_action()
undo_redo.add_do_method(set_color.bind(starting_color, starting_display_color))
undo_redo.add_undo_method(set_color.bind(color, display_color))
undo_redo.commit_action()
@@ -499,18 +502,16 @@ func update_color_button() -> void:
reset_color_button.disabled = true
return
reset_color_button.disabled = false
+ reset_color_button.begin_bulk_theme_override()
if display_color.get_luminance() < 0.455:
- reset_color_button.begin_bulk_theme_override()
reset_color_button.add_theme_color_override("icon_hover_color", Color.WHITE)
reset_color_button.add_theme_color_override("icon_pressed_color",
Color(0.5, 1, 1))
- reset_color_button.end_bulk_theme_override()
else:
- reset_color_button.begin_bulk_theme_override()
reset_color_button.add_theme_color_override("icon_hover_color", Color.BLACK)
reset_color_button.add_theme_color_override("icon_pressed_color",
Color(0, 0.5, 0.5))
- reset_color_button.end_bulk_theme_override()
+ reset_color_button.end_bulk_theme_override()
func hex(col: Color) -> String:
# Removing the saturation and hue clamping fixes hex conversion in edge cases.
diff --git a/src/ui_widgets/number_field_with_slider.gd b/src/ui_widgets/number_field_with_slider.gd
index 7900988..48debfa 100644
--- a/src/ui_widgets/number_field_with_slider.gd
+++ b/src/ui_widgets/number_field_with_slider.gd
@@ -97,19 +97,18 @@ func _draw() -> void:
stylebox.corner_radius_top_right = 5
stylebox.corner_radius_bottom_right = 5
stylebox.bg_color = get_theme_stylebox("normal", "LineEdit").bg_color
- stylebox.draw(ci, Rect2(get_size().x - BUTTON_WIDTH,
- 1, BUTTON_WIDTH - 2, get_size().y - 2))
- var fill_height := (get_size().y - 4) * (element.get_attribute_num(attribute_name) -\
+ stylebox.draw(ci, Rect2(size.x - BUTTON_WIDTH, 1, BUTTON_WIDTH - 2, size.y - 2))
+ var fill_height := (size.y - 4) * (element.get_attribute_num(attribute_name) -\
MIN_VALUE) / MAX_VALUE
# Create a stylebox that'll occupy the exact amount of space.
var fill_stylebox := StyleBoxFlat.new()
fill_stylebox.bg_color = ThemeUtils.tinted_contrast_color
if not slider_dragged and slider_hovered:
- fill_stylebox.bg_color.a = 0.8
+ fill_stylebox.bg_color.a = 0.65
elif not slider_hovered:
- fill_stylebox.bg_color.a = 0.6
- fill_stylebox.draw(ci, Rect2(get_size().x - BUTTON_WIDTH,
- get_size().y - 2 - fill_height, BUTTON_WIDTH - 2, fill_height))
+ fill_stylebox.bg_color.a = 0.5
+ fill_stylebox.draw(ci, Rect2(size.x - BUTTON_WIDTH, size.y - 2 - fill_height,
+ BUTTON_WIDTH - 2, fill_height))
if slider_dragged:
draw_button_border("pressed")
elif slider_hovered:
@@ -153,7 +152,7 @@ func _unhandled_input(event: InputEvent) -> void:
func get_slider_value_at_y(y_coord: float) -> float:
return snappedf(lerpf(MAX_VALUE, MIN_VALUE,
- (y_coord - 4) / (temp_button.get_size().y - 4)), SLIDER_STEP)
+ (y_coord - 4) / (temp_button.size.y - 4)), SLIDER_STEP)
func _on_slider_mouse_exited() -> void:
slider_hovered = false
diff --git a/src/ui_widgets/palette_config.gd b/src/ui_widgets/palette_config.gd
index 2b12c8e..04d0c25 100644
--- a/src/ui_widgets/palette_config.gd
+++ b/src/ui_widgets/palette_config.gd
@@ -16,7 +16,7 @@ var currently_edited_idx := -1
@onready var colors_container: HFlowContainer = $MainContainer/ColorsContainer
@onready var warning_sign: TextureRect = $WarningSign/TextureRect
-func update_theme() -> void:
+func sync_theming() -> void:
warning_sign.modulate = ThemeUtils.warning_icon_color
palette_button.begin_bulk_theme_override()
const CONST_ARR: PackedStringArray = ["normal", "hover", "pressed"]
@@ -46,8 +46,8 @@ func _ready() -> void:
name_edit.text_changed.connect(_on_name_edit_text_changed)
name_edit.text_submitted.connect(_on_name_edit_text_submitted)
mouse_exited.connect(clear_proposed_drop)
- Configs.theme_changed.connect(update_theme)
- update_theme()
+ Configs.theme_changed.connect(sync_theming)
+ sync_theming()
# Rebuilds the content of the colors container.
func rebuild_colors() -> void:
diff --git a/src/ui_widgets/pathdata_field.gd b/src/ui_widgets/pathdata_field.gd
index 0246a39..5074069 100644
--- a/src/ui_widgets/pathdata_field.gd
+++ b/src/ui_widgets/pathdata_field.gd
@@ -51,10 +51,10 @@ func set_value(new_value: String, save := false) -> void:
func setup() -> void:
- Configs.language_changed.connect(update_translation)
- update_translation()
- Configs.theme_changed.connect(update_theme)
- update_theme()
+ Configs.language_changed.connect(sync_localization)
+ sync_localization()
+ Configs.theme_changed.connect(sync_theming)
+ sync_theming()
sync()
element.attribute_changed.connect(_on_element_attribute_changed)
line_edit.tooltip_text = attribute_name
@@ -84,10 +84,10 @@ func _on_element_attribute_changed(attribute_changed: String) -> void:
if attribute_name == attribute_changed:
sync()
-func update_translation() -> void:
+func sync_localization() -> void:
line_edit.placeholder_text = Translator.translate("No path data")
-func update_theme() -> void:
+func sync_theming() -> void:
mini_line_edit_stylebox = get_theme_stylebox("normal", "MiniLineEdit")
mini_line_edit_font_size = get_theme_font_size("font_size", "MiniLineEdit")
mini_line_edit_font_color = get_theme_color("font_color", "MiniLineEdit")
@@ -189,7 +189,7 @@ func _on_commands_gui_input(event: InputEvent) -> void:
var cmd_idx := -1
var event_pos: Vector2 = event.position
- if Rect2(Vector2.ZERO, commands_container.get_size()).has_point(event_pos):
+ if Rect2(Vector2.ZERO, commands_container.size).has_point(event_pos):
cmd_idx = int(event_pos.y / STRIP_HEIGHT)
if event is InputEventMouseMotion and event.button_mask == 0:
@@ -238,10 +238,12 @@ func _commands_draw() -> void:
if selected or hovered:
var stylebox := StyleBoxFlat.new()
stylebox.set_corner_radius_all(3)
- stylebox.bg_color = ThemeUtils.soft_pressed_overlay_color if selected else\
- Color.TRANSPARENT
- if hovered:
- stylebox.bg_color = stylebox.bg_color.blend(Color(ThemeUtils.soft_hover_overlay_color))
+ if hovered and selected:
+ stylebox.bg_color = ThemeUtils.soft_hover_pressed_overlay_color
+ elif selected:
+ stylebox.bg_color = ThemeUtils.soft_pressed_overlay_color
+ elif hovered:
+ stylebox.bg_color = ThemeUtils.soft_hover_overlay_color
stylebox.draw(ci, Rect2(Vector2(0, v_offset), Vector2(commands_container.size.x,
STRIP_HEIGHT)))
# Draw the child controls. They are going to be drawn, not added as a node unless
diff --git a/src/ui_widgets/points_field.gd b/src/ui_widgets/points_field.gd
index a0f7519..7fe82ec 100644
--- a/src/ui_widgets/points_field.gd
+++ b/src/ui_widgets/points_field.gd
@@ -50,10 +50,10 @@ func set_value(new_value: String, save := false) -> void:
func setup() -> void:
- Configs.language_changed.connect(update_translation)
- update_translation()
- Configs.theme_changed.connect(update_theme)
- update_theme()
+ Configs.language_changed.connect(sync_localization)
+ sync_localization()
+ Configs.theme_changed.connect(sync_theming)
+ sync_theming()
sync()
element.attribute_changed.connect(_on_element_attribute_changed)
line_edit.tooltip_text = attribute_name
@@ -82,10 +82,10 @@ func _on_element_attribute_changed(attribute_changed: String) -> void:
if attribute_name == attribute_changed:
sync()
-func update_translation() -> void:
+func sync_localization() -> void:
line_edit.placeholder_text = Translator.translate("No points")
-func update_theme() -> void:
+func sync_theming() -> void:
mini_line_edit_stylebox = get_theme_stylebox("normal", "MiniLineEdit")
mini_line_edit_font_size = get_theme_font_size("font_size", "MiniLineEdit")
mini_line_edit_font_color = get_theme_color("font_color", "MiniLineEdit")
@@ -191,7 +191,7 @@ func _on_points_gui_input(event: InputEvent) -> void:
var cmd_idx := -1
var event_pos: Vector2 = event.position
- if Rect2(Vector2.ZERO, points_container.get_size()).has_point(event_pos):
+ if Rect2(Vector2.ZERO, points_container.size).has_point(event_pos):
cmd_idx = int(event_pos.y / STRIP_HEIGHT)
if event is InputEventMouseMotion and event.button_mask == 0:
@@ -239,10 +239,12 @@ func points_draw() -> void:
if selected or hovered:
var stylebox := StyleBoxFlat.new()
stylebox.set_corner_radius_all(3)
- stylebox.bg_color = ThemeUtils.soft_pressed_overlay_color if selected else\
- Color.TRANSPARENT
- if hovered:
- stylebox.bg_color = stylebox.bg_color.blend(Color(ThemeUtils.soft_hover_overlay_color))
+ if hovered and selected:
+ stylebox.bg_color = ThemeUtils.soft_hover_pressed_overlay_color
+ elif selected:
+ stylebox.bg_color = ThemeUtils.soft_pressed_overlay_color
+ elif hovered:
+ stylebox.bg_color = ThemeUtils.soft_hover_overlay_color
stylebox.draw(ci, Rect2(Vector2(0, v_offset), Vector2(points_container.size.x,
STRIP_HEIGHT)))
# Draw the child controls. They are going to be drawn, not added as a node unless
diff --git a/src/ui_widgets/presented_shortcut.tscn b/src/ui_widgets/presented_shortcut.tscn
index b27c66f..02f6dbd 100644
--- a/src/ui_widgets/presented_shortcut.tscn
+++ b/src/ui_widgets/presented_shortcut.tscn
@@ -21,7 +21,7 @@ theme_override_constants/separation = 6
[node name="Label" type="Label" parent="MarginContainer/MainContainer"]
layout_mode = 2
-theme_override_font_sizes/font_size = 15
+theme_type_variation = &"TitleLabel"
horizontal_alignment = 1
[node name="ShortcutContainer" type="HBoxContainer" parent="MarginContainer/MainContainer"]
diff --git a/src/ui_widgets/profile_frame.gd b/src/ui_widgets/profile_frame.gd
index 259966b..b0f38c8 100644
--- a/src/ui_widgets/profile_frame.gd
+++ b/src/ui_widgets/profile_frame.gd
@@ -27,6 +27,8 @@ func setup_dropdown(values: Array, value_text_map: Dictionary) -> void:
dropdown.value_text_map = value_text_map
func _ready() -> void:
+ Configs.theme_changed.connect(sync_theming)
+ sync_theming()
button.text = Translator.translate("Apply")
button.tooltip_text = Translator.translate("Apply all of this preset's defaults")
control.add_child(dropdown)
@@ -40,6 +42,14 @@ func _ready() -> void:
control.resized.connect(setup_size.call_deferred)
setup_size.call_deferred()
+func sync_theming() -> void:
+ const CONST_ARR: PackedStringArray = ["normal", "hover", "pressed", "disabled"]
+ for theme_style in CONST_ARR:
+ var theme_sb := get_theme_stylebox(theme_style, "TranslucentButton").duplicate()
+ theme_sb.content_margin_top -= 1
+ theme_sb.content_margin_bottom -= 1
+ button.add_theme_stylebox_override(theme_style, theme_sb)
+
func button_update_disabled() -> void:
var should_disable: bool = disabled_check_callback.call()
button.disabled = should_disable
@@ -47,7 +57,7 @@ func button_update_disabled() -> void:
Control.CURSOR_POINTING_HAND
func setup_size() -> void:
- dropdown.position = Vector2(control.size.x - 102, 2)
+ dropdown.position = Vector2(control.size.x - 102, 1)
dropdown.size = Vector2(98, 22)
queue_redraw()
@@ -69,5 +79,5 @@ func _on_mouse_exited() -> void:
func _draw() -> void:
if is_hovered:
get_theme_stylebox("hover", "FlatButton").draw(ci, Rect2(Vector2.ZERO, size))
- ThemeUtils.regular_font.draw_string(ci, Vector2(4, 20), text,
+ ThemeUtils.regular_font.draw_string(ci, Vector2(4, 19), text,
HORIZONTAL_ALIGNMENT_LEFT, -1, 13, ThemeUtils.text_color)
diff --git a/src/ui_widgets/setting_shortcut.gd b/src/ui_widgets/setting_shortcut.gd
index 8ed4b20..ecfc296 100644
--- a/src/ui_widgets/setting_shortcut.gd
+++ b/src/ui_widgets/setting_shortcut.gd
@@ -2,33 +2,34 @@ extends PanelContainer
const delete_icon := preload("res://assets/icons/Delete.svg")
+signal shortcuts_modified(new_shortcuts: Array[InputEvent])
+
@onready var label: Label = %MainContainer/Label
@onready var reset_button: Button = %MainContainer/HBoxContainer/ResetButton
@onready var shortcut_container: HBoxContainer = %ShortcutContainer
@onready var shortcut_buttons: Array[Button] = []
var action: String
-var events: Array[InputEvent] = []
var listening_idx := -1
var pending_event: InputEventKey
-func update_translation() -> void:
+func sync_localization() -> void:
reset_button.tooltip_text = Translator.translate("Reset to default")
func _ready() -> void:
reset_button.pressed.connect(_on_reset_button_pressed)
- Configs.language_changed.connect(update_translation)
- Configs.shortcuts_changed.connect(check_shortcuts_validity)
- update_translation()
+ Configs.language_changed.connect(sync_localization)
+ Configs.shortcuts_changed.connect(sync)
+ sync_localization()
func setup(new_action: String) -> void:
action = new_action
- events = InputMap.action_get_events(action)
sync()
# Syncs based on current events.
func sync() -> void:
+ var events := InputMap.action_get_events(action)
# Show the reset button if any of the actions don't match.
var action_defaults: Array[InputEvent] = Configs.default_shortcuts[action]
if events.size() != action_defaults.size():
@@ -142,12 +143,9 @@ func cancel_listening() -> void:
func delete_shortcut(idx: int) -> void:
- events.remove_at(idx)
- update_shortcut()
- sync()
-
-func update_shortcut() -> void:
- Configs.savedata.action_modify_shortcuts(action, events)
+ var new_events := InputMap.action_get_events(action)
+ new_events.remove_at(idx)
+ shortcuts_modified.emit(new_events)
func _input(event: InputEvent) -> void:
if not (listening_idx >= 0 and event is InputEventKey):
@@ -186,20 +184,19 @@ func _input(event: InputEvent) -> void:
saved_event.alt_pressed = pending_event.alt_pressed
saved_event.shift_pressed = pending_event.shift_pressed
- if listening_idx < events.size():
- events[listening_idx] = saved_event
+ var new_events := InputMap.action_get_events(action)
+ if listening_idx < new_events.size():
+ new_events[listening_idx] = saved_event
else:
- events.append(saved_event)
- update_shortcut()
- sync()
+ new_events.append(saved_event)
+ shortcuts_modified.emit(new_events)
+
pending_event = null
setup_shortcut_button_font_colors(shortcut_button, ThemeUtils.editable_text_color)
listening_idx = -1
func _on_reset_button_pressed() -> void:
- events = Configs.default_shortcuts[action].duplicate(true)
- update_shortcut()
- sync()
+ shortcuts_modified.emit(Configs.default_shortcuts[action])
func setup_shortcut_button_font_colors(button: Button, color: Color) -> void:
var dim_color := Color(color, 0.8)
@@ -220,6 +217,7 @@ func set_shortcut_button_text(button: Button, new_text: String) -> void:
button.text = new_text
func check_shortcuts_validity() -> void:
+ var events := InputMap.action_get_events(action)
for i in events.size():
var event := events[i]
var shortcut_btn := shortcut_buttons[i]
diff --git a/src/ui_widgets/setting_shortcut.tscn b/src/ui_widgets/setting_shortcut.tscn
index de07599..74e876e 100644
--- a/src/ui_widgets/setting_shortcut.tscn
+++ b/src/ui_widgets/setting_shortcut.tscn
@@ -17,7 +17,7 @@ theme_override_constants/separation = 6
[node name="Label" type="Label" parent="MainContainer"]
layout_mode = 2
-theme_override_font_sizes/font_size = 15
+theme_type_variation = &"TitleLabel"
horizontal_alignment = 1
[node name="HBoxContainer" type="HBoxContainer" parent="MainContainer"]
diff --git a/src/ui_widgets/settings_content_generic.gd b/src/ui_widgets/settings_content_generic.gd
new file mode 100644
index 0000000..4347052
--- /dev/null
+++ b/src/ui_widgets/settings_content_generic.gd
@@ -0,0 +1,855 @@
+extends VBoxContainer
+
+const SettingsMenu = preload("res://src/ui_parts/settings_menu.gd")
+
+const SettingFrameScene = preload("res://src/ui_widgets/setting_frame.tscn")
+const ProfileFrameScene = preload("res://src/ui_widgets/profile_frame.tscn")
+
+# If there are multiple setup resources, they will be added as tabs.
+var current_setup_resources: Array[ConfigResource]
+var type: SettingsMenu.TabIndex
+
+var current_setup_setting := ""
+var current_setup_resource_index := 0
+var setting_container: VBoxContainer
+var previews: Dictionary[String, RefCounted] = {}
+
+
+var current_previewed_setting := ""
+signal preview_changed(node: Control)
+
+class SettingBasicColorPreview:
+ var setting_bind: String
+ var text: String
+ func _init(new_setting_bind: String, new_text: String) -> void:
+ setting_bind = new_setting_bind
+ text = new_text
+
+class SettingTextPreview:
+ enum WarningType {NONE, NO_EFFECT_IN_CURRENT_CONFIGURATION, NOT_AVAILABLE_ON_PLATFORM}
+ var text: String
+ var warning: WarningType
+ func _init(new_text: String, new_warning := WarningType.NONE) -> void:
+ text = new_text
+ warning = new_warning
+
+ static func get_platform_availability_warning(bad_platforms_check: bool) -> WarningType:
+ return WarningType.NOT_AVAILABLE_ON_PLATFORM if bad_platforms_check else WarningType.NONE
+
+ static func get_no_effect_in_configuration_warning(configuration_check: bool) -> WarningType:
+ return WarningType.NO_EFFECT_IN_CURRENT_CONFIGURATION if configuration_check else WarningType.NONE
+
+class SettingCodePreview:
+ var text: String
+ func _init(new_text: String) -> void:
+ text = new_text
+
+class SettingFormatterPreview:
+ var resource_bind: Formatter
+ var root_element: ElementRoot
+ var show_only_children: bool
+ func _init(new_resource_bind: ConfigResource,
+ new_root_element: ElementRoot, new_show_only_children := false) -> void:
+ resource_bind = new_resource_bind
+ root_element = new_root_element
+ show_only_children = new_show_only_children
+
+
+func _ready() -> void:
+ Configs.language_changed.connect(setup_content)
+ if current_setup_resources.size() > 1:
+ var categories := HFlowContainer.new()
+ categories.alignment = FlowContainer.ALIGNMENT_CENTER
+ var button_group := ButtonGroup.new()
+ for idx in current_setup_resources.size():
+ var btn := Button.new()
+ btn.toggle_mode = true
+ btn.button_group = button_group
+ btn.pressed.connect(_set_current_setup_resource_index.bind(idx))
+ btn.pressed.connect(setup_content)
+ var update_category_button_text := func() -> void:
+ btn.text = Translator.translate("Editor formatter") if\
+ current_setup_resource_index == 0 else\
+ Translator.translate("Export formatter")
+ Configs.language_changed.connect(update_category_button_text)
+ update_category_button_text.call()
+ btn.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
+ btn.focus_mode = Control.FOCUS_NONE
+ btn.action_mode = BaseButton.ACTION_MODE_BUTTON_PRESS
+ categories.add_child(btn)
+ add_child(categories)
+ setting_container = VBoxContainer.new()
+ setting_container.add_theme_constant_override("separation", 6)
+ add_child(setting_container)
+ categories.get_child(0).button_pressed = true
+ setup_content()
+ else:
+ setting_container = VBoxContainer.new()
+ setting_container.add_theme_constant_override("separation", 6)
+ add_child(setting_container)
+ setup_content()
+
+func _get_current_setup_resource() -> ConfigResource:
+ return current_setup_resources[current_setup_resource_index]
+
+func _set_current_setup_resource_index(new_index: int) -> void:
+ current_setup_resource_index = new_index
+
+func setup(setup_resources: Array[ConfigResource], new_type: SettingsMenu.TabIndex) -> void:
+ type = new_type
+ current_setup_resources = setup_resources
+
+
+func setup_content() -> void:
+ for child in setting_container.get_children():
+ setting_container.remove_child(child)
+ child.queue_free()
+
+ match type:
+ SettingsMenu.TabIndex.FORMATTING: setup_formatting_content()
+ SettingsMenu.TabIndex.THEMING: setup_theming_content()
+ SettingsMenu.TabIndex.TAB_BAR: setup_tab_bar_content()
+ SettingsMenu.TabIndex.OTHER: setup_other_content()
+
+func setup_formatting_content() -> void:
+ var current_setup_resource: Formatter = _get_current_setup_resource()
+
+ current_setup_setting = "preset"
+ add_profile_picker(Translator.translate("Preset"),
+ current_setup_resource.reset_to_default, Formatter.Preset.size(),
+ Formatter.get_preset_value_text_map(), current_setup_resource.is_everything_default)
+ add_preview(SettingTextPreview.new(
+ Translator.translate("Determines the default values of the formatter configs.")))
+
+ add_section("XML")
+ current_setup_setting = "xml_keep_comments"
+ add_checkbox(Translator.translate("Keep comments"))
+ var xml_keep_comments_root_element := ElementRoot.new()
+ xml_keep_comments_root_element.insert_child(0,
+ BasicXNode.new(BasicXNode.NodeType.COMMENT, " Comment "))
+ var xml_keep_comments_circle_element := ElementCircle.new()
+ xml_keep_comments_circle_element.set_attribute("cx", 6)
+ xml_keep_comments_circle_element.set_attribute("cy", 8)
+ xml_keep_comments_circle_element.set_attribute("r", 4)
+ xml_keep_comments_circle_element.set_attribute("fill", "gold")
+ xml_keep_comments_root_element.insert_child(1, xml_keep_comments_circle_element)
+ add_preview(SettingFormatterPreview.new(current_setup_resource,
+ xml_keep_comments_root_element, true))
+
+ current_setup_setting = "xml_add_trailing_newline"
+ add_checkbox(Translator.translate("Add trailing newline"))
+ var xml_add_trailing_newline_root_element := ElementRoot.new()
+ xml_add_trailing_newline_root_element.set_attribute("xmlns", "http://www.w3.org/2000/svg")
+ xml_add_trailing_newline_root_element.set_attribute("width", "16")
+ xml_add_trailing_newline_root_element.set_attribute("height", "16")
+ var xml_add_trailing_newline_circle_element := ElementCircle.new()
+ xml_add_trailing_newline_circle_element.set_attribute("cx", 6)
+ xml_add_trailing_newline_circle_element.set_attribute("cy", 8)
+ xml_add_trailing_newline_circle_element.set_attribute("r", 4)
+ xml_add_trailing_newline_circle_element.set_attribute("fill", "gold")
+ xml_add_trailing_newline_root_element.insert_child(0,
+ xml_add_trailing_newline_circle_element)
+ add_preview(SettingFormatterPreview.new(current_setup_resource,
+ xml_add_trailing_newline_root_element))
+
+ current_setup_setting = "xml_shorthand_tags"
+ add_dropdown(Translator.translate("Use shorthand tag syntax"),
+ range(Formatter.ShorthandTags.size()),
+ Formatter.get_shorthand_tags_value_text_map())
+ var xml_shorthand_tags_root_element := ElementRoot.new()
+ var xml_shorthand_tags_linear_gradient_element := ElementLinearGradient.new()
+ xml_shorthand_tags_linear_gradient_element.set_attribute("id", "a")
+ xml_shorthand_tags_linear_gradient_element.set_attribute("x1", 6)
+ xml_shorthand_tags_linear_gradient_element.set_attribute("y1", 4)
+ xml_shorthand_tags_linear_gradient_element.set_attribute("x2", 8)
+ xml_shorthand_tags_linear_gradient_element.set_attribute("y2", 2)
+ var xml_shorthand_tags_circle_element := ElementCircle.new()
+ xml_shorthand_tags_circle_element.set_attribute("cx", 6)
+ xml_shorthand_tags_circle_element.set_attribute("cy", 8)
+ xml_shorthand_tags_circle_element.set_attribute("r", 4)
+ xml_shorthand_tags_circle_element.set_attribute("fill", "url(#a)")
+ xml_shorthand_tags_root_element.insert_child(0, xml_shorthand_tags_linear_gradient_element)
+ xml_shorthand_tags_root_element.insert_child(1, xml_shorthand_tags_circle_element)
+ add_preview(SettingFormatterPreview.new(current_setup_resource,
+ xml_shorthand_tags_root_element, true))
+
+ current_setup_setting = "xml_shorthand_tags_space_out_slash"
+ add_checkbox(Translator.translate("Space out the slash of shorthand tags"))
+ var xml_shorthand_tags_space_out_slash_root_element := ElementRoot.new()
+ var xml_shorthand_tags_space_out_slash_circle_element := ElementCircle.new()
+ xml_shorthand_tags_space_out_slash_circle_element.set_attribute("cx", 6)
+ xml_shorthand_tags_space_out_slash_circle_element.set_attribute("cy", 8)
+ xml_shorthand_tags_space_out_slash_circle_element.set_attribute("r", 4)
+ xml_shorthand_tags_space_out_slash_root_element.insert_child(0,
+ xml_shorthand_tags_space_out_slash_circle_element)
+ add_preview(SettingFormatterPreview.new(current_setup_resource,
+ xml_shorthand_tags_space_out_slash_root_element, true))
+
+ current_setup_setting = "xml_pretty_formatting"
+ add_checkbox(Translator.translate("Use pretty formatting"))
+ var xml_pretty_formatting_root_element := ElementRoot.new()
+ var xml_pretty_formatting_linear_gradient_element := ElementLinearGradient.new()
+ xml_pretty_formatting_linear_gradient_element.set_attribute("id", "a")
+ xml_pretty_formatting_linear_gradient_element.set_attribute("x1", 6)
+ xml_pretty_formatting_linear_gradient_element.set_attribute("y1", 4)
+ xml_pretty_formatting_linear_gradient_element.set_attribute("x2", 8)
+ xml_pretty_formatting_linear_gradient_element.set_attribute("y2", 2)
+ var xml_pretty_formatting_stop_1 := ElementStop.new()
+ xml_pretty_formatting_stop_1.set_attribute("stop-color", "silver")
+ xml_pretty_formatting_stop_1.set_attribute("offset", "0")
+ var xml_pretty_formatting_stop_2 := ElementStop.new()
+ xml_pretty_formatting_stop_2.set_attribute("stop-color", "gold")
+ xml_pretty_formatting_stop_2.set_attribute("offset", "1")
+ xml_pretty_formatting_linear_gradient_element.insert_child(0, xml_pretty_formatting_stop_1)
+ xml_pretty_formatting_linear_gradient_element.insert_child(0, xml_pretty_formatting_stop_2)
+ var xml_pretty_formatting_circle_element := ElementCircle.new()
+ xml_pretty_formatting_circle_element.set_attribute("cx", 6)
+ xml_pretty_formatting_circle_element.set_attribute("cy", 8)
+ xml_pretty_formatting_circle_element.set_attribute("r", 4)
+ xml_pretty_formatting_circle_element.set_attribute("fill", "url(#a)")
+ xml_pretty_formatting_root_element.insert_child(0, xml_pretty_formatting_linear_gradient_element)
+ xml_pretty_formatting_root_element.insert_child(1, xml_pretty_formatting_circle_element)
+ add_preview(SettingFormatterPreview.new(current_setup_resource,
+ xml_pretty_formatting_root_element))
+
+ current_setup_setting = "xml_indentation_use_spaces"
+ add_checkbox(Translator.translate("Use spaces instead of tabs"),
+ not current_setup_resource.xml_pretty_formatting)
+ add_preview(SettingTextPreview.new(Translator.translate(
+ "When enabled, uses several spaces instead of a single tab for indentation."),
+ SettingTextPreview.get_no_effect_in_configuration_warning(
+ not current_setup_resource.xml_pretty_formatting)))
+
+ current_setup_setting = "xml_indentation_spaces"
+ add_number_dropdown(Translator.translate("Number of indentation spaces"),
+ [2, 3, 4, 6, 8], true, false, Formatter.INDENTS_MIN, Formatter.INDENTS_MAX,
+ not (current_setup_resource.xml_pretty_formatting and\
+ current_setup_resource.xml_indentation_use_spaces))
+ if current_setup_resource.xml_pretty_formatting and\
+ current_setup_resource.xml_indentation_use_spaces:
+ var xml_indentation_spaces_root_element := ElementRoot.new()
+ var xml_indentation_spaces_circle_element := ElementCircle.new()
+ xml_indentation_spaces_circle_element.set_attribute("cx", 6)
+ xml_indentation_spaces_circle_element.set_attribute("cy", 8)
+ xml_indentation_spaces_circle_element.set_attribute("r", 4)
+ xml_indentation_spaces_circle_element.set_attribute("fill", "gold")
+ xml_indentation_spaces_root_element.insert_child(0,
+ xml_indentation_spaces_circle_element)
+ add_preview(SettingFormatterPreview.new(current_setup_resource,
+ xml_indentation_spaces_root_element, false))
+ else:
+ add_preview(SettingTextPreview.new("",
+ SettingTextPreview.WarningType.NO_EFFECT_IN_CURRENT_CONFIGURATION))
+
+ add_section(Translator.translate("Numbers"))
+ current_setup_setting = "number_remove_leading_zero"
+ add_checkbox(Translator.translate("Remove leading zero"))
+ var number_remove_leading_zero_root_element := ElementRoot.new()
+ var number_remove_leading_zero_circle_element := ElementCircle.new()
+ number_remove_leading_zero_circle_element.set_attribute("cx", 0.36)
+ number_remove_leading_zero_circle_element.set_attribute("cy", -0.8)
+ number_remove_leading_zero_circle_element.set_attribute("r", 1.6)
+ number_remove_leading_zero_circle_element.set_attribute("fill", "gold")
+ number_remove_leading_zero_root_element.insert_child(0,
+ number_remove_leading_zero_circle_element)
+ add_preview(SettingFormatterPreview.new(current_setup_resource,
+ number_remove_leading_zero_root_element, true))
+
+ current_setup_setting = "number_use_exponent_if_shorter"
+ add_checkbox(Translator.translate("Use exponential when shorter"))
+ var number_use_exponent_if_shorter_root_element := ElementRoot.new()
+ var number_use_exponent_if_shorter_circle_element := ElementCircle.new()
+ number_use_exponent_if_shorter_circle_element.set_attribute("cx", 800)
+ number_use_exponent_if_shorter_circle_element.set_attribute("cy", -0.005)
+ number_use_exponent_if_shorter_circle_element.set_attribute("r", 2000)
+ number_use_exponent_if_shorter_circle_element.set_attribute("fill", "gold")
+ number_use_exponent_if_shorter_root_element.insert_child(0,
+ number_use_exponent_if_shorter_circle_element)
+ add_preview(SettingFormatterPreview.new(current_setup_resource,
+ number_use_exponent_if_shorter_root_element, true))
+
+ add_section(Translator.translate("Colors"))
+ current_setup_setting = "color_use_named_colors"
+ add_dropdown(Translator.translate("Use named colors"),
+ range(Formatter.NamedColorUse.size()),
+ Formatter.get_named_color_use_value_text_map())
+ var color_use_named_colors_root_element := ElementRoot.new()
+ var color_use_named_colors_circle_1 := ElementCircle.new()
+ color_use_named_colors_circle_1.set_attribute("cx", 6)
+ color_use_named_colors_circle_1.set_attribute("cy", 8)
+ color_use_named_colors_circle_1.set_attribute("r", 4)
+ color_use_named_colors_circle_1.set_attribute("fill", "gold")
+ color_use_named_colors_circle_1.set_attribute("stroke", "crimson")
+ color_use_named_colors_root_element.insert_child(0, color_use_named_colors_circle_1)
+ var color_use_named_colors_circle_2 := ElementCircle.new()
+ color_use_named_colors_circle_2.set_attribute("cx", 3)
+ color_use_named_colors_circle_2.set_attribute("cy", 5)
+ color_use_named_colors_circle_2.set_attribute("r", 2)
+ color_use_named_colors_circle_2.set_attribute("fill", "turquoise")
+ color_use_named_colors_root_element.insert_child(1, color_use_named_colors_circle_2)
+ add_preview(SettingFormatterPreview.new(current_setup_resource,
+ color_use_named_colors_root_element, true))
+
+ current_setup_setting = "color_primary_syntax"
+ add_dropdown(Translator.translate("Primary syntax"),
+ range(Formatter.PrimaryColorSyntax.size()),
+ Formatter.get_primary_color_syntax_value_text_map())
+ var color_primary_syntax_root_element := ElementRoot.new()
+ var color_primary_syntax_circle_element := ElementCircle.new()
+ color_primary_syntax_circle_element.set_attribute("cx", 6)
+ color_primary_syntax_circle_element.set_attribute("cy", 8)
+ color_primary_syntax_circle_element.set_attribute("r", 4)
+ color_primary_syntax_circle_element.set_attribute("fill", "#d4b")
+ color_primary_syntax_circle_element.set_attribute("stroke", "#f4c4d3")
+ color_primary_syntax_root_element.insert_child(0, color_primary_syntax_circle_element)
+ add_preview(SettingFormatterPreview.new(current_setup_resource,
+ color_primary_syntax_root_element, true))
+
+ current_setup_setting = "color_capital_hex"
+ add_checkbox(Translator.translate("Capitalize hexadecimal letters"),
+ current_setup_resource.color_primary_syntax == Formatter.PrimaryColorSyntax.RGB)
+ if current_setup_resource.color_primary_syntax != Formatter.PrimaryColorSyntax.RGB:
+ var color_capital_hex_root_element := ElementRoot.new()
+ var color_capital_hex_circle_element := ElementCircle.new()
+ color_capital_hex_circle_element.set_attribute("cx", 6)
+ color_capital_hex_circle_element.set_attribute("cy", 8)
+ color_capital_hex_circle_element.set_attribute("r", 4)
+ color_capital_hex_circle_element.set_attribute("fill", "#decade")
+ color_capital_hex_root_element.insert_child(0, color_capital_hex_circle_element)
+ add_preview(SettingFormatterPreview.new(current_setup_resource,
+ color_capital_hex_root_element, true))
+ else:
+ add_preview(SettingTextPreview.new("",
+ SettingTextPreview.WarningType.NO_EFFECT_IN_CURRENT_CONFIGURATION))
+
+ add_section(Translator.translate("Pathdata"))
+ current_setup_setting = "pathdata_compress_numbers"
+ add_checkbox(Translator.translate("Compress numbers"))
+ var pathdata_compress_numbers_root_element := ElementRoot.new()
+ var pathdata_compress_numbers_path_element := ElementPath.new()
+ pathdata_compress_numbers_path_element.set_attribute("d", "m 4 6.5 l 0.5 -0.8 v 2 z")
+ pathdata_compress_numbers_path_element.set_attribute("fill", "gold")
+ pathdata_compress_numbers_root_element.insert_child(0, pathdata_compress_numbers_path_element)
+ add_preview(SettingFormatterPreview.new(current_setup_resource,
+ pathdata_compress_numbers_root_element, true))
+
+ current_setup_setting = "pathdata_minimize_spacing"
+ add_checkbox(Translator.translate("Minimize spacing"))
+ var pathdata_minimize_spacing_root_element := ElementRoot.new()
+ var pathdata_minimize_spacing_path_element := ElementPath.new()
+ pathdata_minimize_spacing_path_element.set_attribute("d", "m 4 6.5 l 0.5 -0.8 v 2 z")
+ pathdata_minimize_spacing_path_element.set_attribute("fill", "gold")
+ pathdata_minimize_spacing_root_element.insert_child(0, pathdata_minimize_spacing_path_element)
+ add_preview(SettingFormatterPreview.new(current_setup_resource,
+ pathdata_minimize_spacing_root_element, true))
+
+ current_setup_setting = "pathdata_remove_spacing_after_flags"
+ add_checkbox(Translator.translate("Remove spacing after flags"))
+ var pathdata_remove_spacing_after_flags_root_element := ElementRoot.new()
+ var pathdata_remove_spacing_after_flags_path_element := ElementPath.new()
+ pathdata_remove_spacing_after_flags_path_element.set_attribute("d", "m 1 3.5 a 2 3 0 1 0 4 2 z")
+ pathdata_remove_spacing_after_flags_path_element.set_attribute("fill", "gold")
+ pathdata_remove_spacing_after_flags_root_element.insert_child(0, pathdata_remove_spacing_after_flags_path_element)
+ add_preview(SettingFormatterPreview.new(current_setup_resource,
+ pathdata_remove_spacing_after_flags_root_element, true))
+
+ current_setup_setting = "pathdata_remove_consecutive_commands"
+ add_checkbox(Translator.translate("Remove consecutive commands"))
+ var pathdata_remove_consecutive_commands_root_element := ElementRoot.new()
+ var pathdata_remove_consecutive_commands_path_element := ElementPath.new()
+ pathdata_remove_consecutive_commands_path_element.set_attribute("d",
+ "m 4 6.5 l -1 2 l 2.5 1 q 3.5 -1 2 -2 q -1.5 0.5 -1 -2 z")
+ pathdata_remove_consecutive_commands_path_element.set_attribute("fill", "gold")
+ pathdata_remove_consecutive_commands_root_element.insert_child(0, pathdata_remove_consecutive_commands_path_element)
+ add_preview(SettingFormatterPreview.new(current_setup_resource,
+ pathdata_remove_consecutive_commands_root_element, true))
+
+ add_section(Translator.translate("Transform lists"))
+ current_setup_setting = "transform_list_compress_numbers"
+ add_checkbox(Translator.translate("Compress numbers"))
+ var transform_list_compress_numbers_root_element := ElementRoot.new()
+ var transform_list_compress_numbers_polygon_element := ElementPolygon.new()
+ transform_list_compress_numbers_polygon_element.set_attribute("points", "2 4 5 8 9 1")
+ transform_list_compress_numbers_polygon_element.set_attribute("fill", "gold")
+ transform_list_compress_numbers_polygon_element.set_attribute("transform",
+ "rotate(7.5 -0.5 0.8)")
+ transform_list_compress_numbers_root_element.insert_child(0, transform_list_compress_numbers_polygon_element)
+ add_preview(SettingFormatterPreview.new(current_setup_resource,
+ transform_list_compress_numbers_root_element, true))
+
+ current_setup_setting = "transform_list_minimize_spacing"
+ add_checkbox(Translator.translate("Minimize spacing"))
+ var transform_list_minimize_spacing_root_element := ElementRoot.new()
+ var transform_list_minimize_spacing_polygon_element := ElementPolygon.new()
+ transform_list_minimize_spacing_polygon_element.set_attribute("points", "2 4 5 8 9 1")
+ transform_list_minimize_spacing_polygon_element.set_attribute("fill", "gold")
+ transform_list_minimize_spacing_polygon_element.set_attribute("transform",
+ "rotate(7.5 -0.5 0.8)")
+ transform_list_minimize_spacing_root_element.insert_child(0, transform_list_minimize_spacing_polygon_element)
+ add_preview(SettingFormatterPreview.new(current_setup_resource,
+ transform_list_minimize_spacing_root_element, true))
+
+ current_setup_setting = "transform_list_remove_unnecessary_params"
+ add_checkbox(Translator.translate("Remove unnecessary parameters"))
+ var transform_list_remove_unnecessary_params_root_element := ElementRoot.new()
+ var transform_list_remove_unnecessary_params_polygon_element := ElementPolygon.new()
+ transform_list_remove_unnecessary_params_polygon_element.set_attribute("points", "2 4 5 8 9 1")
+ transform_list_remove_unnecessary_params_polygon_element.set_attribute("fill", "gold")
+ transform_list_remove_unnecessary_params_polygon_element.set_attribute("transform",
+ "scale(2 2) translate(4 0) rotate(30 0 0)")
+ transform_list_remove_unnecessary_params_root_element.insert_child(0, transform_list_remove_unnecessary_params_polygon_element)
+ add_preview(SettingFormatterPreview.new(current_setup_resource,
+ transform_list_remove_unnecessary_params_root_element, true))
+
+func setup_theming_content() -> void:
+ var current_setup_resource := Configs.savedata
+
+ current_setup_setting = "theme_preset"
+ add_profile_picker(Translator.translate("Theme preset"),
+ current_setup_resource.reset_theme_items_to_default,
+ SaveData.ThemePreset.size(), SaveData.get_theme_preset_value_text_map(),
+ current_setup_resource.is_theming_default)
+ add_preview(SettingTextPreview.new(
+ Translator.translate("Determines the default values of theming-related settings, including the highlighter preset.")))
+
+ add_section(Translator.translate("Primary theme colors"))
+ current_setup_setting = "base_color"
+ add_color_edit(Translator.translate("Base color"), false)
+ current_setup_setting = "accent_color"
+ add_color_edit(Translator.translate("Accent color"), false)
+
+ add_section(Translator.translate("SVG Text colors"))
+ current_setup_setting = "highlighter_preset"
+ add_profile_picker(Translator.translate("Highlighter preset"),
+ current_setup_resource.reset_highlighting_items_to_default,
+ SaveData.HighlighterPreset.size(),
+ SaveData.get_highlighter_preset_value_text_map(),
+ current_setup_resource.is_highlighting_default)
+ add_preview(SettingTextPreview.new(
+ Translator.translate("Determines the default values of SVG highlighter settings.")))
+ current_setup_setting = "highlighting_symbol_color"
+ add_color_edit(Translator.translate("Symbol color"))
+ add_preview(SettingCodePreview.new(
+ """"""))
+ current_setup_setting = "highlighting_element_color"
+ add_color_edit(Translator.translate("Element color"))
+ add_preview(SettingCodePreview.new(
+ """"""))
+ current_setup_setting = "highlighting_attribute_color"
+ add_color_edit(Translator.translate("Attribute color"))
+ add_preview(SettingCodePreview.new(
+ """"""))
+ current_setup_setting = "highlighting_string_color"
+ add_color_edit(Translator.translate("String color"))
+ add_preview(SettingCodePreview.new(
+ """"""))
+ current_setup_setting = "highlighting_comment_color"
+ add_color_edit(Translator.translate("Comment color"))
+ add_preview(SettingCodePreview.new(
+ """ Basic text & " ' ]]> """))
+ current_setup_setting = "highlighting_text_color"
+ add_color_edit(Translator.translate("Text color"))
+ add_preview(SettingCodePreview.new(
+ """ Basic text & " ' ]]> """))
+ current_setup_setting = "highlighting_cdata_color"
+ add_color_edit(Translator.translate("CDATA color"))
+ add_preview(SettingCodePreview.new(
+ """ Basic text & " ' ]]> """))
+ current_setup_setting = "highlighting_error_color"
+ add_color_edit(Translator.translate("Error color"))
+ add_preview(SettingCodePreview.new(
+ """ void:
+ add_section(Translator.translate("Input"))
+ current_setup_setting = "tab_mmb_close"
+ add_checkbox(Translator.translate("Close tabs with middle mouse button"))
+ add_preview(SettingTextPreview.new(
+ Translator.translate("When enabled, clicking on a tab with the middle mouse button closes it instead of simply focusing it.")))
+
+func setup_other_content() -> void:
+ add_section(Translator.translate("Input"))
+ current_setup_setting = "invert_zoom"
+ add_checkbox(Translator.translate("Invert zoom direction"))
+ add_preview(SettingTextPreview.new(
+ Translator.translate("Swaps the scroll directions for zooming in and zooming out.")))
+ current_setup_setting = "wraparound_panning"
+ var wraparound_panning := add_checkbox(Translator.translate("Wrap-around panning"))
+ var wraparound_panning_forced_off := not DisplayServer.has_feature(DisplayServer.FEATURE_MOUSE_WARP)
+ add_preview(SettingTextPreview.new(Translator.translate(
+ "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning."),
+ SettingTextPreview.get_platform_availability_warning(wraparound_panning_forced_off)))
+ # Disable mouse wrap if not available.
+ if wraparound_panning_forced_off:
+ wraparound_panning.permanent_disable_checkbox(false)
+
+ current_setup_setting = "use_ctrl_for_zoom"
+ add_checkbox(Translator.translate("Use CTRL for zooming"))
+ add_preview(SettingTextPreview.new(
+ Translator.translate("When enabled, scrolling pans the view instead of zooming in. To zoom, hold CTRL while scrolling.")))
+
+ add_section(Translator.translate("Display"))
+ # Prepare parameters for the UI scale setting.
+ var auto_scale: float = HandlerGUI.get_auto_ui_scale()
+ var all_options := {
+ SaveData.ScalingApproach.CONSTANT_100: 1.0,
+ SaveData.ScalingApproach.CONSTANT_125: 1.25,
+ SaveData.ScalingApproach.CONSTANT_150: 1.5,
+ SaveData.ScalingApproach.CONSTANT_175: 1.75,
+ SaveData.ScalingApproach.CONSTANT_200: 2.0,
+ SaveData.ScalingApproach.CONSTANT_225: 2.25,
+ SaveData.ScalingApproach.CONSTANT_250: 2.5,
+ SaveData.ScalingApproach.CONSTANT_275: 2.75,
+ SaveData.ScalingApproach.CONSTANT_300: 3.0
+ }
+ var dropdown_map := {
+ SaveData.ScalingApproach.AUTO: "Auto (%d%%)" % int(auto_scale * 100),
+ }
+ for approach in all_options.keys():
+ var value: float= all_options[approach]
+ dropdown_map[approach] = "%d%%" % int(value * 100)
+
+ current_setup_setting = "ui_scale"
+ add_dropdown(Translator.translate("UI scale"), dropdown_map.keys(), dropdown_map)
+ add_preview(SettingTextPreview.new(
+ Translator.translate("Determines the scale factor for the interface.")))
+
+ current_setup_setting = "vsync"
+ add_checkbox(Translator.translate("V-Sync"))
+ add_preview(SettingTextPreview.new(
+ Translator.translate("Synchronizes graphics rendering with display refresh rate to prevent screen tearing artifacts. May increase input lag slightly.")))
+
+ current_setup_setting = "max_fps"
+ add_fps_limit_dropdown(Translator.translate("Maximum FPS"))
+ add_preview(SettingTextPreview.new(
+ Translator.translate("Determines the maximum number of frames per second.")))
+
+ current_setup_setting = "keep_screen_on"
+ add_checkbox(Translator.translate("Keep Screen On"))
+ add_preview(SettingTextPreview.new(
+ Translator.translate("Keeps the screen on even after inactivity, so the screensaver does not take over.")))
+
+ add_section(Translator.translate("Miscellaneous"))
+ current_setup_setting = "use_native_file_dialog"
+ var use_native_file_dialog := add_checkbox(Translator.translate("Use native file dialog"))
+ var use_native_file_dialog_forced_on := OS.has_feature("web")
+ var use_native_file_dialog_forced_off :=\
+ (not DisplayServer.has_feature(DisplayServer.FEATURE_NATIVE_DIALOG_FILE))
+ add_preview(SettingTextPreview.new(Translator.translate(
+ "When enabled, uses your operating system's native file dialog instead of GodSVG's built-in one."),
+ SettingTextPreview.get_platform_availability_warning(
+ use_native_file_dialog_forced_on or use_native_file_dialog_forced_off)))
+ # Disable fallback file dialog on web, and native file dialog if not available.
+ if use_native_file_dialog_forced_on:
+ use_native_file_dialog.permanent_disable_checkbox(true)
+ elif use_native_file_dialog_forced_off:
+ use_native_file_dialog.permanent_disable_checkbox(false)
+
+ current_setup_setting = "use_filename_for_window_title"
+ add_checkbox(Translator.translate("Sync window title to file name"))
+ add_preview(SettingTextPreview.new(
+ Translator.translate("When enabled, adds the current file name before the \"GodSVG\" window title.")))
+
+
+func add_section(section_name: String) -> void:
+ var vbox := VBoxContainer.new()
+ vbox.add_theme_constant_override("separation", 0)
+ var label := Label.new()
+ label.add_theme_font_size_override("font_size", 15)
+ label.theme_type_variation = "TitleLabel"
+ label.text = section_name
+ vbox.add_child(label)
+ var spacer := Control.new()
+ spacer.custom_minimum_size.y = 2
+ vbox.add_child(spacer)
+ setting_container.add_child(vbox)
+
+func add_profile_picker(text: String, application_callback: Callable, profile_count: int,
+value_text_map: Dictionary, disabled_check_callback: Callable) -> void:
+ var frame := ProfileFrameScene.instantiate()
+ frame.text = text
+ setup_frame(frame, false)
+ frame.setup_dropdown(range(profile_count), value_text_map)
+ frame.disabled_check_callback = disabled_check_callback
+ frame.value_changed.connect.call_deferred(setup_content)
+ frame.defaults_applied.connect(application_callback)
+ frame.defaults_applied.connect(setup_content)
+ add_frame(frame)
+
+ var resource_permanent_ref := _get_current_setup_resource()
+ resource_permanent_ref.changed_deferred.connect(frame.button_update_disabled)
+ frame.tree_exited.connect(resource_permanent_ref.changed_deferred.disconnect.bind(
+ frame.button_update_disabled), CONNECT_ONE_SHOT)
+
+func add_checkbox(text: String, dim_text := false) -> Control:
+ var frame := SettingFrameScene.instantiate()
+ frame.dim_text = dim_text
+ frame.text = text
+ setup_frame(frame)
+ frame.setup_checkbox()
+ add_frame(frame)
+ # Some checkboxes need to update the dimness of the text of other settings.
+ # There's no continuous editing with checkboxes, so it's safe to just rebuild
+ # the content for them.
+ frame.value_changed.connect(setup_content)
+ return frame
+
+# TODO Typed Dictionary wonkiness
+func add_dropdown(text: String, values: Array[Variant],
+value_text_map: Dictionary) -> Control: # Dictionary[Variant, String]
+ var frame := SettingFrameScene.instantiate()
+ frame.text = text
+ setup_frame(frame)
+ frame.setup_dropdown(values, value_text_map)
+ add_frame(frame)
+ # Some checkboxes need to update the dimness of the text of other settings.
+ # There's no continuous editing with checkboxes, so it's safe to just rebuild
+ # the content for them.
+ frame.value_changed.connect(setup_content)
+ return frame
+
+func add_number_dropdown(text: String, values: Array[float], is_integer := false,
+restricted := true, min_value := -INF, max_value := INF, dim_text := false) -> Control:
+ var frame := SettingFrameScene.instantiate()
+ frame.dim_text = dim_text
+ frame.text = text
+ setup_frame(frame)
+ frame.setup_number_dropdown(values, is_integer, restricted, min_value, max_value)
+ add_frame(frame)
+ return frame
+
+func add_fps_limit_dropdown(text: String, dim_text := false) -> Control:
+ var frame := SettingFrameScene.instantiate()
+ frame.dim_text = dim_text
+ frame.text = text
+ setup_frame(frame)
+ frame.setup_fps_limit_dropdown()
+ add_frame(frame)
+ return frame
+
+func add_color_edit(text: String, enable_alpha := true) -> Control:
+ var frame := SettingFrameScene.instantiate()
+ frame.text = text
+ setup_frame(frame)
+ frame.setup_color(enable_alpha)
+ add_frame(frame)
+ return frame
+
+func setup_frame(frame: Control, has_default := true) -> void:
+ var bind := current_setup_setting
+ var resource_ref := _get_current_setup_resource()
+ frame.setter = func(p: Variant) -> void: resource_ref.set(bind, p)
+ frame.getter = resource_ref.get.bind(bind)
+ if has_default:
+ frame.default = resource_ref.get_setting_default(current_setup_setting)
+ frame.mouse_entered.connect(set_preview.bind(current_setup_setting))
+ frame.mouse_exited.connect(remove_preview.bind(current_setup_setting))
+
+func add_frame(frame: Control) -> void:
+ if setting_container.get_child_count() > 0:
+ setting_container.get_child(-1).add_child(frame)
+ else:
+ setting_container.add_child(frame)
+
+
+func add_preview(preview: RefCounted) -> void:
+ previews[current_setup_setting] = preview
+
+func set_preview(setting: String) -> void:
+ current_previewed_setting = setting
+ emit_preview_changed()
+
+func remove_preview(setting: String) -> void:
+ if current_previewed_setting == setting:
+ current_previewed_setting = ""
+ emit_preview_changed()
+
+func emit_preview_changed() -> void:
+ if current_previewed_setting.is_empty() or not previews.has(current_previewed_setting):
+ preview_changed.emit(Control.new())
+ return
+
+ var preview := previews[current_previewed_setting]
+ if preview is SettingBasicColorPreview:
+ var label := Label.new()
+ label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
+ var update_label_font_color := func() -> void:
+ label.add_theme_color_override("font_color",
+ Configs.savedata.get(preview.setting_bind))
+ Configs.basic_colors_changed.connect(update_label_font_color)
+ label.tree_exiting.connect(Configs.basic_colors_changed.disconnect.bind(
+ update_label_font_color), CONNECT_ONE_SHOT)
+ update_label_font_color.call()
+ label.text = preview.text
+ preview_changed.emit(label)
+ if preview is SettingTextPreview:
+ var has_warning: bool = (preview.warning != preview.WarningType.NONE)
+ var margin_container := MarginContainer.new()
+ margin_container.add_theme_constant_override("margin_left", 6)
+ margin_container.add_theme_constant_override("margin_right", 6)
+ margin_container.add_theme_constant_override("margin_top", 2)
+ margin_container.add_theme_constant_override("margin_bottom", 4)
+ var label := Label.new()
+ label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
+ label.size_flags_vertical = Control.SIZE_EXPAND_FILL
+ label.add_theme_constant_override("line_spacing", 2)
+ label.text = preview.text
+ var preview_font_size := get_theme_font_size("font_size", "Label")
+ while label.get_line_count() >= (2 if has_warning else 3):
+ preview_font_size -= 1
+ label.add_theme_font_size_override("font_size", preview_font_size)
+ if has_warning:
+ var vbox := VBoxContainer.new()
+ vbox.add_theme_constant_override("separation", 2)
+ var no_effect_warning_label := Label.new()
+ no_effect_warning_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
+ no_effect_warning_label.size_flags_vertical = Control.SIZE_EXPAND_FILL
+ no_effect_warning_label.add_theme_constant_override("line_spacing", 2)
+ no_effect_warning_label.add_theme_color_override("font_color",
+ Configs.savedata.basic_color_warning)
+ match preview.warning:
+ preview.WarningType.NO_EFFECT_IN_CURRENT_CONFIGURATION:
+ no_effect_warning_label.text = Translator.translate(
+ "The setting has no effect in the current configuration.")
+ preview.WarningType.NOT_AVAILABLE_ON_PLATFORM:
+ no_effect_warning_label.text = Translator.translate(
+ "The setting can't be changed on this platform.")
+ _:
+ no_effect_warning_label.text = ""
+ while no_effect_warning_label.get_line_count() >= 2:
+ preview_font_size -= 1
+ no_effect_warning_label.add_theme_font_size_override("font_size",
+ preview_font_size)
+ label.add_theme_font_size_override("font_size", preview_font_size)
+ if not preview.text.is_empty():
+ vbox.add_child(label)
+ vbox.add_child(no_effect_warning_label)
+ margin_container.add_child(vbox)
+ else:
+ margin_container.add_child(label)
+ preview_changed.emit(margin_container)
+ elif preview is SettingCodePreview:
+ var code_preview := BetterTextEdit.new()
+ code_preview.editable = false
+ var update_highlighter := func() -> void:
+ code_preview.syntax_highlighter = SVGHighlighter.new()
+ code_preview.add_theme_color_override("font_readonly_color", Color.WHITE)
+
+ var text_edit_default_stylebox := code_preview.get_theme_stylebox("normal")
+ var empty_stylebox := StyleBoxEmpty.new()
+ empty_stylebox.content_margin_left = text_edit_default_stylebox.content_margin_left
+ empty_stylebox.content_margin_right = text_edit_default_stylebox.content_margin_right
+ empty_stylebox.content_margin_top = text_edit_default_stylebox.content_margin_top
+ empty_stylebox.content_margin_bottom = text_edit_default_stylebox.content_margin_bottom
+ code_preview.add_theme_stylebox_override("normal", empty_stylebox)
+ code_preview.add_theme_stylebox_override("read_only", empty_stylebox)
+ code_preview.text = preview.text
+ Configs.highlighting_colors_changed.connect(update_highlighter)
+ code_preview.tree_exiting.connect(Configs.highlighting_colors_changed.disconnect.bind(
+ update_highlighter), CONNECT_ONE_SHOT)
+ update_highlighter.call()
+ preview_changed.emit(code_preview)
+ elif preview is SettingFormatterPreview:
+ var code_preview := BetterTextEdit.new()
+ code_preview.editable = false
+
+ var update_highlighter := func() -> void:
+ code_preview.syntax_highlighter = SVGHighlighter.new()
+
+ var update_text := func() -> void:
+ if preview.show_only_children:
+ code_preview.text = SVGParser.root_children_to_text(
+ preview.root_element, preview.resource_bind)
+ else:
+ code_preview.text = SVGParser.root_to_text(
+ preview.root_element, preview.resource_bind)
+
+ code_preview.add_theme_color_override("font_readonly_color", Color.WHITE)
+ var text_edit_default_stylebox := code_preview.get_theme_stylebox("normal")
+ var empty_stylebox := StyleBoxEmpty.new()
+ empty_stylebox.content_margin_left = text_edit_default_stylebox.content_margin_left
+ empty_stylebox.content_margin_right = text_edit_default_stylebox.content_margin_right
+ empty_stylebox.content_margin_top = text_edit_default_stylebox.content_margin_top
+ empty_stylebox.content_margin_bottom = text_edit_default_stylebox.content_margin_bottom
+ code_preview.add_theme_stylebox_override("normal", empty_stylebox)
+ code_preview.add_theme_stylebox_override("read_only", empty_stylebox)
+ Configs.highlighting_colors_changed.connect(update_highlighter)
+ code_preview.tree_exiting.connect(Configs.highlighting_colors_changed.disconnect.bind(
+ update_highlighter), CONNECT_ONE_SHOT)
+ update_highlighter.call()
+ preview.resource_bind.changed_deferred.connect(update_text)
+ code_preview.tree_exiting.connect(preview.resource_bind.changed_deferred.disconnect.bind(
+ update_text), CONNECT_ONE_SHOT)
+ update_text.call()
+ # TODO Impressively, all this is necessary for scrollbars to work.
+ # TextEdit is so damn janky.
+ code_preview.hide()
+ code_preview.show()
+ await get_tree().process_frame
+ await get_tree().process_frame
+ if is_instance_valid(code_preview) and\
+ not is_zero_approx(code_preview.get_v_scroll_bar().max_value):
+ var tw := code_preview.create_tween().set_loops()
+ tw.tween_interval(1.75)
+ tw.tween_property(code_preview.get_v_scroll_bar(), ^"value",
+ floorf(code_preview.get_v_scroll_bar().max_value -\
+ code_preview.get_visible_line_count()), 0.5)
+ tw.tween_interval(1.75)
+ tw.tween_property(code_preview.get_v_scroll_bar(), ^"value", 0.0, 0.5)
+ preview_changed.emit(code_preview)
diff --git a/src/ui_widgets/settings_content_generic.gd.uid b/src/ui_widgets/settings_content_generic.gd.uid
new file mode 100644
index 0000000..185d2b5
--- /dev/null
+++ b/src/ui_widgets/settings_content_generic.gd.uid
@@ -0,0 +1 @@
+uid://uorwyvmsga5v
diff --git a/src/ui_widgets/settings_content_generic.tscn b/src/ui_widgets/settings_content_generic.tscn
new file mode 100644
index 0000000..8c422c5
--- /dev/null
+++ b/src/ui_widgets/settings_content_generic.tscn
@@ -0,0 +1,12 @@
+[gd_scene load_steps=2 format=3 uid="uid://6p0mvxm7nwqp"]
+
+[ext_resource type="Script" uid="uid://uorwyvmsga5v" path="res://src/ui_widgets/settings_content_generic.gd" id="1_0ufc2"]
+
+[node name="SettingsContentGeneric" type="VBoxContainer"]
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+theme_override_constants/separation = 6
+script = ExtResource("1_0ufc2")
diff --git a/src/ui_widgets/settings_content_palettes.gd b/src/ui_widgets/settings_content_palettes.gd
new file mode 100644
index 0000000..dc2181c
--- /dev/null
+++ b/src/ui_widgets/settings_content_palettes.gd
@@ -0,0 +1,62 @@
+extends VBoxContainer
+
+const PaletteConfigWidgetScene = preload("res://src/ui_widgets/palette_config.tscn")
+
+@onready var palette_container: VBoxContainer = $PaletteContainer
+@onready var add_button: Button = $ButtonsContainer/AddButton
+@onready var import_button: Button = $ButtonsContainer/ImportButton
+
+func _ready() -> void:
+ Configs.language_changed.connect(sync_localization)
+ sync_localization()
+ add_button.pressed.connect(add_empty_palette)
+ import_button.pressed.connect(_popup_xml_palette_options.bind(import_button))
+ rebuild_palettes()
+
+func sync_localization() -> void:
+ add_button.text = Translator.translate("New palette")
+ import_button.text = Translator.translate("New palette from XML")
+
+func rebuild_palettes() -> void:
+ for palette_config in palette_container.get_children():
+ palette_config.queue_free()
+ for palette in Configs.savedata.get_palettes():
+ var palette_config := PaletteConfigWidgetScene.instantiate()
+ palette_container.add_child(palette_config)
+ palette_config.assign_palette(palette)
+ palette_config.layout_changed.connect(rebuild_palettes)
+
+
+func _popup_xml_palette_options(palette_xml_button: Button) -> void:
+ var btn_arr: Array[Button] = []
+ btn_arr.append(ContextPopup.create_button(Translator.translate("Import XML"),
+ add_imported_palette, false, load("res://assets/icons/Import.svg")))
+ btn_arr.append(ContextPopup.create_button(Translator.translate("Paste XML"),
+ add_pasted_palette, !Palette.is_valid_palette(Utils.get_clipboard_web_safe()),
+ load("res://assets/icons/Paste.svg")))
+
+ var context_popup := ContextPopup.new()
+ context_popup.setup(btn_arr, true)
+ HandlerGUI.popup_under_rect_center(context_popup, palette_xml_button.get_global_rect(),
+ get_viewport())
+
+
+func add_empty_palette() -> void:
+ _shared_add_palette_logic(Palette.new())
+
+func add_pasted_palette() -> void:
+ _shared_add_palettes_logic(Palette.text_to_palettes(Utils.get_clipboard_web_safe()))
+
+func add_imported_palette() -> void:
+ FileUtils.open_xml_import_dialog(_on_import_palette_finished)
+
+func _on_import_palette_finished(file_text: String) -> void:
+ _shared_add_palettes_logic(Palette.text_to_palettes(file_text))
+
+func _shared_add_palettes_logic(palettes: Array[Palette]) -> void:
+ if not palettes.is_empty():
+ _shared_add_palette_logic(palettes[0])
+
+func _shared_add_palette_logic(palette: Palette) -> void:
+ Configs.savedata.add_palette(palette)
+ rebuild_palettes()
diff --git a/src/ui_widgets/settings_content_palettes.gd.uid b/src/ui_widgets/settings_content_palettes.gd.uid
new file mode 100644
index 0000000..81f57e4
--- /dev/null
+++ b/src/ui_widgets/settings_content_palettes.gd.uid
@@ -0,0 +1 @@
+uid://2gb2si1sw30b
diff --git a/src/ui_widgets/settings_content_palettes.tscn b/src/ui_widgets/settings_content_palettes.tscn
new file mode 100644
index 0000000..ce2eb1f
--- /dev/null
+++ b/src/ui_widgets/settings_content_palettes.tscn
@@ -0,0 +1,33 @@
+[gd_scene load_steps=4 format=3 uid="uid://b3xlygg7jbmb5"]
+
+[ext_resource type="Script" uid="uid://2gb2si1sw30b" path="res://src/ui_widgets/settings_content_palettes.gd" id="1_6ajas"]
+[ext_resource type="Texture2D" uid="uid://eif2ioi0mw17" path="res://assets/icons/Plus.svg" id="2_ywgeg"]
+[ext_resource type="Texture2D" uid="uid://6ymbl3jqersp" path="res://assets/icons/Import.svg" id="3_p0ru4"]
+
+[node name="SettingsContentPalettes" type="VBoxContainer"]
+offset_right = 40.0
+offset_bottom = 40.0
+theme_override_constants/separation = 8
+script = ExtResource("1_6ajas")
+
+[node name="PaletteContainer" type="VBoxContainer" parent="."]
+layout_mode = 2
+
+[node name="ButtonsContainer" type="HBoxContainer" parent="."]
+layout_mode = 2
+theme_override_constants/separation = 6
+alignment = 1
+
+[node name="AddButton" type="Button" parent="ButtonsContainer"]
+layout_mode = 2
+focus_mode = 0
+mouse_default_cursor_shape = 2
+theme_type_variation = &"TranslucentButton"
+icon = ExtResource("2_ywgeg")
+
+[node name="ImportButton" type="Button" parent="ButtonsContainer"]
+layout_mode = 2
+focus_mode = 0
+mouse_default_cursor_shape = 2
+theme_type_variation = &"TranslucentButton"
+icon = ExtResource("3_p0ru4")
diff --git a/src/ui_widgets/settings_content_shortcuts.gd b/src/ui_widgets/settings_content_shortcuts.gd
new file mode 100644
index 0000000..9d1ce2e
--- /dev/null
+++ b/src/ui_widgets/settings_content_shortcuts.gd
@@ -0,0 +1,71 @@
+extends VBoxContainer
+
+const ShortcutConfigWidgetScene = preload("res://src/ui_widgets/setting_shortcut.tscn")
+const ShortcutShowcaseWidgetScene = preload("res://src/ui_widgets/presented_shortcut.tscn")
+
+@onready var categories_container: HFlowContainer = $CategoriesContainer
+@onready var shortcuts_container: VBoxContainer = $ShortcutsContainer
+
+const shortcut_tab_names: PackedStringArray = ["file", "edit", "view", "tool", "help"]
+
+var undo_redo := UndoRedoRef.new()
+
+func get_translated_shortcut_tab(tab_idx: String) -> String:
+ match tab_idx:
+ "file": return Translator.translate("File")
+ "edit": return Translator.translate("Edit")
+ "view": return Translator.translate("View")
+ "tool": return Translator.translate("Tool")
+ "help": return Translator.translate("Help")
+ return ""
+
+func _ready() -> void:
+ var button_group := ButtonGroup.new()
+ for tab_idx in shortcut_tab_names:
+ var btn := Button.new()
+ btn.toggle_mode = true
+ btn.button_group = button_group
+ btn.pressed.connect(show_shortcuts.bind(tab_idx))
+ var sync_button_locale := func() -> void:
+ btn.text = get_translated_shortcut_tab(tab_idx)
+ Configs.language_changed.connect(sync_button_locale)
+ sync_button_locale.call()
+ btn.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
+ btn.focus_mode = Control.FOCUS_NONE
+ btn.action_mode = BaseButton.ACTION_MODE_BUTTON_PRESS
+ categories_container.add_child(btn)
+ categories_container.get_child(0).button_pressed = true
+ categories_container.get_child(0).pressed.emit()
+
+func _unhandled_input(event: InputEvent) -> void:
+ if ShortcutUtils.is_action_pressed(event, "ui_undo"):
+ undo_redo.undo()
+ elif ShortcutUtils.is_action_pressed(event, "ui_redo"):
+ undo_redo.redo()
+
+
+func show_shortcuts(category: String) -> void:
+ undo_redo.clear_history()
+ for child in shortcuts_container.get_children():
+ child.queue_free()
+
+ for action in ShortcutUtils.get_actions(category):
+ var shortcut_config: Control
+ if ShortcutUtils.is_action_modifiable(action):
+ shortcut_config = ShortcutConfigWidgetScene.instantiate()
+ shortcut_config.shortcuts_modified.connect(
+ func(new_shortcuts: Array[InputEvent]) -> void:
+ _on_shortcuts_modified(action, new_shortcuts))
+ else:
+ shortcut_config = ShortcutShowcaseWidgetScene.instantiate()
+
+ shortcuts_container.add_child(shortcut_config)
+ shortcut_config.label.text = TranslationUtils.get_action_description(action)
+ shortcut_config.setup(action)
+
+func _on_shortcuts_modified(action: String, new_shortcuts: Array[InputEvent]) -> void:
+ undo_redo.create_action()
+ undo_redo.add_do_method(Configs.savedata.action_modify_shortcuts.bind(action, new_shortcuts))
+ undo_redo.add_undo_method(Configs.savedata.action_modify_shortcuts.bind(action,
+ Configs.savedata.action_get_shortcuts(action)))
+ undo_redo.commit_action()
diff --git a/src/ui_widgets/settings_content_shortcuts.gd.uid b/src/ui_widgets/settings_content_shortcuts.gd.uid
new file mode 100644
index 0000000..1fc68a7
--- /dev/null
+++ b/src/ui_widgets/settings_content_shortcuts.gd.uid
@@ -0,0 +1 @@
+uid://orlxtok0bt6x
diff --git a/src/ui_widgets/settings_content_shortcuts.tscn b/src/ui_widgets/settings_content_shortcuts.tscn
new file mode 100644
index 0000000..d7e3e48
--- /dev/null
+++ b/src/ui_widgets/settings_content_shortcuts.tscn
@@ -0,0 +1,15 @@
+[gd_scene load_steps=2 format=3 uid="uid://ybvhb027yskm"]
+
+[ext_resource type="Script" uid="uid://orlxtok0bt6x" path="res://src/ui_widgets/settings_content_shortcuts.gd" id="1_wf8o4"]
+
+[node name="SettingsContentShortcuts" type="VBoxContainer"]
+offset_right = 40.0
+offset_bottom = 40.0
+theme_override_constants/separation = 6
+script = ExtResource("1_wf8o4")
+
+[node name="CategoriesContainer" type="HFlowContainer" parent="."]
+layout_mode = 2
+
+[node name="ShortcutsContainer" type="VBoxContainer" parent="."]
+layout_mode = 2
diff --git a/src/ui_widgets/transform_field.gd b/src/ui_widgets/transform_field.gd
index f57308f..82f04c5 100644
--- a/src/ui_widgets/transform_field.gd
+++ b/src/ui_widgets/transform_field.gd
@@ -14,7 +14,7 @@ func set_value(new_value: String, save := false) -> void:
func _ready() -> void:
- Configs.language_changed.connect(update_translation)
+ Configs.language_changed.connect(sync_localization)
sync()
element.attribute_changed.connect(_on_element_attribute_changed)
tooltip_text = attribute_name
@@ -24,14 +24,14 @@ func _ready() -> void:
text_change_canceled.connect(sync)
button_gui_input.connect(_on_button_gui_input)
pressed.connect(_on_pressed)
- update_translation()
+ sync_localization()
func _on_element_attribute_changed(attribute_changed: String) -> void:
if attribute_name == attribute_changed:
sync()
-func update_translation() -> void:
+func sync_localization() -> void:
placeholder_text = Translator.translate("No transforms")
func setup_font(new_text: String) -> void:
diff --git a/src/ui_widgets/transform_popup.gd b/src/ui_widgets/transform_popup.gd
index c13a785..05d7604 100644
--- a/src/ui_widgets/transform_popup.gd
+++ b/src/ui_widgets/transform_popup.gd
@@ -29,16 +29,16 @@ var undo_redo := UndoRedoRef.new()
@onready var apply_matrix: Button = %ApplyMatrix
func _ready() -> void:
- Configs.language_changed.connect(update_translation)
+ Configs.language_changed.connect(sync_localization)
add_button.pressed.connect(popup_new_transform_context.bind(0, add_button))
apply_matrix.pressed.connect(_on_apply_matrix_pressed)
rebuild()
- update_translation()
+ sync_localization()
func _exit_tree() -> void:
State.queue_svg_save()
-func update_translation() -> void:
+func sync_localization() -> void:
apply_matrix.tooltip_text = Translator.translate("Apply the matrix")
func rebuild() -> void:
@@ -104,7 +104,7 @@ func create_mini_number_field(idx: int, property: String) -> BetterLineEdit:
func update_value(new_value: float, idx: int, property: String) -> void:
- undo_redo.create_action("")
+ undo_redo.create_action()
undo_redo.add_do_method(attribute_ref.set_transform_property.bind(idx, property, new_value))
undo_redo.add_do_method(rebuild)
undo_redo.add_undo_method(attribute_ref.set_transform_list.bind(get_transform_list()))
@@ -112,7 +112,7 @@ func update_value(new_value: float, idx: int, property: String) -> void:
undo_redo.commit_action()
func insert_transform(idx: int, transform_type: String) -> void:
- undo_redo.create_action("")
+ undo_redo.create_action()
undo_redo.add_do_method(attribute_ref.insert_transform.bind(idx, transform_type))
undo_redo.add_do_method(rebuild)
undo_redo.add_undo_method(attribute_ref.set_transform_list.bind(get_transform_list()))
@@ -120,7 +120,7 @@ func insert_transform(idx: int, transform_type: String) -> void:
undo_redo.commit_action()
func delete_transform(idx: int) -> void:
- undo_redo.create_action("")
+ undo_redo.create_action()
undo_redo.add_do_method(attribute_ref.delete_transform.bind(idx))
undo_redo.add_do_method(rebuild)
undo_redo.add_undo_method(attribute_ref.set_transform_list.bind(get_transform_list()))
@@ -129,7 +129,7 @@ func delete_transform(idx: int) -> void:
func _on_apply_matrix_pressed() -> void:
var final_transform := attribute_ref.get_final_precise_transform()
- undo_redo.create_action("")
+ undo_redo.create_action()
undo_redo.add_do_method(attribute_ref.set_transform_list.bind([
Transform.TransformMatrix.new(final_transform[0], final_transform[1],
final_transform[2], final_transform[3], final_transform[4],
diff --git a/src/ui_widgets/unrecognized_field.gd b/src/ui_widgets/unrecognized_field.gd
index afa0ded..7d96f64 100644
--- a/src/ui_widgets/unrecognized_field.gd
+++ b/src/ui_widgets/unrecognized_field.gd
@@ -12,14 +12,14 @@ func set_value(new_value: String, save := false) -> void:
func _ready() -> void:
- Configs.language_changed.connect(update_translation)
+ Configs.language_changed.connect(sync_localization)
sync()
- update_translation()
+ sync_localization()
text_submitted.connect(set_value.bind(true))
func sync() -> void:
text = element.get_attribute_value(attribute_name)
-func update_translation() -> void:
+func sync_localization() -> void:
tooltip_text = attribute_name + "\n(%s)" %\
Translator.translate("GodSVG doesn’t recognize this attribute")
diff --git a/src/utils/ThemeUtils.gd b/src/utils/ThemeUtils.gd
index f95e4b9..844d3a4 100644
--- a/src/utils/ThemeUtils.gd
+++ b/src/utils/ThemeUtils.gd
@@ -636,11 +636,11 @@ static func _setup_button(theme: Theme) -> void:
var normal_translucent_button_stylebox := StyleBoxFlat.new()
normal_translucent_button_stylebox.set_corner_radius_all(5)
normal_translucent_button_stylebox.set_content_margin_all(4)
- normal_translucent_button_stylebox.bg_color = hover_overlay_color
+ normal_translucent_button_stylebox.bg_color = strong_hover_overlay_color
theme.set_stylebox("normal", "TranslucentButton", normal_translucent_button_stylebox)
var hover_translucent_button_stylebox := normal_translucent_button_stylebox.duplicate()
- hover_translucent_button_stylebox.bg_color = strong_hover_overlay_color
+ hover_translucent_button_stylebox.bg_color = stronger_hover_overlay_color
theme.set_stylebox("hover", "TranslucentButton", hover_translucent_button_stylebox)
var pressed_translucent_button_stylebox := normal_translucent_button_stylebox.duplicate()
@@ -836,11 +836,10 @@ static func _setup_checkbox(theme: Theme) -> void:
theme.add_type("CheckBox")
theme.set_constant("h_separation", "CheckBox", 5)
theme.set_color("font_color", "CheckBox", text_color)
- theme.set_color("font_color", "CheckBox", text_color)
theme.set_color("font_disabled_color", "CheckBox", subtle_text_color)
- theme.set_color("font_focus_color", "CheckBox", highlighted_text_color)
+ theme.set_color("font_focus_color", "CheckBox", text_color)
theme.set_color("font_hover_color", "CheckBox", highlighted_text_color)
- theme.set_color("font_pressed_color", "CheckBox", highlighted_text_color)
+ theme.set_color("font_pressed_color", "CheckBox", text_color)
theme.set_color("font_hover_pressed_color", "CheckBox", highlighted_text_color)
theme.set_icon("checked", "CheckBox",
SVGTexture.create_from_string("""
@@ -900,9 +899,9 @@ static func _setup_checkbutton(theme: Theme) -> void:
theme.add_type("CheckButton")
theme.set_color("font_color", "CheckButton", text_color)
theme.set_color("font_disabled_color", "CheckButton", subtle_text_color)
- theme.set_color("font_focus_color", "CheckButton", highlighted_text_color)
+ theme.set_color("font_focus_color", "CheckButton", text_color)
theme.set_color("font_hover_color", "CheckButton", highlighted_text_color)
- theme.set_color("font_pressed_color", "CheckButton", highlighted_text_color)
+ theme.set_color("font_pressed_color", "CheckButton", text_color)
theme.set_color("font_hover_pressed_color", "CheckButton", highlighted_text_color)
theme.set_icon("checked", "CheckButton",
SVGTexture.create_from_string("""
@@ -963,6 +962,7 @@ static func _setup_lineedit(theme: Theme) -> void:
theme.set_color("font_color", "LineEdit", editable_text_color)
theme.set_color("font_uneditable_color", "LineEdit", dimmer_text_color)
theme.set_color("font_placeholder_color", "LineEdit", subtle_text_color)
+ theme.set_color("font_selected_color", "LineEdit", highlighted_text_color)
theme.set_color("selection_color", "LineEdit", selection_color)
theme.set_color("disabled_selection_color", "LineEdit", disabled_selection_color)
theme.set_font_size("font_size", "LineEdit", 12)
@@ -1283,14 +1283,16 @@ static func _setup_textedit(theme: Theme) -> void:
theme.add_type("TextEdit")
theme.set_color("caret_color", "TextEdit", Color.TRANSPARENT)
theme.set_color("selection_color", "TextEdit", selection_color)
+ theme.set_constant("line_spacing", "TextEdit", 3)
theme.set_font_size("font_size", "TextEdit", 12)
theme.set_font("font", "TextEdit", mono_font)
var normal_stylebox := StyleBoxFlat.new()
normal_stylebox.bg_color = line_edit_inner_color
normal_stylebox.set_corner_radius_all(5)
- normal_stylebox.content_margin_left = 5.0
+ normal_stylebox.content_margin_left = 6.0
theme.set_stylebox("normal", "TextEdit", normal_stylebox)
+ theme.set_stylebox("read_only", "TextEdit", normal_stylebox)
var focus_stylebox := StyleBoxFlat.new()
focus_stylebox.draw_center = false
diff --git a/translations/GodSVG.pot b/translations/GodSVG.pot
index dbedc76..230b98e 100644
--- a/translations/GodSVG.pot
+++ b/translations/GodSVG.pot
@@ -469,6 +469,10 @@ msgstr ""
msgid "Theme preset"
msgstr ""
+#: src/ui_parts/settings_menu.gd:
+msgid "Determines the default values of theming-related settings, including the highlighter preset."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Primary theme colors"
msgstr ""
@@ -489,6 +493,10 @@ msgstr ""
msgid "Highlighter preset"
msgstr ""
+#: src/ui_parts/settings_menu.gd:
+msgid "Determines the default values of SVG highlighter settings."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Symbol color"
msgstr ""
@@ -593,7 +601,7 @@ msgid "Close tabs with middle mouse button"
msgstr ""
#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, clicking on a tab with the middle mouse button closes the tab. If turned off, it focuses the tab instead."
+msgid "When enabled, clicking on a tab with the middle mouse button closes it instead of simply focusing it."
msgstr ""
#: src/ui_parts/settings_menu.gd:
@@ -608,16 +616,12 @@ msgstr ""
msgid "Wrap-around panning"
msgstr ""
-#: src/ui_parts/settings_menu.gd:
-msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning."
-msgstr ""
-
#: src/ui_parts/settings_menu.gd:
msgid "Use CTRL for zooming"
msgstr ""
#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, scrolling pans the view. To zoom, hold CTRL while scrolling."
+msgid "When enabled, scrolling pans the view instead of zooming in. To zoom, hold CTRL while scrolling."
msgstr ""
#: src/ui_parts/settings_menu.gd:
@@ -650,15 +654,19 @@ msgid "Determines the maximum number of frames per second."
msgstr ""
#: src/ui_parts/settings_menu.gd:
-msgid "Miscellaneous"
+msgid "Keep Screen On"
msgstr ""
#: src/ui_parts/settings_menu.gd:
-msgid "Use native file dialog"
+msgid "Keeps the screen on even after inactivity, so the screensaver does not take over."
msgstr ""
#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, uses your operating system's native file dialog. If turned off, uses GodSVG's built-in file dialog."
+msgid "Miscellaneous"
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "Use native file dialog"
msgstr ""
#: src/ui_parts/settings_menu.gd:
@@ -666,7 +674,7 @@ msgid "Sync window title to file name"
msgstr ""
#: src/ui_parts/settings_menu.gd:
-msgid "If turned off, the window title remains as \"GodSVG\" without including the current file."
+msgid "When enabled, adds the current file name before the \"GodSVG\" window title."
msgstr ""
#: src/ui_parts/settings_menu.gd:
@@ -708,11 +716,11 @@ msgid "Preset"
msgstr ""
#: src/ui_parts/settings_menu.gd:
-msgid "Keep comments"
+msgid "Determines the default values of the formatter configs."
msgstr ""
#: src/ui_parts/settings_menu.gd:
-msgid "Keep unrecognized XML structures"
+msgid "Keep comments"
msgstr ""
#: src/ui_parts/settings_menu.gd:
@@ -795,6 +803,26 @@ msgstr ""
msgid "Remove unnecessary parameters"
msgstr ""
+#: src/ui_parts/settings_menu.gd:
+msgid "When enabled, uses several spaces instead of a single tab for indentation."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "When enabled, uses your operating system's native file dialog instead of GodSVG's built-in one."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "The setting has no effect in the current configuration."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "The setting can't be changed on this platform."
+msgstr ""
+
#: src/ui_parts/shortcut_panel.gd:
msgid "Horizontal strip"
msgstr ""
diff --git a/translations/bg.po b/translations/bg.po
index 5cc9353..b5bf9ad 100644
--- a/translations/bg.po
+++ b/translations/bg.po
@@ -470,6 +470,10 @@ msgstr "Други"
msgid "Theme preset"
msgstr "Шаблон на тема"
+#: src/ui_parts/settings_menu.gd:
+msgid "Determines the default values of theming-related settings, including the highlighter preset."
+msgstr "Определя стойностите по подразбиране на гамовите настройки, включително шаблона на синтаксовото маркиране."
+
#: src/ui_parts/settings_menu.gd:
msgid "Primary theme colors"
msgstr "Основни цветове на темата"
@@ -490,6 +494,10 @@ msgstr "Цветове на SVG текста"
msgid "Highlighter preset"
msgstr "Шаблон на синтаксово маркиране"
+#: src/ui_parts/settings_menu.gd:
+msgid "Determines the default values of SVG highlighter settings."
+msgstr "Определя стойностите по подразбиране на синтаксовото маркиране за SVG текста."
+
#: src/ui_parts/settings_menu.gd:
msgid "Symbol color"
msgstr "Цвят на символите"
@@ -594,8 +602,8 @@ msgid "Close tabs with middle mouse button"
msgstr "Затваряне на раздели със средното копче на мишката"
#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, clicking on a tab with the middle mouse button closes the tab. If turned off, it focuses the tab instead."
-msgstr "Когато е включено, натискането на раздел със средното копче на мишката затваря раздела. Ако е изключено, средното копче фокусира раздела."
+msgid "When enabled, clicking on a tab with the middle mouse button closes it instead of simply focusing it."
+msgstr "Когато е активирано, натискането на раздел със средното копче на мишката затваря раздела вместо просто да го фокусира."
#: src/ui_parts/settings_menu.gd:
msgid "Invert zoom direction"
@@ -609,17 +617,13 @@ msgstr "Разменя посоките на влачене за намаляв
msgid "Wrap-around panning"
msgstr "Превъртане на курсора"
-#: src/ui_parts/settings_menu.gd:
-msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning."
-msgstr "Превърта курсора когато той достигне краищата на екрана докато влачи гледката."
-
#: src/ui_parts/settings_menu.gd:
msgid "Use CTRL for zooming"
msgstr "Използвай CTRL за увеличение"
#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, scrolling pans the view. To zoom, hold CTRL while scrolling."
-msgstr "Когато е включено, влаченето премества гледката. За увеличение, натисни CTRL докато влачиш."
+msgid "When enabled, scrolling pans the view instead of zooming in. To zoom, hold CTRL while scrolling."
+msgstr "Когато е активирано, влаченето премества гледката. За увеличение, задръж CTRL докато влачиш."
#: src/ui_parts/settings_menu.gd:
msgid "Display"
@@ -650,6 +654,14 @@ msgstr "Максимални кадри в секунда"
msgid "Determines the maximum number of frames per second."
msgstr "Определя максималния брой кадри в секунда."
+#: src/ui_parts/settings_menu.gd:
+msgid "Keep Screen On"
+msgstr "Задръж екрана включен"
+
+#: src/ui_parts/settings_menu.gd:
+msgid "Keeps the screen on even after inactivity, so the screensaver does not take over."
+msgstr "Поддържа екрана включен дори при неактивност, така че скрийнсейвърът да не се включва."
+
#: src/ui_parts/settings_menu.gd:
msgid "Miscellaneous"
msgstr "Разни"
@@ -658,17 +670,13 @@ msgstr "Разни"
msgid "Use native file dialog"
msgstr "Използвай местния файлов мениджър"
-#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, uses your operating system's native file dialog. If turned off, uses GodSVG's built-in file dialog."
-msgstr "Когато е включено, ще бъде използван файловият мениджър на твоята операционна система. Ако е изключено, използва вградения файлов мениджър на GodSVG."
-
#: src/ui_parts/settings_menu.gd:
msgid "Sync window title to file name"
msgstr "Синхронизирай името на прозореца с файла"
#: src/ui_parts/settings_menu.gd:
-msgid "If turned off, the window title remains as \"GodSVG\" without including the current file."
-msgstr "Когато е изключено, името на прозореца остава \"GodSVG\" без да включва настоящия файл."
+msgid "When enabled, adds the current file name before the \"GodSVG\" window title."
+msgstr "Когато е включено, добавя името на настоящия файл пред заглавието на прозореца \"GodSVG\"."
#: src/ui_parts/settings_menu.gd:
msgid "Language"
@@ -709,12 +717,12 @@ msgid "Preset"
msgstr "Шаблон"
#: src/ui_parts/settings_menu.gd:
-msgid "Keep comments"
-msgstr "Запази коментарите"
+msgid "Determines the default values of the formatter configs."
+msgstr "Определя стойностите по подразбиране на настройките на форматировача."
#: src/ui_parts/settings_menu.gd:
-msgid "Keep unrecognized XML structures"
-msgstr "Запази непознатите XML структури"
+msgid "Keep comments"
+msgstr "Запази коментарите"
#: src/ui_parts/settings_menu.gd:
msgid "Add trailing newline"
@@ -734,7 +742,7 @@ msgstr "Включи красивото форматиране"
#: src/ui_parts/settings_menu.gd:
msgid "Use spaces instead of tabs"
-msgstr "Използвай интервали вместо табулации"
+msgstr "Използвай интервали вместо табулатор"
#: src/ui_parts/settings_menu.gd:
msgid "Number of indentation spaces"
@@ -796,6 +804,26 @@ msgstr "Поредици от трансформации"
msgid "Remove unnecessary parameters"
msgstr "Премахни ненужните параметри"
+#: src/ui_parts/settings_menu.gd:
+msgid "When enabled, uses several spaces instead of a single tab for indentation."
+msgstr "Когато е активирано, използва няколко интервала вместо един табулатор за отстъп."
+
+#: src/ui_parts/settings_menu.gd:
+msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning."
+msgstr "Превърта курсора когато той достигне краищата на екрана докато влачи гледката."
+
+#: src/ui_parts/settings_menu.gd:
+msgid "When enabled, uses your operating system's native file dialog instead of GodSVG's built-in one."
+msgstr "Когато е активирано, ще бъде използван файловият мениджър на твоята операционна система вместо вградения файлов мениджър на GodSVG."
+
+#: src/ui_parts/settings_menu.gd:
+msgid "The setting has no effect in the current configuration."
+msgstr "Настройката няма ефект в текущата конфигурация."
+
+#: src/ui_parts/settings_menu.gd:
+msgid "The setting can't be changed on this platform."
+msgstr "Настройката не може да бъде променена на тази платформа."
+
#: src/ui_parts/shortcut_panel.gd:
msgid "Horizontal strip"
msgstr "Хоризонтална лента"
diff --git a/translations/de.po b/translations/de.po
index 31b5f41..9ebe686 100644
--- a/translations/de.po
+++ b/translations/de.po
@@ -472,6 +472,10 @@ msgstr "Anderes"
msgid "Theme preset"
msgstr "Zoom zurücksetzen"
+#: src/ui_parts/settings_menu.gd:
+msgid "Determines the default values of theming-related settings, including the highlighter preset."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
#, fuzzy
msgid "Primary theme colors"
@@ -495,6 +499,10 @@ msgstr "SVG Textfarben"
msgid "Highlighter preset"
msgstr ""
+#: src/ui_parts/settings_menu.gd:
+msgid "Determines the default values of SVG highlighter settings."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Symbol color"
msgstr "Symbolfarbe"
@@ -603,7 +611,8 @@ msgid "Close tabs with middle mouse button"
msgstr "Registerkarten mit mittlerer Maustaste schließen"
#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, clicking on a tab with the middle mouse button closes the tab. If turned off, it focuses the tab instead."
+#, fuzzy
+msgid "When enabled, clicking on a tab with the middle mouse button closes it instead of simply focusing it."
msgstr "Wenn diese Option aktiviert ist, wird die Registerkarte durch Anklicken mit der mittleren Maustaste geschlossen. Wenn diese Option ausgeschaltet ist, wird die Registerkarte stattdessen fokussiert."
#: src/ui_parts/settings_menu.gd:
@@ -618,16 +627,13 @@ msgstr "Tauscht die Scrollrichtung für das Rein- und Rauszoomen."
msgid "Wrap-around panning"
msgstr "Herumwickelndes Verschieben"
-#: src/ui_parts/settings_menu.gd:
-msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning."
-msgstr "Teleportiert den Mauszeiger zur gegenüberliegenden Seite, soblald eine Bildschirmgrenze während des Verschiebens erreicht wird."
-
#: src/ui_parts/settings_menu.gd:
msgid "Use CTRL for zooming"
msgstr "Strg-Taste zum Zoomen benutzen"
#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, scrolling pans the view. To zoom, hold CTRL while scrolling."
+#, fuzzy
+msgid "When enabled, scrolling pans the view instead of zooming in. To zoom, hold CTRL while scrolling."
msgstr "Wenn diese Option aktiviert ist, wird die Ansicht durch Scrollen verschoben. Um zu zoomen muss beim Scrollen die STRG-Taste gedrückt werden."
#: src/ui_parts/settings_menu.gd:
@@ -660,6 +666,14 @@ msgstr ""
msgid "Determines the maximum number of frames per second."
msgstr ""
+#: src/ui_parts/settings_menu.gd:
+msgid "Keep Screen On"
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "Keeps the screen on even after inactivity, so the screensaver does not take over."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Miscellaneous"
msgstr "Verschiedenes"
@@ -668,17 +682,13 @@ msgstr "Verschiedenes"
msgid "Use native file dialog"
msgstr "Nativen Dateidialog verwenden"
-#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, uses your operating system's native file dialog. If turned off, uses GodSVG's built-in file dialog."
-msgstr "Wenn diese Option aktiviert ist, wird der Dateidialog des Betriebssystems verwendet. Wenn diese Option deaktiviert ist, wird GodSVG's eingebauter Dateidialog verwendet."
-
#: src/ui_parts/settings_menu.gd:
msgid "Sync window title to file name"
msgstr "Fenstertitel mit Dateinamen synchronisieren"
#: src/ui_parts/settings_menu.gd:
-msgid "If turned off, the window title remains as \"GodSVG\" without including the current file."
-msgstr "Wenn diese Option deaktiviert ist, bleibt der Fenstertitel \"GodSVG\", ohne die aktuelle Datei anzuzeigen."
+msgid "When enabled, adds the current file name before the \"GodSVG\" window title."
+msgstr ""
#: src/ui_parts/settings_menu.gd:
msgid "Language"
@@ -719,12 +729,13 @@ msgid "Preset"
msgstr "Voreinstellung"
#: src/ui_parts/settings_menu.gd:
-msgid "Keep comments"
-msgstr "Kommentare beibehalten"
+#, fuzzy
+msgid "Determines the default values of the formatter configs."
+msgstr "Verändert den Skalierungsfaktor der Benutzeroberfläche."
#: src/ui_parts/settings_menu.gd:
-msgid "Keep unrecognized XML structures"
-msgstr "Unbekannte XML Strukturen beibehalten"
+msgid "Keep comments"
+msgstr "Kommentare beibehalten"
#: src/ui_parts/settings_menu.gd:
msgid "Add trailing newline"
@@ -806,6 +817,27 @@ msgstr "Transformationlisten"
msgid "Remove unnecessary parameters"
msgstr "Unnötige Parameter entfernen"
+#: src/ui_parts/settings_menu.gd:
+msgid "When enabled, uses several spaces instead of a single tab for indentation."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning."
+msgstr "Teleportiert den Mauszeiger zur gegenüberliegenden Seite, soblald eine Bildschirmgrenze während des Verschiebens erreicht wird."
+
+#: src/ui_parts/settings_menu.gd:
+#, fuzzy
+msgid "When enabled, uses your operating system's native file dialog instead of GodSVG's built-in one."
+msgstr "Wenn diese Option aktiviert ist, wird der Dateidialog des Betriebssystems verwendet. Wenn diese Option deaktiviert ist, wird GodSVG's eingebauter Dateidialog verwendet."
+
+#: src/ui_parts/settings_menu.gd:
+msgid "The setting has no effect in the current configuration."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "The setting can't be changed on this platform."
+msgstr ""
+
#: src/ui_parts/shortcut_panel.gd:
msgid "Horizontal strip"
msgstr "Horizontaler Streifen"
@@ -1373,6 +1405,12 @@ msgstr "Die {format}-Datei speichern"
msgid "Only {extension_list} files are supported for this operation."
msgstr "Nur {extension_list}-Dateien werden für diese Operation unterstützt."
+#~ msgid "If turned off, the window title remains as \"GodSVG\" without including the current file."
+#~ msgstr "Wenn diese Option deaktiviert ist, bleibt der Fenstertitel \"GodSVG\", ohne die aktuelle Datei anzuzeigen."
+
+#~ msgid "Keep unrecognized XML structures"
+#~ msgstr "Unbekannte XML Strukturen beibehalten"
+
#~ msgid "Handle colors"
#~ msgstr "Grifffarbe"
diff --git a/translations/en.po b/translations/en.po
index 6fc2741..3c2f051 100644
--- a/translations/en.po
+++ b/translations/en.po
@@ -470,6 +470,10 @@ msgstr ""
msgid "Theme preset"
msgstr ""
+#: src/ui_parts/settings_menu.gd:
+msgid "Determines the default values of theming-related settings, including the highlighter preset."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Primary theme colors"
msgstr ""
@@ -490,6 +494,10 @@ msgstr ""
msgid "Highlighter preset"
msgstr ""
+#: src/ui_parts/settings_menu.gd:
+msgid "Determines the default values of SVG highlighter settings."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Symbol color"
msgstr ""
@@ -594,7 +602,7 @@ msgid "Close tabs with middle mouse button"
msgstr ""
#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, clicking on a tab with the middle mouse button closes the tab. If turned off, it focuses the tab instead."
+msgid "When enabled, clicking on a tab with the middle mouse button closes it instead of simply focusing it."
msgstr ""
#: src/ui_parts/settings_menu.gd:
@@ -609,16 +617,12 @@ msgstr ""
msgid "Wrap-around panning"
msgstr ""
-#: src/ui_parts/settings_menu.gd:
-msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning."
-msgstr ""
-
#: src/ui_parts/settings_menu.gd:
msgid "Use CTRL for zooming"
msgstr ""
#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, scrolling pans the view. To zoom, hold CTRL while scrolling."
+msgid "When enabled, scrolling pans the view instead of zooming in. To zoom, hold CTRL while scrolling."
msgstr ""
#: src/ui_parts/settings_menu.gd:
@@ -651,15 +655,19 @@ msgid "Determines the maximum number of frames per second."
msgstr ""
#: src/ui_parts/settings_menu.gd:
-msgid "Miscellaneous"
+msgid "Keep Screen On"
msgstr ""
#: src/ui_parts/settings_menu.gd:
-msgid "Use native file dialog"
+msgid "Keeps the screen on even after inactivity, so the screensaver does not take over."
msgstr ""
#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, uses your operating system's native file dialog. If turned off, uses GodSVG's built-in file dialog."
+msgid "Miscellaneous"
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "Use native file dialog"
msgstr ""
#: src/ui_parts/settings_menu.gd:
@@ -667,7 +675,7 @@ msgid "Sync window title to file name"
msgstr ""
#: src/ui_parts/settings_menu.gd:
-msgid "If turned off, the window title remains as \"GodSVG\" without including the current file."
+msgid "When enabled, adds the current file name before the \"GodSVG\" window title."
msgstr ""
#: src/ui_parts/settings_menu.gd:
@@ -709,11 +717,11 @@ msgid "Preset"
msgstr ""
#: src/ui_parts/settings_menu.gd:
-msgid "Keep comments"
+msgid "Determines the default values of the formatter configs."
msgstr ""
#: src/ui_parts/settings_menu.gd:
-msgid "Keep unrecognized XML structures"
+msgid "Keep comments"
msgstr ""
#: src/ui_parts/settings_menu.gd:
@@ -796,6 +804,26 @@ msgstr ""
msgid "Remove unnecessary parameters"
msgstr ""
+#: src/ui_parts/settings_menu.gd:
+msgid "When enabled, uses several spaces instead of a single tab for indentation."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "When enabled, uses your operating system's native file dialog instead of GodSVG's built-in one."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "The setting has no effect in the current configuration."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "The setting can't be changed on this platform."
+msgstr ""
+
#: src/ui_parts/shortcut_panel.gd:
msgid "Horizontal strip"
msgstr ""
diff --git a/translations/es.po b/translations/es.po
index 553b1e6..d85e835 100644
--- a/translations/es.po
+++ b/translations/es.po
@@ -472,6 +472,10 @@ msgstr "Otro"
msgid "Theme preset"
msgstr "Reestablecer el zoom"
+#: src/ui_parts/settings_menu.gd:
+msgid "Determines the default values of theming-related settings, including the highlighter preset."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Primary theme colors"
msgstr ""
@@ -494,6 +498,10 @@ msgstr "Colores del texto de los SVG"
msgid "Highlighter preset"
msgstr ""
+#: src/ui_parts/settings_menu.gd:
+msgid "Determines the default values of SVG highlighter settings."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Symbol color"
msgstr "Color de los símbolos"
@@ -602,7 +610,8 @@ msgid "Close tabs with middle mouse button"
msgstr "Cerrar pestañas con el botón central del ratón"
#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, clicking on a tab with the middle mouse button closes the tab. If turned off, it focuses the tab instead."
+#, fuzzy
+msgid "When enabled, clicking on a tab with the middle mouse button closes it instead of simply focusing it."
msgstr "Si está activado, al hacer clic en una pestaña con el botón central del ratón, esta se cierra. Si está desactivado, se centra en la pestaña."
#: src/ui_parts/settings_menu.gd:
@@ -617,16 +626,13 @@ msgstr "Intercambia las direcciones de desplazamiento para acercar y alejar."
msgid "Wrap-around panning"
msgstr "Desplazamiento envolvente"
-#: src/ui_parts/settings_menu.gd:
-msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning."
-msgstr "Mueve el cursor hacia el lado opuesto cada vez que alcanza el límite de la ventana gráfica mientras se desplaza."
-
#: src/ui_parts/settings_menu.gd:
msgid "Use CTRL for zooming"
msgstr "Usar Ctrl para hacer zoom"
#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, scrolling pans the view. To zoom, hold CTRL while scrolling."
+#, fuzzy
+msgid "When enabled, scrolling pans the view instead of zooming in. To zoom, hold CTRL while scrolling."
msgstr "Si está activado, el desplazamiento panorámico permite ver la vista panorámica. Para hacer zoom, mantén presionada la tecla Ctrl mientras te desplazas."
#: src/ui_parts/settings_menu.gd:
@@ -660,6 +666,14 @@ msgstr "FPS máximos personalizados"
msgid "Determines the maximum number of frames per second."
msgstr "Si la velocidad de fotogramas está limitada, este valor determina la cantidad máxima de fotogramas por segundo."
+#: src/ui_parts/settings_menu.gd:
+msgid "Keep Screen On"
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "Keeps the screen on even after inactivity, so the screensaver does not take over."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Miscellaneous"
msgstr "Misceláneos"
@@ -668,17 +682,13 @@ msgstr "Misceláneos"
msgid "Use native file dialog"
msgstr "Usar diálogo de archivos nativo"
-#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, uses your operating system's native file dialog. If turned off, uses GodSVG's built-in file dialog."
-msgstr "Si está activado, usa el cuadro de diálogo de archivos nativo de tu sistema operativo. Si está desactivado, usa el cuadro de diálogo de archivos integrado de GodSVG."
-
#: src/ui_parts/settings_menu.gd:
msgid "Sync window title to file name"
msgstr "Sincronizar título de la ventana con el nombre del archivo"
#: src/ui_parts/settings_menu.gd:
-msgid "If turned off, the window title remains as \"GodSVG\" without including the current file."
-msgstr "Si está desactivado, el título de la ventana permanece como \"GodSVG\" sin incluir el archivo actual."
+msgid "When enabled, adds the current file name before the \"GodSVG\" window title."
+msgstr ""
#: src/ui_parts/settings_menu.gd:
msgid "Language"
@@ -719,12 +729,13 @@ msgid "Preset"
msgstr "Preajuste"
#: src/ui_parts/settings_menu.gd:
-msgid "Keep comments"
-msgstr "Mantener comentarios"
+#, fuzzy
+msgid "Determines the default values of the formatter configs."
+msgstr "Si la velocidad de fotogramas está limitada, este valor determina la cantidad máxima de fotogramas por segundo."
#: src/ui_parts/settings_menu.gd:
-msgid "Keep unrecognized XML structures"
-msgstr "Mantener estructuras XML no reconocidas"
+msgid "Keep comments"
+msgstr "Mantener comentarios"
#: src/ui_parts/settings_menu.gd:
msgid "Add trailing newline"
@@ -806,6 +817,27 @@ msgstr "Transformar listas"
msgid "Remove unnecessary parameters"
msgstr "Eliminar parámetros innecesarios"
+#: src/ui_parts/settings_menu.gd:
+msgid "When enabled, uses several spaces instead of a single tab for indentation."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning."
+msgstr "Mueve el cursor hacia el lado opuesto cada vez que alcanza el límite de la ventana gráfica mientras se desplaza."
+
+#: src/ui_parts/settings_menu.gd:
+#, fuzzy
+msgid "When enabled, uses your operating system's native file dialog instead of GodSVG's built-in one."
+msgstr "Si está activado, usa el cuadro de diálogo de archivos nativo de tu sistema operativo. Si está desactivado, usa el cuadro de diálogo de archivos integrado de GodSVG."
+
+#: src/ui_parts/settings_menu.gd:
+msgid "The setting has no effect in the current configuration."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "The setting can't be changed on this platform."
+msgstr ""
+
#: src/ui_parts/shortcut_panel.gd:
msgid "Horizontal strip"
msgstr "Franja horizontal"
@@ -1373,6 +1405,12 @@ msgstr "Guardar el archivo {format}"
msgid "Only {extension_list} files are supported for this operation."
msgstr "Solo se admiten archivos {extension_list} para esta operación."
+#~ msgid "If turned off, the window title remains as \"GodSVG\" without including the current file."
+#~ msgstr "Si está desactivado, el título de la ventana permanece como \"GodSVG\" sin incluir el archivo actual."
+
+#~ msgid "Keep unrecognized XML structures"
+#~ msgstr "Mantener estructuras XML no reconocidas"
+
#~ msgid "Handle colors"
#~ msgstr "Colores de los controladores"
diff --git a/translations/et.po b/translations/et.po
index b1b9478..f6d13e1 100644
--- a/translations/et.po
+++ b/translations/et.po
@@ -472,6 +472,10 @@ msgstr "Muu"
msgid "Theme preset"
msgstr "Taasta suurendus"
+#: src/ui_parts/settings_menu.gd:
+msgid "Determines the default values of theming-related settings, including the highlighter preset."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Primary theme colors"
msgstr ""
@@ -494,6 +498,10 @@ msgstr "SVG teksti värvid"
msgid "Highlighter preset"
msgstr ""
+#: src/ui_parts/settings_menu.gd:
+msgid "Determines the default values of SVG highlighter settings."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Symbol color"
msgstr "Sümboli värv"
@@ -602,7 +610,8 @@ msgid "Close tabs with middle mouse button"
msgstr "Sulge vahekaarte keskmise hiireklahviga"
#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, clicking on a tab with the middle mouse button closes the tab. If turned off, it focuses the tab instead."
+#, fuzzy
+msgid "When enabled, clicking on a tab with the middle mouse button closes it instead of simply focusing it."
msgstr "Sisselülitamisel sulgeb keskmise hiireklahviga kaardile vajutamine selle. Väljalülitamisel fokuseeriks see selle."
#: src/ui_parts/settings_menu.gd:
@@ -617,16 +626,13 @@ msgstr "Vahetab kerimissuunad suurendamiseks ja vähendamiseks ümber."
msgid "Wrap-around panning"
msgstr "Takistusteta vaate liigutamine"
-#: src/ui_parts/settings_menu.gd:
-msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning."
-msgstr "Viib kursori akna vastaspoolele, kui see jõuab vaate liigutamise ajal selle servani, et see liikumist ei takistaks."
-
#: src/ui_parts/settings_menu.gd:
msgid "Use CTRL for zooming"
msgstr "Kasuta CTRL klahvi suurendamiseks"
#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, scrolling pans the view. To zoom, hold CTRL while scrolling."
+#, fuzzy
+msgid "When enabled, scrolling pans the view instead of zooming in. To zoom, hold CTRL while scrolling."
msgstr "Sisselülitamisel kerimine liigutab vaadet. Suurendamiseks hoia CTRL klahvi kerimise ajal."
#: src/ui_parts/settings_menu.gd:
@@ -659,6 +665,14 @@ msgstr ""
msgid "Determines the maximum number of frames per second."
msgstr ""
+#: src/ui_parts/settings_menu.gd:
+msgid "Keep Screen On"
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "Keeps the screen on even after inactivity, so the screensaver does not take over."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Miscellaneous"
msgstr "Mitmesugust"
@@ -667,17 +681,13 @@ msgstr "Mitmesugust"
msgid "Use native file dialog"
msgstr "Kasuta süsteemi failidialoogi"
-#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, uses your operating system's native file dialog. If turned off, uses GodSVG's built-in file dialog."
-msgstr "Sisselülitamisel kasutab süsteemi vaikefailidialoogi. Väljalülitamisel GodSVG sisseehitatud failidialoogi."
-
#: src/ui_parts/settings_menu.gd:
msgid "Sync window title to file name"
msgstr "Sünkrooni akna tiitel avatud faili nimega"
#: src/ui_parts/settings_menu.gd:
-msgid "If turned off, the window title remains as \"GodSVG\" without including the current file."
-msgstr "Väljalülitamisel jääb akna nimieks \"GodSVG\" sõltumata avatud failist."
+msgid "When enabled, adds the current file name before the \"GodSVG\" window title."
+msgstr ""
#: src/ui_parts/settings_menu.gd:
msgid "Language"
@@ -718,12 +728,13 @@ msgid "Preset"
msgstr "Eelseadistus"
#: src/ui_parts/settings_menu.gd:
-msgid "Keep comments"
-msgstr "Hoia kommentaarid alles"
+#, fuzzy
+msgid "Determines the default values of the formatter configs."
+msgstr "Muudab kasutajaliidese suurust."
#: src/ui_parts/settings_menu.gd:
-msgid "Keep unrecognized XML structures"
-msgstr "Hoia tundmatud XML struktuurid alles"
+msgid "Keep comments"
+msgstr "Hoia kommentaarid alles"
#: src/ui_parts/settings_menu.gd:
msgid "Add trailing newline"
@@ -805,6 +816,27 @@ msgstr "Teisendused"
msgid "Remove unnecessary parameters"
msgstr "Eemalda ebavajalikud parameetrid"
+#: src/ui_parts/settings_menu.gd:
+msgid "When enabled, uses several spaces instead of a single tab for indentation."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning."
+msgstr "Viib kursori akna vastaspoolele, kui see jõuab vaate liigutamise ajal selle servani, et see liikumist ei takistaks."
+
+#: src/ui_parts/settings_menu.gd:
+#, fuzzy
+msgid "When enabled, uses your operating system's native file dialog instead of GodSVG's built-in one."
+msgstr "Sisselülitamisel kasutab süsteemi vaikefailidialoogi. Väljalülitamisel GodSVG sisseehitatud failidialoogi."
+
+#: src/ui_parts/settings_menu.gd:
+msgid "The setting has no effect in the current configuration."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "The setting can't be changed on this platform."
+msgstr ""
+
#: src/ui_parts/shortcut_panel.gd:
msgid "Horizontal strip"
msgstr "Horisontaalne riba"
@@ -1372,6 +1404,12 @@ msgstr "Salvesta {format} fail"
msgid "Only {extension_list} files are supported for this operation."
msgstr "Ainult {extension_list} failid on toetatud selle tehingu jaoks."
+#~ msgid "If turned off, the window title remains as \"GodSVG\" without including the current file."
+#~ msgstr "Väljalülitamisel jääb akna nimieks \"GodSVG\" sõltumata avatud failist."
+
+#~ msgid "Keep unrecognized XML structures"
+#~ msgstr "Hoia tundmatud XML struktuurid alles"
+
#~ msgid "Handle colors"
#~ msgstr "Pideme värv"
diff --git a/translations/fr.po b/translations/fr.po
index 1d906aa..1049c13 100644
--- a/translations/fr.po
+++ b/translations/fr.po
@@ -472,6 +472,10 @@ msgstr "Autre"
msgid "Theme preset"
msgstr "Réinitialiser le zoom"
+#: src/ui_parts/settings_menu.gd:
+msgid "Determines the default values of theming-related settings, including the highlighter preset."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
#, fuzzy
msgid "Primary theme colors"
@@ -495,6 +499,10 @@ msgstr "Couleurs de texte SVG"
msgid "Highlighter preset"
msgstr ""
+#: src/ui_parts/settings_menu.gd:
+msgid "Determines the default values of SVG highlighter settings."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Symbol color"
msgstr "Couleur de symbole"
@@ -603,7 +611,8 @@ msgid "Close tabs with middle mouse button"
msgstr "Fermer les onglets avec la molette de la souris"
#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, clicking on a tab with the middle mouse button closes the tab. If turned off, it focuses the tab instead."
+#, fuzzy
+msgid "When enabled, clicking on a tab with the middle mouse button closes it instead of simply focusing it."
msgstr "Si activé, cliquer sur un onglet avec la molette de la souris fermera l'onglet. Si désactivé, cette action le rendra actif."
#: src/ui_parts/settings_menu.gd:
@@ -618,16 +627,13 @@ msgstr "Inverser les sens de défilement pour le zoom avant et le zoom arrière.
msgid "Wrap-around panning"
msgstr "Défilement bouclé"
-#: src/ui_parts/settings_menu.gd:
-msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning."
-msgstr "Téléporte le curseur de l'autre côté de la vue à chaque fois qu'il en atteind la limite."
-
#: src/ui_parts/settings_menu.gd:
msgid "Use CTRL for zooming"
msgstr "Utiliser CTRL pour zoomer"
#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, scrolling pans the view. To zoom, hold CTRL while scrolling."
+#, fuzzy
+msgid "When enabled, scrolling pans the view instead of zooming in. To zoom, hold CTRL while scrolling."
msgstr "Si activé, défiler fera balayer la vue. Pour zoomer, maintenez CTRL en défilant."
#: src/ui_parts/settings_menu.gd:
@@ -661,6 +667,14 @@ msgstr "Valeur d'IPS maximale personnalisée"
msgid "Determines the maximum number of frames per second."
msgstr "Si le taux de rafraîchissement est limité, cette valeur déterminera le nombre maximum d'images par seconde."
+#: src/ui_parts/settings_menu.gd:
+msgid "Keep Screen On"
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "Keeps the screen on even after inactivity, so the screensaver does not take over."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Miscellaneous"
msgstr "Divers"
@@ -669,17 +683,13 @@ msgstr "Divers"
msgid "Use native file dialog"
msgstr "Utiliser le sélecteur de fichiers natif"
-#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, uses your operating system's native file dialog. If turned off, uses GodSVG's built-in file dialog."
-msgstr "Si activé, utilise le sélecteur de fichiers système. Si désactivé, utilise la boîte de dialogue intégrée de GodSVG."
-
#: src/ui_parts/settings_menu.gd:
msgid "Sync window title to file name"
msgstr "Synchroniser le titre de la fenêtre avec le nom du fichier"
#: src/ui_parts/settings_menu.gd:
-msgid "If turned off, the window title remains as \"GodSVG\" without including the current file."
-msgstr "Si désactivé, le titre de la fenêtre restera simplement « GodSVG » quel que soit le fichier actuel."
+msgid "When enabled, adds the current file name before the \"GodSVG\" window title."
+msgstr ""
#: src/ui_parts/settings_menu.gd:
msgid "Language"
@@ -720,12 +730,13 @@ msgid "Preset"
msgstr "Préréglage"
#: src/ui_parts/settings_menu.gd:
-msgid "Keep comments"
-msgstr "Garder les commentaires"
+#, fuzzy
+msgid "Determines the default values of the formatter configs."
+msgstr "Si le taux de rafraîchissement est limité, cette valeur déterminera le nombre maximum d'images par seconde."
#: src/ui_parts/settings_menu.gd:
-msgid "Keep unrecognized XML structures"
-msgstr "Conserver les structures XML non reconnues"
+msgid "Keep comments"
+msgstr "Garder les commentaires"
#: src/ui_parts/settings_menu.gd:
msgid "Add trailing newline"
@@ -807,6 +818,27 @@ msgstr "Transformer les listes"
msgid "Remove unnecessary parameters"
msgstr "Retirer les paramètres inutiles"
+#: src/ui_parts/settings_menu.gd:
+msgid "When enabled, uses several spaces instead of a single tab for indentation."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning."
+msgstr "Téléporte le curseur de l'autre côté de la vue à chaque fois qu'il en atteind la limite."
+
+#: src/ui_parts/settings_menu.gd:
+#, fuzzy
+msgid "When enabled, uses your operating system's native file dialog instead of GodSVG's built-in one."
+msgstr "Si activé, utilise le sélecteur de fichiers système. Si désactivé, utilise la boîte de dialogue intégrée de GodSVG."
+
+#: src/ui_parts/settings_menu.gd:
+msgid "The setting has no effect in the current configuration."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "The setting can't be changed on this platform."
+msgstr ""
+
#: src/ui_parts/shortcut_panel.gd:
msgid "Horizontal strip"
msgstr "Rayure horizontale"
@@ -1374,6 +1406,12 @@ msgstr "Enregistrer le fichier {format}"
msgid "Only {extension_list} files are supported for this operation."
msgstr "Seuls les fichiers {extension_list} sont supportés par cette opération."
+#~ msgid "If turned off, the window title remains as \"GodSVG\" without including the current file."
+#~ msgstr "Si désactivé, le titre de la fenêtre restera simplement « GodSVG » quel que soit le fichier actuel."
+
+#~ msgid "Keep unrecognized XML structures"
+#~ msgstr "Conserver les structures XML non reconnues"
+
#~ msgid "Handle colors"
#~ msgstr "Couleurs des poignées"
diff --git a/translations/nl.po b/translations/nl.po
index c4feffa..6a40e55 100644
--- a/translations/nl.po
+++ b/translations/nl.po
@@ -474,6 +474,10 @@ msgstr "Overige"
msgid "Theme preset"
msgstr "Zoom resetten"
+#: src/ui_parts/settings_menu.gd:
+msgid "Determines the default values of theming-related settings, including the highlighter preset."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
#, fuzzy
msgid "Primary theme colors"
@@ -497,6 +501,10 @@ msgstr "SVG tekstkleuren"
msgid "Highlighter preset"
msgstr ""
+#: src/ui_parts/settings_menu.gd:
+msgid "Determines the default values of SVG highlighter settings."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Symbol color"
msgstr "Symboolkleur"
@@ -606,7 +614,7 @@ msgid "Close tabs with middle mouse button"
msgstr "Sluit tabbladen met de middelste muisknop"
#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, clicking on a tab with the middle mouse button closes the tab. If turned off, it focuses the tab instead."
+msgid "When enabled, clicking on a tab with the middle mouse button closes it instead of simply focusing it."
msgstr ""
#: src/ui_parts/settings_menu.gd:
@@ -621,17 +629,13 @@ msgstr "Verwisselt de scroll richtingen voor inzoomen en uitzoomen."
msgid "Wrap-around panning"
msgstr "Omwikkeld rondkijken"
-#: src/ui_parts/settings_menu.gd:
-msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning."
-msgstr "Verplaatst de cursur naar de overkant wanneer het buiten de viewport gaat tijdens het rondkijken."
-
#: src/ui_parts/settings_menu.gd:
msgid "Use CTRL for zooming"
msgstr "Gebruik CTRL om in te zoomen"
#: src/ui_parts/settings_menu.gd:
#, fuzzy
-msgid "If turned on, scrolling pans the view. To zoom, hold CTRL while scrolling."
+msgid "When enabled, scrolling pans the view instead of zooming in. To zoom, hold CTRL while scrolling."
msgstr "Als ingeschakeld, scrollen zal het weergave verschuiven. Om te zoomen,houd CTRL ingedrukt tijdens scrollen."
#: src/ui_parts/settings_menu.gd:
@@ -664,6 +668,14 @@ msgstr ""
msgid "Determines the maximum number of frames per second."
msgstr ""
+#: src/ui_parts/settings_menu.gd:
+msgid "Keep Screen On"
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "Keeps the screen on even after inactivity, so the screensaver does not take over."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Miscellaneous"
msgstr "Overige"
@@ -672,18 +684,13 @@ msgstr "Overige"
msgid "Use native file dialog"
msgstr "Gebruik inheemse bestandendialoog"
-#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, uses your operating system's native file dialog. If turned off, uses GodSVG's built-in file dialog."
-msgstr "Waneer ingeschakeld, gebruikt jouw besturingssysteem's inheemse bestandendialoog. Wanneer uitgeschakeld, gebruikt GodSVG's ingebouwde bestandendialoog."
-
#: src/ui_parts/settings_menu.gd:
msgid "Sync window title to file name"
msgstr "Synchroniseer venstertitel naar bestandsnaam"
#: src/ui_parts/settings_menu.gd:
-#, fuzzy
-msgid "If turned off, the window title remains as \"GodSVG\" without including the current file."
-msgstr "Als dit uitgeschakelt is, blijft de venstertitel simpelweg \"GodSVG\" achteloos van het huidige bestand."
+msgid "When enabled, adds the current file name before the \"GodSVG\" window title."
+msgstr ""
#: src/ui_parts/settings_menu.gd:
msgid "Language"
@@ -724,12 +731,13 @@ msgid "Preset"
msgstr "Voorinstelling"
#: src/ui_parts/settings_menu.gd:
-msgid "Keep comments"
-msgstr "Houdt commentaar bij"
+#, fuzzy
+msgid "Determines the default values of the formatter configs."
+msgstr "Verandert het maat-factor van de gebruikersinterface."
#: src/ui_parts/settings_menu.gd:
-msgid "Keep unrecognized XML structures"
-msgstr "Houdt onherkende XML structuren bij"
+msgid "Keep comments"
+msgstr "Houdt commentaar bij"
#: src/ui_parts/settings_menu.gd:
msgid "Add trailing newline"
@@ -811,6 +819,27 @@ msgstr "Transformeer lijsten"
msgid "Remove unnecessary parameters"
msgstr "Verwijder onnodige parameters"
+#: src/ui_parts/settings_menu.gd:
+msgid "When enabled, uses several spaces instead of a single tab for indentation."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning."
+msgstr "Verplaatst de cursur naar de overkant wanneer het buiten de viewport gaat tijdens het rondkijken."
+
+#: src/ui_parts/settings_menu.gd:
+#, fuzzy
+msgid "When enabled, uses your operating system's native file dialog instead of GodSVG's built-in one."
+msgstr "Waneer ingeschakeld, gebruikt jouw besturingssysteem's inheemse bestandendialoog. Wanneer uitgeschakeld, gebruikt GodSVG's ingebouwde bestandendialoog."
+
+#: src/ui_parts/settings_menu.gd:
+msgid "The setting has no effect in the current configuration."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "The setting can't be changed on this platform."
+msgstr ""
+
#: src/ui_parts/shortcut_panel.gd:
msgid "Horizontal strip"
msgstr "Horizontale lijn"
@@ -1394,6 +1423,13 @@ msgstr "Bewaar het .\"{format}\" bestand"
msgid "Only {extension_list} files are supported for this operation."
msgstr "Deze bestandsextensie is leeg. Alleen {extension_list} bestanden zijn ondersteund."
+#, fuzzy
+#~ msgid "If turned off, the window title remains as \"GodSVG\" without including the current file."
+#~ msgstr "Als dit uitgeschakelt is, blijft de venstertitel simpelweg \"GodSVG\" achteloos van het huidige bestand."
+
+#~ msgid "Keep unrecognized XML structures"
+#~ msgstr "Houdt onherkende XML structuren bij"
+
#~ msgid "Handle colors"
#~ msgstr "Handvatkleuren"
diff --git a/translations/pt_BR.po b/translations/pt_BR.po
index 162f711..0f03949 100644
--- a/translations/pt_BR.po
+++ b/translations/pt_BR.po
@@ -473,6 +473,10 @@ msgstr "Outro"
msgid "Theme preset"
msgstr "Redefinir zoom"
+#: src/ui_parts/settings_menu.gd:
+msgid "Determines the default values of theming-related settings, including the highlighter preset."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Primary theme colors"
msgstr ""
@@ -495,6 +499,10 @@ msgstr "Cores de texto SVG"
msgid "Highlighter preset"
msgstr ""
+#: src/ui_parts/settings_menu.gd:
+msgid "Determines the default values of SVG highlighter settings."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Symbol color"
msgstr "Cor de símbolo"
@@ -603,7 +611,8 @@ msgid "Close tabs with middle mouse button"
msgstr "Fechar guias com o botão do meio do mouse"
#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, clicking on a tab with the middle mouse button closes the tab. If turned off, it focuses the tab instead."
+#, fuzzy
+msgid "When enabled, clicking on a tab with the middle mouse button closes it instead of simply focusing it."
msgstr "Se ligado, clicar em uma guia com o botão do meio do mouse fechará a guia. Se desligado, irá focar na guia."
#: src/ui_parts/settings_menu.gd:
@@ -618,16 +627,13 @@ msgstr "Troca as direções de rolagem para aumentar e diminuir o zoom."
msgid "Wrap-around panning"
msgstr "Movimentação envolvente"
-#: src/ui_parts/settings_menu.gd:
-msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning."
-msgstr "Passa o cursor para o lado oposto da tela quando ele atinge uma borda da viewport quando movimentando a visualização."
-
#: src/ui_parts/settings_menu.gd:
msgid "Use CTRL for zooming"
msgstr "Utilizar CTRL para zoom"
#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, scrolling pans the view. To zoom, hold CTRL while scrolling."
+#, fuzzy
+msgid "When enabled, scrolling pans the view instead of zooming in. To zoom, hold CTRL while scrolling."
msgstr "Se habilitado, a rolagem do mouse irá movimentar a tela. Para realizar o zoom, pressione CTRL enquanto rola."
#: src/ui_parts/settings_menu.gd:
@@ -660,6 +666,14 @@ msgstr ""
msgid "Determines the maximum number of frames per second."
msgstr ""
+#: src/ui_parts/settings_menu.gd:
+msgid "Keep Screen On"
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "Keeps the screen on even after inactivity, so the screensaver does not take over."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Miscellaneous"
msgstr "Variados"
@@ -668,17 +682,13 @@ msgstr "Variados"
msgid "Use native file dialog"
msgstr "Utilizar diálogo de arquivos nativo"
-#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, uses your operating system's native file dialog. If turned off, uses GodSVG's built-in file dialog."
-msgstr "Se habilitado, usa o diálogo de arquivo nativo do sistema operacional. Se desabilitado, usa o diálogo de arquivo embutido no GodSVG."
-
#: src/ui_parts/settings_menu.gd:
msgid "Sync window title to file name"
msgstr "Sincronizar título de janela com o nome do arquivo"
#: src/ui_parts/settings_menu.gd:
-msgid "If turned off, the window title remains as \"GodSVG\" without including the current file."
-msgstr "Se desabilitado, o título da janela permanecerá como \"GodSVG\" sem incluir o nome do arquivo aberto."
+msgid "When enabled, adds the current file name before the \"GodSVG\" window title."
+msgstr ""
#: src/ui_parts/settings_menu.gd:
msgid "Language"
@@ -719,12 +729,13 @@ msgid "Preset"
msgstr "Predefinição"
#: src/ui_parts/settings_menu.gd:
-msgid "Keep comments"
-msgstr "Manter comentários"
+#, fuzzy
+msgid "Determines the default values of the formatter configs."
+msgstr "Muda o fator de escala da interfaçe."
#: src/ui_parts/settings_menu.gd:
-msgid "Keep unrecognized XML structures"
-msgstr "Manter estrutura XML não reconhecida"
+msgid "Keep comments"
+msgstr "Manter comentários"
#: src/ui_parts/settings_menu.gd:
msgid "Add trailing newline"
@@ -806,6 +817,27 @@ msgstr "Transformar listas"
msgid "Remove unnecessary parameters"
msgstr "Remover parâmetros desnecessários"
+#: src/ui_parts/settings_menu.gd:
+msgid "When enabled, uses several spaces instead of a single tab for indentation."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning."
+msgstr "Passa o cursor para o lado oposto da tela quando ele atinge uma borda da viewport quando movimentando a visualização."
+
+#: src/ui_parts/settings_menu.gd:
+#, fuzzy
+msgid "When enabled, uses your operating system's native file dialog instead of GodSVG's built-in one."
+msgstr "Se habilitado, usa o diálogo de arquivo nativo do sistema operacional. Se desabilitado, usa o diálogo de arquivo embutido no GodSVG."
+
+#: src/ui_parts/settings_menu.gd:
+msgid "The setting has no effect in the current configuration."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "The setting can't be changed on this platform."
+msgstr ""
+
#: src/ui_parts/shortcut_panel.gd:
msgid "Horizontal strip"
msgstr "Faixa horizontal"
@@ -1373,6 +1405,12 @@ msgstr "Salvar o arquivo do tipo {format}"
msgid "Only {extension_list} files are supported for this operation."
msgstr "A extensão de arquivo está vazia. Somente arquivos {extension_list} são suportados."
+#~ msgid "If turned off, the window title remains as \"GodSVG\" without including the current file."
+#~ msgstr "Se desabilitado, o título da janela permanecerá como \"GodSVG\" sem incluir o nome do arquivo aberto."
+
+#~ msgid "Keep unrecognized XML structures"
+#~ msgstr "Manter estrutura XML não reconhecida"
+
#~ msgid "Handle colors"
#~ msgstr "Cor de alça"
diff --git a/translations/ru.po b/translations/ru.po
index 66d74aa..62af69e 100644
--- a/translations/ru.po
+++ b/translations/ru.po
@@ -473,6 +473,10 @@ msgstr "Другие"
msgid "Theme preset"
msgstr "Сбросить масштаб"
+#: src/ui_parts/settings_menu.gd:
+msgid "Determines the default values of theming-related settings, including the highlighter preset."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Primary theme colors"
msgstr ""
@@ -495,6 +499,10 @@ msgstr "Цвет SVG текста"
msgid "Highlighter preset"
msgstr ""
+#: src/ui_parts/settings_menu.gd:
+msgid "Determines the default values of SVG highlighter settings."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Symbol color"
msgstr "Цвет символа"
@@ -603,7 +611,8 @@ msgid "Close tabs with middle mouse button"
msgstr "Закрывать вкладки средней клавишей мыши"
#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, clicking on a tab with the middle mouse button closes the tab. If turned off, it focuses the tab instead."
+#, fuzzy
+msgid "When enabled, clicking on a tab with the middle mouse button closes it instead of simply focusing it."
msgstr "Если включено - нажатие на вкладку средней кнопкой мыши закроет ее. Если выключено - вкладка получит фокус."
#: src/ui_parts/settings_menu.gd:
@@ -618,16 +627,13 @@ msgstr "Поменяет местами направление прокрутк
msgid "Wrap-around panning"
msgstr "Захват курсора при прокрутке"
-#: src/ui_parts/settings_menu.gd:
-msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning."
-msgstr "Курсор будет телепортироваться от одного до противоположного края на границе окна просмотра."
-
#: src/ui_parts/settings_menu.gd:
msgid "Use CTRL for zooming"
msgstr "Использовать CTRL для масштабирования"
#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, scrolling pans the view. To zoom, hold CTRL while scrolling."
+#, fuzzy
+msgid "When enabled, scrolling pans the view instead of zooming in. To zoom, hold CTRL while scrolling."
msgstr "Если включено - прокрутка будет перемещать окно просмотра. Чтобы масштабировать зажмите CTRL при прокручивании."
#: src/ui_parts/settings_menu.gd:
@@ -660,6 +666,14 @@ msgstr ""
msgid "Determines the maximum number of frames per second."
msgstr ""
+#: src/ui_parts/settings_menu.gd:
+msgid "Keep Screen On"
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "Keeps the screen on even after inactivity, so the screensaver does not take over."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Miscellaneous"
msgstr "Разное"
@@ -668,17 +682,13 @@ msgstr "Разное"
msgid "Use native file dialog"
msgstr "Использовать родной файловый диалог системы"
-#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, uses your operating system's native file dialog. If turned off, uses GodSVG's built-in file dialog."
-msgstr "Если включено, то будет использоваться родной файловый диалог вашей операционной системы для выбора файлов. Если выключено, то будет использоваться встроенный файловый диалог."
-
#: src/ui_parts/settings_menu.gd:
msgid "Sync window title to file name"
msgstr "Синхронизировать заголовок окна с названием файла"
#: src/ui_parts/settings_menu.gd:
-msgid "If turned off, the window title remains as \"GodSVG\" without including the current file."
-msgstr "Если выключено - заголовок окна будет просто \"GodSVG\", не включая текущий файл."
+msgid "When enabled, adds the current file name before the \"GodSVG\" window title."
+msgstr ""
#: src/ui_parts/settings_menu.gd:
msgid "Language"
@@ -719,12 +729,13 @@ msgid "Preset"
msgstr "Пресет"
#: src/ui_parts/settings_menu.gd:
-msgid "Keep comments"
-msgstr "Сохранять коментарии"
+#, fuzzy
+msgid "Determines the default values of the formatter configs."
+msgstr "Изменить масштаб пользовательского интерфейса."
#: src/ui_parts/settings_menu.gd:
-msgid "Keep unrecognized XML structures"
-msgstr "Сохранять нераспознанные XML"
+msgid "Keep comments"
+msgstr "Сохранять коментарии"
#: src/ui_parts/settings_menu.gd:
msgid "Add trailing newline"
@@ -806,6 +817,27 @@ msgstr "Список трансформаций"
msgid "Remove unnecessary parameters"
msgstr "Удалить ненужные параметры"
+#: src/ui_parts/settings_menu.gd:
+msgid "When enabled, uses several spaces instead of a single tab for indentation."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning."
+msgstr "Курсор будет телепортироваться от одного до противоположного края на границе окна просмотра."
+
+#: src/ui_parts/settings_menu.gd:
+#, fuzzy
+msgid "When enabled, uses your operating system's native file dialog instead of GodSVG's built-in one."
+msgstr "Если включено, то будет использоваться родной файловый диалог вашей операционной системы для выбора файлов. Если выключено, то будет использоваться встроенный файловый диалог."
+
+#: src/ui_parts/settings_menu.gd:
+msgid "The setting has no effect in the current configuration."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "The setting can't be changed on this platform."
+msgstr ""
+
#: src/ui_parts/shortcut_panel.gd:
msgid "Horizontal strip"
msgstr "Горизонтальная полоса"
@@ -1373,6 +1405,12 @@ msgstr "Сохранить {format} файл"
msgid "Only {extension_list} files are supported for this operation."
msgstr "Только файлы с расширениями {extension_list} поддерживаются для этой операции."
+#~ msgid "If turned off, the window title remains as \"GodSVG\" without including the current file."
+#~ msgstr "Если выключено - заголовок окна будет просто \"GodSVG\", не включая текущий файл."
+
+#~ msgid "Keep unrecognized XML structures"
+#~ msgstr "Сохранять нераспознанные XML"
+
#~ msgid "Handle colors"
#~ msgstr "Цвет ручки редактирования"
diff --git a/translations/uk.po b/translations/uk.po
index 4fba247..7369cbf 100644
--- a/translations/uk.po
+++ b/translations/uk.po
@@ -472,6 +472,10 @@ msgstr "Інше"
msgid "Theme preset"
msgstr "Скинути масштаб"
+#: src/ui_parts/settings_menu.gd:
+msgid "Determines the default values of theming-related settings, including the highlighter preset."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Primary theme colors"
msgstr ""
@@ -494,6 +498,10 @@ msgstr "Колір SVG тексту"
msgid "Highlighter preset"
msgstr ""
+#: src/ui_parts/settings_menu.gd:
+msgid "Determines the default values of SVG highlighter settings."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Symbol color"
msgstr "Колір символу"
@@ -602,7 +610,8 @@ msgid "Close tabs with middle mouse button"
msgstr "Закривати вкладки при натисканні середньої кнопки миші"
#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, clicking on a tab with the middle mouse button closes the tab. If turned off, it focuses the tab instead."
+#, fuzzy
+msgid "When enabled, clicking on a tab with the middle mouse button closes it instead of simply focusing it."
msgstr "Якщо увімкнено - клацання на вкладку середньою кнопкою миші закриє її. Якщо вимкнено - фокус буде замінено на неї."
#: src/ui_parts/settings_menu.gd:
@@ -617,16 +626,13 @@ msgstr "Міняє напрям гортання при масштабуванн
msgid "Wrap-around panning"
msgstr "Захопити курсор при гортанні"
-#: src/ui_parts/settings_menu.gd:
-msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning."
-msgstr "Курсор буде телепортуватися від одного краю до протилежного при пересуванні вікна перегляду."
-
#: src/ui_parts/settings_menu.gd:
msgid "Use CTRL for zooming"
msgstr "Використовувати CTRL для масштабування"
#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, scrolling pans the view. To zoom, hold CTRL while scrolling."
+#, fuzzy
+msgid "When enabled, scrolling pans the view instead of zooming in. To zoom, hold CTRL while scrolling."
msgstr "Якщо увімкнено - гортання буде рухати вікно перегляду. Щоб масштабувати, затисніть CTRL доки гортаєте."
#: src/ui_parts/settings_menu.gd:
@@ -659,6 +665,14 @@ msgstr ""
msgid "Determines the maximum number of frames per second."
msgstr ""
+#: src/ui_parts/settings_menu.gd:
+msgid "Keep Screen On"
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "Keeps the screen on even after inactivity, so the screensaver does not take over."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Miscellaneous"
msgstr "Різне"
@@ -667,17 +681,13 @@ msgstr "Різне"
msgid "Use native file dialog"
msgstr "Використовувати рідний файловий діалог"
-#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, uses your operating system's native file dialog. If turned off, uses GodSVG's built-in file dialog."
-msgstr "Якщо увімкнено, то буде використовувати рідний файловий діалог вашої операційної системи для обирання файлів. Якщо вимкнено, то замість буде використовуватися вбудований файловий діалог."
-
#: src/ui_parts/settings_menu.gd:
msgid "Sync window title to file name"
msgstr "Синхронізувати заголовок вікна з назвою поточного файлу"
#: src/ui_parts/settings_menu.gd:
-msgid "If turned off, the window title remains as \"GodSVG\" without including the current file."
-msgstr "Якщо вимкнено - заголовок вікна залишиться як \"GodSVG\", не включаючи назву поточного файлу."
+msgid "When enabled, adds the current file name before the \"GodSVG\" window title."
+msgstr ""
#: src/ui_parts/settings_menu.gd:
msgid "Language"
@@ -719,12 +729,13 @@ msgid "Preset"
msgstr "Пресет"
#: src/ui_parts/settings_menu.gd:
-msgid "Keep comments"
-msgstr "Зберігати коментарі"
+#, fuzzy
+msgid "Determines the default values of the formatter configs."
+msgstr "Змінити масштаб інтерфейсу користувача."
#: src/ui_parts/settings_menu.gd:
-msgid "Keep unrecognized XML structures"
-msgstr "Зберігати не розпізнані структури XML"
+msgid "Keep comments"
+msgstr "Зберігати коментарі"
#: src/ui_parts/settings_menu.gd:
msgid "Add trailing newline"
@@ -809,6 +820,27 @@ msgstr "Список трансформацій"
msgid "Remove unnecessary parameters"
msgstr "Видалити необов'язкові параметри"
+#: src/ui_parts/settings_menu.gd:
+msgid "When enabled, uses several spaces instead of a single tab for indentation."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning."
+msgstr "Курсор буде телепортуватися від одного краю до протилежного при пересуванні вікна перегляду."
+
+#: src/ui_parts/settings_menu.gd:
+#, fuzzy
+msgid "When enabled, uses your operating system's native file dialog instead of GodSVG's built-in one."
+msgstr "Якщо увімкнено, то буде використовувати рідний файловий діалог вашої операційної системи для обирання файлів. Якщо вимкнено, то замість буде використовуватися вбудований файловий діалог."
+
+#: src/ui_parts/settings_menu.gd:
+msgid "The setting has no effect in the current configuration."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "The setting can't be changed on this platform."
+msgstr ""
+
#: src/ui_parts/shortcut_panel.gd:
msgid "Horizontal strip"
msgstr "Горизонтальна смужка"
@@ -1377,6 +1409,12 @@ msgstr "Зберегти {format} файл"
msgid "Only {extension_list} files are supported for this operation."
msgstr "Тільки файли з розширеннями {extension_list} підтримуються для цієї операції."
+#~ msgid "If turned off, the window title remains as \"GodSVG\" without including the current file."
+#~ msgstr "Якщо вимкнено - заголовок вікна залишиться як \"GodSVG\", не включаючи назву поточного файлу."
+
+#~ msgid "Keep unrecognized XML structures"
+#~ msgstr "Зберігати не розпізнані структури XML"
+
#~ msgid "Handle colors"
#~ msgstr "Колір ручки редагування"
diff --git a/translations/zh_CN.po b/translations/zh_CN.po
index e562e82..0630dc7 100644
--- a/translations/zh_CN.po
+++ b/translations/zh_CN.po
@@ -479,6 +479,10 @@ msgstr "其他"
msgid "Theme preset"
msgstr "重置缩放"
+#: src/ui_parts/settings_menu.gd:
+msgid "Determines the default values of theming-related settings, including the highlighter preset."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
#, fuzzy
msgid "Primary theme colors"
@@ -502,6 +506,10 @@ msgstr "SVG 文本颜色"
msgid "Highlighter preset"
msgstr ""
+#: src/ui_parts/settings_menu.gd:
+msgid "Determines the default values of SVG highlighter settings."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Symbol color"
msgstr "符号颜色"
@@ -611,7 +619,7 @@ msgid "Close tabs with middle mouse button"
msgstr ""
#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, clicking on a tab with the middle mouse button closes the tab. If turned off, it focuses the tab instead."
+msgid "When enabled, clicking on a tab with the middle mouse button closes it instead of simply focusing it."
msgstr ""
#: src/ui_parts/settings_menu.gd:
@@ -626,17 +634,13 @@ msgstr ""
msgid "Wrap-around panning"
msgstr ""
-#: src/ui_parts/settings_menu.gd:
-msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning."
-msgstr ""
-
#: src/ui_parts/settings_menu.gd:
msgid "Use CTRL for zooming"
msgstr "使用 CTRL 键缩放"
#: src/ui_parts/settings_menu.gd:
#, fuzzy
-msgid "If turned on, scrolling pans the view. To zoom, hold CTRL while scrolling."
+msgid "When enabled, scrolling pans the view instead of zooming in. To zoom, hold CTRL while scrolling."
msgstr "如果启用,滚动鼠标滚轮将移动视图。按住 CTRL 并滚动滚轮以缩放。"
#: src/ui_parts/settings_menu.gd:
@@ -669,6 +673,14 @@ msgstr ""
msgid "Determines the maximum number of frames per second."
msgstr ""
+#: src/ui_parts/settings_menu.gd:
+msgid "Keep Screen On"
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "Keeps the screen on even after inactivity, so the screensaver does not take over."
+msgstr ""
+
#: src/ui_parts/settings_menu.gd:
msgid "Miscellaneous"
msgstr "杂项"
@@ -677,18 +689,13 @@ msgstr "杂项"
msgid "Use native file dialog"
msgstr "使用系统自带文件选择窗口"
-#: src/ui_parts/settings_menu.gd:
-msgid "If turned on, uses your operating system's native file dialog. If turned off, uses GodSVG's built-in file dialog."
-msgstr "如果启用,将使用操作系统自带的文件选择窗口。反之,将使用 GodSVG 内置的文件选择窗口。"
-
#: src/ui_parts/settings_menu.gd:
msgid "Sync window title to file name"
msgstr "同步窗口标题为文件名"
#: src/ui_parts/settings_menu.gd:
-#, fuzzy
-msgid "If turned off, the window title remains as \"GodSVG\" without including the current file."
-msgstr "如果禁用,不论当前打开的文件是什么,窗口标题都将固定为 “GodSVG”。"
+msgid "When enabled, adds the current file name before the \"GodSVG\" window title."
+msgstr ""
#: src/ui_parts/settings_menu.gd:
msgid "Language"
@@ -731,12 +738,13 @@ msgid "Preset"
msgstr "预设"
#: src/ui_parts/settings_menu.gd:
-msgid "Keep comments"
-msgstr "保留注释"
+#, fuzzy
+msgid "Determines the default values of the formatter configs."
+msgstr "改变用户界面的缩放尺寸。"
#: src/ui_parts/settings_menu.gd:
-msgid "Keep unrecognized XML structures"
-msgstr "保留未知 XML 结构"
+msgid "Keep comments"
+msgstr "保留注释"
#: src/ui_parts/settings_menu.gd:
msgid "Add trailing newline"
@@ -818,6 +826,27 @@ msgstr "变换列表"
msgid "Remove unnecessary parameters"
msgstr "移除不必要的参数"
+#: src/ui_parts/settings_menu.gd:
+msgid "When enabled, uses several spaces instead of a single tab for indentation."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "Warps the cursor to the opposite side whenever it reaches a viewport boundary while panning."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+#, fuzzy
+msgid "When enabled, uses your operating system's native file dialog instead of GodSVG's built-in one."
+msgstr "如果启用,将使用操作系统自带的文件选择窗口。反之,将使用 GodSVG 内置的文件选择窗口。"
+
+#: src/ui_parts/settings_menu.gd:
+msgid "The setting has no effect in the current configuration."
+msgstr ""
+
+#: src/ui_parts/settings_menu.gd:
+msgid "The setting can't be changed on this platform."
+msgstr ""
+
#: src/ui_parts/shortcut_panel.gd:
#, fuzzy
msgid "Horizontal strip"
@@ -1416,6 +1445,13 @@ msgstr "保存 .\"{format}\" 文件"
msgid "Only {extension_list} files are supported for this operation."
msgstr "文件扩展名为空。只有 {extension_list} 内的文件受支持。"
+#, fuzzy
+#~ msgid "If turned off, the window title remains as \"GodSVG\" without including the current file."
+#~ msgstr "如果禁用,不论当前打开的文件是什么,窗口标题都将固定为 “GodSVG”。"
+
+#~ msgid "Keep unrecognized XML structures"
+#~ msgstr "保留未知 XML 结构"
+
#~ msgid "Handle colors"
#~ msgstr "拖拽框颜色"