This commit is contained in:
NaBian 2020-06-22 00:08:26 +08:00
parent 2f08667db8
commit 0cdd558e5d
12 changed files with 210 additions and 30 deletions

View File

@ -4,6 +4,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:hc="https://handyorg.github.io/handycontrol">
<hc:TransitioningContentControl>
<hc:ImageSelector Width="100" Height="100" Margin="32"/>
</hc:TransitioningContentControl>
</UserControl>

View File

@ -30,6 +30,7 @@ namespace HandyControlDemo.UserControl
var selectedIndex = demoInfo.SelectedIndex;
demoInfo.SelectedIndex = -1;
demoInfo.SelectedIndex = selectedIndex;
FilterItems();
}
}
@ -51,6 +52,11 @@ namespace HandyControlDemo.UserControl
private void SearchBar_OnSearchStarted(object sender, FunctionEventArgs<string> e)
{
_searchKey = e.Info;
FilterItems();
}
private void FilterItems()
{
if (string.IsNullOrEmpty(_searchKey))
{
foreach (var item in ViewModelLocator.Instance.Main.DemoInfoCurrent.DemoItemList)

View File

@ -1,38 +1,126 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using HandyControl.Data;
using HandyControl.Interactivity;
using Microsoft.Win32;
namespace HandyControl.Controls
{
public class ImageSelector : Control
{
public static readonly DependencyProperty UriProperty = DependencyProperty.Register(
public ImageSelector() => CommandBindings.Add(new CommandBinding(ControlCommands.Switch, SwitchImage));
private void SwitchImage(object sender, ExecutedRoutedEventArgs e)
{
if (!HasValue)
{
var dialog = new OpenFileDialog
{
RestoreDirectory = true,
Filter = Filter,
DefaultExt = DefaultExt
};
if (dialog.ShowDialog() == true)
{
SetValue(UriPropertyKey, new Uri(dialog.FileName, UriKind.RelativeOrAbsolute));
SetValue(PreviewBrushPropertyKey, new ImageBrush(BitmapFrame.Create(Uri, BitmapCreateOptions.IgnoreImageCache, BitmapCacheOption.None))
{
Stretch = Stretch
});
SetValue(HasValuePropertyKey, ValueBoxes.TrueBox);
SetCurrentValue(ToolTipProperty, dialog.FileName);
}
}
else
{
SetValue(UriPropertyKey, default(Uri));
SetValue(PreviewBrushPropertyKey, default(Brush));
SetValue(HasValuePropertyKey, ValueBoxes.FalseBox);
SetCurrentValue(ToolTipProperty, default);
}
}
public static readonly DependencyProperty StretchProperty = DependencyProperty.Register(
"Stretch", typeof(Stretch), typeof(ImageSelector), new PropertyMetadata(default(Stretch)));
public Stretch Stretch
{
get => (Stretch) GetValue(StretchProperty);
set => SetValue(StretchProperty, value);
}
public static readonly DependencyPropertyKey UriPropertyKey = DependencyProperty.RegisterReadOnly(
"Uri", typeof(Uri), typeof(ImageSelector), new PropertyMetadata(default(Uri)));
public static readonly DependencyProperty UriProperty = UriPropertyKey.DependencyProperty;
public Uri Uri
{
get => (Uri) GetValue(UriProperty);
set => SetValue(UriProperty, value);
}
internal static readonly DependencyProperty SourceProperty = DependencyProperty.Register(
"Source", typeof(ImageSource), typeof(ImageSelector), new PropertyMetadata(default(ImageSource)));
public static readonly DependencyPropertyKey PreviewBrushPropertyKey = DependencyProperty.RegisterReadOnly(
"PreviewBrush", typeof(Brush), typeof(ImageSelector), new PropertyMetadata(default(Brush)));
internal ImageSource Source
public static readonly DependencyProperty PreviewBrushProperty = PreviewBrushPropertyKey.DependencyProperty;
public Brush PreviewBrush
{
get => (ImageSource) GetValue(SourceProperty);
set => SetValue(SourceProperty, value);
get => (Brush) GetValue(PreviewBrushProperty);
set => SetValue(PreviewBrushProperty, value);
}
public static readonly DependencyProperty IsPreviewEnabledProperty = DependencyProperty.Register(
"IsPreviewEnabled", typeof(bool), typeof(ImageSelector), new PropertyMetadata(ValueBoxes.FalseBox));
public static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register(
"StrokeThickness", typeof(double), typeof(ImageSelector), new FrameworkPropertyMetadata(ValueBoxes.Double1Box, FrameworkPropertyMetadataOptions.AffectsRender));
public bool IsPreviewEnabled
public double StrokeThickness
{
get => (bool) GetValue(IsPreviewEnabledProperty);
set => SetValue(IsPreviewEnabledProperty, value);
get => (double) GetValue(StrokeThicknessProperty);
set => SetValue(StrokeThicknessProperty, value);
}
public static readonly DependencyProperty StrokeDashArrayProperty = DependencyProperty.Register(
"StrokeDashArray", typeof(DoubleCollection), typeof(ImageSelector), new FrameworkPropertyMetadata(default(DoubleCollection), FrameworkPropertyMetadataOptions.AffectsRender));
public DoubleCollection StrokeDashArray
{
get => (DoubleCollection) GetValue(StrokeDashArrayProperty);
set => SetValue(StrokeDashArrayProperty, value);
}
public static readonly DependencyProperty DefaultExtProperty = DependencyProperty.Register(
"DefaultExt", typeof(string), typeof(ImageSelector), new PropertyMetadata(".jpg"));
public string DefaultExt
{
get => (string) GetValue(DefaultExtProperty);
set => SetValue(DefaultExtProperty, value);
}
public static readonly DependencyProperty FilterProperty = DependencyProperty.Register(
"Filter", typeof(string), typeof(ImageSelector), new PropertyMetadata("(.jpg)|*.jpg|(.png)|*.png"));
public string Filter
{
get => (string) GetValue(FilterProperty);
set => SetValue(FilterProperty, value);
}
public static readonly DependencyPropertyKey HasValuePropertyKey = DependencyProperty.RegisterReadOnly(
"HasValue", typeof(bool), typeof(ImageSelector), new PropertyMetadata(ValueBoxes.FalseBox));
public static readonly DependencyProperty HasValueProperty = HasValuePropertyKey.DependencyProperty;
public bool HasValue
{
get => (bool) GetValue(HasValueProperty);
set => SetValue(HasValueProperty, value);
}
}
}

View File

@ -12,7 +12,7 @@ namespace HandyControl.Controls
/// </remarks>
public class SimplePanel : Panel
{
protected override Size MeasureOverride(Size availableSize)
protected override Size MeasureOverride(Size constraint)
{
var maxSize = new Size();
@ -20,7 +20,7 @@ namespace HandyControl.Controls
{
if (child != null)
{
child.Measure(availableSize);
child.Measure(constraint);
maxSize.Width = Math.Max(maxSize.Width, child.DesiredSize.Width);
maxSize.Height = Math.Max(maxSize.Height, child.DesiredSize.Height);
}

View File

@ -76,10 +76,8 @@ namespace HandyControl.Data
{
FrameCount = 1;
}
if (_frameDelay == null)
{
_frameDelay = new int[FrameCount];
}
_frameDelay ??= new int[FrameCount];
}
public int FrameDelay(int frame) => _frameDelay[frame];

View File

@ -4,6 +4,8 @@ namespace HandyControl.Expression.Drawing
{
internal static class MathHelper
{
internal const double DBL_EPSILON = 2.2204460492503131e-016;
public static bool AreClose(double value1, double value2) =>
// ReSharper disable once CompareOfFloatsByEqualityOperator
value1 == value2 || IsVerySmall(value1 - value2);
@ -12,6 +14,8 @@ namespace HandyControl.Expression.Drawing
public static bool IsVerySmall(double value) => Math.Abs(value) < 1E-06;
public static bool IsZero(double value) => Math.Abs(value) < 10.0 * DBL_EPSILON;
public static bool IsFiniteDouble(double x) => !double.IsInfinity(x) && !double.IsNaN(x);
public static double DoubleFromMantissaAndExponent(double x, int exp) => x * Math.Pow(2.0, exp);

View File

@ -42,7 +42,8 @@
<Geometry o:Freeze="True" x:Key="AudioGeometry">M627.52666696 962L550.66666696 890.47999971c116.82-92.99999971 191.09999971-230.94 191.09999971-385.2 0-146.99999971-67.61999971-279-174.96-371.57999942L643.84666667 62C770.86666638 172.99999971 850.66666667 330.2 850.66666667 505.09999971c0 182.27999971-86.58 345.42-223.13999971 456.90000029zM405.64666638 782l-76.32-77.22a227.88 227.88 0 0 0 116.40000058-199.26A228.06 228.06 0 0 0 347.86666638 317.84000029L422.86666696 242A334.37999971 334.37999971 0 0 1 550.66666696 505.52 334.62 334.62 0 0 1 405.64666638 782zM205.66666638 596.6C164.26666638 596.6 130.66666667 562.51999971 130.66666667 520.64 130.66666667 478.76000029 164.26666638 444.79999971 205.66666638 444.79999971s74.99999971 33.95999971 75.00000058 75.90000058c0 41.87999971-33.59999971 75.84000029-75.00000058 75.83999942z</Geometry>
<Geometry o:Freeze="True" x:Key="BubbleTailGeometry">M0,0L28,0 28,14.0000006258488 28,15.0010000765324 28.0151405334473,15.0010000765324 28.0455417633057,15.8010965883732C28.4084091186524,22.9596563875675,30.92209815979,29.5507589876652,34.9532623291016,34.9410597383976L34.9984359741211,34.9999815523624 34.0966339111328,34.9885679781437C15.1841707229614,34.5094191133976,2.0535663480814E-07,19.0279375612736,0,0z</Geometry>
<Geometry o:Freeze="True" x:Key="StarGeometry">M535.9 165.2l96.5 195.4c3.9 7.9 11.4 13.3 20.1 14.6l215.7 31.3c21.9 3.2 30.6 30 14.8 45.5L726.8 604.1c-6.3 6.1-9.1 14.9-7.7 23.6L756 842.5c3.7 21.8-19.1 38.4-38.7 28.1L524.4 769.2c-7.8-4.1-17-4.1-24.8 0L306.7 870.6c-19.6 10.3-42.4-6.3-38.7-28.1l36.8-214.8c1.5-8.6-1.4-17.5-7.7-23.6L141.1 452c-15.8-15.4-7.1-42.3 14.8-45.5l215.7-31.3c8.7-1.3 16.2-6.7 20.1-14.6l96.5-195.4c9.7-19.9 37.9-19.9 47.7 0z</Geometry>
<Geometry o:Freeze="True" x:Key="AddGeometry">M938.666667 426.666667h-341.333334V85.333333c0-46.933333-38.4-85.333333-85.333333-85.333333s-85.333333 38.4-85.333333 85.333333v341.333334H85.333333c-46.933333 0-85.333333 38.4-85.333333 85.333333s38.4 85.333333 85.333333 85.333333h341.333334v341.333334c0 46.933333 38.4 85.333333 85.333333 85.333333s85.333333-38.4 85.333333-85.333333v-341.333334h341.333334c46.933333 0 85.333333-38.4 85.333333-85.333333s-38.4-85.333333-85.333333-85.333333z</Geometry>
<Geometry o:Freeze="True" x:Key="AddGeometry">M8,0 C8.5522847,0 9,0.44771525 9,1 L9,7 15,7 C15.552285,7 16,7.4477153 16,8 16,8.5522852 15.552285,9 15,9 L9,9 9,15 C9,15.552285 8.5522847,16 8,16 7.4477153,16 7,15.552285 7,15 L7,9 1,9 C0.44771528,9 0,8.5522852 0,8 0,7.4477153 0.44771528,7 1,7 L7,7 7,1 C7,0.44771525 7.4477153,0 8,0 z</Geometry>
<Geometry o:Freeze="True" x:Key="RemoveGeometry">M10.899495,0 C11.155417,0 11.411339,0.097630501 11.606602,0.29289246 11.997126,0.68341732 11.997126,1.3165817 11.606602,1.7071066 L7.3639612,5.9497471 11.606602,10.192388 C11.997126,10.582912 11.997126,11.216077 11.606602,11.606601 11.216077,11.997126 10.582912,11.997126 10.192388,11.606601 L5.9497476,7.3639607 1.7071068,11.606601 C1.3165827,11.997126 0.68341756,11.997126 0.29289341,11.606601 -0.097630978,11.216077 -0.097630978,10.582912 0.29289341,10.192388 L4.5355338,5.9497471 0.29289341,1.7071066 C-0.097630978,1.3165817 -0.097630978,0.68341732 0.29289341,0.29289246 0.48815536,0.097630501 0.74407768,0 1,0 1.2559223,0 1.5118446,0.097630501 1.7071068,0.29289246 L5.9497476,4.5355334 10.192388,0.29289246 C10.38765,0.097630501 10.643572,0 10.899495,0 z</Geometry>
<Geometry o:Freeze="True" x:Key="SubGeometry">M62.5797 488.9508c0.2632 42.5185 34.985 77.2116 77.5035 77.5035l743.0216-0.6728c42.5185 0.3215 76.7437-33.9333 76.4518-76.4805l0 0c-0.2918-42.5175-34.985-77.2106-77.5045-77.5035l-743.0216-0.087C96.513 411.4473 62.2879 446.4323 62.5797 488.9508L62.5797 488.9508z</Geometry>
<Geometry o:Freeze="True" x:Key="WarningGeometry">M943.644188 827.215696l-351.176649-608.204749c-42.945473-74.36249-113.147387-74.36249-156.092861 0l-351.176649 608.204749c-42.946498 74.431167-7.811716 135.14955 78.012605 135.14955l702.420949 0C951.455904 962.36422 986.555836 901.645838 943.644188 827.215696zM466.187532 391.579035c12.621133-13.644108 28.66175-20.466675 48.233578-20.466675 19.580028 0 35.612444 6.75389 48.241778 20.194018 12.544256 13.473954 18.820484 30.325365 18.820484 50.587035 0 17.430551-26.19759 145.621205-34.929778 238.882082l-63.105666 0c-7.666162-93.259852-36.090106-221.450507-36.090106-238.882082C447.358847 421.938226 453.643275 405.155491 466.187532 391.579035zM561.76804 835.026386c-13.268949 12.928641-29.062535 19.375023-47.345906 19.375023-18.275171 0-34.076957-6.447407-47.346931-19.375023-13.235123-12.89379-19.818859-28.517221-19.818859-46.869269 0-18.249546 6.583736-34.043131 19.818859-47.278254 13.268949-13.235123 29.07176-19.852685 47.346931-19.852685 18.283371 0 34.076957 6.617562 47.345906 19.852685 13.235123 13.235123 19.827059 29.028709 19.827059 47.278254C581.595099 806.51019 575.003163 822.132597 561.76804 835.026386z</Geometry>
<Geometry o:Freeze="True" x:Key="InfoGeometry">M505.6512 39.0144c-261.2224 3.4816-470.1184 218.112-466.6368 479.4368 3.4816 261.12 218.112 470.1184 479.3344 466.6368 261.2224-3.4816 470.1184-218.112 466.7392-479.3344C981.504 244.4288 766.8736 35.5328 505.6512 39.0144zM558.08 196.608c48.128 0 62.2592 27.9552 62.2592 59.8016 0 39.8336-31.9488 76.6976-86.3232 76.6976-45.568 0-67.1744-22.9376-65.9456-60.8256C468.0704 240.4352 494.7968 196.608 558.08 196.608zM434.7904 807.6288c-32.8704 0-56.9344-19.968-33.8944-107.6224l37.6832-155.5456c6.5536-24.8832 7.68-34.9184 0-34.9184-9.8304 0-52.5312 17.2032-77.7216 34.2016l-16.384-26.9312c79.9744-66.7648 171.8272-105.8816 211.2512-105.8816 32.8704 0 38.2976 38.912 21.9136 98.6112l-43.2128 163.5328c-7.68 28.8768-4.4032 38.912 3.2768 38.912 9.9328 0 42.1888-11.9808 73.9328-36.9664l18.6368 24.8832C552.5504 777.728 467.6608 807.6288 434.7904 807.6288z</Geometry>

View File

@ -1,7 +1,55 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:hc="clr-namespace:HandyControl.Controls">
xmlns:hc="clr-namespace:HandyControl.Controls"
xmlns:themes="clr-namespace:HandyControl.Themes"
xmlns:interactivity="clr-namespace:HandyControl.Interactivity">
<Style x:Key="ImageSelectorBaseStyle" TargetType="hc:ImageSelector"/>
<ResourceDictionary.MergedDictionaries>
<themes:SharedResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Basic/Geometries.xaml"/>
<themes:SharedResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Styles/Rectangle.xaml"/>
<themes:SharedResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Styles/Border.xaml"/>
<themes:SharedResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Styles/Button.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="ImageSelectorBaseStyle" TargetType="hc:ImageSelector">
<Setter Property="Focusable" Value="False"/>
<Setter Property="Stretch" Value="UniformToFill"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="StrokeThickness" Value="1"/>
<Setter Property="Background" Value="{DynamicResource RegionBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource BorderBrush}"/>
<Setter Property="StrokeDashArray" Value="2,2"/>
<Setter Property="hc:IconSwitchElement.Geometry" Value="{StaticResource AddGeometry}"/>
<Setter Property="hc:IconSwitchElement.GeometrySelected" Value="{StaticResource RemoveGeometry}"/>
<Setter Property="hc:BorderElement.CornerRadius" Value="{StaticResource DefaultCornerRadius}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="hc:ImageSelector">
<Button Command="interactivity:ControlCommands.Switch" Style="{StaticResource ButtonCustom}" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
<Border Background="{TemplateBinding Background}" CornerRadius="{Binding Path=(hc:BorderElement.CornerRadius),RelativeSource={RelativeSource TemplatedParent}}">
<hc:DashBorder BorderDashArray="{TemplateBinding StrokeDashArray}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" BorderDashThickness="{TemplateBinding StrokeThickness}" Background="{TemplateBinding PreviewBrush}" CornerRadius="{Binding Path=(hc:BorderElement.CornerRadius),RelativeSource={RelativeSource TemplatedParent}}">
<Border Width="30" Height="30" Background="{TemplateBinding Background}" Style="{StaticResource BorderCircular}">
<hc:ToggleBlock IsChecked="{TemplateBinding HasValue}">
<hc:ToggleBlock.CheckedContent>
<Path Data="{TemplateBinding hc:IconSwitchElement.GeometrySelected}" Width="12" Height="12" Fill="{DynamicResource PrimaryBrush}"/>
</hc:ToggleBlock.CheckedContent>
<hc:ToggleBlock.UnCheckedContent>
<Path Data="{TemplateBinding hc:IconSwitchElement.Geometry}" Width="16" Height="16" Fill="{DynamicResource PrimaryBrush}"/>
</hc:ToggleBlock.UnCheckedContent>
</hc:ToggleBlock>
</Border>
</hc:DashBorder>
</Border>
</Button>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{DynamicResource SecondaryRegionBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource PrimaryBrush}"/>
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>

View File

@ -2,7 +2,7 @@
<Style TargetType="Image">
<Setter Property="Stretch" Value="Uniform" />
<Setter Property="RenderOptions.BitmapScalingMode" Value="LowQuality" />
<Setter Property="RenderOptions.BitmapScalingMode" Value="NearestNeighbor" />
</Style>
</ResourceDictionary>

View File

@ -1,9 +1,21 @@
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);
}
}

View File

@ -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

View File

@ -1,6 +1,7 @@
using System;
using System.Windows;
using System.Windows.Media;
using HandyControl.Expression.Drawing;
using HandyControl.Tools.Interop;
namespace HandyControl.Tools
@ -79,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;
}
}
}