diff --git a/src/VirtualStreetSnap/App.axaml b/src/VirtualStreetSnap/App.axaml
index a8feead..0b4e050 100644
--- a/src/VirtualStreetSnap/App.axaml
+++ b/src/VirtualStreetSnap/App.axaml
@@ -23,6 +23,7 @@
+
\ No newline at end of file
diff --git a/src/VirtualStreetSnap/Assets/i18n/en-US.json b/src/VirtualStreetSnap/Assets/i18n/en-US.json
index eac1962..7af6207 100644
--- a/src/VirtualStreetSnap/Assets/i18n/en-US.json
+++ b/src/VirtualStreetSnap/Assets/i18n/en-US.json
@@ -72,5 +72,9 @@
"InvalidFileFormat": "Invalid File Format",
"LoadingImage": "Loading Image...",
"LoadingView": "Loading View...",
- "Curve": "Curve"
+ "Curve": "Curve",
+ "BorderColor": "Border Color",
+ "CommonSettings": "Common Settings",
+ "BorderThickness": "Border Thickness",
+ "BorderSettings": "Border Settings"
}
\ No newline at end of file
diff --git a/src/VirtualStreetSnap/Assets/i18n/zh-CN.json b/src/VirtualStreetSnap/Assets/i18n/zh-CN.json
index 7a3b2b4..802252c 100644
--- a/src/VirtualStreetSnap/Assets/i18n/zh-CN.json
+++ b/src/VirtualStreetSnap/Assets/i18n/zh-CN.json
@@ -72,5 +72,9 @@
"InvalidFileFormat": "无效的文件格式",
"LoadingImage": "加载图像...",
"LoadingView": "加载视图...",
- "Curve": "曲线"
+ "Curve": "曲线",
+ "BorderColor": "边框颜色",
+ "CommonSettings": "常规设置",
+ "BorderThickness": "边框厚度",
+ "BorderSettings": "边框设置"
}
\ No newline at end of file
diff --git a/src/VirtualStreetSnap/Controls/SettingsCard.axaml b/src/VirtualStreetSnap/Controls/SettingsCard.axaml
new file mode 100644
index 0000000..95deaa6
--- /dev/null
+++ b/src/VirtualStreetSnap/Controls/SettingsCard.axaml
@@ -0,0 +1,32 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/VirtualStreetSnap/Controls/SettingsCard.axaml.cs b/src/VirtualStreetSnap/Controls/SettingsCard.axaml.cs
new file mode 100644
index 0000000..9b9bc09
--- /dev/null
+++ b/src/VirtualStreetSnap/Controls/SettingsCard.axaml.cs
@@ -0,0 +1,27 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace VirtualStreetSnap.Controls;
+
+public partial class SettingsCard : ContentControl
+{
+ public static readonly StyledProperty SettingNameProperty =
+ AvaloniaProperty.Register(nameof(SettingName));
+
+ public string SettingName
+ {
+ get { return GetValue(SettingNameProperty); }
+ set { SetValue(SettingNameProperty, value); }
+ }
+
+ public SettingsCard()
+ {
+ InitializeComponent();
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+}
\ No newline at end of file
diff --git a/src/VirtualStreetSnap/Models/AppConfig.cs b/src/VirtualStreetSnap/Models/AppConfig.cs
index 0d03526..c931a52 100644
--- a/src/VirtualStreetSnap/Models/AppConfig.cs
+++ b/src/VirtualStreetSnap/Models/AppConfig.cs
@@ -1,4 +1,5 @@
using System.ComponentModel;
+using Avalonia.Media;
namespace VirtualStreetSnap.Models;
@@ -30,7 +31,39 @@ protected virtual void OnPropertyChanged(string propertyName)
public class Overlays
{
public required Guides Guides { get; set; }
- public bool Focus { get; set; } = true;
+ public bool ShowFocusBorder { get; set; } = true;
+ private int _focusBorderThickness = 10;
+
+ public int FocusBorderThickness
+ {
+ get => _focusBorderThickness;
+ set
+ {
+ if (_focusBorderThickness == value) return;
+ _focusBorderThickness = value;
+ OnPropertyChanged(nameof(FocusBorderThickness));
+ }
+ }
+
+ private Color _focusBorderColor = Colors.Brown;
+
+ public Color FocusBorderColor
+ {
+ get => _focusBorderColor;
+ set
+ {
+ if (_focusBorderColor == value) return;
+ _focusBorderColor = value;
+ OnPropertyChanged(nameof(FocusBorderColor));
+ }
+ }
+
+ public event PropertyChangedEventHandler? PropertyChanged;
+
+ protected virtual void OnPropertyChanged(string propertyName)
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
}
public class Guides
diff --git a/src/VirtualStreetSnap/Program.cs b/src/VirtualStreetSnap/Program.cs
index 94a0871..94b5a14 100644
--- a/src/VirtualStreetSnap/Program.cs
+++ b/src/VirtualStreetSnap/Program.cs
@@ -1,5 +1,8 @@
using Avalonia;
using System;
+using System.Diagnostics;
+using System.IO;
+using System.Text;
namespace VirtualStreetSnap;
@@ -9,8 +12,17 @@ sealed class Program
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread]
- public static void Main(string[] args) => BuildAvaloniaApp()
- .StartWithClassicDesktopLifetime(args);
+ public static void Main(string[] args)
+ {
+ Trace.Listeners.Add(new TextWriterTraceListener("VirtualStreetSnap.log"));
+ Trace.AutoFlush = true;
+ TextWriter originalConsoleOutput = Console.Out;
+ MultiTextWriter multiTextWriter = new MultiTextWriter(originalConsoleOutput, new TraceTextWriter());
+ Console.SetOut(multiTextWriter);
+
+ BuildAvaloniaApp()
+ .StartWithClassicDesktopLifetime(args);
+ }
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
@@ -18,4 +30,45 @@ public static AppBuilder BuildAvaloniaApp()
.UsePlatformDetect()
.WithInterFont()
.LogToTrace();
+}
+
+public class MultiTextWriter : TextWriter
+{
+ private readonly TextWriter _consoleWriter;
+ private readonly TextWriter _traceWriter;
+
+ public MultiTextWriter(TextWriter consoleWriter, TextWriter traceWriter)
+ {
+ _consoleWriter = consoleWriter;
+ _traceWriter = traceWriter;
+ }
+
+ public override Encoding Encoding => Encoding.UTF8;
+
+ public override void WriteLine(string value)
+ {
+ _consoleWriter.WriteLine(value);
+ _traceWriter.WriteLine(value);
+ }
+
+ public override void Write(string value)
+ {
+ _consoleWriter.Write(value);
+ _traceWriter.Write(value);
+ }
+}
+
+public class TraceTextWriter : TextWriter
+{
+ public override Encoding Encoding => Encoding.UTF8;
+
+ public override void WriteLine(string value)
+ {
+ Trace.WriteLine(value);
+ }
+
+ public override void Write(string value)
+ {
+ Trace.Write(value);
+ }
}
\ No newline at end of file
diff --git a/src/VirtualStreetSnap/Services/ConfigService.cs b/src/VirtualStreetSnap/Services/ConfigService.cs
index 82f816c..198074b 100644
--- a/src/VirtualStreetSnap/Services/ConfigService.cs
+++ b/src/VirtualStreetSnap/Services/ConfigService.cs
@@ -70,7 +70,7 @@ private static AppConfig NewDefaultConfig()
Ratio = false,
Opacity = 0.5f
},
- Focus = true
+ ShowFocusBorder = true
}
};
}
diff --git a/src/VirtualStreetSnap/ViewModels/SettingsViewModel.cs b/src/VirtualStreetSnap/ViewModels/SettingsViewModel.cs
index 4389586..f22ed91 100644
--- a/src/VirtualStreetSnap/ViewModels/SettingsViewModel.cs
+++ b/src/VirtualStreetSnap/ViewModels/SettingsViewModel.cs
@@ -4,6 +4,7 @@
using System.IO;
using System.Linq;
using System.Threading.Tasks;
+using Avalonia.Media;
using CommunityToolkit.Mvvm.ComponentModel;
using VirtualStreetSnap.Models;
using VirtualStreetSnap.Services;
@@ -14,7 +15,7 @@ public partial class SettingsViewModel : ViewModelBase
{
[ObservableProperty]
private AppConfig _config = ConfigService.Instance;
-
+
[ObservableProperty]
private string _appVersion = "Unknown";
@@ -22,6 +23,12 @@ public partial class SettingsViewModel : ViewModelBase
[ObservableProperty]
private string _filePrefix = "IMG";
+ [ObservableProperty]
+ private Color _focusBorderColor = Colors.Brown;
+
+ [ObservableProperty]
+ private int _focusBorderThickness = 10;
+
[ObservableProperty]
private LanguageModel _selectedLanguage;
@@ -41,11 +48,14 @@ public SettingsViewModel()
FilePrefix = Config.Settings.FilePrefix;
SelectedLanguage = LanguageModels.FirstOrDefault(x => x.Identifier == Config.Settings.Language) ??
LanguageModels.First();
+ FocusBorderColor = Config.Overlays.FocusBorderColor;
+ FocusBorderThickness = Config.Overlays.FocusBorderThickness;
// Set the default values if the config is not existing
ConfigService.SaveConfig();
GetFileVersion();
}
-
+
+
public void GetFileVersion()
{
var exeDir = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory);
@@ -56,6 +66,10 @@ public void GetFileVersion()
if (version == null) return;
AppVersion = version;
}
+
+ partial void OnFocusBorderColorChanged(Color value) => Config.Overlays.FocusBorderColor = value;
+
+ partial void OnFocusBorderThicknessChanged(int value) => Config.Overlays.FocusBorderThickness = value;
partial void OnSelectedLanguageChanged(LanguageModel value)
{
diff --git a/src/VirtualStreetSnap/ViewModels/SnapShotViewModel.cs b/src/VirtualStreetSnap/ViewModels/SnapShotViewModel.cs
index a7ac9ab..abc8c83 100644
--- a/src/VirtualStreetSnap/ViewModels/SnapShotViewModel.cs
+++ b/src/VirtualStreetSnap/ViewModels/SnapShotViewModel.cs
@@ -1,6 +1,9 @@
using System.Collections.ObjectModel;
+using System.ComponentModel;
using System.Linq;
+using Avalonia;
using Avalonia.Media;
+using Avalonia.Media.Immutable;
using CommunityToolkit.Mvvm.ComponentModel;
using VirtualStreetSnap.Models;
using VirtualStreetSnap.Services;
@@ -24,8 +27,22 @@ public partial class SnapShotViewModel : ViewModelBase
[ObservableProperty]
private float _guideLinesOpacity = 0.5f;
- [ObservableProperty]
- private Color _borderColor = Colors.Brown;
+
+ private Thickness _focusBorderThickness;
+
+ public Thickness FocusBorderThickness
+ {
+ get => _focusBorderThickness;
+ private set => SetProperty(ref _focusBorderThickness, value);
+ }
+
+ private IImmutableSolidColorBrush _focusFocusBorderBrush;
+
+ public IImmutableSolidColorBrush FocusBorderBrush
+ {
+ get => _focusFocusBorderBrush;
+ private set => SetProperty(ref _focusFocusBorderBrush, value);
+ }
[ObservableProperty]
private SizeRatio? _selectedSizeRatio;
@@ -64,6 +81,19 @@ public SnapShotViewModel()
ShowGuideLinesGrid = Config.Overlays.Guides.Grid;
ShowGuideLinesCenter = Config.Overlays.Guides.Center;
ShowGuideLinesRatio = Config.Overlays.Guides.Ratio;
- ShowFocusBorder = Config.Overlays.Focus;
+ ShowFocusBorder = Config.Overlays.ShowFocusBorder;
+ var thickness = Config.Overlays.FocusBorderThickness;
+ FocusBorderThickness = new Thickness(thickness);
+ FocusBorderBrush = new ImmutableSolidColorBrush(Config.Overlays.FocusBorderColor);
+
+ Config.Overlays.PropertyChanged += OnOverlaysPropertyChanged;
+ }
+
+ private void OnOverlaysPropertyChanged(object? sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == nameof(Config.Overlays.FocusBorderColor))
+ FocusBorderBrush = new ImmutableSolidColorBrush(Config.Overlays.FocusBorderColor);
+ else if (e.PropertyName == nameof(Config.Overlays.FocusBorderThickness))
+ FocusBorderThickness = new Thickness(Config.Overlays.FocusBorderThickness);
}
}
\ No newline at end of file
diff --git a/src/VirtualStreetSnap/Views/SettingsView.axaml b/src/VirtualStreetSnap/Views/SettingsView.axaml
index 427d3cc..9ab5c32 100644
--- a/src/VirtualStreetSnap/Views/SettingsView.axaml
+++ b/src/VirtualStreetSnap/Views/SettingsView.axaml
@@ -6,6 +6,7 @@
xmlns:models="clr-namespace:VirtualStreetSnap.Models"
xmlns:i18n="clr-namespace:VirtualStreetSnap.Localizer"
xmlns:services="clr-namespace:VirtualStreetSnap.Services"
+ xmlns:controls="clr-namespace:VirtualStreetSnap.Controls"
mc:Ignorable="d" d:DesignWidth="1280" d:DesignHeight="720"
services:ToplevelService.Register="{Binding}"
x:Class="VirtualStreetSnap.Views.SettingsView"
@@ -15,47 +16,71 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
\ No newline at end of file
diff --git a/src/VirtualStreetSnap/Views/SnapShotView.axaml b/src/VirtualStreetSnap/Views/SnapShotView.axaml
index 582687e..74b644d 100644
--- a/src/VirtualStreetSnap/Views/SnapShotView.axaml
+++ b/src/VirtualStreetSnap/Views/SnapShotView.axaml
@@ -54,14 +54,16 @@
Opacity="{Binding ShowGuideLinesRatio}" />
-
-
+