From edb206ffa5914b97ac7f892386027ef73458bc77 Mon Sep 17 00:00:00 2001
From: CJKmkp <2564608840@qq.com>
Date: Sun, 31 Aug 2025 15:35:28 +0800
Subject: [PATCH] =?UTF-8?q?add:=E6=96=B0=E8=AE=BE=E7=BD=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Ink Canvas/InkCanvasForClass.csproj | 9 +-
Ink Canvas/MainWindow.xaml | 15 +
Ink Canvas/MainWindow.xaml.cs | 16 +
.../SettingsViews/AboutPanel.xaml | 191 +
.../SettingsViews/AboutPanel.xaml.cs | 243 ++
.../SettingsViews/AppearancePanel.xaml | 12 +
.../SettingsViews/AppearancePanel.xaml.cs | 76 +
.../FloatingBarDnDSettingsPanel.xaml | 98 +
.../FloatingBarDnDSettingsPanel.xaml.cs | 128 +
.../SettingsViews/SettingsBaseView.xaml | 54 +
.../SettingsViews/SettingsBaseView.xaml.cs | 184 +
.../Windows/SettingsViews/SettingsWindow.xaml | 3273 +++++++++++++++++
.../SettingsViews/SettingsWindow.xaml.cs | 325 ++
...vasForClass.csproj.AssemblyReference.cache | Bin 35374 -> 35826 bytes
14 files changed, 4618 insertions(+), 6 deletions(-)
create mode 100644 Ink Canvas/Windows/SettingsViews/SettingsViews/AboutPanel.xaml
create mode 100644 Ink Canvas/Windows/SettingsViews/SettingsViews/AboutPanel.xaml.cs
create mode 100644 Ink Canvas/Windows/SettingsViews/SettingsViews/AppearancePanel.xaml
create mode 100644 Ink Canvas/Windows/SettingsViews/SettingsViews/AppearancePanel.xaml.cs
create mode 100644 Ink Canvas/Windows/SettingsViews/SettingsViews/FloatingBarDnDSettingsPanel.xaml
create mode 100644 Ink Canvas/Windows/SettingsViews/SettingsViews/FloatingBarDnDSettingsPanel.xaml.cs
create mode 100644 Ink Canvas/Windows/SettingsViews/SettingsViews/SettingsBaseView.xaml
create mode 100644 Ink Canvas/Windows/SettingsViews/SettingsViews/SettingsBaseView.xaml.cs
create mode 100644 Ink Canvas/Windows/SettingsViews/SettingsWindow.xaml
create mode 100644 Ink Canvas/Windows/SettingsViews/SettingsWindow.xaml.cs
diff --git a/Ink Canvas/InkCanvasForClass.csproj b/Ink Canvas/InkCanvasForClass.csproj
index 4c53cecb..2bf113a3 100644
--- a/Ink Canvas/InkCanvasForClass.csproj
+++ b/Ink Canvas/InkCanvasForClass.csproj
@@ -24,12 +24,8 @@
false
False
true
- Debug;Release;x86 Debug
-
-
- embedded
- bin\$(Configuration)\
- True
+ Release;x86 Debug;Debug
+ AnyCPU;x86
embedded
@@ -128,6 +124,7 @@
+
diff --git a/Ink Canvas/MainWindow.xaml b/Ink Canvas/MainWindow.xaml
index 42bc95ac..98f6a1a7 100644
--- a/Ink Canvas/MainWindow.xaml
+++ b/Ink Canvas/MainWindow.xaml
@@ -531,6 +531,21 @@
+
+
+
+
+
+
+ 打开新的设置窗口,提供更丰富的设置选项和更好的用户体验。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Ink Canvas/Windows/SettingsViews/SettingsViews/AboutPanel.xaml.cs b/Ink Canvas/Windows/SettingsViews/SettingsViews/AboutPanel.xaml.cs
new file mode 100644
index 00000000..30dffb67
--- /dev/null
+++ b/Ink Canvas/Windows/SettingsViews/SettingsViews/AboutPanel.xaml.cs
@@ -0,0 +1,243 @@
+using OSVersionExtension;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Management;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using iNKORE.UI.WPF.Helpers;
+using static Ink_Canvas.Windows.SettingsWindow;
+
+namespace Ink_Canvas.Windows.SettingsViews {
+ ///
+ /// AboutPanel.xaml 的交互逻辑
+ ///
+ public partial class AboutPanel : UserControl {
+ public AboutPanel() {
+ InitializeComponent();
+
+ // 关于页面图片横幅
+ if (File.Exists(App.RootPath + "icc-about-illustrations.png")) {
+ try {
+ CopyrightBannerImage.Visibility = Visibility.Visible;
+ CopyrightBannerImage.Source =
+ new BitmapImage(new Uri($"file://{App.RootPath + "icc-about-illustrations.png"}"));
+ }
+ catch { }
+ } else {
+ CopyrightBannerImage.Visibility = Visibility.Collapsed;
+ }
+
+ // 关于页面构建时间
+ var buildTime = FileBuildTimeHelper.GetBuildDateTime(System.Reflection.Assembly.GetExecutingAssembly());
+ if (buildTime != null) {
+ var bt = ((DateTimeOffset)buildTime).LocalDateTime;
+ var m = bt.Month.ToString().PadLeft(2, '0');
+ var d = bt.Day.ToString().PadLeft(2, '0');
+ var h = bt.Hour.ToString().PadLeft(2, '0');
+ var min = bt.Minute.ToString().PadLeft(2, '0');
+ var s = bt.Second.ToString().PadLeft(2, '0');
+ AboutBuildTime.Text =
+ $"build-{bt.Year}-{m}-{d}-{h}:{min}:{s}";
+ }
+
+ // 关于页面系统版本
+ AboutSystemVersion.Text = $"{OSVersion.GetOperatingSystem()} {OSVersion.GetOSVersion().Version}";
+
+ // 关于页面触摸设备
+ var _t_touch = new Thread(() => {
+ var touchcount = TouchTabletDetectHelper.GetTouchTabletDevices().Count;
+ var support = TouchTabletDetectHelper.IsTouchEnabled();
+ Dispatcher.BeginInvoke(() =>
+ AboutTouchTabletText.Text = $"{touchcount}个设备,{(support ? "支持触摸设备" : "无触摸支持")}");
+ });
+ _t_touch.Start();
+ }
+
+ public static class TouchTabletDetectHelper {
+ [System.Runtime.InteropServices.DllImport("user32.dll")]
+ public static extern int GetSystemMetrics(int nIndex);
+
+ public static bool IsTouchEnabled()
+ {
+ const int MAXTOUCHES_INDEX = 95;
+ int maxTouches = GetSystemMetrics(MAXTOUCHES_INDEX);
+
+ return maxTouches > 0;
+ }
+
+ public class USBDeviceInfo
+ {
+ public USBDeviceInfo(string deviceID, string pnpDeviceID, string description)
+ {
+ this.DeviceID = deviceID;
+ this.PnpDeviceID = pnpDeviceID;
+ this.Description = description;
+ }
+ public string DeviceID { get; private set; }
+ public string PnpDeviceID { get; private set; }
+ public string Description { get; private set; }
+ }
+
+ public static List GetTouchTabletDevices()
+ {
+ List devices = new List();
+
+ ManagementObjectCollection collection;
+ using (var searcher = new ManagementObjectSearcher(@"Select * From Win32_PnPEntity"))
+ collection = searcher.Get();
+
+ foreach (var device in collection) {
+ var name = new StringBuilder((string)device.GetPropertyValue("Name")).ToString();
+ if (!name.Contains("Pentablet")) continue;
+ devices.Add(new USBDeviceInfo(
+ (string)device.GetPropertyValue("DeviceID"),
+ (string)device.GetPropertyValue("PNPDeviceID"),
+ (string)device.GetPropertyValue("Description")
+ ));
+ }
+
+ collection.Dispose();
+ return devices;
+ }
+ }
+
+ public static class FileBuildTimeHelper {
+ public struct _IMAGE_FILE_HEADER
+ {
+ public ushort Machine;
+ public ushort NumberOfSections;
+ public uint TimeDateStamp;
+ public uint PointerToSymbolTable;
+ public uint NumberOfSymbols;
+ public ushort SizeOfOptionalHeader;
+ public ushort Characteristics;
+ };
+
+ public static DateTimeOffset? GetBuildDateTime(Assembly assembly)
+ {
+ var path = assembly.Location;
+ if (File.Exists(path))
+ {
+ var buffer = new byte[Math.Max(Marshal.SizeOf(typeof(_IMAGE_FILE_HEADER)), 4)];
+ using (var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read))
+ {
+ fileStream.Position = 0x3C;
+ fileStream.Read(buffer, 0, 4);
+ fileStream.Position = BitConverter.ToUInt32(buffer, 0); // COFF header offset
+ fileStream.Read(buffer, 0, 4); // "PE\0\0"
+ fileStream.Read(buffer, 0, buffer.Length);
+ }
+ var pinnedBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned);
+ try
+ {
+ var coffHeader = (_IMAGE_FILE_HEADER)Marshal.PtrToStructure(pinnedBuffer.AddrOfPinnedObject(), typeof(_IMAGE_FILE_HEADER));
+ return DateTimeOffset.FromUnixTimeSeconds(coffHeader.TimeDateStamp);
+ }
+ finally
+ {
+ pinnedBuffer.Free();
+ }
+ }
+ else
+ {
+ return null;
+ }
+ }
+ }
+
+ public event EventHandler IsTopBarNeedShadowEffect;
+ public event EventHandler IsTopBarNeedNoShadowEffect;
+
+ private void ScrollViewerEx_ScrollChanged(object sender, ScrollChangedEventArgs e) {
+ var scrollViewer = (ScrollViewer)sender;
+ if (scrollViewer.VerticalOffset >= 10) {
+ IsTopBarNeedShadowEffect?.Invoke(this, new RoutedEventArgs());
+ } else {
+ IsTopBarNeedNoShadowEffect?.Invoke(this, new RoutedEventArgs());
+ }
+ }
+
+ private void ScrollBar_Scroll(object sender, RoutedEventArgs e) {
+ var scrollbar = (ScrollBar)sender;
+ var scrollviewer = scrollbar.FindAscendant();
+ if (scrollviewer != null) scrollviewer.ScrollToVerticalOffset(scrollbar.Track.Value);
+ }
+
+ private void ScrollBarTrack_MouseEnter(object sender, MouseEventArgs e) {
+ var border = (Border)sender;
+ if (border.Child is Track track) {
+ track.Width = 16;
+ track.Margin = new Thickness(0, 0, -2, 0);
+ var scrollbar = track.FindAscendant();
+ if (scrollbar != null) scrollbar.Width = 16;
+ var grid = track.FindAscendant();
+ if (grid.FindDescendantByName("ScrollBarBorderTrackBackground") is Border backgroundBorder) {
+ backgroundBorder.Width = 8;
+ backgroundBorder.CornerRadius = new CornerRadius(4);
+ backgroundBorder.Opacity = 1;
+ }
+ var thumb = track.Thumb.Template.FindName("ScrollbarThumbEx", track.Thumb) ;
+ if (thumb != null) {
+ var _thumb = thumb as Border;
+ _thumb.CornerRadius = new CornerRadius(4);
+ _thumb.Width = 8;
+ _thumb.Margin = new Thickness(-0.75, 0, 1, 0);
+ _thumb.Background = new SolidColorBrush(Color.FromRgb(138, 138, 138));
+ }
+ }
+ }
+
+ private void ScrollBarTrack_MouseLeave(object sender, MouseEventArgs e) {
+ var border = (Border)sender;
+ border.Background = new SolidColorBrush(Colors.Transparent);
+ border.CornerRadius = new CornerRadius(0);
+ if (border.Child is Track track) {
+ track.Width = 6;
+ track.Margin = new Thickness(0, 0, 0, 0);
+ var scrollbar = track.FindAscendant();
+ if (scrollbar != null) scrollbar.Width = 6;
+ var grid = track.FindAscendant();
+ if (grid.FindDescendantByName("ScrollBarBorderTrackBackground") is Border backgroundBorder) {
+ backgroundBorder.Width = 3;
+ backgroundBorder.CornerRadius = new CornerRadius(1.5);
+ backgroundBorder.Opacity = 0;
+ }
+ var thumb = track.Thumb.Template.FindName("ScrollbarThumbEx", track.Thumb) ;
+ if (thumb != null) {
+ var _thumb = thumb as Border;
+ _thumb.CornerRadius = new CornerRadius(1.5);
+ _thumb.Width = 3;
+ _thumb.Margin = new Thickness(0);
+ _thumb.Background = new SolidColorBrush(Color.FromRgb(195, 195, 195));
+ }
+ }
+ }
+
+ private void ScrollbarThumb_MouseDown(object sender, MouseButtonEventArgs e) {
+ var thumb = (Thumb)sender;
+ var border = thumb.Template.FindName("ScrollbarThumbEx",thumb);
+ ((Border)border).Background = new SolidColorBrush(Color.FromRgb(95, 95, 95));
+ }
+
+ private void ScrollbarThumb_MouseUp(object sender, MouseButtonEventArgs e) {
+ var thumb = (Thumb)sender;
+ var border = thumb.Template.FindName("ScrollbarThumbEx",thumb);
+ ((Border)border).Background = new SolidColorBrush(Color.FromRgb(138, 138, 138));
+ }
+ }
+}
diff --git a/Ink Canvas/Windows/SettingsViews/SettingsViews/AppearancePanel.xaml b/Ink Canvas/Windows/SettingsViews/SettingsViews/AppearancePanel.xaml
new file mode 100644
index 00000000..c1067873
--- /dev/null
+++ b/Ink Canvas/Windows/SettingsViews/SettingsViews/AppearancePanel.xaml
@@ -0,0 +1,12 @@
+
+
+
+
+
diff --git a/Ink Canvas/Windows/SettingsViews/SettingsViews/AppearancePanel.xaml.cs b/Ink Canvas/Windows/SettingsViews/SettingsViews/AppearancePanel.xaml.cs
new file mode 100644
index 00000000..42ef2c40
--- /dev/null
+++ b/Ink Canvas/Windows/SettingsViews/SettingsViews/AppearancePanel.xaml.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Ink_Canvas.Windows.SettingsViews {
+ public partial class AppearancePanel : UserControl {
+ public AppearancePanel() {
+ InitializeComponent();
+ BaseView.SettingsPanels.Add(new SettingsViewPanel() {
+ Title = "新版设置测试",
+ Items = new ObservableCollection(new SettingsItem[] {
+ new SettingsItem() {
+ Title = "默认ToggleSwitch",
+ Description = "这是测试文本,这是测试文本",
+ Type = SettingsItemType.SingleToggleSwtich,
+ IsSeparatorVisible = true
+ },
+ new SettingsItem() {
+ Title = "默认开启的ToggleSwitch",
+ Description = "这是测试文本,这是测试文本324234324",
+ Type = SettingsItemType.SingleToggleSwtich,
+ IsSeparatorVisible = true,
+ ToggleSwitchToggled = true,
+ },
+ new SettingsItem() {
+ Title = "默认关闭的ToggleSwitch",
+ Description = "这是测试文本,这是测试文本fsdsdffsd",
+ Type = SettingsItemType.SingleToggleSwtich,
+ IsSeparatorVisible = true,
+ ToggleSwitchToggled = false,
+ },
+ new SettingsItem() {
+ Title = "绿色的ToggleSwitch",
+ Description = "这是测试文本,这是测试文本fs大风刮过4sd",
+ Type = SettingsItemType.SingleToggleSwtich,
+ IsSeparatorVisible = true,
+ ToggleSwitchToggled = true,
+ ToggleSwitchBackground = new SolidColorBrush(Color.FromRgb(51, 209, 122)),
+ },
+ new SettingsItem() {
+ Title = "默认禁用的的ToggleSwitch",
+ Description = "这是测试文本",
+ Type = SettingsItemType.SingleToggleSwtich,
+ IsSeparatorVisible = true,
+ ToggleSwitchToggled = true,
+ ToggleSwitchEnabled = false,
+ ToggleSwitchBackground = new SolidColorBrush(Color.FromRgb(51, 209, 122)),
+ },
+ new SettingsItem() {
+ Title = "控制上面的ToggleSwitch是否启用",
+ Description = "12423432452312322335",
+ Type = SettingsItemType.SingleToggleSwtich,
+ IsSeparatorVisible = true,
+ ToggleSwitchToggled = false,
+ },
+ })
+ });
+ BaseView.SettingsPanels[0].Items[5].OnToggleSwitchToggled += (sender, args) => {
+ var item = (SettingsItem)sender;
+ BaseView.SettingsPanels[0].Items[4].ToggleSwitchEnabled = item.ToggleSwitchToggled;
+ };
+ }
+ }
+}
diff --git a/Ink Canvas/Windows/SettingsViews/SettingsViews/FloatingBarDnDSettingsPanel.xaml b/Ink Canvas/Windows/SettingsViews/SettingsViews/FloatingBarDnDSettingsPanel.xaml
new file mode 100644
index 00000000..29895a05
--- /dev/null
+++ b/Ink Canvas/Windows/SettingsViews/SettingsViews/FloatingBarDnDSettingsPanel.xaml
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Ink Canvas/Windows/SettingsViews/SettingsViews/FloatingBarDnDSettingsPanel.xaml.cs b/Ink Canvas/Windows/SettingsViews/SettingsViews/FloatingBarDnDSettingsPanel.xaml.cs
new file mode 100644
index 00000000..857de922
--- /dev/null
+++ b/Ink Canvas/Windows/SettingsViews/SettingsViews/FloatingBarDnDSettingsPanel.xaml.cs
@@ -0,0 +1,128 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using iNKORE.UI.WPF.DragDrop;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement.Menu;
+
+namespace Ink_Canvas.Windows.SettingsViews {
+
+ public class FloatingBarItem {
+ public DrawingImage IconSource { get; set; }
+ }
+
+ public partial class FloatingBarDnDSettingsPanel : UserControl {
+
+ public class BarItemsDropTarget : IDropTarget {
+ public ObservableCollection BarItems { get; set; } =
+ new ObservableCollection();
+
+ void IDropTarget.DragOver(IDropInfo info) {
+ info.Effects = DragDropEffects.Move;
+ info.DropTargetAdorner = DropTargetAdorners.Insert;
+ }
+
+ void IDropTarget.Drop(IDropInfo info) {
+ if (info.Data is FloatingBarItem draggedItem) {
+ var targetCollection = info.TargetCollection as ObservableCollection;
+ var sourceCollection = info.DragInfo.SourceCollection as ObservableCollection;
+
+ Trace.WriteLine(info.InsertIndex);
+
+ // 在同一个 ObservableCollection 中移动
+ if (targetCollection.Equals(sourceCollection)) {
+ if (info.InsertIndex == 0) {
+ targetCollection.Move(targetCollection.IndexOf(info.Data as FloatingBarItem),0);
+ } else if (info.InsertIndex == targetCollection.Count) {
+ targetCollection.Remove(info.Data as FloatingBarItem);
+ targetCollection.Add(info.Data as FloatingBarItem);
+ } else if ((info.InsertIndex - targetCollection.IndexOf(info.Data as FloatingBarItem) == 1 &&
+ info.InsertPosition == RelativeInsertPosition.AfterTargetItem) ||
+ (info.InsertIndex - targetCollection.IndexOf(info.Data as FloatingBarItem) == 0 &&
+ info.InsertPosition == RelativeInsertPosition.BeforeTargetItem)) { } else {
+ targetCollection.Move(targetCollection.IndexOf(info.Data as FloatingBarItem),info.InsertIndex - 1);
+ }
+ } else { // 跨 ObservableCollection 移动
+ sourceCollection.Remove(info.Data as FloatingBarItem);
+ targetCollection.Insert(info.InsertIndex, info.Data as FloatingBarItem);
+ }
+ }
+ }
+
+ void IDropTarget.DragEnter(IDropInfo info) {
+
+ }
+
+ void IDropTarget.DragLeave(IDropInfo info) {
+
+ }
+
+ }
+
+ public class BarDrawerItemsDropTarget : IDropTarget {
+ public ObservableCollection BarDrawerItems { get; set; } =
+ new ObservableCollection();
+
+ void IDropTarget.DragOver(IDropInfo info) {
+ info.Effects = DragDropEffects.Move;
+ info.DropTargetAdorner = DropTargetAdorners.Insert;
+ }
+
+ void IDropTarget.Drop(IDropInfo info) {
+ if (info.Data is FloatingBarItem draggedItem) {
+ var targetCollection = info.TargetCollection as ObservableCollection;
+ var sourceCollection = info.DragInfo.SourceCollection as ObservableCollection;
+
+ // 在同一个 ObservableCollection 中移动
+ if (targetCollection.Equals(sourceCollection)) {
+ targetCollection.Insert(info.InsertIndex, info.Data as FloatingBarItem);
+ } else { // 跨 ObservableCollection 移动
+ sourceCollection.Remove(info.Data as FloatingBarItem);
+ targetCollection.Insert(info.InsertIndex, info.Data as FloatingBarItem);
+ }
+ }
+ }
+
+ void IDropTarget.DragEnter(IDropInfo info) {
+
+ }
+
+ void IDropTarget.DragLeave(IDropInfo info) {
+
+ }
+
+ }
+
+ public BarItemsDropTarget barItems { get; set; } = new BarItemsDropTarget();
+ public BarDrawerItemsDropTarget barDrawerItems { get; set; } = new BarDrawerItemsDropTarget();
+
+ public FloatingBarDnDSettingsPanel() {
+ InitializeComponent();
+
+ ToolbarItemsControl.DataContext = barItems;
+ ToolbarDrawerItemsControl.DataContext = barDrawerItems;
+
+ barItems.BarItems.Add(new FloatingBarItem() {
+ IconSource = FindResource("EraserIcon") as DrawingImage,
+ });
+ barDrawerItems.BarDrawerItems.Add(new FloatingBarItem() {
+ IconSource = FindResource("CursorIcon") as DrawingImage,
+ });
+ barDrawerItems.BarDrawerItems.Add(new FloatingBarItem() {
+ IconSource = FindResource("PenIcon") as DrawingImage,
+ });
+ }
+ }
+}
diff --git a/Ink Canvas/Windows/SettingsViews/SettingsViews/SettingsBaseView.xaml b/Ink Canvas/Windows/SettingsViews/SettingsViews/SettingsBaseView.xaml
new file mode 100644
index 00000000..2f78f3b4
--- /dev/null
+++ b/Ink Canvas/Windows/SettingsViews/SettingsViews/SettingsBaseView.xaml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Ink Canvas/Windows/SettingsViews/SettingsViews/SettingsBaseView.xaml.cs b/Ink Canvas/Windows/SettingsViews/SettingsViews/SettingsBaseView.xaml.cs
new file mode 100644
index 00000000..6cab7b05
--- /dev/null
+++ b/Ink Canvas/Windows/SettingsViews/SettingsViews/SettingsBaseView.xaml.cs
@@ -0,0 +1,184 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using iNKORE.UI.WPF.Helpers;
+using iNKORE.UI.WPF.Modern.Controls;
+
+namespace Ink_Canvas.Windows.SettingsViews {
+
+ public class SettingsViewPanel {
+ public string Title { get; set; }
+ public Visibility _TitleVisibility => String.IsNullOrWhiteSpace(Title) ? Visibility.Collapsed : Visibility.Visible;
+ public Thickness _PanelMargin =>
+ String.IsNullOrWhiteSpace(Title) ? new Thickness(0) : new Thickness(0, 12, 0, 0);
+ public ObservableCollection Items { get; set; } = new ObservableCollection() { };
+ }
+
+ public enum SettingsItemType {
+ Plain, // 只显示Title和Description
+ SingleToggleSwtich,
+ ToggleSwitchWithArrowButton,
+ SelectionButtons,
+ }
+
+ public class SettingsItem : INotifyPropertyChanged {
+ public string Title { get; set; }
+ public string Description { get; set; }
+ public SettingsItemType Type { get; set; } = SettingsItemType.Plain;
+ public bool IsClickable { get; set; } = false;
+ public bool IsSeparatorVisible { get; set; } = true;
+ public Visibility _SeparatorVisibility => IsSeparatorVisible ? Visibility.Visible : Visibility.Collapsed;
+ public Visibility _ToggleSwitchVisibility =>
+ Type == SettingsItemType.SingleToggleSwtich || Type == SettingsItemType.ToggleSwitchWithArrowButton ? Visibility.Visible : Visibility.Collapsed;
+ private bool _toggleSwitchToggled;
+ public bool ToggleSwitchToggled {
+ get => _toggleSwitchToggled;
+ set {
+ if (_toggleSwitchToggled != value) {
+ _toggleSwitchToggled = value;
+ OnPropertyChanged(nameof(ToggleSwitchToggled)); // 通知绑定控件属性变化
+ OnToggleSwitchToggled?.Invoke(this, EventArgs.Empty); // 触发事件
+ }
+ }
+ }
+ public event EventHandler OnToggleSwitchToggled;
+ public event PropertyChangedEventHandler PropertyChanged;
+ protected virtual void OnPropertyChanged(string propertyName) {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
+
+ private SolidColorBrush _toggleSwitchBackground = new SolidColorBrush(Color.FromRgb(53, 132, 228));
+ public SolidColorBrush ToggleSwitchBackground {
+ get => _toggleSwitchBackground;
+ set {
+ if (_toggleSwitchBackground != value) {
+ _toggleSwitchBackground = value;
+ OnPropertyChanged(nameof(ToggleSwitchBackground)); // 通知绑定控件属性变化
+ }
+ }
+ }
+
+ private bool _toggleSwitchEnabled = true;
+ public bool ToggleSwitchEnabled {
+ get => _toggleSwitchEnabled;
+ set {
+ if (_toggleSwitchEnabled != value) {
+ _toggleSwitchEnabled = value;
+ OnPropertyChanged(nameof(ToggleSwitchEnabled)); // 通知绑定控件属性变化
+ }
+ }
+ }
+ }
+
+ public partial class SettingsBaseView : UserControl {
+ public SettingsBaseView() {
+ InitializeComponent();
+ SettingsViewBaseItemsControl.ItemsSource = SettingsPanels;
+ }
+
+ public ObservableCollection SettingsPanels { get; set; } =
+ new ObservableCollection() { };
+
+ public event EventHandler IsTopBarNeedShadowEffect;
+ public event EventHandler IsTopBarNeedNoShadowEffect;
+
+ private void ScrollViewerEx_ScrollChanged(object sender, ScrollChangedEventArgs e) {
+ var scrollViewer = (ScrollViewer)sender;
+ if (scrollViewer.VerticalOffset >= 10) {
+ IsTopBarNeedShadowEffect?.Invoke(this, new RoutedEventArgs());
+ } else {
+ IsTopBarNeedNoShadowEffect?.Invoke(this, new RoutedEventArgs());
+ }
+ }
+
+ private void ScrollBar_Scroll(object sender, RoutedEventArgs e) {
+ var scrollbar = (ScrollBar)sender;
+ var scrollviewer = scrollbar.FindAscendant();
+ if (scrollviewer != null) scrollviewer.ScrollToVerticalOffset(scrollbar.Track.Value);
+ }
+
+ private void ScrollBarTrack_MouseEnter(object sender, MouseEventArgs e) {
+ var border = (Border)sender;
+ if (border.Child is Track track) {
+ track.Width = 16;
+ track.Margin = new Thickness(0, 0, -2, 0);
+ var scrollbar = track.FindAscendant();
+ if (scrollbar != null) scrollbar.Width = 16;
+ var grid = track.FindAscendant();
+ if (grid.FindDescendantByName("ScrollBarBorderTrackBackground") is Border backgroundBorder) {
+ backgroundBorder.Width = 8;
+ backgroundBorder.CornerRadius = new CornerRadius(4);
+ backgroundBorder.Opacity = 1;
+ }
+ var thumb = track.Thumb.Template.FindName("ScrollbarThumbEx", track.Thumb) ;
+ if (thumb != null) {
+ var _thumb = thumb as Border;
+ _thumb.CornerRadius = new CornerRadius(4);
+ _thumb.Width = 8;
+ _thumb.Margin = new Thickness(-0.75, 0, 1, 0);
+ _thumb.Background = new SolidColorBrush(Color.FromRgb(138, 138, 138));
+ }
+ }
+ }
+
+ private void ToggleSwitch_OnToggled(object sender, RoutedEventArgs e) {
+ var toggleswitch = sender as ToggleSwitch;
+ var item = toggleswitch.Tag as SettingsItem;
+ item.ToggleSwitchToggled = toggleswitch.IsOn;
+ }
+
+ private void ScrollBarTrack_MouseLeave(object sender, MouseEventArgs e) {
+ var border = (Border)sender;
+ border.Background = new SolidColorBrush(Colors.Transparent);
+ border.CornerRadius = new CornerRadius(0);
+ if (border.Child is Track track) {
+ track.Width = 6;
+ track.Margin = new Thickness(0, 0, 0, 0);
+ var scrollbar = track.FindAscendant();
+ if (scrollbar != null) scrollbar.Width = 6;
+ var grid = track.FindAscendant();
+ if (grid.FindDescendantByName("ScrollBarBorderTrackBackground") is Border backgroundBorder) {
+ backgroundBorder.Width = 3;
+ backgroundBorder.CornerRadius = new CornerRadius(1.5);
+ backgroundBorder.Opacity = 0;
+ }
+ var thumb = track.Thumb.Template.FindName("ScrollbarThumbEx", track.Thumb) ;
+ if (thumb != null) {
+ var _thumb = thumb as Border;
+ _thumb.CornerRadius = new CornerRadius(1.5);
+ _thumb.Width = 3;
+ _thumb.Margin = new Thickness(0);
+ _thumb.Background = new SolidColorBrush(Color.FromRgb(195, 195, 195));
+ }
+ }
+ }
+
+ private void ScrollbarThumb_MouseDown(object sender, MouseButtonEventArgs e) {
+ var thumb = (Thumb)sender;
+ var border = thumb.Template.FindName("ScrollbarThumbEx",thumb);
+ ((Border)border).Background = new SolidColorBrush(Color.FromRgb(95, 95, 95));
+ }
+
+ private void ScrollbarThumb_MouseUp(object sender, MouseButtonEventArgs e) {
+ var thumb = (Thumb)sender;
+ var border = thumb.Template.FindName("ScrollbarThumbEx",thumb);
+ ((Border)border).Background = new SolidColorBrush(Color.FromRgb(138, 138, 138));
+ }
+ }
+
+}
diff --git a/Ink Canvas/Windows/SettingsViews/SettingsWindow.xaml b/Ink Canvas/Windows/SettingsViews/SettingsWindow.xaml
new file mode 100644
index 00000000..d18b8d7c
--- /dev/null
+++ b/Ink Canvas/Windows/SettingsViews/SettingsWindow.xaml
@@ -0,0 +1,3273 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Ink Canvas/Windows/SettingsViews/SettingsWindow.xaml.cs b/Ink Canvas/Windows/SettingsViews/SettingsWindow.xaml.cs
new file mode 100644
index 00000000..93ca47ce
--- /dev/null
+++ b/Ink Canvas/Windows/SettingsViews/SettingsWindow.xaml.cs
@@ -0,0 +1,325 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Management;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Interop;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+using Ink_Canvas.Windows.SettingsViews;
+using iNKORE.UI.WPF.Helpers;
+using iNKORE.UI.WPF.Modern.Controls;
+using OSVersionExtension;
+
+namespace Ink_Canvas.Windows {
+ public partial class SettingsWindow : Window {
+
+ public SettingsWindow() {
+ InitializeComponent();
+
+ // 初始化侧边栏项目
+ SidebarItemsControl.ItemsSource = SidebarItems;
+ SidebarItems.Add(new SidebarItem() {
+ Type = SidebarItemType.Item,
+ Title = "启动时行为",
+ Name = "StartupItem",
+ IconSource = FindResource("StartupIcon") as DrawingImage,
+ Selected = false,
+ });
+ SidebarItems.Add(new SidebarItem() {
+ Type = SidebarItemType.Item,
+ Title = "画板和墨迹",
+ Name = "CanvasAndInkItem",
+ IconSource = FindResource("CanvasAndInkIcon") as DrawingImage,
+ Selected = false,
+ });
+ SidebarItems.Add(new SidebarItem() {
+ Type = SidebarItemType.Item,
+ Title = "手势操作",
+ Name = "GesturesItem",
+ IconSource = FindResource("GesturesIcon") as DrawingImage,
+ Selected = false,
+ });
+ SidebarItems.Add(new SidebarItem() {
+ Type = SidebarItemType.Separator
+ });
+ SidebarItems.Add(new SidebarItem() {
+ Type = SidebarItemType.Item,
+ Title = "个性化和外观",
+ Name = "AppearanceItem",
+ IconSource = FindResource("AppearanceIcon") as DrawingImage,
+ Selected = false,
+ });
+ SidebarItems.Add(new SidebarItem() {
+ Type = SidebarItemType.Item,
+ Title = "墨迹转形状",
+ Name = "InkRecognitionItem",
+ IconSource = FindResource("InkRecognitionIcon") as DrawingImage,
+ Selected = false,
+ });
+ SidebarItems.Add(new SidebarItem() {
+ Type = SidebarItemType.Item,
+ Title = "几何与形状绘制",
+ Name = "ShapeDrawingItem",
+ IconSource = FindResource("ShapeDrawingIcon") as DrawingImage,
+ Selected = false,
+ });
+ SidebarItems.Add(new SidebarItem() {
+ Type = SidebarItemType.Item,
+ Title = "自动化行为",
+ Name = "AutomationItem",
+ IconSource = FindResource("AutomationIcon") as DrawingImage,
+ Selected = false,
+ });
+ SidebarItems.Add(new SidebarItem() {
+ Type = SidebarItemType.Separator
+ });
+ SidebarItems.Add(new SidebarItem() {
+ Type = SidebarItemType.Item,
+ Title = "PowerPoint 支持",
+ Name = "PowerPointItem",
+ IconSource = FindResource("PowerPointIcon") as DrawingImage,
+ Selected = false,
+ });
+ SidebarItems.Add(new SidebarItem() {
+ Type = SidebarItemType.Item,
+ Title = "插件和脚本",
+ Name = "ExtensionsItem",
+ IconSource = FindResource("ExtensionsIcon") as DrawingImage,
+ Selected = false,
+ });
+ SidebarItems.Add(new SidebarItem() {
+ Type = SidebarItemType.Separator
+ });
+ SidebarItems.Add(new SidebarItem() {
+ Type = SidebarItemType.Item,
+ Title = "存储空间",
+ Name = "StorageItem",
+ IconSource = FindResource("StorageIcon") as DrawingImage,
+ Selected = false,
+ });
+ SidebarItems.Add(new SidebarItem() {
+ Type = SidebarItemType.Item,
+ Title = "截图和屏幕捕捉",
+ Name = "SnapshotItem",
+ IconSource = FindResource("SnapshotIcon") as DrawingImage,
+ Selected = false,
+ });
+ SidebarItems.Add(new SidebarItem() {
+ Type = SidebarItemType.Item,
+ Title = "点名器设置",
+ Name = "LuckyRandomItem",
+ IconSource = FindResource("LuckyRandomIcon") as DrawingImage,
+ Selected = false,
+ });
+ SidebarItems.Add(new SidebarItem() {
+ Type = SidebarItemType.Item,
+ Title = "高级选项",
+ Name = "AdvancedItem",
+ IconSource = FindResource("AdvancedIcon") as DrawingImage,
+ Selected = false,
+ });
+ SidebarItems.Add(new SidebarItem() {
+ Type = SidebarItemType.Item,
+ Title = "关于 InkCanvasForClass",
+ Name = "AboutItem",
+ IconSource = FindResource("AboutIcon") as DrawingImage,
+ Selected = false,
+ });
+ _selectedSidebarItemName = "CanvasAndInkItem";
+ UpdateSidebarItemsSelection();
+
+ SettingsPanes = new Grid[] {
+ AboutPane,
+ ExtensionsPane,
+ CanvasAndInkPane,
+ GesturesPane,
+ StartupPane,
+ AppearancePane,
+ InkRecognitionPane,
+ AutomationPane,
+ PowerPointPane
+ };
+
+ SettingsPaneScrollViewers = new ScrollViewer[] {
+ SettingsAboutPanel.AboutScrollViewerEx,
+ CanvasAndInkScrollViewerEx,
+ GesturesScrollViewerEx,
+ StartupScrollViewerEx,
+ AppearanceScrollViewerEx,
+ InkRecognitionScrollViewerEx,
+ AutomationScrollViewerEx,
+ PowerPointScrollViewerEx
+ };
+
+ SettingsAboutPanel.IsTopBarNeedShadowEffect += (o, s) => DropShadowEffectTopBar.Opacity = 0.25;
+ SettingsAboutPanel.IsTopBarNeedNoShadowEffect += (o, s) => DropShadowEffectTopBar.Opacity = 0;
+ }
+
+ public Grid[] SettingsPanes = new Grid[] { };
+ public ScrollViewer[] SettingsPaneScrollViewers = new ScrollViewer[] { };
+
+ public enum SidebarItemType {
+ Item,
+ Separator
+ }
+
+ public class SidebarItem {
+ public SidebarItemType Type { get; set; }
+ public string Title { get; set; }
+ public string Name { get; set; }
+ public ImageSource IconSource { get; set; }
+ public bool Selected { get; set; }
+ public Visibility _spVisibility {
+ get => this.Type == SidebarItemType.Separator ? Visibility.Visible : Visibility.Collapsed;
+ }
+ public Visibility _siVisibility {
+ get => this.Type == SidebarItemType.Item ? Visibility.Visible : Visibility.Collapsed;
+ }
+
+ public SolidColorBrush _siBackground {
+ get => this.Selected
+ ? new SolidColorBrush(Color.FromRgb(217, 217, 217))
+ : new SolidColorBrush(Colors.Transparent);
+ }
+ }
+
+ public string _selectedSidebarItemName = "";
+ public ObservableCollection SidebarItems = new ObservableCollection();
+
+ public void UpdateSidebarItemsSelection() {
+ foreach (var si in SidebarItems) {
+ si.Selected = si.Name == _selectedSidebarItemName;
+ if (si.Selected) SettingsWindowTitle.Text = si.Title;
+ }
+ CollectionViewSource.GetDefaultView(SidebarItems).Refresh();
+
+ AboutPane.Visibility = _selectedSidebarItemName == "AboutItem" ? Visibility.Visible : Visibility.Collapsed;
+ ExtensionsPane.Visibility = _selectedSidebarItemName == "ExtensionsItem" ? Visibility.Visible : Visibility.Collapsed;
+ CanvasAndInkPane.Visibility = _selectedSidebarItemName == "CanvasAndInkItem" ? Visibility.Visible : Visibility.Collapsed;
+ GesturesPane.Visibility = _selectedSidebarItemName == "GesturesItem" ? Visibility.Visible : Visibility.Collapsed;
+ StartupPane.Visibility = _selectedSidebarItemName == "StartupItem" ? Visibility.Visible : Visibility.Collapsed;
+ AppearancePane.Visibility = _selectedSidebarItemName == "AppearanceItem" ? Visibility.Visible : Visibility.Collapsed;
+ InkRecognitionPane.Visibility = _selectedSidebarItemName == "InkRecognitionItem" ? Visibility.Visible : Visibility.Collapsed;
+ AutomationPane.Visibility = _selectedSidebarItemName == "AutomationItem" ? Visibility.Visible : Visibility.Collapsed;
+ PowerPointPane.Visibility = _selectedSidebarItemName == "PowerPointItem" ? Visibility.Visible : Visibility.Collapsed;
+ foreach (var sv in SettingsPaneScrollViewers) {
+ sv.ScrollToTop();
+ }
+ }
+
+ private void ScrollViewerEx_ScrollChanged(object sender, ScrollChangedEventArgs e) {
+ var scrollViewer = (ScrollViewer)sender;
+ if (scrollViewer.VerticalOffset >= 10) {
+ DropShadowEffectTopBar.Opacity = 0.25;
+ } else {
+ DropShadowEffectTopBar.Opacity = 0;
+ }
+ }
+
+ private void ScrollBar_Scroll(object sender, RoutedEventArgs e) {
+ var scrollbar = (ScrollBar)sender;
+ var scrollviewer = scrollbar.FindAscendant();
+ if (scrollviewer != null) scrollviewer.ScrollToVerticalOffset(scrollbar.Track.Value);
+ }
+
+ private void ScrollBarTrack_MouseEnter(object sender, MouseEventArgs e) {
+ var border = (Border)sender;
+ if (border.Child is Track track) {
+ track.Width = 16;
+ track.Margin = new Thickness(0, 0, -2, 0);
+ var scrollbar = track.FindAscendant();
+ if (scrollbar != null) scrollbar.Width = 16;
+ var grid = track.FindAscendant();
+ if (grid.FindDescendantByName("ScrollBarBorderTrackBackground") is Border backgroundBorder) {
+ backgroundBorder.Width = 8;
+ backgroundBorder.CornerRadius = new CornerRadius(4);
+ backgroundBorder.Opacity = 1;
+ }
+ var thumb = track.Thumb.Template.FindName("ScrollbarThumbEx", track.Thumb) ;
+ if (thumb != null) {
+ var _thumb = thumb as Border;
+ _thumb.CornerRadius = new CornerRadius(4);
+ _thumb.Width = 8;
+ _thumb.Margin = new Thickness(-0.75, 0, 1, 0);
+ _thumb.Background = new SolidColorBrush(Color.FromRgb(138, 138, 138));
+ }
+ }
+ }
+
+ private void ScrollBarTrack_MouseLeave(object sender, MouseEventArgs e) {
+ var border = (Border)sender;
+ border.Background = new SolidColorBrush(Colors.Transparent);
+ border.CornerRadius = new CornerRadius(0);
+ if (border.Child is Track track) {
+ track.Width = 6;
+ track.Margin = new Thickness(0, 0, 0, 0);
+ var scrollbar = track.FindAscendant();
+ if (scrollbar != null) scrollbar.Width = 6;
+ var grid = track.FindAscendant();
+ if (grid.FindDescendantByName("ScrollBarBorderTrackBackground") is Border backgroundBorder) {
+ backgroundBorder.Width = 3;
+ backgroundBorder.CornerRadius = new CornerRadius(1.5);
+ backgroundBorder.Opacity = 0;
+ }
+ var thumb = track.Thumb.Template.FindName("ScrollbarThumbEx", track.Thumb) ;
+ if (thumb != null) {
+ var _thumb = thumb as Border;
+ _thumb.CornerRadius = new CornerRadius(1.5);
+ _thumb.Width = 3;
+ _thumb.Margin = new Thickness(0);
+ _thumb.Background = new SolidColorBrush(Color.FromRgb(195, 195, 195));
+ }
+ }
+ }
+
+ private void ScrollbarThumb_MouseDown(object sender, MouseButtonEventArgs e) {
+ var thumb = (Thumb)sender;
+ var border = thumb.Template.FindName("ScrollbarThumbEx",thumb);
+ ((Border)border).Background = new SolidColorBrush(Color.FromRgb(95, 95, 95));
+ }
+
+ private void ScrollbarThumb_MouseUp(object sender, MouseButtonEventArgs e) {
+ var thumb = (Thumb)sender;
+ var border = thumb.Template.FindName("ScrollbarThumbEx",thumb);
+ ((Border)border).Background = new SolidColorBrush(Color.FromRgb(138, 138, 138));
+ }
+
+ private Border _sidebarItemMouseDownBorder = null;
+
+ private void SidebarItem_MouseDown(object sender, MouseButtonEventArgs e) {
+ if (_sidebarItemMouseDownBorder != null || _sidebarItemMouseDownBorder == sender) return;
+ _sidebarItemMouseDownBorder = (Border)sender;
+ var bd = sender as Border;
+ if (bd.FindDescendantByName("MouseFeedbackBorder") is Border feedbackBd) feedbackBd.Opacity = 0.12;
+ }
+
+ private void SidebarItem_MouseUp(object sender, MouseButtonEventArgs e) {
+ if (_sidebarItemMouseDownBorder == null || _sidebarItemMouseDownBorder != sender) return;
+ if (_sidebarItemMouseDownBorder.Tag is SidebarItem data) _selectedSidebarItemName = data.Name;
+ SidebarItem_MouseLeave(sender, null);
+ UpdateSidebarItemsSelection();
+ }
+
+ private void SidebarItem_MouseLeave(object sender, MouseEventArgs e) {
+ if (_sidebarItemMouseDownBorder == null || _sidebarItemMouseDownBorder != sender) return;
+ if (_sidebarItemMouseDownBorder.FindDescendantByName("MouseFeedbackBorder") is Border feedbackBd) feedbackBd.Opacity = 0;
+ _sidebarItemMouseDownBorder = null;
+ }
+ }
+}
diff --git a/Ink Canvas/obj/Debug/net472/InkCanvasForClass.csproj.AssemblyReference.cache b/Ink Canvas/obj/Debug/net472/InkCanvasForClass.csproj.AssemblyReference.cache
index 4af914e22079d93b58f0e03491291464a0dba41e..44b9fc7383ebb573862944afd3220347eedadfaa 100644
GIT binary patch
delta 121
zcmV-<0EYjrlmhaX0tf~HF8}}l0b!F7A62nk^c$0=iB^+8NCyf{VQyh(Wo>0{bdzx-
z6O$erO_MM|L>(Mcd2@7SZ7xG^Zf0p`b#h^JX>V>WNp5p=VQg%ZAq+kfO=)9tZ*y;E
bbS_F$V{&P5bO8#JAwWx$?MYsB~nPN5rPzerDB>lwSbNUk9l0Hux!{Qv*}