返回提交历史

XFEstudio/MyFirstRespo

优化滚动,框架正式升级为.NET 9.0

9f47318
X
XFEstudio <mail@xfegzs.com>
提交于

代码差异

10 个文件 +195 -34
Modified XFEToolBox/Profiles/CacheProfiles/AppCacheProfile.cs +2 -1
@@ -7,5 +7,6 @@ public partial class AppCacheProfile
7 7 {
8 8 [ProfileProperty]
9 9 private string noticeText = "";
10 public AppCacheProfile() => ProfilePath = @$"{AppPath.CacheProfile}\{typeof(AppCacheProfile)}.xfe";
10 public AppCacheProfile() => ProfilePath = @$"{AppPath.CacheProfile}\{typeof(AppCacheProfile)}.xprofile";
11
11 12 }
Modified XFEToolBox/Profiles/CrossVersionProfiles/ConsoleProfile.cs +15 -1
@@ -5,11 +5,25 @@ namespace XFEToolBox.Profiles.CrossVersionProfiles;
5 5
6 6 public partial class ConsoleProfile
7 7 {
8 /// <summary>
9 /// 控制台端口
10 /// </summary>
8 11 [ProfileProperty]
9 12 private int consolePort = 3280;
13 /// <summary>
14 /// 控制台连接密码
15 /// </summary>
10 16 [ProfileProperty]
11 17 private string consolePassword = "";
18 /// <summary>
19 /// 是否只在本机回路中开放
20 /// </summary>
12 21 [ProfileProperty]
13 22 private bool localOnly = true;
14 public ConsoleProfile() => ProfilePath = @$"{AppPath.LocalProfile}\{typeof(ConsoleProfile)}.xfe";
23 /// <summary>
24 /// 最大行数
25 /// </summary>
26 [ProfileProperty]
27 private int maxLine = 9999;
28 public ConsoleProfile() => ProfilePath = @$"{AppPath.LocalProfile}\{typeof(ConsoleProfile)}.xprofile";
15 29 }
Modified XFEToolBox/Profiles/CrossVersionProfiles/SystemProfile.cs +10 -1
@@ -5,13 +5,22 @@ namespace XFEToolBox.Profiles.CrossVersionProfiles;
5 5
6 6 public partial class SystemProfile
7 7 {
8 /// <summary>
9 /// 当前窗口DPI缩放
10 /// </summary>
8 11 [ProfileProperty]
9 12 private double currentWindowDPIScale = 1.0;
13 /// <summary>
14 /// 主窗体宽度
15 /// </summary>
10 16 [ProfileProperty]
11 17 private double mainWindowWidth = 720;
18 /// <summary>
19 /// 主窗体高度
20 /// </summary>
12 21 [ProfileProperty]
13 22 private double mainWindowHeight = 450;
14 public SystemProfile() => ProfilePath = @$"{AppPath.LocalProfile}\{typeof(SystemProfile)}.xfe";
23 public SystemProfile() => ProfilePath = @$"{AppPath.LocalProfile}\{typeof(SystemProfile)}.xprofile";
15 24 /// <summary>
16 25 /// 工具箱现在是否可以被关闭
17 26 /// </summary>
Modified XFEToolBox/Resources/Style/MainStyle.xaml +4 -0
@@ -146,6 +146,7 @@
146 146 <Setter Property="VerticalAlignment" Value="Center"/>
147 147 </Style>
148 148 <Style x:Key="NavigationButton" TargetType="RadioButton">
149 <Setter Property="IsTabStop" Value="False"/>
149 150 <Setter Property="RenderTransformOrigin" Value="0.5,0.5"/>
150 151 <Setter Property="Margin" Value="10,5"/>
151 152 <Setter Property="Template">
@@ -252,10 +253,12 @@
252 253 </Style>
253 254 <Style x:Key="NavigationFrame" TargetType="Frame">
254 255 <Setter Property="NavigationUIVisibility" Value="Hidden"/>
256 <Setter Property="IsTabStop" Value="False"/>
255 257 <Setter Property="Grid.Column" Value="1"/>
256 258 <Setter Property="Grid.Row" Value="1"/>
257 259 </Style>
258 260 <Style x:Key="ConsoleScrollBar" TargetType="ScrollBar">
261 <Setter Property="IsTabStop" Value="False"/>
259 262 <Setter Property="Template">
260 263 <Setter.Value>
261 264 <ControlTemplate TargetType="ScrollBar">
@@ -336,6 +339,7 @@
336 339 <Style x:Key="FoldButton" TargetType="Button">
337 340 <Style.Setters>
338 341 <Setter Property="Opacity" Value="1"/>
342 <Setter Property="IsTabStop" Value="False"/>
339 343 <Setter Property="Template">
340 344 <Setter.Value>
341 345 <ControlTemplate TargetType="Button">
Modified XFEToolBox/Utilities/DecoratedTextConverter.cs +75 -4
@@ -4,14 +4,24 @@ using System.Windows;
4 4 using System.Windows.Controls;
5 5 using System.Windows.Documents;
6 6 using System.Windows.Media;
7 using System.Windows.Threading;
7 8
8 9 namespace XFEToolBox.Utilities;
9 10
10 11 public partial class DecoratedTextConverter
11 12 {
13 /// <summary>
14 /// 装饰文本
15 /// </summary>
16 /// <returns></returns>
12 17 [GeneratedRegex(@"\[(?:(?:(?<type>color)\s+(?<color>\#[0-9a-fA-F]{6}|\w+)(?:\s+(?<background>\#[0-9a-fA-F]{6}|\w+))?)|(?:(?<type>hyperlink)\s+(?:color:\s*(?<color>\#[0-9a-fA-F]{6}|\w+)(?<background>\s+\#[0-9a-fA-F]{6}|\w+)?(?:\s+))?link:\s*(?<link>.+)\s+text:\s*(?<text>.+))|(?:(?<type>foldblock)\s+(?:color:\s*(?<color>\#[0-9a-fA-F]{6}|\w+)\s+(?<background>\#[0-9a-fA-F]{6}|\w+))\s+title:\s*(?<title>.+)\s+text:\s*(?<text>(?s).+)))\]")]
13 18 public static partial Regex DecorationRegex();
14
19 /// <summary>
20 /// 转为文本块
21 /// </summary>
22 /// <param name="decoratedText"></param>
23 /// <param name="defaultColor"></param>
24 /// <returns></returns>
15 25 public static TextBlock ConvertToTextBlock(string decoratedText, Color defaultColor)
16 26 {
17 27 var results = ConvertToInlineList(decoratedText, defaultColor);
@@ -25,13 +35,49 @@ public partial class DecoratedTextConverter
25 35 }
26 36 return textBlock;
27 37 }
38 /// <summary>
39 /// 转为文本块
40 /// </summary>
41 /// <param name="decoratedText"></param>
42 /// <param name="defaultColor"></param>
43 /// <param name="dispatcher"></param>
44 /// <returns></returns>
45 public static async Task<TextBlock> ConvertToTextBlockAsync(string decoratedText, Color defaultColor, Dispatcher dispatcher)
46 {
47 var results = await ConvertToInlineListAsync(decoratedText, defaultColor, dispatcher);
48 var textBlock = new TextBlock();
49 foreach (var result in results)
50 {
51 if (result is Inline inline)
52 textBlock.Inlines.Add(inline);
53 else
54 textBlock.Inlines.Add((UIElement)result);
55 }
56 return textBlock;
57 }
58 /// <summary>
59 /// 转为行内组件列表
60 /// </summary>
61 /// <param name="decoratedText"></param>
62 /// <param name="defaultColor"></param>
63 /// <returns></returns>
28 64 public static List<object> ConvertToInlineList(string decoratedText, Color defaultColor)
29 65 {
30 66 var results = ConvertText(decoratedText, defaultColor);
67 return ConvertToInlineList(results, decoratedText);
68 }
69 /// <summary>
70 /// 转为行内组件列表
71 /// </summary>
72 /// <param name="decTextSpans"></param>
73 /// <param name="decoratedText"></param>
74 /// <returns></returns>
75 public static List<object> ConvertToInlineList(List<DecTextSpan> decTextSpans, string decoratedText = "")
76 {
31 77 var inLineList = new List<object>();
32 if (results.Count > 0)
78 if (decTextSpans.Count > 0)
33 79 {
34 foreach (var result in results)
80 foreach (var result in decTextSpans)
35 81 {
36 82 if (result is HyperLinkDecSpan hyperLinkDecSpan)
37 83 {
@@ -151,7 +197,7 @@ public partial class DecoratedTextConverter
151 197 }
152 198 }
153 199 }
154 else
200 else if (decoratedText != string.Empty)
155 201 {
156 202 inLineList.Add(new Span(new Run(decoratedText))
157 203 {
@@ -160,6 +206,24 @@ public partial class DecoratedTextConverter
160 206 }
161 207 return inLineList;
162 208 }
209 /// <summary>
210 /// 转为行内组件列表
211 /// </summary>
212 /// <param name="decoratedText"></param>
213 /// <param name="defaultColor"></param>
214 /// <param name="dispatcher"></param>
215 /// <returns></returns>
216 public static async Task<List<object>> ConvertToInlineListAsync(string decoratedText, Color defaultColor, Dispatcher dispatcher)
217 {
218 var result = await ConvertTextAsync(decoratedText, defaultColor);
219 return dispatcher.Invoke(() => ConvertToInlineList(result, decoratedText));
220 }
221 /// <summary>
222 /// 转为装饰文本
223 /// </summary>
224 /// <param name="decoratedText"></param>
225 /// <param name="defaultColor"></param>
226 /// <returns></returns>
163 227 public static List<DecTextSpan> ConvertText(string decoratedText, Color defaultColor)
164 228 {
165 229 var textSpanList = new List<DecTextSpan>();
@@ -212,4 +276,11 @@ public partial class DecoratedTextConverter
212 276 }
213 277 return textSpanList;
214 278 }
279 /// <summary>
280 /// 转为装饰文本
281 /// </summary>
282 /// <param name="decoratedText"></param>
283 /// <param name="defaultColor"></param>
284 /// <returns></returns>
285 public static async Task<List<DecTextSpan>> ConvertTextAsync(string decoratedText, Color defaultColor) => await Task.Run(() => ConvertText(decoratedText, defaultColor));
215 286 }
Modified XFEToolBox/ViewModel/ConsolePageViewModel.cs +83 -22
@@ -1,5 +1,6 @@
1 1 using CommunityToolkit.Mvvm.ComponentModel;
2 2 using CommunityToolkit.Mvvm.Input;
3 using System.Diagnostics;
3 4 using System.Net;
4 5 using System.Windows.Controls;
5 6 using System.Windows.Media;
@@ -23,6 +24,7 @@ public partial class ConsolePageViewModel(ConsolePage viewPage) : ObservableObje
23 24 private bool canCleanUp = false;
24 25
25 26 private bool lastLineIsEnd = true;
27 private bool autoScroll = true;
26 28 public ConsolePage ViewPage { get; set; } = viewPage;
27 29 public XFEConsoleTerminalServer? TerminalServer { get; set; }
28 30
@@ -48,38 +50,49 @@ public partial class ConsolePageViewModel(ConsolePage viewPage) : ObservableObje
48 50 TerminalServer = null;
49 51 }
50 52
51 private void TerminalServer_ErrorOccurred(XFEConsoleClientInfo sender, Exception e)
53 private async void TerminalServer_ErrorOccurred(XFEConsoleClientInfo sender, Exception e)
52 54 {
53 55 var code = e.InnerException?.InnerException is HttpListenerException ? (e.InnerException.InnerException as HttpListenerException)!.ErrorCode : 0;
54 56 if (code != 995)
55 ShowMessageWithTimeLine($"[foldblock color: white #ff0000 title: 错误:{e.Message} text: {e}]");
57 await ShowMessageWithTimeLineAsync($"[foldblock color: white #ff0000 title: 错误:{e.Message} text: {e}]");
56 58 }
57 59
58 private void TerminalServer_MessageReceived(XFEConsoleClientInfo sender, string e)
60 private async void TerminalServer_MessageReceived(XFEConsoleClientInfo sender, string e)
59 61 {
60 62 var dictionary = new XFEDictionary(e);
61 63 var isLine = dictionary["IsLine"] == "true";
62 64 var textMessage = dictionary["Text"];
63 65 if (lastLineIsEnd)
64 ShowMessageWithTimeLine($"{sender.ClientName}> {textMessage}", isLine);
66 await ShowMessageWithTimeLineAsync($"{sender.ClientName}> {textMessage}", isLine);
65 67 else
66 ShowMessage($"{textMessage}", isLine);
68 await ShowMessageAsync($"{textMessage}", isLine);
67 69 }
68 70
69 private void TerminalServer_Disconnected(XFEConsoleTerminalServer sender, XFEConsoleClientInfo e)
71 private async void TerminalServer_Disconnected(XFEConsoleTerminalServer sender, XFEConsoleClientInfo e)
70 72 {
71 ShowMessageWithTimeLine($"[color #9898e7]客户端断开连接 [color white]{e.ClientName}");
73 await ShowMessageWithTimeLineAsync($"[color #9898e7]客户端断开连接 [color white]{e.ClientName}");
72 74 }
73 75
74 private void TerminalServer_Connected(XFEConsoleTerminalServer sender, XFEConsoleClientInfo e)
76 private async void TerminalServer_Connected(XFEConsoleTerminalServer sender, XFEConsoleClientInfo e)
75 77 {
76 ShowMessageWithTimeLine($"[color #9898e7]客户端连接 [color white]{e.ClientName}");
78 await ShowMessageWithTimeLineAsync($"[color #9898e7]客户端连接 [color white]{e.ClientName}");
77 79 }
78 80
79 private void TerminalServer_ServerStarted(XFEConsoleTerminalServer sender)
81 private async void TerminalServer_ServerStarted(XFEConsoleTerminalServer sender)
80 82 {
81 ShowMessageWithTimeLine($"控制台服务器已在端口:[hyperlink color: #05ff00 link: http://localhost:{ConsoleProfile.ConsolePort}/ text: {ConsoleProfile.ConsolePort}] 上运行");
83 await ShowMessageWithTimeLineAsync($"控制台服务器已在端口:[hyperlink color: #05ff00 link: http://localhost:{ConsoleProfile.ConsolePort}/ text: {ConsoleProfile.ConsolePort}] 上运行");
82 84 }
85
86 internal void ScrollChanged(object sender, ScrollChangedEventArgs e)
87 {
88 if (e.VerticalChange < 0)
89 autoScroll = false;
90 else if (e.VerticalChange > 0 && e.VerticalOffset + e.ViewportHeight == e.ExtentHeight)
91 autoScroll = true;
92 if (autoScroll)
93 ViewPage.scrollViewer.ScrollToEnd();
94 }
95
83 96 /// <summary>
84 97 /// 显示消息
85 98 /// </summary>
@@ -113,38 +126,85 @@ public partial class ConsolePageViewModel(ConsolePage viewPage) : ObservableObje
113 126 });
114 127 lastLineIsEnd = isLineEnd;
115 128 }
129
130 /// <summary>
131 /// 显示消息
132 /// </summary>
133 /// <param name="message"></param>
134 /// <param name="defaultColor"></param>
135 public async Task ShowMessageAsync(string message, Color defaultColor, bool isLineEnd, bool forceLine = false)
136 {
137 if (!CanCleanUp)
138 CanCleanUp = true;
139 if (!lastLineIsEnd && !forceLine)
140 {
141 var lastControl = ViewPage.consoleStackPanel.Children.Count > 0 ? ViewPage.consoleStackPanel.Children[^1] : null;
142 if (lastControl is TextBlock lastTextBlock)
143 {
144 var inLineList = await DecoratedTextConverter.ConvertToInlineListAsync(message, defaultColor, ViewPage.Dispatcher);
145 ViewPage.Dispatcher.Invoke(() =>
146 {
147 lastTextBlock.Inlines.AddRange(inLineList);
148 lastLineIsEnd = isLineEnd;
149 });
150 }
151 return;
152 }
153 var textBlock = await DecoratedTextConverter.ConvertToTextBlockAsync(message, defaultColor, ViewPage.Dispatcher);
154 textBlock.TextWrapping = System.Windows.TextWrapping.Wrap;
155 textBlock.FontSize = 13;
156 textBlock.FontFamily = new FontFamily("Consolas");
157 ViewPage.Dispatcher.Invoke(() => ViewPage.consoleStackPanel.Children.Add(textBlock));
158 lastLineIsEnd = isLineEnd;
159 }
160
116 161 /// <summary>
117 162 /// 显示消息
118 163 /// </summary>
119 164 /// <param name="message"></param>
120 165 public void ShowMessage(string message, bool isLineEnd = true, bool forceLine = false) => ShowMessage(message, Colors.White, isLineEnd, forceLine);
166
167 /// <summary>
168 /// 显示消息
169 /// </summary>
170 /// <param name="message"></param>
171 public async Task ShowMessageAsync(string message, bool isLineEnd = true, bool forceLine = false) => await ShowMessageAsync(message, Colors.White, isLineEnd, forceLine);
172
121 173 /// <summary>
122 174 /// 显示附带时间轴的消息
123 175 /// </summary>
124 176 /// <param name="message"></param>
125 177 public void ShowMessageWithTimeLine(string message, bool isLineEnd = true) => ShowMessage($"[{DateTime.Now:HH:mm:ss}] {message}", isLineEnd, true);
178
179 /// <summary>
180 /// 显示附带时间轴的消息
181 /// </summary>
182 /// <param name="message"></param>
183 public async Task ShowMessageWithTimeLineAsync(string message, bool isLineEnd = true) => await ShowMessageAsync($"[{DateTime.Now:HH:mm:ss}] {message}", isLineEnd, true);
184
185 #region Command
126 186 [RelayCommand]
127 private void StartServer()
187 private async Task StartServer()
128 188 {
129 189 CanRestartServer = false;
130 190 CanStartServer = false;
131 191 try
132 192 {
133 ShowMessageWithTimeLine("[color yellow]正在启动服务器...");
193 await ShowMessageWithTimeLineAsync("[color yellow]正在启动服务器...");
134 194 _ = StartConsoleServer();
135 195 CanStopServer = true;
136 196 CanRestartServer = true;
137 197 }
138 198 catch (Exception ex)
139 199 {
140 ShowMessageWithTimeLine($"[color red]无法启动服务器:{ex}");
200 await ShowMessageWithTimeLineAsync($"[color red]无法启动服务器:{ex}");
141 201 CanRestartServer = false;
142 202 CanStopServer = false;
143 203 CanStartServer = true;
144 204 }
145 205 }
146 206 [RelayCommand]
147 private void StopServer()
207 private async Task StopServer()
148 208 {
149 209 CanRestartServer = false;
150 210 CanStopServer = false;
@@ -152,11 +212,11 @@ public partial class ConsolePageViewModel(ConsolePage viewPage) : ObservableObje
152 212 {
153 213 ShutDownServer();
154 214 CanStartServer = true;
155 ShowMessageWithTimeLine("[color yellow]服务器已关闭");
215 await ShowMessageWithTimeLineAsync("[color yellow]服务器已关闭");
156 216 }
157 217 catch (Exception ex)
158 218 {
159 ShowMessageWithTimeLine($"[color red]关闭服务器时出现错误:{ex}");
219 await ShowMessageWithTimeLineAsync($"[color red]关闭服务器时出现错误:{ex}");
160 220 if (TerminalServer is not null && TerminalServer.Server.Server.IsListening)
161 221 {
162 222 CanRestartServer = true;
@@ -169,7 +229,7 @@ public partial class ConsolePageViewModel(ConsolePage viewPage) : ObservableObje
169 229 }
170 230 }
171 231 [RelayCommand]
172 private void RestartServer()
232 private async Task RestartServer()
173 233 {
174 234 CanRestartServer = false;
175 235 CanStartServer = false;
@@ -177,16 +237,16 @@ public partial class ConsolePageViewModel(ConsolePage viewPage) : ObservableObje
177 237 try
178 238 {
179 239 ShutDownServer();
180 ShowMessageWithTimeLine("[color yellow]服务器已关闭");
240 await ShowMessageWithTimeLineAsync("[color yellow]服务器已关闭");
181 241 _ = StartConsoleServer();
182 242 CanStartServer = false;
183 243 CanStopServer = true;
184 244 CanRestartServer = true;
185 ShowMessageWithTimeLine("[color yellow]服务器重启完成");
245 await ShowMessageWithTimeLineAsync("[color yellow]服务器重启完成");
186 246 }
187 247 catch (Exception ex)
188 248 {
189 ShowMessageWithTimeLine($"[color red]重启服务器时出现错误:{ex}");
249 await ShowMessageWithTimeLineAsync($"[color red]重启服务器时出现错误:{ex}");
190 250 if (TerminalServer is not null && TerminalServer.Server.Server.IsListening)
191 251 {
192 252 CanRestartServer = true;
@@ -207,4 +267,5 @@ public partial class ConsolePageViewModel(ConsolePage viewPage) : ObservableObje
207 267 CanCleanUp = false;
208 268 ViewPage.consoleStackPanel.Children.Clear();
209 269 }
210 }
270 #endregion
271 }
Modified XFEToolBox/Views/Pages/ConsolePage.xaml +1 -1
@@ -62,7 +62,7 @@
62 62 </StackPanel>
63 63 </Grid>
64 64 <Border Grid.Column="0" Grid.Row="1" CornerRadius="0,0,15,0" Background="Black" Padding="0,5,3,5">
65 <ScrollViewer VerticalScrollBarVisibility="Auto">
65 <ScrollViewer x:Name="scrollViewer" x:FieldModifier="internal" VerticalScrollBarVisibility="Auto" IsTabStop="False" ScrollChanged="ScrollViewer_ScrollChanged">
66 66 <ScrollViewer.Resources>
67 67 <Style TargetType="ScrollBar" BasedOn="{StaticResource ConsoleScrollBar}"/>
68 68 </ScrollViewer.Resources>
Modified XFEToolBox/Views/Pages/ConsolePage.xaml.cs +2 -0
@@ -17,4 +17,6 @@ public partial class ConsolePage : Page
17 17 DataContext = ViewModel;
18 18 Current = this;
19 19 }
20
21 private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e) => ViewModel.ScrollChanged(sender, e);
20 22 }
Modified XFEToolBox/Views/Windows/MainWindow.xaml.cs +1 -2
@@ -1,5 +1,4 @@
1 using System.Diagnostics;
2 using System.Windows;
1 using System.Windows;
3 2 using System.Windows.Media.Animation;
4 3 using XFEExtension.NetCore.InputSimulator;
5 4 using XFEToolBox.Profiles.CrossVersionProfiles;
Modified XFEToolBox/XFEToolBox.csproj +2 -2
@@ -2,12 +2,12 @@
2 2
3 3 <PropertyGroup>
4 4 <OutputType>WinExe</OutputType>
5 <TargetFramework>net8.0-windows</TargetFramework>
5 <TargetFramework>net9.0-windows</TargetFramework>
6 6 <Nullable>enable</Nullable>
7 7 <ImplicitUsings>enable</ImplicitUsings>
8 8 <UseWPF>true</UseWPF>
9 9 <ApplicationIcon>Resources\Icon\XFEToolBoxIcon.ico</ApplicationIcon>
10 <Version>0.0.1</Version>
10 <Version>0.0.2</Version>
11 11 </PropertyGroup>
12 12
13 13 <ItemGroup>