add Gravatar
This commit is contained in:
1 parent
3a425d0058
commit
5d8e4e566a
35 files changed
+636
-93
No files matched your search
@@ -1,4 +1,9 @@
|
||||
using System.Windows;
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using HandyControl.Data;
|
||||
using HandyControl.Tools.Converter;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
@@ -10,5 +15,41 @@ namespace HandyControl.Controls
|
||||
public static void SetCornerRadius(DependencyObject element, CornerRadius value) => element.SetValue(CornerRadiusProperty, value);
|
||||
|
||||
public static CornerRadius GetCornerRadius(DependencyObject element) => (CornerRadius)element.GetValue(CornerRadiusProperty);
|
||||
|
||||
public static readonly DependencyProperty CircularProperty = DependencyProperty.RegisterAttached(
|
||||
"Circular", typeof(bool), typeof(BorderElement), new PropertyMetadata(ValueBoxes.FalseBox, OnCircularChanged));
|
||||
|
||||
private static void OnCircularChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (d is Border border)
|
||||
{
|
||||
if ((bool)e.NewValue)
|
||||
{
|
||||
border.SetBinding(FrameworkElement.MinWidthProperty,
|
||||
new Binding(FrameworkElement.ActualWidthProperty.Name) { Source = border });
|
||||
border.SetBinding(FrameworkElement.MinHeightProperty,
|
||||
new Binding(FrameworkElement.ActualHeightProperty.Name) { Source = border });
|
||||
var binding = new MultiBinding
|
||||
{
|
||||
Converter = new BorderCircularConverter()
|
||||
};
|
||||
binding.Bindings.Add(new Binding(FrameworkElement.ActualWidthProperty.Name) {Source = border});
|
||||
binding.Bindings.Add(new Binding(FrameworkElement.ActualHeightProperty.Name) { Source = border });
|
||||
border.SetBinding(Border.CornerRadiusProperty, binding);
|
||||
}
|
||||
else
|
||||
{
|
||||
BindingOperations.ClearBinding(border, FrameworkElement.MinWidthProperty);
|
||||
BindingOperations.ClearBinding(border, FrameworkElement.MinHeightProperty);
|
||||
BindingOperations.ClearBinding(border, Border.CornerRadiusProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetCircular(DependencyObject element, bool value)
|
||||
=> element.SetValue(CircularProperty, value);
|
||||
|
||||
public static bool GetCircular(DependencyObject element)
|
||||
=> (bool) element.GetValue(CircularProperty);
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,6 @@ namespace HandyControl.Controls
|
||||
=> element.SetValue(HighlightBrushProperty, value);
|
||||
|
||||
public static Brush GetHighlightBrush(DependencyObject element)
|
||||
=> (Brush) element.GetValue(HighlightBrushProperty);
|
||||
=> (Brush) element.GetValue(HighlightBrushProperty);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
public interface IGravatarGenerator
|
||||
{
|
||||
object GetGravatar(string id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
public class Badge : ContentControl
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
public class Dialog : ContentControl
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using HandyControl.Tools;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
public class Gravatar : ContentControl
|
||||
{
|
||||
public static readonly DependencyProperty GeneratorProperty = DependencyProperty.Register(
|
||||
"Generator", typeof(IGravatarGenerator), typeof(Gravatar), new PropertyMetadata(new GithubGravatarGenerator()));
|
||||
|
||||
public IGravatarGenerator Generator
|
||||
{
|
||||
get => (IGravatarGenerator) GetValue(GeneratorProperty);
|
||||
set => SetValue(GeneratorProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IdProperty = DependencyProperty.Register(
|
||||
"Id", typeof(string), typeof(Gravatar), new PropertyMetadata(default(string), OnIdChanged));
|
||||
|
||||
private static void OnIdChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var ctl = (Gravatar) d;
|
||||
if (ctl.Source != null) return;
|
||||
ctl.Content = ctl.Generator.GetGravatar((string)e.NewValue);
|
||||
}
|
||||
|
||||
public string Id
|
||||
{
|
||||
get => (string) GetValue(IdProperty);
|
||||
set => SetValue(IdProperty, value);
|
||||
}
|
||||
|
||||
|
||||
public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(
|
||||
"Source", typeof(ImageSource), typeof(Gravatar), new PropertyMetadata(default(ImageSource), OnSourceChanged));
|
||||
|
||||
private static void OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var ctl = (Gravatar)d;
|
||||
ctl.Background = new ImageBrush((ImageSource)e.NewValue);
|
||||
}
|
||||
|
||||
public ImageSource Source
|
||||
{
|
||||
get => (ImageSource) GetValue(SourceProperty);
|
||||
set => SetValue(SourceProperty, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,6 +86,7 @@
|
||||
<Compile Include="Controls\Attach\PanelElement.cs" />
|
||||
<Compile Include="Controls\Attach\VisualElement.cs" />
|
||||
<Compile Include="Controls\Base\HeaderedSelectableItem.cs" />
|
||||
<Compile Include="Controls\Base\IGravatarGenerator.cs" />
|
||||
<Compile Include="Controls\Base\ISelectable.cs" />
|
||||
<Compile Include="Controls\Base\RegularItemsControl.cs" />
|
||||
<Compile Include="Controls\Base\SelectableItem.cs" />
|
||||
@@ -108,10 +109,13 @@
|
||||
<Compile Include="Controls\Attach\TitleElement.cs" />
|
||||
<Compile Include="Controls\Button\ContextMenuButton.cs" />
|
||||
<Compile Include="Controls\Button\ContextMenuToggleButton.cs" />
|
||||
<Compile Include="Controls\Other\Badge.cs" />
|
||||
<Compile Include="Controls\Other\Carousel.cs" />
|
||||
<Compile Include="Controls\Cover\CoverView\CoverView.cs" />
|
||||
<Compile Include="Controls\Other\ChatBubble.cs" />
|
||||
<Compile Include="Controls\Other\Dialog.cs" />
|
||||
<Compile Include="Controls\Other\GotoTop.cs" />
|
||||
<Compile Include="Controls\Other\Gravatar.cs" />
|
||||
<Compile Include="Controls\Transfer\Transfer.cs" />
|
||||
<Compile Include="Controls\Transfer\TransferGroup.cs" />
|
||||
<Compile Include="Controls\Transfer\TransferItem.cs" />
|
||||
@@ -174,8 +178,11 @@
|
||||
<Compile Include="Data\ResourceToken.cs" />
|
||||
<Compile Include="Data\SystemVersionInfo.cs" />
|
||||
<Compile Include="Tools\Converter\Boolean2StrConverter.cs" />
|
||||
<Compile Include="Tools\Converter\BorderClipConverter.cs" />
|
||||
<Compile Include="Tools\Converter\BorderCircularConverter.cs" />
|
||||
<Compile Include="Tools\Converter\Int2StrConverter.cs" />
|
||||
<Compile Include="Tools\Extension\EnumerableExtension.cs" />
|
||||
<Compile Include="Tools\GithubGravatarGenerator.cs" />
|
||||
<Compile Include="Tools\Helper\ColorHelper.cs" />
|
||||
<Compile Include="Tools\GifImageAnimator.cs" />
|
||||
<Compile Include="Data\GrowlInfo.cs" />
|
||||
@@ -384,6 +391,10 @@
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Themes\Styles\Base\GravatarBaseStyle.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Themes\Styles\Base\ProgressButtonBaseStyle.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
@@ -436,6 +447,10 @@
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Themes\Styles\Gravatar.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Themes\Styles\GroupBox.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
|
||||
@@ -1,95 +1,76 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 1.3
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">1.3</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1">this is my long string</data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
[base64 mime encoded serialized .NET Framework object]
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
@@ -108,13 +89,13 @@
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
<value>1.3</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Confirm" xml:space="preserve">
|
||||
<value>Confirm</value>
|
||||
|
||||
@@ -15,5 +15,7 @@
|
||||
<converter:Object2BooleanConverter x:Key="Object2BooleanConverter"/>
|
||||
<converter:Boolean2StrConverter x:Key="Boolean2StrConverter"/>
|
||||
<converter:Int2StrConverter x:Key="Int2StrConverter"/>
|
||||
<converter:BorderClipConverter x:Key="BorderClipConverter"/>
|
||||
<converter:BorderCircularConverter x:Key="BorderCircularConverter"/>
|
||||
|
||||
</ResourceDictionary>
|
||||
@@ -0,0 +1,22 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="clr-namespace:HandyControl.Controls">
|
||||
|
||||
<Style x:Key="GravatarBaseStyle" TargetType="controls:Gravatar">
|
||||
<Setter Property="Width" Value="72"/>
|
||||
<Setter Property="Height" Value="72"/>
|
||||
<Setter Property="Background" Value="{DynamicResource SecondaryRegionBrush}"/>
|
||||
<Setter Property="controls:BorderElement.CornerRadius" Value="4"/>
|
||||
<Setter Property="Padding" Value="6"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="controls:Gravatar">
|
||||
<Border ClipToBounds="True" CornerRadius="{Binding Path=(controls:BorderElement.CornerRadius),RelativeSource={RelativeSource TemplatedParent}}" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
|
||||
<ContentPresenter Margin="{TemplateBinding Padding}"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
@@ -1,6 +1,11 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="clr-namespace:HandyControl.Controls">
|
||||
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="../Basic/Converters.xaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<!--用于包裹一个区域-->
|
||||
<Style x:Key="BorderRegionStyle" TargetType="Border">
|
||||
<Setter Property="Padding" Value="10"/>
|
||||
@@ -21,4 +26,20 @@
|
||||
<Setter Property="Background" Value="{DynamicResource ThirdlyTextBrush}"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="BorderCircular" TargetType="Border">
|
||||
<Setter Property="controls:BorderElement.Circular" Value="True"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="BorderClip" BasedOn="{StaticResource BorderCircular}" TargetType="Border">
|
||||
<Setter Property="Clip">
|
||||
<Setter.Value>
|
||||
<MultiBinding Converter="{StaticResource BorderClipConverter}">
|
||||
<Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}"/>
|
||||
<Binding Path="ActualHeight" RelativeSource="{RelativeSource Self}"/>
|
||||
<Binding Path="CornerRadius" RelativeSource="{RelativeSource Self}"/>
|
||||
</MultiBinding>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
@@ -0,0 +1,29 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="clr-namespace:HandyControl.Controls">
|
||||
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="Base/GravatarBaseStyle.xaml"/>
|
||||
<ResourceDictionary Source="Border.xaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<Style BasedOn="{StaticResource GravatarBaseStyle}" TargetType="controls:Gravatar"/>
|
||||
|
||||
<Style x:Key="GravatarCircle" BasedOn="{StaticResource GravatarBaseStyle}" TargetType="controls:Gravatar">
|
||||
<Setter Property="Padding" Value="16"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="controls:Gravatar">
|
||||
<Border Style="{StaticResource BorderClip}" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
|
||||
<ContentPresenter Margin="{TemplateBinding Padding}"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="GravatarCircleImg" BasedOn="{StaticResource GravatarCircle}" TargetType="controls:Gravatar">
|
||||
<Setter Property="Padding" Value="0"/>
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
@@ -58,6 +58,7 @@
|
||||
<ResourceDictionary Source="Transfer.xaml"/>
|
||||
<ResourceDictionary Source="ChatBubble.xaml"/>
|
||||
<ResourceDictionary Source="GotoTop.xaml"/>
|
||||
<ResourceDictionary Source="Gravatar.xaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
</ResourceDictionary>
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace HandyControl.Tools.Converter
|
||||
{
|
||||
public class BorderCircularConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (values.Length == 2 && values[0] is double width && values[1] is double height)
|
||||
{
|
||||
if (width < double.Epsilon || height < double.Epsilon)
|
||||
{
|
||||
return new CornerRadius();
|
||||
}
|
||||
|
||||
var min = Math.Min(width, height);
|
||||
return new CornerRadius(min/2);
|
||||
}
|
||||
|
||||
return DependencyProperty.UnsetValue;
|
||||
}
|
||||
|
||||
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
//referenced from https://stackoverflow.com/a/5650367/9639378
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace HandyControl.Tools.Converter
|
||||
{
|
||||
public class BorderClipConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (values.Length == 3 && values[0] is double width && values[1] is double height && values[2] is CornerRadius radius)
|
||||
{
|
||||
if (width < double.Epsilon || height < double.Epsilon)
|
||||
{
|
||||
return Geometry.Empty;
|
||||
}
|
||||
|
||||
var clip = new RectangleGeometry(new Rect(0, 0, width, height), radius.TopLeft, radius.TopLeft);
|
||||
clip.Freeze();
|
||||
|
||||
return clip;
|
||||
}
|
||||
|
||||
return DependencyProperty.UnsetValue;
|
||||
}
|
||||
|
||||
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Shapes;
|
||||
using HandyControl.Controls;
|
||||
|
||||
namespace HandyControl.Tools
|
||||
{
|
||||
public class GithubGravatarGenerator : IGravatarGenerator
|
||||
{
|
||||
private const int RenderDataMaxLength = 15;
|
||||
|
||||
public object GetGravatar(string id)
|
||||
{
|
||||
var hashcode = GetHashCode(id);
|
||||
var renderData = GetRenderData(hashcode);
|
||||
var renderBrush = GetRenderBrush(hashcode);
|
||||
var geometryGroup = new GeometryGroup();
|
||||
|
||||
void AddRec(int i, int j, bool hidden = false)
|
||||
{
|
||||
var rec = new RectangleGeometry(new Rect(new Point(i, j), hidden ? new Size() : new Size(1, 1)));
|
||||
geometryGroup.Children.Add(rec);
|
||||
}
|
||||
|
||||
var index = 0;
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
for (int j = 0; j < 5; j++, index++)
|
||||
{
|
||||
AddRec(i, j, renderData[index] == 0);
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < 5; j++, index++)
|
||||
{
|
||||
AddRec(2, j, renderData[index] == 0);
|
||||
}
|
||||
|
||||
index -= 10;
|
||||
for (int i = 3; i < 5; i++)
|
||||
{
|
||||
for (int j = 0; j < 5; j++, index++)
|
||||
{
|
||||
AddRec(i, j, renderData[index] == 0);
|
||||
}
|
||||
index -= 10;
|
||||
}
|
||||
|
||||
var path = new Path
|
||||
{
|
||||
Data = geometryGroup,
|
||||
Fill = renderBrush,
|
||||
VerticalAlignment = VerticalAlignment.Top
|
||||
};
|
||||
|
||||
RenderOptions.SetEdgeMode(path, EdgeMode.Aliased);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
private string GetHashCode(string id)
|
||||
{
|
||||
var md5 = MD5.Create();
|
||||
var bytes = Encoding.ASCII.GetBytes(id);
|
||||
var hash = md5.ComputeHash(bytes);
|
||||
var stringBuilder = new StringBuilder();
|
||||
foreach (var item in hash)
|
||||
{
|
||||
stringBuilder.Append(item.ToString("X2"));
|
||||
}
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
|
||||
private int[] GetRenderData(string hashcode)
|
||||
{
|
||||
var arr = new int[RenderDataMaxLength];
|
||||
for (int i = 0; i < RenderDataMaxLength; i++)
|
||||
{
|
||||
var c = hashcode[i];
|
||||
var v = (int) c;
|
||||
arr[i] = v % 2;
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
private Brush GetRenderBrush(string hashcode)
|
||||
{
|
||||
var v = (double)int.Parse(hashcode.Substring(hashcode.Length - 7), NumberStyles.HexNumber);
|
||||
var scale = v / 0xfffffff;
|
||||
var color = Hsl2Rgb(scale);
|
||||
return new SolidColorBrush(color);
|
||||
}
|
||||
|
||||
//adapted from https://github.com/stewartlord/identicon.js/blob/4fad7cafec1b7a4d896015e084e861625ef5d64f/identicon.js#L110
|
||||
private Color Hsl2Rgb(double h, double s = 0.7, double b = 0.5)
|
||||
{
|
||||
h *= 6;
|
||||
var arr = new[]
|
||||
{
|
||||
b += s *= b < .5 ? b : 1 - b,
|
||||
b - h % 1 * s * 2,
|
||||
b -= s *= 2,
|
||||
b,
|
||||
b + h % 1 * s,
|
||||
b + s
|
||||
};
|
||||
|
||||
var hValue = (int) Math.Floor(h);
|
||||
|
||||
return Color.FromRgb((byte) (arr[hValue % 6] * 255), (byte) (arr[(hValue | 16) % 6] * 255),
|
||||
(byte) (arr[(hValue | 8) % 6] * 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user