Merge branch 'master' into master

This commit is contained in:
NaBian authored and GitHub committed 2020-07-12 00:09:38 +08:00
commit ea8c8a9795
608 files changed
+11322 -6260

No files matched your search

@@ -37,15 +37,12 @@ namespace HandyControl.Tools.Converter
{
if (source == null) throw GetConvertFromException(null);
switch (source)
return source switch
{
case string s:
return FromString(s, cultureInfo);
case double d:
return new ColLayout((int)d);
default:
return new ColLayout(Convert.ToInt32(source, cultureInfo));
}
string s => FromString(s, cultureInfo),
double d => new ColLayout((int) d),
_ => new ColLayout(Convert.ToInt32(source, cultureInfo))
};
}
[SecurityCritical]
@@ -108,53 +105,31 @@ namespace HandyControl.Tools.Converter
i++;
}
switch (i)
return i switch
{
case 1:
return new ColLayout(lengths[0]);
case 2:
return new ColLayout
{
Xs = lengths[0],
Sm = lengths[1]
};
case 3:
return new ColLayout
{
Xs = lengths[0],
Sm = lengths[1],
Md = lengths[2]
};
case 4:
return new ColLayout
{
Xs = lengths[0],
Sm = lengths[1],
Md = lengths[2],
Lg = lengths[3]
};
case 5:
return new ColLayout
{
Xs = lengths[0],
Sm = lengths[1],
Md = lengths[2],
Lg = lengths[3],
Xl = lengths[4]
};
case 6:
return new ColLayout
{
Xs = lengths[0],
Sm = lengths[1],
Md = lengths[2],
Lg = lengths[3],
Xl = lengths[4],
Xxl = lengths[5]
};
}
throw new FormatException("InvalidStringColLayout");
1 => new ColLayout(lengths[0]),
2 => new ColLayout {Xs = lengths[0], Sm = lengths[1]},
3 => new ColLayout {Xs = lengths[0], Sm = lengths[1], Md = lengths[2]},
4 => new ColLayout {Xs = lengths[0], Sm = lengths[1], Md = lengths[2], Lg = lengths[3]},
5 => new ColLayout
{
Xs = lengths[0],
Sm = lengths[1],
Md = lengths[2],
Lg = lengths[3],
Xl = lengths[4]
},
6 => new ColLayout
{
Xs = lengths[0],
Sm = lengths[1],
Md = lengths[2],
Lg = lengths[3],
Xl = lengths[4],
Xxl = lengths[5]
},
_ => throw new FormatException("InvalidStringColLayout")
};
}
}
}
@@ -0,0 +1,16 @@
using System;
using System.Globalization;
using System.Windows.Data;
namespace HandyControl.Tools.Converter
{
public class Object2StringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) => value?.ToString();
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
@@ -0,0 +1,20 @@
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace HandyControl.Tools.Converter
{
public class Object2VisibilityReConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value == null ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
@@ -10,8 +10,6 @@ namespace HandyControl.Tools.Extension
{
private readonly DependencyObject _proxy;
private bool _isInternalAction;
public LangExtension()
{
_proxy = new DependencyObject();
@@ -51,7 +49,6 @@ namespace HandyControl.Tools.Extension
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (_isInternalAction) return this;
if (!(serviceProvider.GetService(typeof(IProvideValueTarget)) is IProvideValueTarget provideValueTarget)) return this;
if (provideValueTarget.TargetObject.GetType().FullName == "System.Windows.SharedDp") return this;
if (!(provideValueTarget.TargetObject is DependencyObject targetObject)) return this;
@@ -61,14 +58,7 @@ namespace HandyControl.Tools.Extension
{
case string key:
{
var binding = new Binding(key)
{
Converter = Converter,
ConverterParameter = ConverterParameter,
UpdateSourceTrigger = UpdateSourceTrigger.Explicit,
Source = Source,
Mode = BindingMode.OneWay
};
var binding = CreateLangBinding(key);
BindingOperations.SetBinding(targetObject, targetProperty, binding);
return binding.ProvideValue(serviceProvider);
}
@@ -76,10 +66,8 @@ namespace HandyControl.Tools.Extension
{
if (element.DataContext != null)
{
_isInternalAction = true;
SetLangBinding(element, targetProperty, keyBinding.Path, element.DataContext);
_isInternalAction = false;
return element.GetValue(targetProperty);
var binding = SetLangBinding(element, targetProperty, keyBinding.Path, element.DataContext);
return binding.ProvideValue(serviceProvider);
}
SetTargetProperty(element, targetProperty);
@@ -91,10 +79,8 @@ namespace HandyControl.Tools.Extension
{
if (element.DataContext != null)
{
_isInternalAction = true;
SetLangBinding(element, targetProperty, keyBinding.Path, element.DataContext);
_isInternalAction = false;
return element.GetValue(targetProperty);
var binding = SetLangBinding(element, targetProperty, keyBinding.Path, element.DataContext);
return binding.ProvideValue(serviceProvider);
}
SetTargetProperty(element, targetProperty);
@@ -134,9 +120,9 @@ namespace HandyControl.Tools.Extension
}
}
private void SetLangBinding(DependencyObject targetObject, DependencyProperty targetProperty, PropertyPath path, object dataContext)
private BindingBase SetLangBinding(DependencyObject targetObject, DependencyProperty targetProperty, PropertyPath path, object dataContext)
{
if (targetProperty == null) return;
if (targetProperty == null) return null;
BindingOperations.SetBinding(targetObject, targetProperty, new Binding
{
@@ -146,16 +132,20 @@ namespace HandyControl.Tools.Extension
});
var key = targetObject.GetValue(targetProperty) as string;
if (string.IsNullOrEmpty(key)) return;
if (string.IsNullOrEmpty(key)) return null;
BindingOperations.SetBinding(targetObject, targetProperty, new Binding(key)
{
Converter = Converter,
ConverterParameter = ConverterParameter,
UpdateSourceTrigger = UpdateSourceTrigger.Explicit,
Source = Source,
Mode = BindingMode.OneWay
});
var binding = CreateLangBinding(key);
BindingOperations.SetBinding(targetObject, targetProperty, binding);
return binding;
}
private BindingBase CreateLangBinding(string key) => new Binding(key)
{
Converter = Converter,
ConverterParameter = ConverterParameter,
UpdateSourceTrigger = UpdateSourceTrigger.Explicit,
Source = Source,
Mode = BindingMode.OneWay
};
}
}
@@ -1,9 +1,23 @@
using System.Windows;
using HandyControl.Expression.Drawing;
namespace HandyControl.Tools.Extension
{
public static class ValueExtension
{
public static Thickness Add(this Thickness a, Thickness b) => new Thickness(a.Left + b.Left, a.Top + b.Top, a.Right + b.Right, a.Bottom + b.Bottom);
public static bool IsZero(this Thickness thickness) =>
MathHelper.IsZero(thickness.Left)
&& MathHelper.IsZero(thickness.Top)
&& MathHelper.IsZero(thickness.Right)
&& MathHelper.IsZero(thickness.Bottom);
public static bool IsUniform(this Thickness thickness) =>
MathHelper.AreClose(thickness.Left, thickness.Top)
&& MathHelper.AreClose(thickness.Left, thickness.Right)
&& MathHelper.AreClose(thickness.Left, thickness.Bottom);
public static bool IsNaN(this double value) => double.IsNaN(value);
}
}
@@ -92,10 +92,7 @@ namespace HandyControl.Tools
{
// Construct the image array
//
if (ImageInfoList == null)
{
ImageInfoList = new List<GifImageInfo>();
}
ImageInfoList ??= new List<GifImageInfo>();
// Add the new image
//
@@ -108,7 +105,7 @@ namespace HandyControl.Tools
{
AnimationThread = new Thread(AnimateImages50Ms)
{
Name = typeof(ImageAnimator).Name,
Name = nameof(ImageAnimator),
IsBackground = true
};
AnimationThread.Start();
@@ -168,13 +165,18 @@ namespace HandyControl.Tools
if (Equals(image, imageInfo.Image))
{
if ((onFrameChangedHandler == imageInfo.FrameChangedHandler) || (onFrameChangedHandler != null && onFrameChangedHandler.Equals(imageInfo.FrameChangedHandler)))
if (onFrameChangedHandler == imageInfo.FrameChangedHandler || onFrameChangedHandler != null && onFrameChangedHandler.Equals(imageInfo.FrameChangedHandler))
{
ImageInfoList.Remove(imageInfo);
}
break;
}
}
if (!ImageInfoList.Any())
{
AnimationThread = null;
}
}
finally
{
@@ -224,7 +226,7 @@ namespace HandyControl.Tools
[SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals")]
private static void AnimateImages50Ms()
{
while (true)
while (ImageInfoList.Any())
{
// Acquire reader-lock to access imageInfoList, elemens in the list can be modified w/o needing a writer-lock.
// Observe that we don't need to check if the thread is waiting or a writer lock here since the thread this
@@ -104,7 +104,7 @@ namespace HandyControl.Tools
}
public static void SetHost(DependencyObject element, bool value)
=> element.SetValue(HostProperty, value);
=> element.SetValue(HostProperty, ValueBoxes.BooleanBox(value));
public static bool GetHost(DependencyObject element)
=> (bool) element.GetValue(HostProperty);
@@ -1,14 +1,13 @@
using System;
using System.ComponentModel;
using System.Globalization;
#if !netle40
#if !NET40
using System.Runtime.CompilerServices;
#endif
using System.Windows;
using System.Windows.Markup;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using HandyControl.Controls;
using HandyControl.Data;
using HandyControl.Properties.Langs;
@@ -38,7 +37,7 @@ namespace HandyControl.Tools
}
}
public void SetSystemVersionInfo(SystemVersionInfo info) => BlurWindow.SystemVersionInfo = info;
public SystemVersionInfo SystemVersionInfo { get; set; }
public void SetLang(string lang)
{
@@ -49,7 +48,7 @@ namespace HandyControl.Tools
public void SetConfig(HandyControlConfig config)
{
SetSystemVersionInfo(config.SystemVersionInfo);
SystemVersionInfo = config.SystemVersionInfo;
SetLang(config.Lang);
SetTimelineFrameRate(config.TimelineFrameRate);
}
@@ -60,10 +59,10 @@ namespace HandyControl.Tools
public void SetWindowDefaultStyle(object resourceKey = null)
{
var metadata = resourceKey == null
? new FrameworkPropertyMetadata(Application.Current.FindResource(typeof(System.Windows.Window)))
? new FrameworkPropertyMetadata(Application.Current.FindResource(typeof(Window)))
: new FrameworkPropertyMetadata(Application.Current.FindResource(resourceKey));
FrameworkElement.StyleProperty.OverrideMetadata(typeof(System.Windows.Window), metadata);
FrameworkElement.StyleProperty.OverrideMetadata(typeof(Window), metadata);
}
public void SetNavigationWindowDefaultStyle(object resourceKey = null)
@@ -77,7 +76,7 @@ namespace HandyControl.Tools
public event PropertyChangedEventHandler PropertyChanged;
#if netle40
#if NET40
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
@@ -1,6 +1,7 @@
using System;
using System.Windows;
using System.Windows.Media;
using HandyControl.Expression.Drawing;
using HandyControl.Tools.Interop;
namespace HandyControl.Tools
@@ -17,8 +18,12 @@ namespace HandyControl.Tools
var dC = InteropMethods.GetDC(IntPtr.Zero);
if (dC != IntPtr.Zero)
{
DeviceDpiX = InteropMethods.GetDeviceCaps(dC, 88);
DeviceDpiY = InteropMethods.GetDeviceCaps(dC, 90);
// 沿着屏幕宽度每逻辑英寸的像素数。在具有多个显示器的系统中,这个值对所有显示器都是相同的
const int logicPixelsX = 88;
// 沿着屏幕高度每逻辑英寸的像素数
const int logicPixelsY = 90;
DeviceDpiX = InteropMethods.GetDeviceCaps(dC, logicPixelsX);
DeviceDpiY = InteropMethods.GetDeviceCaps(dC, logicPixelsY);
InteropMethods.ReleaseDC(IntPtr.Zero, dC);
}
else
@@ -75,5 +80,25 @@ namespace HandyControl.Tools
result.Transform(TransformFromDevice.Matrix);
return result;
}
public static double RoundLayoutValue(double value, double dpiScale)
{
double newValue;
if (!MathHelper.AreClose(dpiScale, 1.0))
{
newValue = Math.Round(value * dpiScale) / dpiScale;
if (double.IsNaN(newValue) || double.IsInfinity(newValue) || MathHelper.AreClose(newValue, double.MaxValue))
{
newValue = value;
}
}
else
{
newValue = Math.Round(value);
}
return newValue;
}
}
}
@@ -0,0 +1,149 @@
using System;
using System.Windows;
using System.Windows.Input;
namespace HandyControl.Tools
{
/// <summary>
/// 输入层点击帮助类
/// </summary>
public static class InputClickHelper
{
private static readonly DependencyProperty InputInfoProperty = DependencyProperty.RegisterAttached(
"InputInfo", typeof(InputInfo), typeof(InputClickHelper), new PropertyMetadata(default(InputInfo)));
private static void SetInputInfo(DependencyObject element, InputInfo value) => element.SetValue(InputInfoProperty, value);
private static InputInfo GetInputInfo(DependencyObject element) => (InputInfo)element.GetValue(InputInfoProperty);
/// <summary>
/// 将 MouseDown MouseMove MouseUp 封装为点击事件
/// </summary>
/// <param name="element">要被附加的元素</param>
/// <param name="clickEventHandler">点击的事件</param>
/// <param name="dragStarted">因为拖动而结束点击时触发</param>
public static void AttachMouseDownMoveUpToClick(UIElement element, EventHandler clickEventHandler,
EventHandler dragStarted = null)
{
var inputInfo = GetOrCreateInputInfo(element);
inputInfo.ClickEventHandler += clickEventHandler;
inputInfo.DragStarted += dragStarted;
element.MouseDown -= Element_MouseDown;
element.MouseDown += Element_MouseDown;
element.MouseMove -= Element_MouseMove;
element.MouseMove += Element_MouseMove;
element.MouseUp -= Element_MouseUp;
element.MouseUp += Element_MouseUp;
element.LostMouseCapture -= Element_LostMouseCapture;
element.LostMouseCapture += Element_LostMouseCapture;
}
/// <summary>
/// 去掉对 <paramref name="element" /> 的点击时间的监听
/// </summary>
/// <param name="element"></param>
/// <param name="clickEventHandler">点击的事件</param>
/// <param name="dragStarted">因为拖动而结束点击时触发的事件</param>
public static void DetachMouseDownMoveUpToClick(UIElement element, EventHandler clickEventHandler,
EventHandler dragStarted = null)
{
var inputInfo = GetInputInfo(element);
if (inputInfo == null) return;
inputInfo.ClickEventHandler -= clickEventHandler;
inputInfo.DragStarted -= dragStarted;
if (inputInfo.IsEmpty())
{
element.ClearValue(InputInfoProperty);
element.MouseDown -= Element_MouseDown;
element.MouseMove -= Element_MouseMove;
element.MouseUp -= Element_MouseUp;
element.LostMouseCapture -= Element_LostMouseCapture;
}
}
private static void Element_LostMouseCapture(object sender, MouseEventArgs e)
{
var element = (UIElement)sender;
GetInputInfo(element)?.LostCapture();
}
private static void Element_MouseUp(object sender, MouseButtonEventArgs e)
{
var element = (UIElement)sender;
GetInputInfo(element)?.Up(e.GetPosition(element));
}
private static void Element_MouseMove(object sender, MouseEventArgs e)
{
var element = (UIElement)sender;
GetInputInfo(element)?.Move(e.GetPosition(element));
}
private static void Element_MouseDown(object sender, MouseButtonEventArgs e)
{
var element = (UIElement)sender;
GetInputInfo(element)?.Down(e.GetPosition(element));
}
private static InputInfo GetOrCreateInputInfo(UIElement element)
{
var inputInfo = GetInputInfo(element);
if (inputInfo == null)
{
inputInfo = new InputInfo();
SetInputInfo(element, inputInfo);
}
return inputInfo;
}
private class InputInfo
{
private const double ToleranceSquared = 0.01;
private Point _downedPosition;
private bool _isClick;
public event EventHandler ClickEventHandler;
public event EventHandler DragStarted;
public void Down(Point position)
{
_downedPosition = position;
_isClick = true;
}
public void Move(Point position)
{
if (!_isClick) return;
if ((position - _downedPosition).LengthSquared > ToleranceSquared)
{
_isClick = false;
DragStarted?.Invoke(null, EventArgs.Empty);
}
}
public void Up(Point position)
{
_isClick = _isClick && (position - _downedPosition).LengthSquared <= ToleranceSquared;
if (!_isClick) return;
ClickEventHandler?.Invoke(null, EventArgs.Empty);
_isClick = false;
}
public void LostCapture() => _isClick = false;
public bool IsEmpty() => ClickEventHandler is null && DragStarted is null;
}
}
}
@@ -27,6 +27,7 @@ namespace HandyControl.Tools
public static T GetChild<T>(DependencyObject d) where T : DependencyObject
{
if (d == null) return default;
if (d is T t) return t;
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(d); i++)
@@ -132,15 +132,17 @@ namespace HandyControl.Tools
{
get
{
#if netle40
return WindowResizeBorderThickness;
InteropValues.APPBARDATA appBarData = default;
var autoHide = InteropMethods.SHAppBarMessage(4, ref appBarData) != 0;
#if NET40
return WindowResizeBorderThickness.Add(new Thickness(autoHide ? -8 : 0));
#elif Core
var hdc = InteropMethods.GetDC(IntPtr.Zero);
var scale = InteropMethods.GetDeviceCaps(hdc, InteropValues.DESKTOPVERTRES) / (float)InteropMethods.GetDeviceCaps(hdc, InteropValues.VERTRES);
InteropMethods.ReleaseDC(IntPtr.Zero, hdc);
return WindowResizeBorderThickness.Add(new Thickness(4 * scale));
return WindowResizeBorderThickness.Add(new Thickness((autoHide ? - 4 : 4) * scale));
#else
return WindowResizeBorderThickness.Add(new Thickness(4));
return WindowResizeBorderThickness.Add(new Thickness(autoHide ? - 4 : 4));
#endif
}
}
@@ -17,7 +17,7 @@ namespace HandyControl.Tools.Interop
{
#region common
public const int E_FAIL = unchecked((int)0x80004005);
internal const int E_FAIL = unchecked((int)0x80004005);
internal static readonly IntPtr HRGN_NONE = new IntPtr(-1);
@@ -461,7 +461,10 @@ namespace HandyControl.Tools.Interop
[ReflectionPermission(SecurityAction.Assert, Unrestricted = true),
SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode)]
public static void PtrToStructure(IntPtr lparam, object data) => Marshal.PtrToStructure(lparam, data);
internal static void PtrToStructure(IntPtr lparam, object data) => Marshal.PtrToStructure(lparam, data);
[DllImport(InteropValues.ExternDll.Shell32, CallingConvention = CallingConvention.StdCall)]
internal static extern uint SHAppBarMessage(int dwMessage, ref InteropValues.APPBARDATA pData);
#endregion
@@ -48,6 +48,7 @@ namespace HandyControl.Tools.Interop
NIIF_ERROR = 0x00000003,
WM_ACTIVATE = 0x0006,
WM_QUIT = 0x0012,
WM_GETMINMAXINFO = 0x0024,
WM_WINDOWPOSCHANGING = 0x0046,
WM_WINDOWPOSCHANGED = 0x0047,
WM_SETICON = 0x0080,
@@ -85,7 +86,8 @@ namespace HandyControl.Tools.Interop
SC_MINIMIZE = 0xF020,
SC_MAXIMIZE = 0xF030,
SC_RESTORE = 0xF120,
SRCCOPY = 0x00CC0020;
SRCCOPY = 0x00CC0020,
MONITOR_DEFAULTTONEAREST = 0x00000002;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
internal class NOTIFYICONDATA
@@ -933,5 +935,26 @@ namespace HandyControl.Tools.Interop
return length;
}
}
[StructLayout(LayoutKind.Sequential)]
internal class MINMAXINFO
{
public POINT ptReserved;
public POINT ptMaxSize;
public POINT ptMaxPosition;
public POINT ptMinTrackSize;
public POINT ptMaxTrackSize;
}
[StructLayout(LayoutKind.Sequential)]
internal struct APPBARDATA
{
public int cbSize;
public IntPtr hWnd;
public uint uCallbackMessage;
public uint uEdge;
public RECT rc;
public int lParam;
}
}
}
@@ -66,18 +66,9 @@ namespace HandyControl.Tools
public Deque(IEnumerable<T> backCollection, IEnumerable<T> frontCollection)
{
if (backCollection == null && frontCollection == null) throw new ArgumentException("Collections cannot both be null");
_front = new List<T>();
_back = new List<T>();
if (backCollection != null)
{
foreach (var item in backCollection) _back.Add(item);
}
if (frontCollection != null)
{
foreach (var item in frontCollection) _front.Add(item);
}
_front = frontCollection != null ? new List<T>(frontCollection) : new List<T>();
_back = backCollection != null ? new List<T>(backCollection) : new List<T>();
}
public void AddFirst(T item)
@@ -0,0 +1,30 @@
using System.Windows;
using System.Windows.Controls;
using HandyControl.Data;
namespace HandyControl.Tools
{
public class ComboBoxItemCapsuleStyleSelector : StyleSelector
{
public override Style SelectStyle(object item, DependencyObject container)
{
if (container is ComboBoxItem comboBoxItem && VisualHelper.GetParent<ComboBox>(comboBoxItem) is { } comboBox)
{
var count = comboBox.Items.Count;
if (count == 1)
{
return ResourceHelper.GetResource<Style>(ResourceToken.ComboBoxItemCapsuleSingle);
}
var index = comboBox.ItemContainerGenerator.IndexFromContainer(comboBoxItem);
return index == 0
? ResourceHelper.GetResource<Style>(ResourceToken.ComboBoxItemCapsuleHorizontalFirst)
: ResourceHelper.GetResource<Style>(index == count - 1
? ResourceToken.ComboBoxItemCapsuleHorizontalLast
: ResourceToken.ComboBoxItemCapsuleDefault);
}
return null;
}
}
}
@@ -8,7 +8,7 @@ namespace HandyControl.Tools
{
public override Style SelectStyle(object item, DependencyObject container)
{
if (item is TabItem tabItem && tabItem.Parent is TabControl tabControl)
if (container is TabItem tabItem && VisualHelper.GetParent<TabControl>(tabItem) is { } tabControl)
{
var count = tabControl.Items.Count;
if (count == 1)
@@ -16,7 +16,7 @@ namespace HandyControl.Tools
return ResourceHelper.GetResource<Style>(ResourceToken.TabItemCapsuleSingle);
}
var index = tabControl.Items.IndexOf(tabItem);
var index = tabControl.ItemContainerGenerator.IndexFromContainer(tabItem);
return index == 0
? ResourceHelper.GetResource<Style>(
tabControl.TabStripPlacement == Dock.Top || tabControl.TabStripPlacement == Dock.Bottom