diff --git a/Changelog.md b/Changelog.md index 4438b45f1..a224026df 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,21 @@ # Changelog for Fluent.Ribbon +## 3.6.1 + +- ### Bug fixes + + - [#29](../../issues/29) - Backstage flicker + - [#112](../../issues/112) - Backstage flicker + - [#192](../../issues/192) - Background of RibbonGroupBox can't be set/changed + - [#197](../../issues/197) - Some adaptions to better align with Office 2013 + - [#200](../../issues/200) - KeyTips in SplitButton no longer work + - [#201](../../issues/201) - Cannot change Fluent.Button Icon Dynamically + - [#202](../../issues/202) - Center the button labels in Office 2013 theme + - [#206](../../issues/206) - Center alignment button inside RIbbonGroupBox + - [#214](../../issues/214) - Assign a StringFormat binding to a RibbonGroupBox Header + +Commits: [v3.6.0...v3.6.1](../../compare/v3.6.0...v3.6.1) + ## 3.6.0 - ### Bug fixes diff --git a/Fluent/Adorners/KeyTipAdorner.cs b/Fluent/Adorners/KeyTipAdorner.cs index 9d129e5e6..365f72f48 100644 --- a/Fluent/Adorners/KeyTipAdorner.cs +++ b/Fluent/Adorners/KeyTipAdorner.cs @@ -1095,7 +1095,15 @@ protected override Visual GetVisualChild(int index) [Conditional("DEBUG")] private void Log(string format, params object[] args) { - Debug.WriteLine("[" + this.AdornedElement.GetType().Name + "] " + string.Format(format, args)); + var name = this.AdornedElement.GetType().Name; + + var headeredControl = this.AdornedElement as IHeaderedControl; + if (headeredControl != null) + { + name += string.Format(" ({0})", headeredControl.Header); + } + + Debug.WriteLine("[" + name + "] " + string.Format(format, args), "KeyTipAdorner"); } #endregion diff --git a/Fluent/AttachedProperties/RibbonProperties.cs b/Fluent/AttachedProperties/RibbonProperties.cs index 57adf80f2..0c93ac927 100644 --- a/Fluent/AttachedProperties/RibbonProperties.cs +++ b/Fluent/AttachedProperties/RibbonProperties.cs @@ -31,6 +31,9 @@ public static void SetTitleBarHeight(UIElement element, double value) /// /// Gets TitleBarHeight for element /// + [AttachedPropertyBrowsableForType(typeof(Ribbon))] + [AttachedPropertyBrowsableForType(typeof(RibbonTitleBar))] + [AttachedPropertyBrowsableForType(typeof(RibbonWindow))] public static double GetTitleBarHeight(UIElement element) { return (double)element.GetValue(TitleBarHeightProperty); diff --git a/Fluent/Controls/BackstageAdorner.cs b/Fluent/Controls/BackstageAdorner.cs index 8f6440b46..0599a5ae7 100644 --- a/Fluent/Controls/BackstageAdorner.cs +++ b/Fluent/Controls/BackstageAdorner.cs @@ -20,8 +20,6 @@ namespace Fluent /// internal class BackstageAdorner : Adorner { - #region Fields - // Backstage private readonly Backstage backstage; @@ -31,10 +29,6 @@ internal class BackstageAdorner : Adorner // Collection of visual children private readonly VisualCollection visualChildren; - #endregion - - #region Constructors - /// /// Constructor /// @@ -82,16 +76,6 @@ public void Clear() this.visualChildren.Clear(); } - #endregion - - // Adorner offset from top of window - private double GetTopOffset() - { - var topOffset = this.backstage.TranslatePoint(new Point(0, this.backstage.ActualHeight), this.AdornedElement).Y; - - return topOffset; - } - #region Layout & Visual Children /// @@ -104,9 +88,7 @@ private double GetTopOffset() /// The actual size used protected override Size ArrangeOverride(Size finalSize) { - var topOffset = this.GetTopOffset(); - - this.backstageContent.Arrange(new Rect(0, topOffset, finalSize.Width, Math.Max(0, finalSize.Height - topOffset))); + this.backstageContent.Arrange(new Rect(0, 0, finalSize.Width, Math.Max(0, finalSize.Height))); return finalSize; } @@ -119,10 +101,8 @@ protected override Size ArrangeOverride(Size finalSize) /// protected override Size MeasureOverride(Size constraint) { - var topOffset = this.GetTopOffset(); - // TODO: fix it! (below ugly workaround) in measureoverride we cannot get RenderSize, we must use DesiredSize - this.backstageContent.Measure(new Size(this.AdornedElement.RenderSize.Width, Math.Max(0, this.AdornedElement.RenderSize.Height - topOffset))); + this.backstageContent.Measure(new Size(this.AdornedElement.RenderSize.Width, Math.Max(0, this.AdornedElement.RenderSize.Height))); return this.AdornedElement.RenderSize; } diff --git a/Fluent/Controls/Button.cs b/Fluent/Controls/Button.cs index ae4d9dab9..9957f4b56 100644 --- a/Fluent/Controls/Button.cs +++ b/Fluent/Controls/Button.cs @@ -164,6 +164,25 @@ public bool IsDefinitive #endregion + #region CornerRadius + + /// + /// Gets or sets the CornerRadius for the element + /// + public CornerRadius CornerRadius + { + get { return (CornerRadius)this.GetValue(CornerRadiusProperty); } + set { this.SetValue(CornerRadiusProperty, value); } + } + + /// + /// Using a DependencyProperty as the backing store for CornerRadius. This enables animation, styling, binding, etc... + /// + public static readonly DependencyProperty CornerRadiusProperty = + DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(Button), new PropertyMetadata(default(CornerRadius))); + + #endregion CornerRadius + #endregion #region Constructors diff --git a/Fluent/Controls/RibbonGroupBox.cs b/Fluent/Controls/RibbonGroupBox.cs index 0fff507ea..4ee381b8c 100644 --- a/Fluent/Controls/RibbonGroupBox.cs +++ b/Fluent/Controls/RibbonGroupBox.cs @@ -232,9 +232,9 @@ private void UpdateScalableControlSubscribing(bool registerEvents) /// /// Gets or sets group box header /// - public object Header + public string Header { - get { return this.GetValue(HeaderProperty); } + get { return (string)this.GetValue(HeaderProperty); } set { this.SetValue(HeaderProperty, value); } } @@ -242,7 +242,14 @@ public object Header /// Using a DependencyProperty as the backing store for Header. This enables animation, styling, binding, etc... /// public static readonly DependencyProperty HeaderProperty = - RibbonControl.HeaderProperty.AddOwner(typeof(RibbonGroupBox)); + DependencyProperty.Register("Header", typeof(string), typeof(RibbonGroupBox), new UIPropertyMetadata()); + + object IHeaderedControl.Header + { + get { return this.Header; } + + set { this.Header = (string)value; } + } #endregion diff --git a/Fluent/Controls/SplitButton.cs b/Fluent/Controls/SplitButton.cs index 36559a893..a08b7108a 100644 --- a/Fluent/Controls/SplitButton.cs +++ b/Fluent/Controls/SplitButton.cs @@ -40,20 +40,16 @@ protected override IEnumerator LogicalChildren { get { - if (this.Icon != null) + var baseEnumerator = base.LogicalChildren; + while (baseEnumerator.MoveNext()) { - yield return this.Icon; + yield return baseEnumerator.Current; } if (this.button != null) { yield return this.button; } - - foreach (var item in this.Items) - { - yield return item; - } } } diff --git a/Fluent/Converters/ObjectToImageConverter.cs b/Fluent/Converters/ObjectToImageConverter.cs index 1045f4366..385dcdd96 100644 --- a/Fluent/Converters/ObjectToImageConverter.cs +++ b/Fluent/Converters/ObjectToImageConverter.cs @@ -62,7 +62,9 @@ public object Convert(object value, Type targetType, object parameter, CultureIn var image = new Image { - Source = ExtractImage(imageSource, desiredSize) + // We have to use a frozen instance. Otherwise we run into trouble if the same instance is used in multiple locations. + // In case of BitmapImage it even gets worse when using the same Uri... + Source = (ImageSource)ExtractImage(imageSource, desiredSize).GetAsFrozen() }; return image; diff --git a/Fluent/Converters/ThicknessConverter.cs b/Fluent/Converters/ThicknessConverter.cs index ebac62bd7..c79a7f2d3 100644 --- a/Fluent/Converters/ThicknessConverter.cs +++ b/Fluent/Converters/ThicknessConverter.cs @@ -2,6 +2,7 @@ { using System; using System.Globalization; + using System.Linq; using System.Windows; using System.Windows.Data; @@ -10,6 +11,8 @@ /// public class ThicknessConverter : IMultiValueConverter { + private static readonly System.Windows.ThicknessConverter systemThicknessConverter = new System.Windows.ThicknessConverter(); + #region Implementation of IMultiValueConverter /// @@ -21,10 +24,17 @@ public class ThicknessConverter : IMultiValueConverter /// The array of values that the source bindings in the produces. The value indicates that the source binding has no value to provide for conversion.The type of the binding target property.The converter parameter to use.The culture to use in the converter. public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { - return new Thickness(System.Convert.ToDouble(values[0]), - System.Convert.ToDouble(values[1]), - System.Convert.ToDouble(values[2]), - System.Convert.ToDouble(values[3])); + if (values.Any(x => x == DependencyProperty.UnsetValue)) + { + if (parameter != null) + { + return (Thickness)systemThicknessConverter.ConvertFromString((string)parameter); + } + + return new Thickness(); + } + + return new Thickness(System.Convert.ToDouble(values[0]), System.Convert.ToDouble(values[1]), System.Convert.ToDouble(values[2]), System.Convert.ToDouble(values[3])); } /// diff --git a/Fluent/Internal/DoubleUtil.cs b/Fluent/Internal/DoubleUtil.cs index 57113297f..87d03e438 100644 --- a/Fluent/Internal/DoubleUtil.cs +++ b/Fluent/Internal/DoubleUtil.cs @@ -31,11 +31,9 @@ public static bool AreClose(double value1, double value2) } // This computes (|value1-value2| / (|value1| + |value2| + 10.0)) < DBL_EPSILON - double eps = (Math.Abs(value1) + Math.Abs(value2) + 10.0) * DBL_EPSILON; - double delta = value1 - value2; + var eps = (Math.Abs(value1) + Math.Abs(value2) + 10.0) * DBL_EPSILON; + var delta = value1 - value2; return (-eps < delta) && (eps > delta); } - - public static readonly double Zero = 0D; } } \ No newline at end of file diff --git a/Fluent/Themes/Generic/Controls/TwoLineLabel.xaml b/Fluent/Themes/Generic/Controls/TwoLineLabel.xaml index 5557502b3..faa777864 100644 --- a/Fluent/Themes/Generic/Controls/TwoLineLabel.xaml +++ b/Fluent/Themes/Generic/Controls/TwoLineLabel.xaml @@ -18,7 +18,6 @@ HorizontalAlignment="Center" VerticalAlignment="Center" /> @@ -65,7 +64,7 @@ Value="Center" /> + Value="3,0,0,0" /> diff --git a/Fluent/Themes/Office2010/Controls/BackstageTabControl.xaml b/Fluent/Themes/Office2010/Controls/BackstageTabControl.xaml index 00954245d..b53c34507 100644 --- a/Fluent/Themes/Office2010/Controls/BackstageTabControl.xaml +++ b/Fluent/Themes/Office2010/Controls/BackstageTabControl.xaml @@ -1,11 +1,7 @@  - - - - - + xmlns:Fluent="clr-namespace:Fluent" + xmlns:Converters="clr-namespace:Fluent.Converters"> @@ -75,6 +71,7 @@ + + \ No newline at end of file diff --git a/Fluent/Themes/Office2010/Controls/Button.xaml b/Fluent/Themes/Office2010/Controls/Button.xaml index c9defe757..d7391b65c 100644 --- a/Fluent/Themes/Office2010/Controls/Button.xaml +++ b/Fluent/Themes/Office2010/Controls/Button.xaml @@ -8,19 +8,19 @@ + CornerRadius="{TemplateBinding CornerRadius}" + BorderThickness="{TemplateBinding BorderThickness}" + Background="{TemplateBinding Background}" + BorderBrush="{TemplateBinding BorderBrush}"> - + SnapsToDevicePixels="True" /> + - - @@ -74,7 +70,7 @@ Style="{DynamicResource TwoLineLabelStyle}" HorizontalAlignment="Center" VerticalAlignment="Center" - Margin="2,-1,2,2" + Margin="2,0,2,2" HasGlyph="{TemplateBinding HasTriangle}" /> @@ -221,7 +217,7 @@ Value="1,0,0,0" /> + Value="-2,0,2,1" /> @@ -248,7 +244,7 @@ Value="False" /> + Value="2,0,2,1" /> diff --git a/Fluent/Themes/Office2013/Controls/Ribbon.xaml b/Fluent/Themes/Office2013/Controls/Ribbon.xaml index 5d966fa72..5b8062965 100644 --- a/Fluent/Themes/Office2013/Controls/Ribbon.xaml +++ b/Fluent/Themes/Office2013/Controls/Ribbon.xaml @@ -42,11 +42,11 @@ ContextMenu="{Binding ContextMenu, ElementName=PART_LayoutRoot}"> - + - - + + diff --git a/Fluent/Themes/Office2013/Controls/RibbonGroupBox.xaml b/Fluent/Themes/Office2013/Controls/RibbonGroupBox.xaml index 409a23e9d..bddf4cdf7 100644 --- a/Fluent/Themes/Office2013/Controls/RibbonGroupBox.xaml +++ b/Fluent/Themes/Office2013/Controls/RibbonGroupBox.xaml @@ -31,8 +31,14 @@ Value="Auto" /> + + + @@ -58,18 +64,18 @@ + Background="{TemplateBinding BorderBrush}"> + @@ -401,9 +410,10 @@ + - - + + - - + + Background="{TemplateBinding Background}" + BorderBrush="{TemplateBinding BorderBrush}"> @@ -766,16 +778,16 @@ Value="False" /> diff --git a/Fluent/Themes/Office2013/Controls/ScreenTip.xaml b/Fluent/Themes/Office2013/Controls/ScreenTip.xaml index 7a371be02..9f766168f 100644 --- a/Fluent/Themes/Office2013/Controls/ScreenTip.xaml +++ b/Fluent/Themes/Office2013/Controls/ScreenTip.xaml @@ -59,7 +59,8 @@ - + + + diff --git a/Fluent/Themes/Office2013/Controls/SplitButton.xaml b/Fluent/Themes/Office2013/Controls/SplitButton.xaml index 703288214..d6c237e54 100644 --- a/Fluent/Themes/Office2013/Controls/SplitButton.xaml +++ b/Fluent/Themes/Office2013/Controls/SplitButton.xaml @@ -15,7 +15,7 @@ + Value="False" /> @@ -34,7 +34,7 @@ + Value="32" /> @@ -49,7 +49,8 @@ + Background="{DynamicResource TransparentBrush}" + VerticalAlignment="Stretch"> - - @@ -230,9 +228,9 @@ - + Value="1,0,0,0" /> @@ -251,9 +249,6 @@ - + Value="{DynamicResource ButtonHoverOuterBorderBrush}" /> @@ -327,7 +322,7 @@ + Value="2,0,2,1" /> @@ -446,7 +442,7 @@ Value="False" /> + Value="2,0,-1,1" /> diff --git a/Fluent/Themes/Windows8/Controls/BackstageTabControl.xaml b/Fluent/Themes/Windows8/Controls/BackstageTabControl.xaml index 4f8848576..96ce6346e 100644 --- a/Fluent/Themes/Windows8/Controls/BackstageTabControl.xaml +++ b/Fluent/Themes/Windows8/Controls/BackstageTabControl.xaml @@ -1,11 +1,7 @@  - - - - - + xmlns:Fluent="clr-namespace:Fluent" + xmlns:Converters="clr-namespace:Fluent.Converters"> @@ -75,6 +71,7 @@ + + \ No newline at end of file diff --git a/Fluent/Themes/Windows8/Controls/Button.xaml b/Fluent/Themes/Windows8/Controls/Button.xaml index 03b20ff84..ced61f751 100644 --- a/Fluent/Themes/Windows8/Controls/Button.xaml +++ b/Fluent/Themes/Windows8/Controls/Button.xaml @@ -8,9 +8,10 @@ @@ -26,8 +27,7 @@ Content="{Binding LargeIcon, RelativeSource={RelativeSource TemplatedParent}, Converter={x:Static Converters:StaticConverters.ObjectToImageConverter}}" Width="32" Margin="3,2" - SnapsToDevicePixels="True"> - + SnapsToDevicePixels="True" /> - + Value="{DynamicResource ButtonHoverBorderBrush}" /> +