Merge branch 'net6' of https://github.com/InkCanvasForClass/community into net6
This commit is contained in:
@@ -722,64 +722,60 @@ namespace Ink_Canvas.Helpers
|
||||
|
||||
var m = new Matrix(scale, 0, 0, scale, tx, ty);
|
||||
geom.Transform = new MatrixTransform(m);
|
||||
return StrokesFromOutlinedGeometry(geom, templateDa, 0.35);
|
||||
|
||||
var filled = FilledGlyphStroke.TryCreate(geom, templateDa);
|
||||
if (filled == null)
|
||||
return list;
|
||||
|
||||
list.Add(filled);
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 把字形几何作为「实心填充」绘制的笔画。仍是 WPF <see cref="Stroke"/>,可被 InkCanvas 选择/移动/删除,
|
||||
/// 但渲染时直接 DrawGeometry(brush, null, geom),不再走 StylusPoints 描边路径。
|
||||
/// </summary>
|
||||
internal sealed class FilledGlyphStroke : Stroke
|
||||
{
|
||||
private readonly Geometry _geometry;
|
||||
|
||||
private FilledGlyphStroke(StylusPointCollection pts, Geometry geometry, DrawingAttributes da)
|
||||
: base(pts)
|
||||
{
|
||||
_geometry = geometry;
|
||||
if (da != null)
|
||||
DrawingAttributes = da.Clone();
|
||||
}
|
||||
|
||||
private static List<Stroke> StrokesFromOutlinedGeometry(Geometry geometry, DrawingAttributes da, double tolerance)
|
||||
public static FilledGlyphStroke TryCreate(Geometry geometry, DrawingAttributes templateDa)
|
||||
{
|
||||
var list = new List<Stroke>();
|
||||
if (geometry == null || geometry.IsEmpty() || da == null)
|
||||
return list;
|
||||
if (geometry == null || geometry.IsEmpty())
|
||||
return null;
|
||||
|
||||
Geometry outlined;
|
||||
try
|
||||
var b = geometry.Bounds;
|
||||
if (b.IsEmpty || b.Width < 0.5 || b.Height < 0.5)
|
||||
return null;
|
||||
|
||||
// StylusPoints 用 bounds 四角,保证命中测试 / 选区 / 包围盒计算正常。
|
||||
var pts = new StylusPointCollection
|
||||
{
|
||||
outlined = geometry.GetOutlinedPathGeometry(tolerance, ToleranceType.Absolute);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return list;
|
||||
}
|
||||
new StylusPoint(b.Left, b.Top, 0.5f),
|
||||
new StylusPoint(b.Right, b.Top, 0.5f),
|
||||
new StylusPoint(b.Right, b.Bottom, 0.5f),
|
||||
new StylusPoint(b.Left, b.Bottom, 0.5f),
|
||||
};
|
||||
|
||||
if (outlined == null || outlined.IsEmpty())
|
||||
return list;
|
||||
return new FilledGlyphStroke(pts, geometry, templateDa);
|
||||
}
|
||||
|
||||
Geometry flat;
|
||||
try
|
||||
{
|
||||
flat = outlined.GetFlattenedPathGeometry(tolerance, ToleranceType.Absolute);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return list;
|
||||
}
|
||||
protected override void DrawCore(DrawingContext drawingContext, DrawingAttributes drawingAttributes)
|
||||
{
|
||||
if (drawingContext == null || _geometry == null)
|
||||
return;
|
||||
|
||||
if (!(flat is PathGeometry pg))
|
||||
return list;
|
||||
|
||||
foreach (var fig in pg.Figures)
|
||||
{
|
||||
var pts = new StylusPointCollection();
|
||||
pts.Add(new StylusPoint(fig.StartPoint.X, fig.StartPoint.Y, 0.5f));
|
||||
foreach (var seg in fig.Segments)
|
||||
{
|
||||
switch (seg)
|
||||
{
|
||||
case LineSegment ls:
|
||||
pts.Add(new StylusPoint(ls.Point.X, ls.Point.Y, 0.5f));
|
||||
break;
|
||||
case PolyLineSegment pls:
|
||||
foreach (var p in pls.Points)
|
||||
pts.Add(new StylusPoint(p.X, p.Y, 0.5f));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pts.Count >= 2)
|
||||
list.Add(new Stroke(pts) { DrawingAttributes = da.Clone() });
|
||||
}
|
||||
|
||||
return list;
|
||||
var color = drawingAttributes != null ? drawingAttributes.Color : Colors.Black;
|
||||
drawingContext.DrawGeometry(new SolidColorBrush(color), null, _geometry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3418,7 +3418,11 @@
|
||||
<controls:QuickPanelButton IconSource="{DynamicResource QuickPanelBlackboardIcon}" Label="{i18n:I18n Key=QuickPanel_Whiteboard}" ButtonMouseUp="ImageBlackboard_MouseUp" />
|
||||
<controls:QuickPanelButton x:Name="BtnExitPptFromSidebarRight" IconSource="{DynamicResource QuickPanelEndSlideshowIcon}" Label="{i18n:I18n Key=QuickPanel_ExitShow}" LabelFontSize="7" Visibility="Collapsed" ButtonMouseUp="ExitPPTSlideShow_MouseUp" />
|
||||
<controls:QuickPanelButton IconSource="{DynamicResource QuickPanelEyeIcon}" Label="{i18n:I18n Key=QuickPanel_Show}" ButtonMouseUp="UnFoldFloatingBar_MouseUp" />
|
||||
<controls:QuickPanelButton IconSource="{DynamicResource QuickPanelChevronLeftIcon}" ButtonMouseUp="HideQuickPanel_MouseUp" />
|
||||
<controls:QuickPanelButton IconSource="{DynamicResource QuickPanelChevronLeftIcon}" ButtonMouseUp="HideQuickPanel_MouseUp" RenderTransformOrigin="0.5,0.5">
|
||||
<controls:QuickPanelButton.RenderTransform>
|
||||
<RotateTransform Angle="180" />
|
||||
</controls:QuickPanelButton.RenderTransform>
|
||||
</controls:QuickPanelButton>
|
||||
</ikw:SimpleStackPanel>
|
||||
</Border>
|
||||
</Viewbox>
|
||||
|
||||
@@ -2269,9 +2269,15 @@ namespace Ink_Canvas
|
||||
|
||||
if (Settings.PowerPointSettings.EnablePPTButtonEnhancedPreview && bar != null)
|
||||
{
|
||||
if (bar.IsPreviewExpanded)
|
||||
// 侧边条点击时,把增强预览重定向到同侧的底部条上展开
|
||||
var targetBar = ResolvePreviewTargetBar(bar);
|
||||
if (targetBar == null)
|
||||
{
|
||||
bar.IsPreviewExpanded = false;
|
||||
_pptManager.TryShowSlideNavigation();
|
||||
}
|
||||
else if (targetBar.IsPreviewExpanded)
|
||||
{
|
||||
targetBar.IsPreviewExpanded = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2292,9 +2298,9 @@ namespace Ink_Canvas
|
||||
Thumbnail = s.Thumbnail
|
||||
});
|
||||
}
|
||||
bar.PreviewItems = items;
|
||||
bar.CurrentSlide = _pptManager?.GetCurrentSlideNumber() ?? 0;
|
||||
bar.IsPreviewExpanded = true;
|
||||
targetBar.PreviewItems = items;
|
||||
targetBar.CurrentSlide = _pptManager?.GetCurrentSlideNumber() ?? 0;
|
||||
targetBar.IsPreviewExpanded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2332,6 +2338,35 @@ namespace Ink_Canvas
|
||||
finally { if (bar != null) bar.IsPreviewExpanded = false; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 选择承载增强预览的底部条:
|
||||
/// - 来自侧边条的点击重定向到同侧底部条;
|
||||
/// - 若同侧底部条不可用,退化到任意可用的底部条;
|
||||
/// - 来自底部条的点击保持原行为。
|
||||
/// </summary>
|
||||
private Controls.PptNavBar ResolvePreviewTargetBar(Controls.PptNavBar source)
|
||||
{
|
||||
if (source == null) return null;
|
||||
switch (source.Direction)
|
||||
{
|
||||
case Controls.PptNavBar.NavDirection.LeftSide:
|
||||
return PickVisibleBar(LeftBottomPanelForPPTNavigation, RightBottomPanelForPPTNavigation) ?? source;
|
||||
case Controls.PptNavBar.NavDirection.RightSide:
|
||||
return PickVisibleBar(RightBottomPanelForPPTNavigation, LeftBottomPanelForPPTNavigation) ?? source;
|
||||
default:
|
||||
return source;
|
||||
}
|
||||
}
|
||||
|
||||
private static Controls.PptNavBar PickVisibleBar(params Controls.PptNavBar[] candidates)
|
||||
{
|
||||
foreach (var c in candidates)
|
||||
{
|
||||
if (c != null && c.Visibility == Visibility.Visible) return c;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private sealed class PptEnhancedPreviewItem
|
||||
{
|
||||
public int SlideNumber { get; set; }
|
||||
|
||||
@@ -1864,7 +1864,7 @@
|
||||
<value>Finger mode BoundsWidth</value>
|
||||
</data>
|
||||
<data name="Advanced_EdgeGestureUtilHint_Part1" xml:space="preserve">
|
||||
<value>EdgeGestureUtil is newly introduced in ICC to temporarily block edge gestures when using touch (e.g., on Windows 10: swipe from the left edge to Task View, from the right edge to Action Center; on Windows 11: swipe up from the bottom to open Start). It works by using</value>
|
||||
<value>EdgeGestureUtil is newly introduced in ICC to temporarily block edge gestures when using touch (e.g., on Windows 10: swipe from the left edge to Task View, from the right edge to Action Center; on Windows 11: swipe up from the bottom to open Start). It works by using System.EdgeGesture.DisableTouchWhenFullscreen (When the app window is active and in full-screen mode (or an owned window is active), prevents edge gesture behavior.) If anything is abnormal, turn this option off; it should take effect immediately. (Not available on Windows 7/8.)</value>
|
||||
</data>
|
||||
<data name="Advanced_EdgeGestureUtilHint_Part2" xml:space="preserve">
|
||||
<value>(When the app window is active and in full-screen mode (or an owned window is active), prevents edge gesture behavior.) If anything is abnormal, turn this option off; it should take effect immediately. (Not available on Windows 7/8.)</value>
|
||||
|
||||
@@ -1907,7 +1907,7 @@
|
||||
<value>手指模式 BoundsWidth</value>
|
||||
</data>
|
||||
<data name="Advanced_EdgeGestureUtilHint_Part1" xml:space="preserve">
|
||||
<value>EdgeGestureUtil是icc最新引入的可以暂时阻止在使用触摸时触发边缘手势(如Windows10环境下,屏幕左边缘滑动进入任务视图,右边缘滑动弹出通知中心;Windows11环境下,底部向上滑动打开开始菜单),其原理是使用了</value>
|
||||
<value>EdgeGestureUtil是icc最新引入的可以暂时阻止在使用触摸时触发边缘手势(如Windows10环境下,屏幕左边缘滑动进入任务视图,右边缘滑动弹出通知中心;Windows11环境下,底部向上滑动打开开始菜单),其原理是使用了 System.EdgeGesture.DisableTouchWhenFullscreen (当应用程序窗口处于活动状态且处于全屏模式 (或拥有的窗口) 处于活动状态时,防止边缘手势行为。)来实现的。如果有异常,请关闭该选项,该选项应该能够实时生效。(Win7和Win8用户该选项无法使用)</value>
|
||||
</data>
|
||||
<data name="Advanced_EdgeGestureUtilHint_Part2" xml:space="preserve">
|
||||
<value>(当应用程序窗口处于活动状态且处于全屏模式 (或拥有的窗口) 处于活动状态时,防止边缘手势行为。)来实现的。如果有异常,请关闭该选项,该选项应该能够实时生效。(Win7和Win8用户该选项无法使用)</value>
|
||||
|
||||
@@ -302,7 +302,7 @@
|
||||
<TextBlock Text="{i18n:I18n Key=AutoSave_Title}" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"/>
|
||||
|
||||
<controls:LabeledSettingsCard x:Name="CardSaveScreenshotsInDateFolders"
|
||||
Header="{i18n:I18n Key=Storage_AutoSaveInkOnScreenshot}"
|
||||
Header="{i18n:I18n Key=Storage_ScreenshotsByDateFolder}"
|
||||
Icon="{x:Static ui:SegoeFluentIcons.Folder}"
|
||||
Toggled="ToggleSwitchSaveScreenshotsInDateFolders_Toggled"/>
|
||||
|
||||
|
||||
@@ -79,6 +79,7 @@ namespace Ink_Canvas.Windows.SettingsViews
|
||||
RegisterDpiChangedListener();
|
||||
LoadPluginSettingsPages();
|
||||
UpdateUpdateBadgeVisibility();
|
||||
_ = PreloadAllPagesAsync();
|
||||
};
|
||||
|
||||
this.Closed += (sender, e) =>
|
||||
@@ -694,6 +695,42 @@ namespace Ink_Canvas.Windows.SettingsViews
|
||||
return NavigationViewControl;
|
||||
}
|
||||
|
||||
private async System.Threading.Tasks.Task PreloadAllPagesAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var tags = _pageTypes.Keys.ToList();
|
||||
foreach (var tag in tags)
|
||||
{
|
||||
if (_pages.ContainsKey(tag))
|
||||
continue;
|
||||
if (!_pageTypes.TryGetValue(tag, out var type))
|
||||
continue;
|
||||
if (type == typeof(PluginSettingsPage))
|
||||
continue;
|
||||
|
||||
await Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_pages.ContainsKey(tag))
|
||||
return;
|
||||
var page = Activator.CreateInstance(type);
|
||||
_pages[tag] = page;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"预加载设置页面 {tag} 失败: {ex.Message}");
|
||||
}
|
||||
}, System.Windows.Threading.DispatcherPriority.Background);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"异步预加载设置页面时出错: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateUpdateBadgeVisibility()
|
||||
{
|
||||
try
|
||||
|
||||
Reference in New Issue
Block a user