diff options
12 files changed, 558 insertions, 34 deletions
diff --git a/Xamarin.PropertyEditing.Tests/MockControls/MockControl.cs b/Xamarin.PropertyEditing.Tests/MockControls/MockControl.cs index 585bb7f..0302d6f 100644 --- a/Xamarin.PropertyEditing.Tests/MockControls/MockControl.cs +++ b/Xamarin.PropertyEditing.Tests/MockControls/MockControl.cs @@ -15,10 +15,10 @@ namespace Xamarin.PropertyEditing.Tests.MockControls bool canWrite = true, bool flag = false, IEnumerable<Type> converterTypes = null, string description = null, bool constrained = true, ValueSources valueSources = ValueSources.Local | ValueSources.Default | ValueSources.Binding, - IReadOnlyList<InputMode> inputModes = null, PropertyVariationOption[] options = null, bool isUncommon = false, ITypeInfo realType = null) + IReadOnlyList<InputMode> inputModes = null, PropertyVariationOption[] options = null, bool isUncommon = false, ITypeInfo realType = null, bool ignoreEnum = false) { IPropertyInfo propertyInfo; - if (typeof(T).IsEnum) { + if (typeof(T).IsEnum && !ignoreEnum) { var underlyingType = typeof (T).GetEnumUnderlyingType (); var enumPropertyInfoType = typeof (MockEnumPropertyInfo<,>) .MakeGenericType (underlyingType, typeof (T)); diff --git a/Xamarin.PropertyEditing.Tests/MockControls/MockSampleControl.cs b/Xamarin.PropertyEditing.Tests/MockControls/MockSampleControl.cs index 8fec0e1..a3c3d1f 100644 --- a/Xamarin.PropertyEditing.Tests/MockControls/MockSampleControl.cs +++ b/Xamarin.PropertyEditing.Tests/MockControls/MockSampleControl.cs @@ -11,6 +11,7 @@ namespace Xamarin.PropertyEditing.Tests.MockControls { public MockSampleControl () { + AddProperty<AutoResizingFlags> ("Autoresizing", ReadWrite, valueSources: ValueSources.Local, ignoreEnum: true); AddProperty<TimeSpan> ("TimeSpan", ReadWrite, valueSources: ValueSources.Local | ValueSources.Resource | ValueSources.Binding); AddProperty<TimeSpan> ("TimeSpanReadOnly", ReadOnly, canWrite: false, valueSources: ValueSources.Local | ValueSources.Resource | ValueSources.Binding); AddProperty<bool> ("Boolean", ReadWrite, valueSources: ValueSources.Local | ValueSources.Resource | ValueSources.Binding); diff --git a/Xamarin.PropertyEditing.Windows/AutoResizingMaskEditorControl.cs b/Xamarin.PropertyEditing.Windows/AutoResizingMaskEditorControl.cs new file mode 100644 index 0000000..23ba339 --- /dev/null +++ b/Xamarin.PropertyEditing.Windows/AutoResizingMaskEditorControl.cs @@ -0,0 +1,116 @@ +using System; +using System.ComponentModel; +using System.Windows; +using System.Windows.Automation; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using Xamarin.PropertyEditing.Drawing; +using Xamarin.PropertyEditing.ViewModels; + +namespace Xamarin.PropertyEditing.Windows +{ + [TemplatePart (Name = "sizingButton", Type = typeof(ButtonBase))] + [TemplatePart (Name = "windowRect", Type = typeof (FrameworkElement))] + [TemplatePart (Name = "elementRect", Type = typeof (FrameworkElement))] + internal class AutoResizingMaskEditorControl + : PropertyEditorControl + { + public AutoResizingMaskEditorControl () + { + DataContextChanged += OnDataContextChanged; + } + + public override void OnApplyTemplate () + { + base.OnApplyTemplate (); + + this.sizingButton = GetTemplateChild ("sizingButton") as ButtonBase; + if (this.sizingButton == null) + throw new InvalidOperationException ($"Template for {nameof(AutoResizingMaskEditorControl)} must have a sizingButton"); + + this.window = GetTemplateChild ("windowRect") as FrameworkElement; + if (this.window == null) + throw new InvalidOperationException ($"Template for {nameof(AutoResizingMaskEditorControl)} must have a windowRect"); + + this.elementVisual = GetTemplateChild ("elementRect") as FrameworkElement; + if (this.elementVisual == null) + throw new InvalidOperationException ($"Template for {nameof(AutoResizingMaskEditorControl)} must have a elementRect"); + + this.window.SizeChanged += OnPreviewWindowSizeChanged; + + UpdateSizeName(); + UpdateVisual(); + } + + private AutoResizingPropertyViewModel vm; + private ButtonBase sizingButton; + private FrameworkElement elementVisual, window; + + private void OnDataContextChanged (object sender, DependencyPropertyChangedEventArgs e) + { + if (this.vm != null) { + this.vm.PropertyChanged -= OnViewModelPropertyChanged; + } + + this.vm = e.NewValue as AutoResizingPropertyViewModel; + if (this.vm != null) { + this.vm.PropertyChanged += OnViewModelPropertyChanged; + } + + UpdateSizeName(); + } + + private void OnViewModelPropertyChanged (object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == nameof(AutoResizingPropertyViewModel.WidthSizable) || e.PropertyName == nameof(AutoResizingPropertyViewModel.HeightSizable)) { + UpdateSizeName (); + UpdateVisual(); + } else if (e.PropertyName == nameof(AutoResizingPropertyViewModel.LeftMarginFixed) + || e.PropertyName == nameof(AutoResizingPropertyViewModel.RightMarginFixed) + || e.PropertyName == nameof(AutoResizingPropertyViewModel.TopMarginFixed) + || e.PropertyName == nameof(AutoResizingPropertyViewModel.BottomMarginFixed)) { + UpdateVisual(); + } + } + + private void OnPreviewWindowSizeChanged (object sender, SizeChangedEventArgs e) + { + UpdateVisual (); + } + + private void UpdateVisual () + { + if (this.vm == null) + return; + + var elementRect = this.vm.GetPreviewElementRectangle (new CommonSize (this.window.ActualWidth, this.window.ActualHeight), this.vm.Value); + Canvas.SetLeft (this.elementVisual, elementRect.X); + Canvas.SetTop (this.elementVisual, elementRect.Y); + this.elementVisual.Width = elementRect.Width; + this.elementVisual.Height = elementRect.Height; + } + + private void UpdateSizeName () + { + if (this.sizingButton == null) + return; + + string name = null; + if (this.vm != null) { + string current; + if (!this.vm.HeightSizable && !this.vm.WidthSizable) + current = Properties.Resources.AutoresizingFixedSized; + else if (this.vm.HeightSizable && !this.vm.WidthSizable) + current = Properties.Resources.AutoresizingHeightSizable; + else if (!this.vm.HeightSizable && this.vm.WidthSizable) + current = Properties.Resources.AutoresizingWidthSizable; + else + current = Properties.Resources.AutoresizingWidthHeightSizable; + + name = String.Format (Properties.Resources.AutoresizingSizingName, current); + } + + AutomationProperties.SetName (this.sizingButton, name); + } + } +} diff --git a/Xamarin.PropertyEditing.Windows/EditorPropertySelector.cs b/Xamarin.PropertyEditing.Windows/EditorPropertySelector.cs index f970cb3..a2b4e6a 100644 --- a/Xamarin.PropertyEditing.Windows/EditorPropertySelector.cs +++ b/Xamarin.PropertyEditing.Windows/EditorPropertySelector.cs @@ -113,6 +113,7 @@ namespace Xamarin.PropertyEditing.Windows { typeof(TypePropertyViewModel), typeof(TypeEditorControl) }, { typeof(CollectionPropertyViewModel), typeof(CollectionEditor) }, { typeof(RatioViewModel), typeof(RatioEditorControl) }, + { typeof(AutoResizingPropertyViewModel), typeof(AutoResizingMaskEditorControl) } }; } } diff --git a/Xamarin.PropertyEditing.Windows/Themes/Resources.xaml b/Xamarin.PropertyEditing.Windows/Themes/Resources.xaml index 4a883d6..1996520 100644 --- a/Xamarin.PropertyEditing.Windows/Themes/Resources.xaml +++ b/Xamarin.PropertyEditing.Windows/Themes/Resources.xaml @@ -6,7 +6,8 @@ xmlns:prop="clr-namespace:Xamarin.PropertyEditing.Properties;assembly=Xamarin.PropertyEditing" xmlns:system="clr-namespace:System;assembly=mscorlib" xmlns:vm="clr-namespace:Xamarin.PropertyEditing.ViewModels;assembly=Xamarin.PropertyEditing" - xmlns:pe="clr-namespace:Xamarin.PropertyEditing;assembly=Xamarin.PropertyEditing"> + xmlns:pe="clr-namespace:Xamarin.PropertyEditing;assembly=Xamarin.PropertyEditing" + xmlns:common="clr-namespace:Xamarin.PropertyEditing.Common;assembly=Xamarin.PropertyEditing"> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="MenuButtonStyle.xaml" /> @@ -414,6 +415,125 @@ </Setter> </Style> + <Style TargetType="local:AutoResizingMaskEditorControl"> + <Setter Property="UseLayoutRounding" Value="True" /> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="local:AutoResizingMaskEditorControl"> + <ControlTemplate.Resources> + <Style x:Key="MarginButton" TargetType="ToggleButton"> + <Setter Property="BorderThickness" Value="0" /> + <Setter Property="Foreground" Value="{DynamicResource GuidelineEnabledForegroundBrush}" /> + <Setter Property="Background" Value="Transparent" /> + <Setter Property="RenderTransformOrigin" Value="0.5,0.5" /> + <Setter Property="Padding" Value="0" /> + <Setter Property="VerticalAlignment" Value="Center" /> + <Setter Property="HorizontalAlignment" Value="Center" /> + <Setter Property="Template"> + <Setter.Value> + <ControlTemplate TargetType="ToggleButton"> + <Border BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" Margin="{TemplateBinding Margin}" Padding="{TemplateBinding Padding}" UseLayoutRounding="{TemplateBinding UseLayoutRounding}"> + <Polyline Stroke="{TemplateBinding Foreground}" Points="4,15 4,12 4,15 4,18 4,15 26,15 26,15 26,12 26,15 26,18 26,15" Height="30" Width="30" /> + </Border> + </ControlTemplate> + </Setter.Value> + </Setter> + <Style.Triggers> + <Trigger Property="IsChecked" Value="False"> + <Setter Property="Foreground" Value="{DynamicResource GuidelineDisabledForegroundBrush}" /> + </Trigger> + </Style.Triggers> + </Style> + </ControlTemplate.Resources> + + <Grid VerticalAlignment="Top" Height="100" UseLayoutRounding="{TemplateBinding UseLayoutRounding}"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="Auto"/> + <ColumnDefinition /> + </Grid.ColumnDefinitions> + + <Border Grid.Row="0" Grid.Column="0" BorderBrush="{DynamicResource InputBorderBrush}" BorderThickness="1" Background="{DynamicResource InputBackgroundBrush}"> + <Grid> + <Grid.RowDefinitions> + <RowDefinition /> + <RowDefinition Height="40" /> + <RowDefinition /> + </Grid.RowDefinitions> + <Grid.ColumnDefinitions> + <ColumnDefinition /> + <ColumnDefinition Width="40" /> + <ColumnDefinition /> + </Grid.ColumnDefinitions> + <ToggleButton Style="{StaticResource MarginButton}" AutomationProperties.Name="{x:Static prop:Resources.AutoresizingLeftMarginName}" IsChecked="{Binding LeftMarginFixed,Mode=TwoWay}" Grid.Row="1" Grid.Column="0" /> + <ToggleButton Style="{StaticResource MarginButton}" AutomationProperties.Name="{x:Static prop:Resources.AutoresizingTopMarginName}" IsChecked="{Binding TopMarginFixed,Mode=TwoWay}" Grid.Row="0" Grid.Column="1"> + <ToggleButton.RenderTransform> + <RotateTransform Angle="90" /> + </ToggleButton.RenderTransform> + </ToggleButton> + <ToggleButton Style="{StaticResource MarginButton}" AutomationProperties.Name="{x:Static prop:Resources.AutoresizingRightMarginName}" IsChecked="{Binding RightMarginFixed,Mode=TwoWay}" Grid.Row="1" Grid.Column="2" /> + <ToggleButton Style="{StaticResource MarginButton}" AutomationProperties.Name="{x:Static prop:Resources.AutoresizingBottomMarginName}" IsChecked="{Binding BottomMarginFixed,Mode=TwoWay}" Grid.Row="2" Grid.Column="1"> + <ToggleButton.RenderTransform> + <RotateTransform Angle="90" /> + </ToggleButton.RenderTransform> + </ToggleButton> + + <Button Name="sizingButton" Grid.Row="1" Grid.Column="1" Command="{Binding CycleSizingCommand,Mode=OneTime}" BorderThickness="1" BorderBrush="{DynamicResource GuidelineDisabledForegroundBrush}" Background="Transparent" Content="{Binding}" AutomationProperties.HelpText="{x:Static prop:Resources.AutoresizingSizingHelpText}"> + <Button.ContentTemplate> + <DataTemplate DataType="vm:AutoResizingPropertyViewModel"> + <Grid> + <Polyline Name="widthSizable" Stroke="{DynamicResource GuidelineEnabledForegroundBrush}" Points="0,15 0.2,14.8 0,15 0.2,15.2 0,15 30,15 30,15 29.8,14.8 30,15 29.8,15.2 30,15" Width="30" Height="30" SnapsToDevicePixels="True" /> + <Polyline Name="heightSizable" Stroke="{DynamicResource GuidelineEnabledForegroundBrush}" Points="15,0 14.8,0.2 15,0 15.2,0.2 15,0 15,30 15,30 14.8,29.8 15,30 15.2,29.8 15,30" Width="30" Height="30" SnapsToDevicePixels="True" /> + </Grid> + <DataTemplate.Triggers> + <DataTrigger Binding="{Binding HeightSizable}" Value="False"> + <Setter TargetName="heightSizable" Property="Stroke" Value="{DynamicResource GuidelineDisabledForegroundBrush}" /> + </DataTrigger> + <DataTrigger Binding="{Binding WidthSizable}" Value="False"> + <Setter TargetName="widthSizable" Property="Stroke" Value="{DynamicResource GuidelineDisabledForegroundBrush}" /> + </DataTrigger> + </DataTemplate.Triggers> + </DataTemplate> + </Button.ContentTemplate> + </Button> + </Grid> + </Border> + + <Border Grid.Row="0" Grid.Column="1" BorderBrush="{DynamicResource InputBorderBrush}" BorderThickness="1" Background="{DynamicResource InputBackgroundBrush}" Margin="2,0,0,0"> + <Border Name="osBorder" Margin="2" Background="{DynamicResource ExampleWindowBackgroundBrush}" BorderThickness="0"> + <Grid> + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition /> + </Grid.RowDefinitions> + + <Border Grid.Row="0" BorderThickness="0" Background="{DynamicResource ExampleWindowTitleBackgroundBrush}" Height="4" /> + <Canvas Grid.Row="1" Margin="6,6,0,0"> + <Canvas.Resources> + <Storyboard FillBehavior="Stop" RepeatBehavior="Forever" AutoReverse="True" Duration="0:0:0.5" x:Key="GrowStoryboard" Storyboard.TargetName="windowRect"> + <DoubleAnimation Storyboard.TargetProperty="Width" To="{Binding ElementName=osBorder,Path=ActualWidth}" /> + <DoubleAnimation Storyboard.TargetProperty="Height" To="{Binding ElementName=osBorder,Path=ActualHeight}" /> + </Storyboard> + </Canvas.Resources> + <Canvas.Triggers> + <EventTrigger RoutedEvent="MouseEnter"> + <BeginStoryboard Storyboard="{StaticResource GrowStoryboard}" Name="BeginGrowStoryboard" /> + </EventTrigger> + <EventTrigger RoutedEvent="MouseLeave"> + <RemoveStoryboard BeginStoryboardName="BeginGrowStoryboard" /> + </EventTrigger> + </Canvas.Triggers> + <Rectangle Name="windowRect" Fill="White" Width="30" Height="30" Margin="0" HorizontalAlignment="Left" VerticalAlignment="Top" SnapsToDevicePixels="False" /> + <Rectangle Name="elementRect" Fill="Red" Margin="0" HorizontalAlignment="Left" VerticalAlignment="Top" SnapsToDevicePixels="False" /> + </Canvas> + </Grid> + </Border> + </Border> + </Grid> + </ControlTemplate> + </Setter.Value> + </Setter> + </Style> + <Style TargetType="local:ObjectEditorControl"> <Setter Property="Template"> <Setter.Value> diff --git a/Xamarin.PropertyEditing.Windows/Themes/VS.Dark.xaml b/Xamarin.PropertyEditing.Windows/Themes/VS.Dark.xaml index cb76cf1..113401b 100644 --- a/Xamarin.PropertyEditing.Windows/Themes/VS.Dark.xaml +++ b/Xamarin.PropertyEditing.Windows/Themes/VS.Dark.xaml @@ -20,6 +20,11 @@ <SolidColorBrush x:Key="VariantBackgroundBrush">#ABABAB</SolidColorBrush> <SolidColorBrush x:Key="VariantLineBrush">#5E5E5E</SolidColorBrush> + <SolidColorBrush x:Key="GuidelineDisabledForegroundBrush">#777777</SolidColorBrush> + <SolidColorBrush x:Key="GuidelineEnabledForegroundBrush">#F56D4F</SolidColorBrush> + <SolidColorBrush x:Key="ExampleWindowTitleBackgroundBrush">#575757</SolidColorBrush> + <SolidColorBrush x:Key="ExampleWindowBackgroundBrush">#7D7D7F</SolidColorBrush> + <SolidColorBrush x:Key="AdvancedExpanderCollapsedForegroundBrush">#F1F1F1</SolidColorBrush> <SolidColorBrush x:Key="AdvancedExpanderMouseOverForegroundBrush">#007ACC</SolidColorBrush> <SolidColorBrush x:Key="AdvancedExpanderMouseOverBorderBrush">#3E3E40</SolidColorBrush> diff --git a/Xamarin.PropertyEditing.Windows/Xamarin.PropertyEditing.Windows.csproj b/Xamarin.PropertyEditing.Windows/Xamarin.PropertyEditing.Windows.csproj index b21e249..fd84130 100644 --- a/Xamarin.PropertyEditing.Windows/Xamarin.PropertyEditing.Windows.csproj +++ b/Xamarin.PropertyEditing.Windows/Xamarin.PropertyEditing.Windows.csproj @@ -53,6 +53,7 @@ <Link>Properties\GlobalAssemblyInfo.cs</Link> </Compile> <Compile Include="ArrangeModeLocalizedConverter.cs" /> + <Compile Include="AutoResizingMaskEditorControl.cs" /> <Compile Include="BoolEditorControl.cs" /> <Compile Include="BoolsToVisibilityConverter.cs" /> <Compile Include="BrushBoxControl.cs" /> diff --git a/Xamarin.PropertyEditing/Common/AutoResizingFlags.cs b/Xamarin.PropertyEditing/Common/AutoResizingFlags.cs new file mode 100644 index 0000000..8c21b55 --- /dev/null +++ b/Xamarin.PropertyEditing/Common/AutoResizingFlags.cs @@ -0,0 +1,19 @@ +using System; + +namespace Xamarin.PropertyEditing.Common +{ + [Flags] + public enum AutoResizingFlags + { + None = 0, + FlexibleLeftMargin = 1 << 0, + FlexibleWidth = 1 << 1, + FlexibleRightMargin = 1 << 2, + FlexibleTopMargin = 1 << 3, + FlexibleHeight = 1 << 4, + FlexibleBottomMargin = 1 << 5, + FlexibleMargins = FlexibleBottomMargin | FlexibleTopMargin | FlexibleLeftMargin | FlexibleRightMargin, + FlexibleDimensions = FlexibleHeight | FlexibleWidth, + All = FlexibleMargins | FlexibleDimensions + } +} diff --git a/Xamarin.PropertyEditing/Properties/Resources.Designer.cs b/Xamarin.PropertyEditing/Properties/Resources.Designer.cs index c8cc438..1d9813f 100644 --- a/Xamarin.PropertyEditing/Properties/Resources.Designer.cs +++ b/Xamarin.PropertyEditing/Properties/Resources.Designer.cs @@ -1270,5 +1270,71 @@ namespace Xamarin.PropertyEditing.Properties { return ResourceManager.GetString("PropertyButtonName", resourceCulture); } } + + public static string AutoresizingBottomMarginName { + get { + return ResourceManager.GetString("AutoresizingBottomMarginName", resourceCulture); + } + } + + public static string AutoresizingFixedSized { + get { + return ResourceManager.GetString("AutoresizingFixedSized", resourceCulture); + } + } + + public static string AutoresizingHeightSizable { + get { + return ResourceManager.GetString("AutoresizingHeightSizable", resourceCulture); + } + } + + public static string AutoresizingLeftMarginName { + get { + return ResourceManager.GetString("AutoresizingLeftMarginName", resourceCulture); + } + } + + public static string AutoresizingRightMarginName { + get { + return ResourceManager.GetString("AutoresizingRightMarginName", resourceCulture); + } + } + + public static string AutoresizingSizingHelpText { + get { + return ResourceManager.GetString("AutoresizingSizingHelpText", resourceCulture); + } + } + + public static string AutoresizingSizingName { + get { + return ResourceManager.GetString("AutoresizingSizingName", resourceCulture); + } + } + + public static string AutoresizingTopMarginName { + get { + return ResourceManager.GetString("AutoresizingTopMarginName", resourceCulture); + } + } + + public static string AutoresizingWidthHeightSizable { + get { + return ResourceManager.GetString("AutoresizingWidthHeightSizable", resourceCulture); + } + } + + public static string AutoresizingWidthSizable { + get { + return ResourceManager.GetString("AutoresizingWidthSizable", resourceCulture); + } + } + + public static string Autosizing { + get { + return ResourceManager.GetString("Autosizing", resourceCulture); + } + } } } diff --git a/Xamarin.PropertyEditing/Properties/Resources.resx b/Xamarin.PropertyEditing/Properties/Resources.resx index e778724..6713737 100644 --- a/Xamarin.PropertyEditing/Properties/Resources.resx +++ b/Xamarin.PropertyEditing/Properties/Resources.resx @@ -1,17 +1,17 @@ <?xml version="1.0" encoding="utf-8"?> <root> - <!-- - Microsoft ResX Schema - + <!-- + 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 + + 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> @@ -26,36 +26,36 @@ <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 + + 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 + + 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 + + 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 + + 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 + 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 + 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 + value : The object must be serialized into a byte array : using a System.ComponentModel.TypeConverter : and then encoded with base64 encoding. --> @@ -633,7 +633,7 @@ <data name="AccessibilityDateTime" xml:space="preserve"> <value>{0} DateTime Editor</value> <comment>Editor for DateTime Value</comment> - </data> + </data> <data name="AccessibilityXEditor" xml:space="preserve"> <value>{0} X Editor</value> <comment>Editor for X Value</comment> @@ -649,7 +649,7 @@ <data name="AccessibilityHeightEditor" xml:space="preserve"> <value>{0} Height Editor</value> <comment>Editor for Height Value</comment> - </data> + </data> <data name="ArrangeByLabel" xml:space="preserve"> <value>Arrange By:</value> </data> @@ -725,7 +725,7 @@ <data name="AccessibilityPathEditor" xml:space="preserve"> <value>{0} {1} Path Editor</value> <comment>Editor for File/Directory Path Editor</comment> - </data> + </data> <data name="ChooseFileOrDirectory" xml:space="preserve"> <value>Choose a {0}</value> <comment>Choose a File or Directory</comment> @@ -751,7 +751,7 @@ </data> <data name="RemoveVariant" xml:space="preserve"> <value>Remove Variant</value> - </data> + </data> <data name="CreateBindingTitle" xml:space="preserve"> <value>Create Binding</value> <comment>Create Binding for Object.Property</comment> @@ -809,4 +809,41 @@ <data name="PropertyButtonName" xml:space="preserve"> <value>Advanced options</value> </data> + <data name="AutoresizingLeftMarginName" xml:space="preserve"> + <value>Left margin fixed</value> + </data> + <data name="Autosizing" xml:space="preserve"> + <value>Autosizing</value> + </data> + <data name="Example" xml:space="preserve"> + <value>Example</value> + </data> + <data name="AutoresizingBottomMarginName" xml:space="preserve"> + <value>Bottom margin fixed</value> + </data> + <data name="AutoresizingRightMarginName" xml:space="preserve"> + <value>Right margin fixed</value> + </data> + <data name="AutoresizingSizingHelpText" xml:space="preserve"> + <value>Cycles through width and height sizable</value> + </data> + <data name="AutoresizingTopMarginName" xml:space="preserve"> + <value>Top margin fixed</value> + </data> + <data name="AutoresizingFixedSized" xml:space="preserve"> + <value>fixed size</value> + </data> + <data name="AutoresizingHeightSizable" xml:space="preserve"> + <value>height sizable</value> + </data> + <data name="AutoresizingSizingName" xml:space="preserve"> + <value>Sizing, {0}</value> + <comment>Name, {Current State}</comment> + </data> + <data name="AutoresizingWidthHeightSizable" xml:space="preserve"> + <value>width and height sizable</value> + </data> + <data name="AutoresizingWidthSizable" xml:space="preserve"> + <value>width sizable</value> + </data> </root>
\ No newline at end of file diff --git a/Xamarin.PropertyEditing/ViewModels/AutoResizingPropertyViewModel.cs b/Xamarin.PropertyEditing/ViewModels/AutoResizingPropertyViewModel.cs new file mode 100644 index 0000000..2f29af8 --- /dev/null +++ b/Xamarin.PropertyEditing/ViewModels/AutoResizingPropertyViewModel.cs @@ -0,0 +1,157 @@ +using System.Collections.Generic; +using System.Windows.Input; +using Xamarin.PropertyEditing.Common; +using Xamarin.PropertyEditing.Drawing; + +namespace Xamarin.PropertyEditing.ViewModels +{ + internal class AutoResizingPropertyViewModel + : PropertyViewModel<AutoResizingFlags> + { + public AutoResizingPropertyViewModel (TargetPlatform platform, IPropertyInfo property, IEnumerable<IObjectEditor> editors, PropertyVariation variation = null) + : base (platform, property, editors, variation) + { + ToggleMaskCommand = new RelayCommand<AutoResizingFlags> (ToggleFlag); + CycleSizingCommand = new RelayCommand (OnCycleSizing); + } + + public ICommand ToggleMaskCommand + { + get; + } + + public ICommand CycleSizingCommand + { + get; + } + + public bool LeftMarginFixed + { + get => (Value & AutoResizingFlags.FlexibleLeftMargin) != AutoResizingFlags.FlexibleLeftMargin; + set => SetFlag (AutoResizingFlags.FlexibleLeftMargin, !value); + } + + public bool RightMarginFixed + { + get => (Value & AutoResizingFlags.FlexibleRightMargin) != AutoResizingFlags.FlexibleRightMargin; + set => SetFlag (AutoResizingFlags.FlexibleRightMargin, !value); + } + + public bool TopMarginFixed + { + get => (Value & AutoResizingFlags.FlexibleTopMargin) != AutoResizingFlags.FlexibleTopMargin; + set => SetFlag (AutoResizingFlags.FlexibleTopMargin, !value); + } + + public bool BottomMarginFixed + { + get => (Value & AutoResizingFlags.FlexibleBottomMargin) != AutoResizingFlags.FlexibleBottomMargin; + set => SetFlag (AutoResizingFlags.FlexibleBottomMargin, !value); + } + + public bool HeightSizable + { + get => (Value & AutoResizingFlags.FlexibleHeight) == AutoResizingFlags.FlexibleHeight; + set => SetFlag (AutoResizingFlags.FlexibleHeight, value); + } + + public bool WidthSizable + { + get => (Value & AutoResizingFlags.FlexibleWidth) == AutoResizingFlags.FlexibleWidth; + set => SetFlag (AutoResizingFlags.FlexibleWidth, value); + } + + public CommonRectangle GetPreviewElementRectangle (CommonSize window, AutoResizingFlags flags) + { + const int Offset = 5; + const double multiplier = .75; + double width = 10, height = 10; + double left; + bool fixedLeft = !flags.HasFlag (AutoResizingFlags.FlexibleLeftMargin), + fixedRight = !flags.HasFlag (AutoResizingFlags.FlexibleRightMargin); + + if (fixedLeft) + left = Offset; + else if (fixedRight) + left = window.Width - Offset - width; + else + left = (window.Width / 2) - (width / 2); + + if (flags.HasFlag (AutoResizingFlags.FlexibleWidth)) { + if (fixedRight && fixedLeft) { + width = window.Width - (Offset * 2); + } else if (fixedRight) { + left = window.Width - (window.Width * multiplier); + width = window.Width - left - Offset; + } else if (fixedLeft) { + width = (window.Width * multiplier) - Offset; + } else { + width = window.Width * multiplier; + left = (window.Width - width) / 2; + } + } + + double top; + bool fixedTop = !flags.HasFlag (AutoResizingFlags.FlexibleTopMargin), + fixedBottom = !flags.HasFlag (AutoResizingFlags.FlexibleBottomMargin); + + if (fixedTop) + top = Offset; + else if (fixedBottom) + top = window.Height - Offset - height; + else + top = (window.Height / 2) - (height / 2); + + if (flags.HasFlag (AutoResizingFlags.FlexibleHeight)) { + if (fixedBottom && fixedTop) { + height = window.Height - (Offset * 2); + } else if (fixedBottom) { + top = window.Height - (window.Height * multiplier); + height = window.Height - top - Offset; + } else if (fixedTop) { + height = (window.Height * multiplier) - Offset; + } else { + height = window.Height * multiplier; + top = (window.Height - height) / 2; + } + } + + return new CommonRectangle (left, top, width, height); + } + + protected override void OnValueChanged () + { + base.OnValueChanged (); + + OnPropertyChanged (nameof(LeftMarginFixed)); + OnPropertyChanged (nameof(RightMarginFixed)); + OnPropertyChanged (nameof(TopMarginFixed)); + OnPropertyChanged (nameof(BottomMarginFixed)); + OnPropertyChanged (nameof(HeightSizable)); + OnPropertyChanged (nameof(WidthSizable)); + } + + private void SetFlag (AutoResizingFlags flag, bool set) + { + Value = (set) ? Value | flag : Value & ~flag; + } + + private void ToggleFlag (AutoResizingFlags flag) + { + Value = Value ^ flag; + } + + private void OnCycleSizing () + { + if (!WidthSizable && !HeightSizable) { + WidthSizable = true; + } else if (WidthSizable && !HeightSizable) { + HeightSizable = true; + } else if (WidthSizable && HeightSizable) { + WidthSizable = false; + } else if (!WidthSizable && HeightSizable) { + HeightSizable = false; + } + } + } +} diff --git a/Xamarin.PropertyEditing/ViewModels/PropertiesViewModel.cs b/Xamarin.PropertyEditing/ViewModels/PropertiesViewModel.cs index 8e5cceb..5862ad9 100644 --- a/Xamarin.PropertyEditing/ViewModels/PropertiesViewModel.cs +++ b/Xamarin.PropertyEditing/ViewModels/PropertiesViewModel.cs @@ -655,6 +655,7 @@ namespace Xamarin.PropertyEditing.ViewModels { typeof(object), (tp,p,e,v) => new ObjectPropertyViewModel (tp, p, e, v) }, { typeof(ITypeInfo), (tp,p,e,v) => new TypePropertyViewModel (tp, p, e, v) }, { typeof(CommonRatio), (tp, p, e, v) => new RatioViewModel (tp, p, e, v) }, + { typeof(AutoResizingFlags), (tp, p, e, v) => new AutoResizingPropertyViewModel (tp, p, e, v) }, }; } } |