diff --git a/InkCanvasForClass/MainWindow.xaml b/InkCanvasForClass/MainWindow.xaml index a4eb1a6..eb9375b 100644 --- a/InkCanvasForClass/MainWindow.xaml +++ b/InkCanvasForClass/MainWindow.xaml @@ -3445,10 +3445,7 @@ - - + Canvas.Left="28" Margin="0,-2,0,-2" Background="#2563eb"/> @@ -4339,7 +4336,7 @@ - - 2) - ShowNotification("正在清空墨迹并收纳至侧边栏,可进入批注模式后通过【撤销】功能来恢复原先墨迹。"); + ShowNewToast("正在清空墨迹并收纳至屏幕两边,可进入批注模式后通过 “撤销” 功能来恢复原先墨迹。",MW_Toast.ToastType.Informative, 3000); CursorWithDelIcon_Click(null, null); RectangleSelectionHitTestBorder.Visibility = Visibility.Collapsed; }); diff --git a/InkCanvasForClass/MainWindow_cs/MW_FloatingBarIcons.cs b/InkCanvasForClass/MainWindow_cs/MW_FloatingBarIcons.cs index 6efeb7c..de03149 100644 --- a/InkCanvasForClass/MainWindow_cs/MW_FloatingBarIcons.cs +++ b/InkCanvasForClass/MainWindow_cs/MW_FloatingBarIcons.cs @@ -563,6 +563,15 @@ namespace Ink_Canvas { CircleEraserIconGeometry, LassoSelectIconGeometry }; + + TextBlock[] iconTextBlocksFloatingBar = new TextBlock[] { + SelectionToolBarTextBlock, + PenToolbarTextBlock, + InkEraserToolbarTextBlock, + CircleEraserToolbarTextBlock, + LassoToolToolbarTextBlock + }; + string[] iconGeometryPathStringsFloatingBar = new string[] { XamlGraphicsIconGeometries.LinedCursorIcon, XamlGraphicsIconGeometries.LinedPenIcon, @@ -592,6 +601,10 @@ namespace Ink_Canvas { BoardEraserLabel }; + foreach (var tb in iconTextBlocksFloatingBar) { + tb.Foreground = new SolidColorBrush(Colors.Black); + } + foreach (var gd in iconGeometryDrawingsFloatingBar) { gd.Brush = new SolidColorBrush(Color.FromRgb(27, 27, 27)); gd.Geometry = Geometry.Parse(iconGeometryPathStringsFloatingBar[Array.IndexOf(iconGeometryDrawingsFloatingBar, gd)]); @@ -613,7 +626,8 @@ namespace Ink_Canvas { if (mode != ICCToolsEnum.CursorMode) { // floating bar var ngdf = iconGeometryDrawingsFloatingBar[(int)mode]; - ngdf.Brush = new SolidColorBrush(Color.FromRgb(30, 58, 138)); + ngdf.Brush = new SolidColorBrush(Colors.White); + iconTextBlocksFloatingBar[(int)mode].Foreground = new SolidColorBrush(Colors.White); ngdf.Geometry = Geometry.Parse(iconGeometryPathStringsFloatingBar[(int)mode+5]); FloatingbarSelectionBG.Visibility = Visibility.Visible; var iconPosI = (int)mode == 1 ? highlightStepWidth : diff --git a/InkCanvasForClass/MainWindow_cs/MW_Notification.cs b/InkCanvasForClass/MainWindow_cs/MW_Notification.cs index a5baf0f..e19cd98 100644 --- a/InkCanvasForClass/MainWindow_cs/MW_Notification.cs +++ b/InkCanvasForClass/MainWindow_cs/MW_Notification.cs @@ -22,5 +22,14 @@ namespace Ink_Canvas notification.ShowAnimatedWithAutoDispose(3000 + notice.Length * 10); return notification; } + + public MW_Toast ShowNewToast(string notice, MW_Toast.ToastType type, int autoCloseMs) { + var notification = new MW_Toast(type, notice, (self) => { + GridNotifications.Children.Remove(self); + }); + GridNotifications.Children.Add(notification); + notification.ShowAnimatedWithAutoDispose(autoCloseMs + notice.Length * 10); + return notification; + } } } \ No newline at end of file diff --git a/InkCanvasForClass/MainWindow_cs/MW_Save&OpenStrokes.cs b/InkCanvasForClass/MainWindow_cs/MW_Save&OpenStrokes.cs index 5980144..558a636 100644 --- a/InkCanvasForClass/MainWindow_cs/MW_Save&OpenStrokes.cs +++ b/InkCanvasForClass/MainWindow_cs/MW_Save&OpenStrokes.cs @@ -35,10 +35,10 @@ namespace Ink_Canvas { savePathWithName = savePath + @"\" + DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss-fff") + ".icstk"; var fs = new FileStream(savePathWithName, FileMode.Create); inkCanvas.Strokes.Save(fs); - if (newNotice) ShowNotification("墨迹成功保存至 " + savePathWithName); + if (newNotice) ShowNewToast("墨迹成功保存至 " + savePathWithName, MW_Toast.ToastType.Success, 2500); } catch (Exception ex) { - ShowNotification("墨迹保存失败"); + ShowNewToast("墨迹保存失败!", MW_Toast.ToastType.Error, 3000); LogHelper.WriteLogToFile("墨迹保存失败 | " + ex.ToString(), LogHelper.LogType.Error); } } @@ -81,7 +81,7 @@ namespace Ink_Canvas { if (inkCanvas.Visibility != Visibility.Visible) SymbolIconCursor_Click(sender, null); } catch { - ShowNotification("墨迹打开失败"); + ShowNewToast("墨迹打开失败!", MW_Toast.ToastType.Error, 3000); } } } diff --git a/InkCanvasForClass/MainWindow_cs/MW_Screenshot.cs b/InkCanvasForClass/MainWindow_cs/MW_Screenshot.cs index 337153f..ccc4be5 100644 --- a/InkCanvasForClass/MainWindow_cs/MW_Screenshot.cs +++ b/InkCanvasForClass/MainWindow_cs/MW_Screenshot.cs @@ -29,7 +29,7 @@ namespace Ink_Canvas } if (!isHideNotification) { - ShowNotification("截图成功保存至 " + savePath); + ShowNewToast("截图成功保存至 " + savePath, MW_Toast.ToastType.Success, 3000); } } @@ -38,7 +38,7 @@ namespace Ink_Canvas var bitmap = GetScreenshotBitmap(); string savePath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); bitmap.Save(savePath + @"\" + DateTime.Now.ToString("u").Replace(':', '-') + ".png", ImageFormat.Png); - ShowNotification("截图成功保存至【桌面" + @"\" + DateTime.Now.ToString("u").Replace(':', '-') + ".png】"); + ShowNewToast("截图成功保存至【桌面" + @"\" + DateTime.Now.ToString("u").Replace(':', '-') + ".png】", MW_Toast.ToastType.Success, 3000); if (Settings.Automation.IsAutoSaveStrokesAtScreenshot) SaveInkCanvasStrokes(false, false); } diff --git a/InkCanvasForClass/MainWindow_cs/MW_Settings.cs b/InkCanvasForClass/MainWindow_cs/MW_Settings.cs index 1f83a39..fbf78ba 100644 --- a/InkCanvasForClass/MainWindow_cs/MW_Settings.cs +++ b/InkCanvasForClass/MainWindow_cs/MW_Settings.cs @@ -20,6 +20,8 @@ using System.Security.Principal; using System.IO; using System.Reflection; using System.Threading; +using System.Timers; +using Ink_Canvas.Popups; using Ookii.Dialogs.Wpf; namespace Ink_Canvas { @@ -1644,7 +1646,7 @@ namespace Ink_Canvas { } catch { } - ShowNotification("设置已重置为默认推荐设置~"); + ShowNewToast("设置已重置为默认推荐设置~", MW_Toast.ToastType.Success, 2500); } private async void SpecialVersionResetToSuggestion_Click() { @@ -1859,6 +1861,26 @@ namespace Ink_Canvas { UpdateSettingsPaneCustomScrollBarStatus(); } + public void SettingsPaneScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e) { + var scrollViewer = (ScrollViewer)sender; + var sb = new Storyboard(); + var ofs = scrollViewer.VerticalOffset; + var animation = new DoubleAnimation + { + From = ofs, + To = ofs - e.Delta * 2.5, + Duration = TimeSpan.FromMilliseconds(155) + }; + animation.EasingFunction = new CubicEase() { + EasingMode = EasingMode.EaseOut, + }; + Storyboard.SetTargetProperty(animation, new PropertyPath(ColorPalette.ScrollViewerBehavior.VerticalOffsetProperty)); + Storyboard.SetTargetName(animation,"SettingsPanelScrollViewer"); + sb.Children.Add(animation); + scrollViewer.ScrollToVerticalOffset(ofs); + sb.Begin(scrollViewer); + } + public void UpdateSettingsPaneCustomScrollBarStatus() { var scrollPercentage = SettingsPanelScrollViewer.VerticalOffset / (SettingsPanelScrollViewer.ExtentHeight - SettingsPanelScrollViewer.ActualHeight); @@ -1985,73 +2007,92 @@ namespace Ink_Canvas { } } + private void SettingsPaneScrollViewer_ScrollToAnimated(double offset) { + var sb = new Storyboard(); + var ofs = SettingsPanelScrollViewer.VerticalOffset; + var animation = new DoubleAnimation + { + From = ofs, + To = offset, + Duration = TimeSpan.FromMilliseconds(155) + }; + animation.EasingFunction = new CubicEase() { + EasingMode = EasingMode.EaseOut, + }; + Storyboard.SetTargetProperty(animation, new PropertyPath(ColorPalette.ScrollViewerBehavior.VerticalOffsetProperty)); + Storyboard.SetTargetName(animation,"SettingsPanelScrollViewer"); + sb.Children.Add(animation); + SettingsPanelScrollViewer.ScrollToVerticalOffset(ofs); + sb.Begin(SettingsPanelScrollViewer); + } + public void SettingsStartupJumpToGroupBox(object sender, MouseButtonEventArgs e) { var transform = SettingsStartupGroupBox.TransformToVisual(SettingsPanelScrollViewer); var position = transform.Transform(new Point(0, 0)); - SettingsPanelScrollViewer.ScrollToVerticalOffset(SettingsPanelScrollViewer.VerticalOffset + position.Y - 10); + SettingsPaneScrollViewer_ScrollToAnimated(SettingsPanelScrollViewer.VerticalOffset + position.Y - 10); } public void SettingsCanvasJumpToGroupBox(object sender, MouseButtonEventArgs e) { var transform = SettingsCanvasGroupBox.TransformToVisual(SettingsPanelScrollViewer); var position = transform.Transform(new Point(0, 0)); - SettingsPanelScrollViewer.ScrollToVerticalOffset(SettingsPanelScrollViewer.VerticalOffset + position.Y - 10); + SettingsPaneScrollViewer_ScrollToAnimated(SettingsPanelScrollViewer.VerticalOffset + position.Y - 10); } public void SettingsGestureJumpToGroupBox(object sender, MouseButtonEventArgs e) { var transform = SettingsGestureGroupBox.TransformToVisual(SettingsPanelScrollViewer); var position = transform.Transform(new Point(0, 0)); - SettingsPanelScrollViewer.ScrollToVerticalOffset(SettingsPanelScrollViewer.VerticalOffset + position.Y - 10); + SettingsPaneScrollViewer_ScrollToAnimated(SettingsPanelScrollViewer.VerticalOffset + position.Y - 10); } public void SettingsInkRecognitionJumpToGroupBox(object sender, MouseButtonEventArgs e) { var transform = SettingsInkRecognitionGroupBox.TransformToVisual(SettingsPanelScrollViewer); var position = transform.Transform(new Point(0, 0)); - SettingsPanelScrollViewer.ScrollToVerticalOffset(SettingsPanelScrollViewer.VerticalOffset + position.Y - 10); + SettingsPaneScrollViewer_ScrollToAnimated(SettingsPanelScrollViewer.VerticalOffset + position.Y - 10); } public void SettingsAppearanceJumpToGroupBox(object sender, MouseButtonEventArgs e) { var transform = SettingsAppearanceGroupBox.TransformToVisual(SettingsPanelScrollViewer); var position = transform.Transform(new Point(0, 0)); - SettingsPanelScrollViewer.ScrollToVerticalOffset(SettingsPanelScrollViewer.VerticalOffset + position.Y - 10); + SettingsPaneScrollViewer_ScrollToAnimated(SettingsPanelScrollViewer.VerticalOffset + position.Y - 10); } public void SettingsPPTJumpToGroupBox(object sender, MouseButtonEventArgs e) { var transform = SettingsPPTGroupBox.TransformToVisual(SettingsPanelScrollViewer); var position = transform.Transform(new Point(0, 0)); - SettingsPanelScrollViewer.ScrollToVerticalOffset(SettingsPanelScrollViewer.VerticalOffset + position.Y - 10); + SettingsPaneScrollViewer_ScrollToAnimated(SettingsPanelScrollViewer.VerticalOffset + position.Y - 10); } public void SettingsAdvancedJumpToGroupBox(object sender, MouseButtonEventArgs e) { var transform = SettingsAdvancedGroupBox.TransformToVisual(SettingsPanelScrollViewer); var position = transform.Transform(new Point(0, 0)); - SettingsPanelScrollViewer.ScrollToVerticalOffset(SettingsPanelScrollViewer.VerticalOffset + position.Y - 10); + SettingsPaneScrollViewer_ScrollToAnimated(SettingsPanelScrollViewer.VerticalOffset + position.Y - 10); } public void SettingsAutomationJumpToGroupBox(object sender, MouseButtonEventArgs e) { var transform = SettingsAutomationGroupBox.TransformToVisual(SettingsPanelScrollViewer); var position = transform.Transform(new Point(0, 0)); - SettingsPanelScrollViewer.ScrollToVerticalOffset(SettingsPanelScrollViewer.VerticalOffset + position.Y - 10); + SettingsPaneScrollViewer_ScrollToAnimated(SettingsPanelScrollViewer.VerticalOffset + position.Y - 10); } public void SettingsRandWindowJumpToGroupBox(object sender, MouseButtonEventArgs e) { var transform = SettingsRandWindowGroupBox.TransformToVisual(SettingsPanelScrollViewer); var position = transform.Transform(new Point(0, 0)); - SettingsPanelScrollViewer.ScrollToVerticalOffset(SettingsPanelScrollViewer.VerticalOffset + position.Y - 10); + SettingsPaneScrollViewer_ScrollToAnimated(SettingsPanelScrollViewer.VerticalOffset + position.Y - 10); } public void SettingsAboutJumpToGroupBox(object sender, MouseButtonEventArgs e) { var transform = SettingsAboutGroupBox.TransformToVisual(SettingsPanelScrollViewer); var position = transform.Transform(new Point(0, 0)); - SettingsPanelScrollViewer.ScrollToVerticalOffset(SettingsPanelScrollViewer.VerticalOffset + position.Y - 10); + SettingsPaneScrollViewer_ScrollToAnimated(SettingsPanelScrollViewer.VerticalOffset + position.Y - 10); } #endregion diff --git a/InkCanvasForClass/MainWindow_cs/MW_SimulatePressure&InkToShape.cs b/InkCanvasForClass/MainWindow_cs/MW_SimulatePressure&InkToShape.cs index e31f1e0..09d0add 100644 --- a/InkCanvasForClass/MainWindow_cs/MW_SimulatePressure&InkToShape.cs +++ b/InkCanvasForClass/MainWindow_cs/MW_SimulatePressure&InkToShape.cs @@ -1,12 +1,16 @@ using Ink_Canvas.Helpers; using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; +using System.Threading; using System.Windows; using System.Windows.Controls; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; +using System.Windows.Shapes; +using System.Windows.Threading; using Point = System.Windows.Point; namespace Ink_Canvas { @@ -24,14 +28,15 @@ namespace Ink_Canvas { try { newStrokes.Add(e.Stroke); if (newStrokes.Count > 4) newStrokes.RemoveAt(0); - for (var i = 0; i < newStrokes.Count; i++) - if (!inkCanvas.Strokes.Contains(newStrokes[i])) - newStrokes.RemoveAt(i--); - - for (var i = 0; i < circles.Count; i++) - if (!inkCanvas.Strokes.Contains(circles[i].Stroke)) - circles.RemoveAt(i); + Dispatcher.InvokeAsync(() => { + for (var i = 0; i < newStrokes.Count; i++) + if (!inkCanvas.Strokes.Contains(newStrokes[i])) + newStrokes.RemoveAt(i--); + for (var i = 0; i < circles.Count; i++) + if (!inkCanvas.Strokes.Contains(circles[i].Stroke)) + circles.RemoveAt(i); + }); var strokeReco = new StrokeCollection(); var result = InkRecognizeHelper.RecognizeShape(newStrokes); for (var i = newStrokes.Count - 1; i >= 0; i--) { @@ -42,18 +47,17 @@ namespace Ink_Canvas { result = newResult; break; } - //Label.Visibility = Visibility.Visible; - //Label.Content = circles.Count.ToString() + "\n" + newResult.InkDrawingNode.GetShapeName(); } if (result.InkDrawingNode.GetShapeName() == "Circle" && Settings.InkToShape.IsInkToShapeRounded == true) { - var shape = result.InkDrawingNode.GetShape(); - if (shape.Width > 75) { + var shapeWidth = Dispatcher.Invoke(()=>result.InkDrawingNode.GetShape().Width); + var shapeHeight = Dispatcher.Invoke(()=>result.InkDrawingNode.GetShape().Height); + if (shapeWidth > 75) { foreach (var circle in circles) //判断是否画同心圆 - if (Math.Abs(result.Centroid.X - circle.Centroid.X) / shape.Width < 0.12 && - Math.Abs(result.Centroid.Y - circle.Centroid.Y) / shape.Width < 0.12) { + if (Math.Abs(result.Centroid.X - circle.Centroid.X) / shapeWidth < 0.12 && + Math.Abs(result.Centroid.Y - circle.Centroid.Y) / shapeWidth < 0.12) { result.Centroid = circle.Centroid; break; } @@ -64,8 +68,8 @@ namespace Ink_Canvas { (result.Centroid.Y - circle.Centroid.Y); d = Math.Sqrt(d); //判断是否画外切圆 - var x = shape.Width / 2.0 + circle.R - d; - if (Math.Abs(x) / shape.Width < 0.1) { + var x = shapeWidth / 2.0 + circle.R - d; + if (Math.Abs(x) / shapeWidth < 0.1) { var sinTheta = (result.Centroid.Y - circle.Centroid.Y) / d; var cosTheta = (result.Centroid.X - circle.Centroid.X) / d; var newX = result.Centroid.X + x * cosTheta; @@ -74,8 +78,8 @@ namespace Ink_Canvas { } //判断是否画外切圆 - x = Math.Abs(circle.R - shape.Width / 2.0) - d; - if (Math.Abs(x) / shape.Width < 0.1) { + x = Math.Abs(circle.R - shapeWidth / 2.0) - d; + if (Math.Abs(x) / shapeWidth < 0.1) { var sinTheta = (result.Centroid.Y - circle.Centroid.Y) / d; var cosTheta = (result.Centroid.X - circle.Centroid.X) / d; var newX = result.Centroid.X + x * cosTheta; @@ -84,31 +88,37 @@ namespace Ink_Canvas { } } - var iniP = new Point(result.Centroid.X - shape.Width / 2, - result.Centroid.Y - shape.Height / 2); - var endP = new Point(result.Centroid.X + shape.Width / 2, - result.Centroid.Y + shape.Height / 2); + var iniP = new Point(result.Centroid.X - shapeWidth / 2, + result.Centroid.Y - shapeHeight / 2); + var endP = new Point(result.Centroid.X + shapeWidth / 2, + result.Centroid.Y + shapeHeight / 2); var pointList = GenerateEllipseGeometry(iniP, endP); var point = new StylusPointCollection(pointList); var stroke = new Stroke(point) { - DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone() + DrawingAttributes = Dispatcher.Invoke(()=>inkCanvas.DefaultDrawingAttributes.Clone()) }; - circles.Add(new Circle(result.Centroid, shape.Width / 2.0, stroke)); - SetNewBackupOfStroke(); - _currentCommitType = CommitReason.ShapeRecognition; - inkCanvas.Strokes.Remove(result.InkDrawingNode.Strokes); - inkCanvas.Strokes.Add(stroke); + circles.Add(new Circle(result.Centroid, shapeWidth / 2.0, stroke)); + Dispatcher.InvokeAsync(() => { + SetNewBackupOfStroke(); + _currentCommitType = CommitReason.ShapeRecognition; + inkCanvas.Strokes.Remove(result.InkDrawingNode.Strokes); + inkCanvas.Strokes.Add(stroke); + }); _currentCommitType = CommitReason.UserInput; newStrokes = new StrokeCollection(); } } else if (result.InkDrawingNode.GetShapeName().Contains("Ellipse") && Settings.InkToShape.IsInkToShapeRounded == true) { - var shape = result.InkDrawingNode.GetShape(); - //var shape1 = result.InkDrawingNode.GetShape(); - //shape1.Fill = Brushes.Gray; - //Canvas.Children.Add(shape1); - var p = result.InkDrawingNode.HotPoints; + var shapeWidth = Dispatcher.Invoke(()=>result.InkDrawingNode.GetShape().Width); + var shapeHeight = Dispatcher.Invoke(()=>result.InkDrawingNode.GetShape().Height); + PointCollection p = new PointCollection(); + Point[] _p = new Point[]{}; + Dispatcher.Invoke(() => { + var arr = result.InkDrawingNode.HotPoints.ToArray(); + _p = arr; + }); + p = new PointCollection(_p); var a = GetDistance(p[0], p[2]) / 2; //长半轴 var b = GetDistance(p[1], p[3]) / 2; //短半轴 if (a < b) { @@ -120,25 +130,25 @@ namespace Ink_Canvas { result.Centroid = new Point((p[0].X + p[2].X) / 2, (p[0].Y + p[2].Y) / 2); var needRotation = true; - if (shape.Width > 75 || (shape.Height > 75 && p.Count == 4)) { - var iniP = new Point(result.Centroid.X - shape.Width / 2, - result.Centroid.Y - shape.Height / 2); - var endP = new Point(result.Centroid.X + shape.Width / 2, - result.Centroid.Y + shape.Height / 2); + if (shapeWidth > 75 || (shapeHeight > 75 && p.Count == 4)) { + var iniP = new Point(result.Centroid.X - shapeWidth / 2, + result.Centroid.Y - shapeHeight / 2); + var endP = new Point(result.Centroid.X + shapeWidth / 2, + result.Centroid.Y + shapeHeight / 2); foreach (var circle in circles) //判断是否画同心椭圆 if (Math.Abs(result.Centroid.X - circle.Centroid.X) / a < 0.2 && Math.Abs(result.Centroid.Y - circle.Centroid.Y) / a < 0.2) { result.Centroid = circle.Centroid; - iniP = new Point(result.Centroid.X - shape.Width / 2, - result.Centroid.Y - shape.Height / 2); - endP = new Point(result.Centroid.X + shape.Width / 2, - result.Centroid.Y + shape.Height / 2); + iniP = new Point(result.Centroid.X - shapeWidth / 2, + result.Centroid.Y - shapeHeight / 2); + endP = new Point(result.Centroid.X + shapeWidth / 2, + result.Centroid.Y + shapeHeight / 2); //再判断是否与圆相切 if (Math.Abs(a - circle.R) / a < 0.2) { - if (shape.Width >= shape.Height) { + if (shapeWidth >= shapeHeight) { iniP.X = result.Centroid.X - circle.R; endP.X = result.Centroid.X + circle.R; iniP.Y = result.Centroid.Y - b; @@ -170,22 +180,27 @@ namespace Ink_Canvas { SetNewBackupOfStroke(); _currentCommitType = CommitReason.ShapeRecognition; - inkCanvas.Strokes.Remove(result.InkDrawingNode.Strokes); + Dispatcher.InvokeAsync(() => { + inkCanvas.Strokes.Remove(result.InkDrawingNode.Strokes); + }); newStrokes = new StrokeCollection(); var _pointList = GenerateEllipseGeometry(iniP, endP, false, true); var _point = new StylusPointCollection(_pointList); var _stroke = new Stroke(_point) { - DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone() + DrawingAttributes = Dispatcher.Invoke(()=>inkCanvas.DefaultDrawingAttributes.Clone()) }; - var _dashedLineStroke = - GenerateDashedLineEllipseStrokeCollection(iniP, endP, true, false); - var strokes = new StrokeCollection() { - _stroke, - _dashedLineStroke - }; - inkCanvas.Strokes.Add(strokes); - _currentCommitType = CommitReason.UserInput; + Dispatcher.InvokeAsync(() => { + var _dashedLineStroke = + GenerateDashedLineEllipseStrokeCollection(iniP, endP, true, + false); + var strokes = new StrokeCollection() { + _stroke, + _dashedLineStroke + }; + inkCanvas.Strokes.Add(strokes); + _currentCommitType = CommitReason.UserInput; + }); return; } } @@ -215,7 +230,7 @@ namespace Ink_Canvas { var pointList = GenerateEllipseGeometry(iniP, endP); var point = new StylusPointCollection(pointList); var stroke = new Stroke(point) { - DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone() + DrawingAttributes = Dispatcher.Invoke(()=>inkCanvas.DefaultDrawingAttributes.Clone()) }; if (needRotation) { @@ -227,19 +242,26 @@ namespace Ink_Canvas { stroke.Transform(m, false); } - SetNewBackupOfStroke(); - _currentCommitType = CommitReason.ShapeRecognition; - inkCanvas.Strokes.Remove(result.InkDrawingNode.Strokes); - inkCanvas.Strokes.Add(stroke); - _currentCommitType = CommitReason.UserInput; - GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed; - newStrokes = new StrokeCollection(); + Dispatcher.InvokeAsync(() => { + SetNewBackupOfStroke(); + _currentCommitType = CommitReason.ShapeRecognition; + inkCanvas.Strokes.Remove(result.InkDrawingNode.Strokes); + inkCanvas.Strokes.Add(stroke); + _currentCommitType = CommitReason.UserInput; + GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed; + newStrokes = new StrokeCollection(); + }); } } else if (result.InkDrawingNode.GetShapeName().Contains("Triangle") && Settings.InkToShape.IsInkToShapeTriangle == true) { - var shape = result.InkDrawingNode.GetShape(); - var p = result.InkDrawingNode.HotPoints; + PointCollection p = new PointCollection(); + Point[] _p = new Point[]{}; + Dispatcher.Invoke(() => { + var arr = result.InkDrawingNode.HotPoints.ToArray(); + _p = arr; + }); + p = new PointCollection(_p); if ((Math.Max(Math.Max(p[0].X, p[1].X), p[2].X) - Math.Min(Math.Min(p[0].X, p[1].X), p[2].X) >= 100 || Math.Max(Math.Max(p[0].Y, p[1].Y), p[2].Y) - @@ -260,15 +282,18 @@ namespace Ink_Canvas { //pointList.Add(p[0]); var point = new StylusPointCollection(pointList); var stroke = new Stroke(GenerateFakePressureTriangle(point)) { - DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone() + DrawingAttributes = Dispatcher.Invoke(()=>inkCanvas.DefaultDrawingAttributes.Clone()) }; - SetNewBackupOfStroke(); - _currentCommitType = CommitReason.ShapeRecognition; - inkCanvas.Strokes.Remove(result.InkDrawingNode.Strokes); - inkCanvas.Strokes.Add(stroke); - _currentCommitType = CommitReason.UserInput; - GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed; - newStrokes = new StrokeCollection(); + + Dispatcher.InvokeAsync(() => { + SetNewBackupOfStroke(); + _currentCommitType = CommitReason.ShapeRecognition; + inkCanvas.Strokes.Remove(result.InkDrawingNode.Strokes); + inkCanvas.Strokes.Add(stroke); + _currentCommitType = CommitReason.UserInput; + GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed; + newStrokes = new StrokeCollection(); + }); } } else if ((result.InkDrawingNode.GetShapeName().Contains("Rectangle") || @@ -277,8 +302,13 @@ namespace Ink_Canvas { result.InkDrawingNode.GetShapeName().Contains("Square") || result.InkDrawingNode.GetShapeName().Contains("Trapezoid")) && Settings.InkToShape.IsInkToShapeRectangle == true) { - var shape = result.InkDrawingNode.GetShape(); - var p = result.InkDrawingNode.HotPoints; + PointCollection p = new PointCollection(); + Point[] _p = new Point[]{}; + Dispatcher.Invoke(() => { + var arr = result.InkDrawingNode.HotPoints.ToArray(); + _p = arr; + }); + p = new PointCollection(_p); if ((Math.Max(Math.Max(Math.Max(p[0].X, p[1].X), p[2].X), p[3].X) - Math.Min(Math.Min(Math.Min(p[0].X, p[1].X), p[2].X), p[3].X) >= 100 || Math.Max(Math.Max(Math.Max(p[0].Y, p[1].Y), p[2].Y), p[3].Y) - @@ -302,22 +332,27 @@ namespace Ink_Canvas { pointList.Add(p[0]); var point = new StylusPointCollection(pointList); var stroke = new Stroke(GenerateFakePressureRectangle(point)) { - DrawingAttributes = inkCanvas.DefaultDrawingAttributes.Clone() + DrawingAttributes = Dispatcher.Invoke(()=>inkCanvas.DefaultDrawingAttributes.Clone()) }; - SetNewBackupOfStroke(); - _currentCommitType = CommitReason.ShapeRecognition; - inkCanvas.Strokes.Remove(result.InkDrawingNode.Strokes); - inkCanvas.Strokes.Add(stroke); - _currentCommitType = CommitReason.UserInput; - GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed; - newStrokes = new StrokeCollection(); + + Dispatcher.InvokeAsync(() => { + SetNewBackupOfStroke(); + _currentCommitType = CommitReason.ShapeRecognition; + inkCanvas.Strokes.Remove(result.InkDrawingNode.Strokes); + inkCanvas.Strokes.Add(stroke); + _currentCommitType = CommitReason.UserInput; + GridInkCanvasSelectionCover.Visibility = Visibility.Collapsed; + newStrokes = new StrokeCollection(); + }); + } } } catch { } } - InkToShapeProcess(); + var _t = new Thread(InkToShapeProcess); + _t.Start(); } foreach (var stylusPoint in e.Stroke.StylusPoints) diff --git a/InkCanvasForClass/MainWindow_cs/MW_Timer.cs b/InkCanvasForClass/MainWindow_cs/MW_Timer.cs index 86e7c23..6b6c46d 100644 --- a/InkCanvasForClass/MainWindow_cs/MW_Timer.cs +++ b/InkCanvasForClass/MainWindow_cs/MW_Timer.cs @@ -141,25 +141,25 @@ namespace Ink_Canvas { if (arg.Contains("EasiNote")) { Dispatcher.Invoke(() => { - ShowNotification("“希沃白板 5”已自动关闭"); + ShowNewToast("“希沃白板 5”已自动关闭", MW_Toast.ToastType.Warning, 3000); }); } if (arg.Contains("HiteAnnotation")) { Dispatcher.Invoke(() => { - ShowNotification("“鸿合屏幕书写”已自动关闭"); + ShowNewToast("“鸿合屏幕书写”已自动关闭", MW_Toast.ToastType.Warning, 3000); }); } if (arg.Contains("Ink Canvas Annotation") || arg.Contains("Ink Canvas Artistry")) { Dispatcher.Invoke(() => { - ShowNotification("“ICA”已自动关闭"); + ShowNewToast("“ICA”已自动关闭", MW_Toast.ToastType.Warning, 3000); }); } if (arg.Contains("\"Ink Canvas.exe\"")) { Dispatcher.Invoke(() => { - ShowNotification("“Ink Canvas”已自动关闭"); + ShowNewToast("“Ink Canvas”已自动关闭", MW_Toast.ToastType.Warning, 3000); }); } @@ -172,7 +172,7 @@ namespace Ink_Canvas { if (arg.Contains("VcomTeach")) { Dispatcher.Invoke(() => { - ShowNotification("“优教授课端”已自动关闭"); + ShowNewToast("“优教授课端”已自动关闭", MW_Toast.ToastType.Warning, 3000); }); } diff --git a/InkCanvasForClass/Popups/ColorPalette.xaml b/InkCanvasForClass/Popups/ColorPalette.xaml index 8d8f3f3..8ad87dd 100644 --- a/InkCanvasForClass/Popups/ColorPalette.xaml +++ b/InkCanvasForClass/Popups/ColorPalette.xaml @@ -487,10 +487,10 @@ - - - - + + + + @@ -631,14 +631,13 @@ - + - - - + + - + diff --git a/InkCanvasForClass/Popups/ColorPalette.xaml.cs b/InkCanvasForClass/Popups/ColorPalette.xaml.cs index 3cdd7ad..07d00cf 100644 --- a/InkCanvasForClass/Popups/ColorPalette.xaml.cs +++ b/InkCanvasForClass/Popups/ColorPalette.xaml.cs @@ -94,21 +94,6 @@ namespace Ink_Canvas.Popups { public GeometryDrawing[] PenModeTabButtonIcons; public TextBlock[] PenModeTabButtonTexts; - private void SCManipulationBoundaryFeedback(object sender, ManipulationBoundaryFeedbackEventArgs e) { - e.Handled = true; - } - - private void QuickActionsScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e) - { - ScrollViewer scrollViewer = (ScrollViewer)sender; - if (e.Delta < 0) { - scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset + 24); - } else { - scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset - 24); - } - e.Handled = true; - } - #region 暗色亮色成員 /// @@ -663,7 +648,7 @@ namespace Ink_Canvas.Popups { #region 筆觸模式 相關邏輯 - public void UpdatePenModeButtonsCheckedDisplayStatus() { + private void UpdatePenModeButtonsCheckedDisplayStatus() { foreach (var bd in PenModeTabButtonBorders) { bd.Background = new SolidColorBrush(Colors.Transparent); } @@ -685,11 +670,41 @@ namespace Ink_Canvas.Popups { PenModeTabButtonTexts[(int)_penModeSelected].FontWeight = FontWeights.Bold; } + /// + /// 根據傳入的觸筆模式修改Quick Action 子項目的可見性。 + /// + /// + private void UpdateQuickActionItemsVisibilityByPenMode(PenMode penMode) { + _isDisplayQuickActions = true; + if (penMode == PenMode.PenMode) { + _isDisplayInkRecognitionQuickAction = true; + _isDisplayInkPressureQuickAction = true; + _isDisplayCircleTipShapeQuickAction = false; + _isDisplayFingerModeQuickAction = true; + } else if (penMode == PenMode.HighlighterMode) { + _isDisplayInkRecognitionQuickAction = true; + _isDisplayInkPressureQuickAction = false; + _isDisplayCircleTipShapeQuickAction = true; + _isDisplayFingerModeQuickAction = true; + } else if (penMode == PenMode.LaserPenMode) { + _isDisplayQuickActions = false; + } + UpdateQuickActionVisibility(_isDisplayQuickActions); + UpdateQuickActionItemsVisibility(new QuickActionItemsVisibility() { + InkRecognition = _isDisplayInkRecognitionQuickAction, + InkPressure = _isDisplayInkPressureQuickAction, + CircleTipShape = _isDisplayCircleTipShapeQuickAction, + FingerMode = _isDisplayFingerModeQuickAction + }); + } + private void PenTabButton_MouseDown(object sender, MouseButtonEventArgs e) { var pre = _penModeSelected; _penModeSelected = (PenMode)Array.IndexOf(PenModeTabButtonBorders, (Border)sender); + QuickActionItemsScrollToLeft(); UpdatePenModeButtonsCheckedDisplayStatus(); ChangedColorButtonsTransparentVisibility(_penModeSelected == PenMode.HighlighterMode); + UpdateQuickActionItemsVisibilityByPenMode(_penModeSelected); PenModeChanged?.Invoke(this, new PenModeChangedEventArgs() { @@ -701,6 +716,231 @@ namespace Ink_Canvas.Popups { #endregion + #region Quick Action 滾動邏輯 + + private void SCManipulationBoundaryFeedback(object sender, ManipulationBoundaryFeedbackEventArgs e) { + e.Handled = true; + } + + public static class ScrollViewerBehavior + { + public static readonly DependencyProperty HorizontalOffsetProperty = DependencyProperty.RegisterAttached("HorizontalOffset", typeof(double), typeof(ScrollViewerBehavior), new UIPropertyMetadata(0.0, OnHorizontalOffsetChanged)); + public static void SetHorizontalOffset(FrameworkElement target, double value) => target.SetValue(HorizontalOffsetProperty, value); + public static double GetHorizontalOffset(FrameworkElement target) => (double)target.GetValue(HorizontalOffsetProperty); + private static void OnHorizontalOffsetChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) => (target as ScrollViewer)?.ScrollToHorizontalOffset((double)e.NewValue); + + public static readonly DependencyProperty VerticalOffsetProperty = DependencyProperty.RegisterAttached("VerticalOffset", typeof(double), typeof(ScrollViewerBehavior), new UIPropertyMetadata(0.0, OnVerticalOffsetChanged)); + public static void SetVerticalOffset(FrameworkElement target, double value) => target.SetValue(VerticalOffsetProperty, value); + public static double GetVerticalOffset(FrameworkElement target) => (double)target.GetValue(VerticalOffsetProperty); + private static void OnVerticalOffsetChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) => (target as ScrollViewer)?.ScrollToVerticalOffset((double)e.NewValue); + } + + private void UpdateQuickActionsDotsIndicatorDisplayStatus(int highlightedDotIndex) { + if (highlightedDotIndex == 1) { + QuickActionDot1.Background = new SolidColorBrush(Color.FromRgb(39, 39, 42)); + QuickActionDot2.Background = new SolidColorBrush(Color.FromRgb(212, 212, 216)); + } else { + QuickActionDot2.Background = new SolidColorBrush(Color.FromRgb(39, 39, 42)); + QuickActionDot1.Background = new SolidColorBrush(Color.FromRgb(212, 212, 216)); + } + } + + private void QuickActionsScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e) { + UpdateQuickActionsDotsIndicatorDisplayStatus(((ScrollViewer)sender).HorizontalOffset >= 110 ? 2 : 1); + } + + private void QuickActionsScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e) + { + ScrollViewer scrollViewer = (ScrollViewer)sender; + if (e.Delta < 0) { + //scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset + 270); + var sb = new Storyboard(); + var ofs = scrollViewer.HorizontalOffset; + var animation = new DoubleAnimation + { + From = ofs, + To = 120, + Duration = TimeSpan.FromMilliseconds(200) + }; + animation.EasingFunction = new CubicEase() { + EasingMode = EasingMode.EaseOut, + }; + Storyboard.SetTargetProperty(animation, new PropertyPath(ScrollViewerBehavior.HorizontalOffsetProperty)); + Storyboard.SetTargetName(animation,"QuickActionScrollViewer"); + sb.Children.Add(animation); + scrollViewer.ScrollToHorizontalOffset(ofs); + sb.Begin(scrollViewer); + } else { + //scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset - 270); + var sb = new Storyboard(); + var ofs = scrollViewer.HorizontalOffset; + var animation = new DoubleAnimation + { + From = ofs, + To = 0, + Duration = TimeSpan.FromMilliseconds(200) + }; + animation.EasingFunction = new CubicEase(){ + EasingMode = EasingMode.EaseOut, + }; + Storyboard.SetTargetProperty(animation, new PropertyPath(ScrollViewerBehavior.HorizontalOffsetProperty)); + Storyboard.SetTargetName(animation,"QuickActionScrollViewer"); + sb.Children.Add(animation); + scrollViewer.ScrollToHorizontalOffset(ofs); + sb.Begin(scrollViewer); + } + e.Handled = true; + } + + private void QuickActionItemsScrollToLeft() { + var sb = new Storyboard(); + var ofs = QuickActionScrollViewer.HorizontalOffset; + var animation = new DoubleAnimation + { + From = ofs, + To = 0, + Duration = TimeSpan.FromMilliseconds(200) + }; + animation.EasingFunction = new CubicEase(){ + EasingMode = EasingMode.EaseOut, + }; + Storyboard.SetTargetProperty(animation, new PropertyPath(ScrollViewerBehavior.HorizontalOffsetProperty)); + Storyboard.SetTargetName(animation,"QuickActionScrollViewer"); + sb.Children.Add(animation); + QuickActionScrollViewer.ScrollToHorizontalOffset(ofs); + sb.Begin(QuickActionScrollViewer); + } + + #endregion + + #region Quick Action 可見性管理 成員 + + private bool _isDisplayQuickActions = true; + public bool IsDisplayQuickActions + { + get => _isDisplayQuickActions; + set + { + var pre = _isDisplayQuickActions; + _isDisplayQuickActions = value; + UpdateQuickActionVisibility(value); + UpdateQuickActionItemsVisibility(new QuickActionItemsVisibility() { + InkRecognition = _isDisplayInkRecognitionQuickAction, + InkPressure = _isDisplayInkPressureQuickAction, + CircleTipShape = _isDisplayCircleTipShapeQuickAction, + FingerMode = _isDisplayFingerModeQuickAction + }); + + QuickActionsVisibilityChanged?.Invoke(this, new QuickActionsVisibilityChangedEventsArgs() + { + PreviousStatus = pre, + NowStatus = value, + TriggerMode = TriggerMode.TriggeredByCode, + }); + } + } + + public struct QuickActionItemsVisibility { + public bool InkRecognition; + public bool InkPressure; + public bool CircleTipShape; + public bool FingerMode; + } + + public class QuickActionsVisibilityChangedEventsArgs : EventArgs { + public bool PreviousStatus { get; set; } + public bool NowStatus { get; set; } + public TriggerMode TriggerMode { get; set; } + public bool IsItemsVisibilityChanged { get; set; } = false; + public QuickActionItemsVisibility ItemsVisibility { get; set; } + } + + private void InvokeQuickActionItemsVisibilityEvent() { + UpdateQuickActionItemsVisibility(new QuickActionItemsVisibility() { + InkRecognition = _isDisplayInkRecognitionQuickAction, + InkPressure = _isDisplayInkPressureQuickAction, + CircleTipShape = _isDisplayCircleTipShapeQuickAction, + FingerMode = _isDisplayFingerModeQuickAction + }); + QuickActionsVisibilityChanged?.Invoke(this, new QuickActionsVisibilityChangedEventsArgs() + { + PreviousStatus = _isDisplayQuickActions, + NowStatus = _isDisplayQuickActions, + TriggerMode = TriggerMode.TriggeredByCode, + IsItemsVisibilityChanged = true, + ItemsVisibility = new QuickActionItemsVisibility() { + InkRecognition = _isDisplayInkRecognitionQuickAction, + InkPressure = _isDisplayInkPressureQuickAction, + CircleTipShape = _isDisplayCircleTipShapeQuickAction, + FingerMode = _isDisplayFingerModeQuickAction + } + }); + } + + private bool _isDisplayInkRecognitionQuickAction = true; + + public bool IsDisplayInkRecognitionQuickAction { + get => _isDisplayInkRecognitionQuickAction; + set { + _isDisplayInkRecognitionQuickAction = value; + InvokeQuickActionItemsVisibilityEvent(); + } + } + + private bool _isDisplayInkPressureQuickAction = true; + + public bool IsDisplayInkPressureQuickAction { + get => _isDisplayInkPressureQuickAction; + set { + _isDisplayInkPressureQuickAction = value; + InvokeQuickActionItemsVisibilityEvent(); + } + } + + private bool _isDisplayCircleTipShapeQuickAction = true; + + public bool IsDisplayCircleTipShapeQuickAction { + get => _isDisplayCircleTipShapeQuickAction; + set { + _isDisplayCircleTipShapeQuickAction = value; + InvokeQuickActionItemsVisibilityEvent(); + } + } + + private bool _isDisplayFingerModeQuickAction = true; + + public bool IsDisplayFingerModeQuickAction { + get => _isDisplayFingerModeQuickAction; + set { + _isDisplayFingerModeQuickAction = value; + InvokeQuickActionItemsVisibilityEvent(); + } + } + + #endregion + + #region Quick Action 可見性管理 相關邏輯 + + private void UpdateQuickActionItemsVisibility(QuickActionItemsVisibility visibility) { + QuickActionItems.Children[0].Visibility = visibility.InkRecognition ? Visibility.Visible : Visibility.Collapsed; + QuickActionItems.Children[1].Visibility = visibility.InkPressure ? Visibility.Visible : Visibility.Collapsed; + QuickActionItems.Children[2].Visibility = visibility.CircleTipShape ? Visibility.Visible : Visibility.Collapsed; + QuickActionItems.Children[3].Visibility = visibility.FingerMode ? Visibility.Visible : Visibility.Collapsed; + } + + private void UpdateQuickActionVisibility(bool isVisible) { + foreach (var fe in new FrameworkElement[] { + _QuickAction_Grid, + _QuickAction_Dots, + _QuickAction_Line1, + _QuickAction_Line2 + }) { + fe.Visibility = isVisible ? Visibility.Visible : Visibility.Collapsed; + } + } + + #endregion + public enum TriggerMode { TriggeredByUser, TriggeredByCode @@ -819,32 +1059,6 @@ namespace Ink_Canvas.Popups { CustomColorPanel.Visibility = Visibility.Collapsed; } - private bool _isDisplayQuickActions = true; - public bool IsDisplayQuickActions - { - get => _isDisplayQuickActions; - set - { - var pre = _isDisplayQuickActions; - _isDisplayQuickActions = value; - QuickActionsVisibilityChanged?.Invoke(this, new QuickActionsVisibilityChangedEventsArgs() - { - PreviousStatus = pre, - NowStatus = value, - TriggerMode = TriggerMode.TriggeredByCode, - }); - } - } - - - - - public class QuickActionsVisibilityChangedEventsArgs : EventArgs { - public bool PreviousStatus { get; set; } - public bool NowStatus { get; set; } - public TriggerMode TriggerMode { get; set; } - } - public event EventHandler ColorSelectionChanged; public event EventHandler CustomColorChanged; public event EventHandler PenModeChanged; @@ -880,6 +1094,8 @@ namespace Ink_Canvas.Popups { UpdateColorButtonsCheckedDisplayStatus(); UpdateColorPaletteColorsAndColorModeChangeButton(); ChangedColorButtonsTransparentVisibility(false); + UpdateQuickActionsDotsIndicatorDisplayStatus(1); + UpdateQuickActionItemsVisibilityByPenMode(PenMode.PenMode); } } } \ No newline at end of file