diff options
author | Bertrand Le Roy <beleroy@microsoft.com> | 2017-12-30 03:11:32 +0300 |
---|---|---|
committer | Bertrand Le Roy <beleroy@microsoft.com> | 2018-01-16 22:35:26 +0300 |
commit | 1f66be4672c90296e56c2c9e5ad3695c266c6d04 (patch) | |
tree | 4485fb643411601ea7d550880590b6228e099c88 | |
parent | 3209d96cb4db998373c2d7876a33b423d860eed0 (diff) |
Add a DPI-dependent bitmap icon control, change brush selection tabs from vector canvas into those new bitmap icon controls.bleroy-dpi-aware-icon-win
23 files changed, 210 insertions, 29 deletions
diff --git a/Xamarin.PropertyEditing.Mac/Themes/MacThemeManager.cs b/Xamarin.PropertyEditing.Mac/Themes/MacThemeManager.cs index 4f196ea..07bcd2a 100644 --- a/Xamarin.PropertyEditing.Mac/Themes/MacThemeManager.cs +++ b/Xamarin.PropertyEditing.Mac/Themes/MacThemeManager.cs @@ -23,5 +23,7 @@ namespace Xamarin.PropertyEditing.Themes break; } } + + protected override string IconModifier => Theme == PropertyEditorTheme.Dark ? "~dark" : ""; } } diff --git a/Xamarin.PropertyEditing.Windows/IconThemeImage.cs b/Xamarin.PropertyEditing.Windows/IconThemeImage.cs new file mode 100644 index 0000000..d7d587a --- /dev/null +++ b/Xamarin.PropertyEditing.Windows/IconThemeImage.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Windows; +using System.Windows.Media.Imaging; + +namespace Xamarin.PropertyEditing.Windows +{ + sealed class IconThemeImage : MultiSourceImage + { + static readonly List<WeakReference<IconThemeImage>> instances = new List<WeakReference<IconThemeImage>> (); + + static IconThemeImage () + { + PropertyEditorPanel.ThemeManager.ThemeChanged += (s, e) => { + for (var i = instances.Count - 1; i >= 0; i--) { + if (instances[i].TryGetTarget (out IconThemeImage image)) + image.ReloadIcon (); + else + instances.RemoveAt (i); + } + }; + } + + static void OnPropertyChanged (DependencyObject d, DependencyPropertyChangedEventArgs e) + => ((IconThemeImage)d).ReloadIcon (); + + readonly WeakReference<IconThemeImage> weakReference; + + public IconThemeImage () + { + this.weakReference = new WeakReference<IconThemeImage> (this, true); + instances.Add (this.weakReference); + } + + public static readonly DependencyProperty IconNameProperty = DependencyProperty.Register ( + nameof (IconName), + typeof (string), + typeof (IconThemeImage), + new PropertyMetadata (OnPropertyChanged)); + + public string IconName + { + get => (string)GetValue (IconNameProperty); + set => SetValue (IconNameProperty, value); + } + + public static readonly DependencyProperty IconSizeProperty = DependencyProperty.Register ( + nameof (IconSize), + typeof (int), + typeof (IconThemeImage), + new PropertyMetadata (OnPropertyChanged)); + + public int IconSize + { + get => (int)GetValue (IconSizeProperty); + set => SetValue (IconSizeProperty, value); + } + + public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register ( + nameof (IsSelected), + typeof (bool), + typeof (IconThemeImage), + new PropertyMetadata (OnPropertyChanged)); + + public bool IsSelected + { + get => (bool)GetValue (IsSelectedProperty); + set => SetValue (IsSelectedProperty, value); + } + + static readonly Dictionary<string, List<BitmapImage>> iconCache + = new Dictionary<string, List<BitmapImage>> (); + + void ReloadIcon () + { + if (string.IsNullOrEmpty (IconName) || IconSize <= 0) { + Source = null; + return; + } + + var iconName = PropertyEditorPanel.ThemeManager.GetIconName ( + IconName, + IconSize, + IsSelected); + + Width = IconSize; + Height = IconSize; + + if (iconCache.TryGetValue (iconName, out List<BitmapImage> images)) { + Sources = images; + return; + } + + images = new List<BitmapImage> (); + iconCache.Add (iconName, images); + + var iconsDirectory = "Icons"; + + foreach (var suffix in new[] { "", "@2x" }) { + var path = $"pack://application:,,,/Xamarin.PropertyEditing.Windows;component/{iconsDirectory}/{iconName}{suffix}.png"; + images.Add (new BitmapImage (new Uri (path))); + } + + Sources = images; + } + } +}
\ No newline at end of file diff --git a/Xamarin.PropertyEditing.Windows/Icons/property-brush-none-16.png b/Xamarin.PropertyEditing.Windows/Icons/property-brush-none-16.png Binary files differnew file mode 100644 index 0000000..61a8083 --- /dev/null +++ b/Xamarin.PropertyEditing.Windows/Icons/property-brush-none-16.png diff --git a/Xamarin.PropertyEditing.Windows/Icons/property-brush-none-16@2x.png b/Xamarin.PropertyEditing.Windows/Icons/property-brush-none-16@2x.png Binary files differnew file mode 100644 index 0000000..2ee673b --- /dev/null +++ b/Xamarin.PropertyEditing.Windows/Icons/property-brush-none-16@2x.png diff --git a/Xamarin.PropertyEditing.Windows/Icons/property-brush-none-16~dark.png b/Xamarin.PropertyEditing.Windows/Icons/property-brush-none-16~dark.png Binary files differnew file mode 100644 index 0000000..933a8c6 --- /dev/null +++ b/Xamarin.PropertyEditing.Windows/Icons/property-brush-none-16~dark.png diff --git a/Xamarin.PropertyEditing.Windows/Icons/property-brush-none-16~dark@2x.png b/Xamarin.PropertyEditing.Windows/Icons/property-brush-none-16~dark@2x.png Binary files differnew file mode 100644 index 0000000..985d294 --- /dev/null +++ b/Xamarin.PropertyEditing.Windows/Icons/property-brush-none-16~dark@2x.png diff --git a/Xamarin.PropertyEditing.Windows/Icons/property-brush-none-16~dark~sel.png b/Xamarin.PropertyEditing.Windows/Icons/property-brush-none-16~dark~sel.png Binary files differnew file mode 100644 index 0000000..b8e1080 --- /dev/null +++ b/Xamarin.PropertyEditing.Windows/Icons/property-brush-none-16~dark~sel.png diff --git a/Xamarin.PropertyEditing.Windows/Icons/property-brush-none-16~dark~sel@2x.png b/Xamarin.PropertyEditing.Windows/Icons/property-brush-none-16~dark~sel@2x.png Binary files differnew file mode 100644 index 0000000..0c0d3c0 --- /dev/null +++ b/Xamarin.PropertyEditing.Windows/Icons/property-brush-none-16~dark~sel@2x.png diff --git a/Xamarin.PropertyEditing.Windows/Icons/property-brush-none-16~sel.png b/Xamarin.PropertyEditing.Windows/Icons/property-brush-none-16~sel.png Binary files differnew file mode 100644 index 0000000..b8e1080 --- /dev/null +++ b/Xamarin.PropertyEditing.Windows/Icons/property-brush-none-16~sel.png diff --git a/Xamarin.PropertyEditing.Windows/Icons/property-brush-none-16~sel@2x.png b/Xamarin.PropertyEditing.Windows/Icons/property-brush-none-16~sel@2x.png Binary files differnew file mode 100644 index 0000000..0c0d3c0 --- /dev/null +++ b/Xamarin.PropertyEditing.Windows/Icons/property-brush-none-16~sel@2x.png diff --git a/Xamarin.PropertyEditing.Windows/Icons/property-brush-solid-16.png b/Xamarin.PropertyEditing.Windows/Icons/property-brush-solid-16.png Binary files differnew file mode 100644 index 0000000..751fb88 --- /dev/null +++ b/Xamarin.PropertyEditing.Windows/Icons/property-brush-solid-16.png diff --git a/Xamarin.PropertyEditing.Windows/Icons/property-brush-solid-16@2x.png b/Xamarin.PropertyEditing.Windows/Icons/property-brush-solid-16@2x.png Binary files differnew file mode 100644 index 0000000..69ce2d4 --- /dev/null +++ b/Xamarin.PropertyEditing.Windows/Icons/property-brush-solid-16@2x.png diff --git a/Xamarin.PropertyEditing.Windows/Icons/property-brush-solid-16~dark.png b/Xamarin.PropertyEditing.Windows/Icons/property-brush-solid-16~dark.png Binary files differnew file mode 100644 index 0000000..4b1b582 --- /dev/null +++ b/Xamarin.PropertyEditing.Windows/Icons/property-brush-solid-16~dark.png diff --git a/Xamarin.PropertyEditing.Windows/Icons/property-brush-solid-16~dark@2x.png b/Xamarin.PropertyEditing.Windows/Icons/property-brush-solid-16~dark@2x.png Binary files differnew file mode 100644 index 0000000..7bf8685 --- /dev/null +++ b/Xamarin.PropertyEditing.Windows/Icons/property-brush-solid-16~dark@2x.png diff --git a/Xamarin.PropertyEditing.Windows/Icons/property-brush-solid-16~dark~sel.png b/Xamarin.PropertyEditing.Windows/Icons/property-brush-solid-16~dark~sel.png Binary files differnew file mode 100644 index 0000000..3bbdbb0 --- /dev/null +++ b/Xamarin.PropertyEditing.Windows/Icons/property-brush-solid-16~dark~sel.png diff --git a/Xamarin.PropertyEditing.Windows/Icons/property-brush-solid-16~dark~sel@2x.png b/Xamarin.PropertyEditing.Windows/Icons/property-brush-solid-16~dark~sel@2x.png Binary files differnew file mode 100644 index 0000000..0aa1109 --- /dev/null +++ b/Xamarin.PropertyEditing.Windows/Icons/property-brush-solid-16~dark~sel@2x.png diff --git a/Xamarin.PropertyEditing.Windows/Icons/property-brush-solid-16~sel.png b/Xamarin.PropertyEditing.Windows/Icons/property-brush-solid-16~sel.png Binary files differnew file mode 100644 index 0000000..3bbdbb0 --- /dev/null +++ b/Xamarin.PropertyEditing.Windows/Icons/property-brush-solid-16~sel.png diff --git a/Xamarin.PropertyEditing.Windows/Icons/property-brush-solid-16~sel@2x.png b/Xamarin.PropertyEditing.Windows/Icons/property-brush-solid-16~sel@2x.png Binary files differnew file mode 100644 index 0000000..0aa1109 --- /dev/null +++ b/Xamarin.PropertyEditing.Windows/Icons/property-brush-solid-16~sel@2x.png diff --git a/Xamarin.PropertyEditing.Windows/MultiSourceImage.cs b/Xamarin.PropertyEditing.Windows/MultiSourceImage.cs new file mode 100644 index 0000000..422dc16 --- /dev/null +++ b/Xamarin.PropertyEditing.Windows/MultiSourceImage.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; + +namespace Xamarin.PropertyEditing.Windows +{ + class MultiSourceImage : Image + { + public static readonly DependencyProperty SourcesProperty = DependencyProperty.Register ( + nameof (Sources), + typeof (IReadOnlyList<ImageSource>), + typeof (MultiSourceImage), + new PropertyMetadata (OnPropertyChanged)); + + public IReadOnlyList<ImageSource> Sources + { + get => (IReadOnlyList<ImageSource>)GetValue (SourcesProperty); + set => SetValue (SourcesProperty, value); + } + + void SetSource (IReadOnlyList<ImageSource> images) + { + if (images == null || images.Count == 0) { + Source = null; + return; + } + + var presentationSource = PresentationSource.FromVisual ((Visual)Parent); + var scaleFactor = presentationSource != null ? + presentationSource.CompositionTarget.TransformToDevice.M11 : 1.0; + var minSize = Math.Max (Width, Height) * scaleFactor; + + Source = images.FirstOrDefault (i => i.Width >= minSize && i.Height >= minSize) + ?? images.LastOrDefault (); + } + + static void OnPropertyChanged (DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var image = (MultiSourceImage)d; + image.SetSource (image.Sources); + } + } +}
\ No newline at end of file diff --git a/Xamarin.PropertyEditing.Windows/Themes/Resources.xaml b/Xamarin.PropertyEditing.Windows/Themes/Resources.xaml index c07f23e..f1d42d2 100644 --- a/Xamarin.PropertyEditing.Windows/Themes/Resources.xaml +++ b/Xamarin.PropertyEditing.Windows/Themes/Resources.xaml @@ -498,21 +498,19 @@ <local:BrushChoiceTemplateSelector x:Key="BrushChoiceTemplateSelector"> <local:BrushChoiceTemplateSelector.NoBrushTemplate> <DataTemplate> - <RadioButton Style="{DynamicResource ChoiceControlItem}" GroupName="{Binding Name,RelativeSource={RelativeSource FindAncestor,AncestorType=local:ChoiceControl},Mode=OneTime}"> - <Canvas HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="30" Height="20" Margin="4,4,0,0"> - <Polygon Points="0,0 24,0 0,14" Fill="{DynamicResource VectorGlyphBrush}" StrokeThickness="0"/> - <Polygon Points="25,1 25,15 1,15" Fill="{DynamicResource VectorGlyphBrush}" StrokeThickness="0"/> - </Canvas> + <RadioButton Style="{DynamicResource ChoiceControlItem}" Width="32" + GroupName="{Binding Name,RelativeSource={RelativeSource FindAncestor,AncestorType=local:ChoiceControl},Mode=OneTime}"> + <local:IconThemeImage IconSize="16" IconName="property-brush-none" + IsSelected="{Binding IsChecked, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type RadioButton}}}"/> </RadioButton> </DataTemplate> </local:BrushChoiceTemplateSelector.NoBrushTemplate> <local:BrushChoiceTemplateSelector.SolidBrushTemplate> <DataTemplate> - <RadioButton Style="{DynamicResource ChoiceControlItem}" GroupName="{Binding Name,RelativeSource={RelativeSource FindAncestor,AncestorType=local:ChoiceControl},Mode=OneTime}"> - <Canvas HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="30" Height="20" Margin="4,4,0,0"> - <Rectangle Canvas.Left="0" Canvas.Top="0" Width="25" Height="15" Stroke="{DynamicResource VectorGlyphBrush}" StrokeThickness="1"/> - <Rectangle Canvas.Left="2" Canvas.Top="2" Width="21" Height="11" Fill="{DynamicResource VectorGlyphBrush}" StrokeThickness="0"/> - </Canvas> + <RadioButton Style="{DynamicResource ChoiceControlItem}" Width="32" + GroupName="{Binding Name,RelativeSource={RelativeSource FindAncestor,AncestorType=local:ChoiceControl},Mode=OneTime}"> + <local:IconThemeImage IconSize="16" IconName="property-brush-solid" + IsSelected="{Binding IsChecked, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type RadioButton}}}"/> </RadioButton> </DataTemplate> </local:BrushChoiceTemplateSelector.SolidBrushTemplate> diff --git a/Xamarin.PropertyEditing.Windows/Themes/WinThemeManager.cs b/Xamarin.PropertyEditing.Windows/Themes/WinThemeManager.cs index 1136453..2371a68 100644 --- a/Xamarin.PropertyEditing.Windows/Themes/WinThemeManager.cs +++ b/Xamarin.PropertyEditing.Windows/Themes/WinThemeManager.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.Drawing; @@ -14,26 +14,28 @@ namespace Xamarin.PropertyEditing.Themes public class WinThemeManager : BaseThemeManager { - ResourceDictionary dark = new ResourceDictionary () { - Source = new Uri ("pack://application:,,,/Xamarin.PropertyEditing.Windows;component/Themes/VS.Dark.xaml") - }; - ResourceDictionary light = new ResourceDictionary () { - Source = new Uri ("pack://application:,,,/Xamarin.PropertyEditing.Windows;component/Themes/VS.Light.xaml") - }; - protected override void SetTheme () { switch (Theme) { case PropertyEditorTheme.Dark: - Application.Current.Resources.MergedDictionaries.Remove (light); - Application.Current.Resources.MergedDictionaries.Add (dark); + Application.Current.Resources.MergedDictionaries.Remove (this.light); + Application.Current.Resources.MergedDictionaries.Add (this.dark); break; case PropertyEditorTheme.Light: - Application.Current.Resources.MergedDictionaries.Remove (dark); - Application.Current.Resources.MergedDictionaries.Add (light); + Application.Current.Resources.MergedDictionaries.Remove (this.dark); + Application.Current.Resources.MergedDictionaries.Add (this.light); break; } } + + protected override string IconModifier => Theme == PropertyEditorTheme.Dark ? "~dark" : ""; + + ResourceDictionary dark = new ResourceDictionary () { + Source = new Uri ("pack://application:,,,/Xamarin.PropertyEditing.Windows;component/Themes/VS.Dark.xaml") + }; + ResourceDictionary light = new ResourceDictionary () { + Source = new Uri ("pack://application:,,,/Xamarin.PropertyEditing.Windows;component/Themes/VS.Light.xaml") + }; } } diff --git a/Xamarin.PropertyEditing.Windows/Xamarin.PropertyEditing.Windows.csproj b/Xamarin.PropertyEditing.Windows/Xamarin.PropertyEditing.Windows.csproj index 037d0d4..d01cddd 100644 --- a/Xamarin.PropertyEditing.Windows/Xamarin.PropertyEditing.Windows.csproj +++ b/Xamarin.PropertyEditing.Windows/Xamarin.PropertyEditing.Windows.csproj @@ -70,6 +70,8 @@ <Compile Include="DoubleToPercentageConverter.cs" /> <Compile Include="DoubleToQuantityConverter.cs" /> <Compile Include="TextBoxEx.cs" /> + <Compile Include="IconThemeImage.cs" /> + <Compile Include="MultiSourceImage.cs" /> <Compile Include="ToggleButtonEx.cs" /> <Compile Include="EditorPropertySelector.cs" /> <Compile Include="EnumEditorControl.cs" /> @@ -130,5 +132,23 @@ <Generator>MSBuild:Compile</Generator> </Page> </ItemGroup> + <ItemGroup> + <Resource Include="Icons\property-brush-none-16%402x.png" /> + <Resource Include="Icons\property-brush-none-16.png" /> + <Resource Include="Icons\property-brush-none-16~dark%402x.png" /> + <Resource Include="Icons\property-brush-none-16~dark.png" /> + <Resource Include="Icons\property-brush-none-16~dark~sel%402x.png" /> + <Resource Include="Icons\property-brush-none-16~dark~sel.png" /> + <Resource Include="Icons\property-brush-none-16~sel%402x.png" /> + <Resource Include="Icons\property-brush-none-16~sel.png" /> + <Resource Include="Icons\property-brush-solid-16%402x.png" /> + <Resource Include="Icons\property-brush-solid-16.png" /> + <Resource Include="Icons\property-brush-solid-16~dark%402x.png" /> + <Resource Include="Icons\property-brush-solid-16~dark.png" /> + <Resource Include="Icons\property-brush-solid-16~dark~sel%402x.png" /> + <Resource Include="Icons\property-brush-solid-16~dark~sel.png" /> + <Resource Include="Icons\property-brush-solid-16~sel%402x.png" /> + <Resource Include="Icons\property-brush-solid-16~sel.png" /> + </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> </Project> diff --git a/Xamarin.PropertyEditing/Themes/BaseThemeManager.cs b/Xamarin.PropertyEditing/Themes/BaseThemeManager.cs index 1431591..50bc00b 100644 --- a/Xamarin.PropertyEditing/Themes/BaseThemeManager.cs +++ b/Xamarin.PropertyEditing/Themes/BaseThemeManager.cs @@ -4,29 +4,34 @@ namespace Xamarin.PropertyEditing.Themes { public abstract class BaseThemeManager { - PropertyEditorTheme theme; - public BaseThemeManager () { NotifyThemeChanged (); } - protected abstract void SetTheme (); - public PropertyEditorTheme Theme { get { - return theme; + return this.theme; } set { - if (theme != value) { - theme = value; + if (this.theme != value) { + this.theme = value; NotifyThemeChanged (); } } } + public string GetIconName (string name, int size, bool selected = false) + => $"{name}-{size}{IconModifier}{(selected ? "~sel" : "")}"; + + protected abstract void SetTheme (); + + protected abstract string IconModifier { get; } + + PropertyEditorTheme theme; + void NotifyThemeChanged () { SetTheme (); |