diff --git a/Changelog.md b/Changelog.md index 9838646e8..3b2658136 100644 --- a/Changelog.md +++ b/Changelog.md @@ -14,6 +14,7 @@ - [#840](../../issues/840) - Ribbon does not scroll anymore - [#848](../../issues/848) - Colorful-Theme and Fullscreen Issue - [#849](../../issues/849) - QuickAccessToolBar not editable anymore (thanks @chrfin) + - [#851](../../issues/851) - Tab KeyTips Are Shown Together With Tab-Item KeyTips (different to 7.0.0) ## 8.0.0 diff --git a/Fluent.Ribbon.Tests/Misc/LogicalTreeTests.cs b/Fluent.Ribbon.Tests/Misc/LogicalTreeTests.cs index 1a47cc296..f16544233 100644 --- a/Fluent.Ribbon.Tests/Misc/LogicalTreeTests.cs +++ b/Fluent.Ribbon.Tests/Misc/LogicalTreeTests.cs @@ -69,11 +69,26 @@ public void CheckLogicalChildSupport(KeyValuePair item Assert.That(control, Is.Not.Null); - var metadata = dependencyProperty.GetMetadata(control); + if (excludedTypesForLogicalChildSupportTest.Contains(controlType)) + { + Assert.That(control is ILogicalChildSupport, Is.False, "Type must NOT implement ILogicalChildSupport"); + return; + } + else + { + Assert.That(control is ILogicalChildSupport, Is.True, "Type must implement ILogicalChildSupport"); + } - Assert.That(metadata.PropertyChangedCallback == LogicalChildSupportHelper.OnLogicalChildPropertyChanged); + var metadata = dependencyProperty.GetMetadata(control); - Assert.That(controlType.GetInterfaces(), Does.Contain(typeof(ILogicalChildSupport))); + if (excludedPropertiesForLogicalChildSupportTest.Contains(dependencyProperty)) + { + Assert.That(metadata.PropertyChangedCallback != LogicalChildSupportHelper.OnLogicalChildPropertyChanged, "PropertyChangedCallback must not be LogicalChildSupportHelper.OnLogicalChildPropertyChanged"); + } + else + { + Assert.That(metadata.PropertyChangedCallback == LogicalChildSupportHelper.OnLogicalChildPropertyChanged, "PropertyChangedCallback must be LogicalChildSupportHelper.OnLogicalChildPropertyChanged"); + } if (dependencyProperty.ReadOnly) { @@ -100,7 +115,8 @@ private static IEnumerable GetTypesWithImplementedInterface(Type type) private static readonly Type[] excludedTypesForLogicalChildSupportTest = { - typeof(LargeIconProviderProperties) + typeof(LargeIconProviderProperties), + typeof(GalleryItem) }; private static readonly DependencyProperty[] excludedPropertiesForLogicalChildSupportTest = @@ -116,16 +132,6 @@ private static IEnumerable> GetTypesThatM { foreach (var keyValuePair in GetDependencyPropertiesWithPropertyTypeObject()) { - if (excludedTypesForLogicalChildSupportTest.Contains(keyValuePair.Key)) - { - continue; - } - - if (excludedPropertiesForLogicalChildSupportTest.Contains(keyValuePair.Value)) - { - continue; - } - yield return keyValuePair; } } @@ -164,7 +170,14 @@ private static void TestLogicalTree(Type controlType, DependencyProperty propert { var children = LogicalTreeHelper.GetChildren(control); - Assert.That(children, Does.Contain(value), "Logical children must contain the value."); + if (excludedPropertiesForLogicalChildSupportTest.Contains(property)) + { + Assert.That(children, Does.Not.Contain(value), "Logical children must NOT contain the value."); + } + else + { + Assert.That(children, Does.Contain(value), "Logical children must contain the value."); + } } SetValue(null); @@ -183,7 +196,14 @@ private static void TestLogicalTree(Type controlType, DependencyProperty propert { var children = LogicalTreeHelper.GetChildren(control); - Assert.That(children, Does.Contain(value), "Logical children must contain the value."); + if (excludedPropertiesForLogicalChildSupportTest.Contains(property)) + { + Assert.That(children, Does.Not.Contain(value), "Logical children must NOT contain the value."); + } + else + { + Assert.That(children, Does.Contain(value), "Logical children must contain the value."); + } } { @@ -207,12 +227,26 @@ private static void TestLogicalTree(Type controlType, DependencyProperty propert { var children = LogicalTreeHelper.GetChildren(control); - Assert.That(children, Does.Contain(value), "Logical children must contain the value."); + if (excludedPropertiesForLogicalChildSupportTest.Contains(property)) + { + Assert.That(children, Does.Not.Contain(value), "Logical children must NOT contain the value."); + } + else + { + Assert.That(children, Does.Contain(value), "Logical children must contain the value."); + } } { var parent = LogicalTreeHelper.GetParent(value); - Assert.That(parent, Is.EqualTo(control), "Parent should match."); + if (excludedPropertiesForLogicalChildSupportTest.Contains(property)) + { + Assert.That(parent, Is.Not.EqualTo(control), "Parent should match."); + } + else + { + Assert.That(parent, Is.EqualTo(control), "Parent should match."); + } } SetValue(null); diff --git a/Fluent.Ribbon/Adorners/KeyTipAdorner.cs b/Fluent.Ribbon/Adorners/KeyTipAdorner.cs index bd727ad5a..32449137d 100644 --- a/Fluent.Ribbon/Adorners/KeyTipAdorner.cs +++ b/Fluent.Ribbon/Adorners/KeyTipAdorner.cs @@ -1,4 +1,4 @@ -// ReSharper disable once CheckNamespace +// ReSharper disable once CheckNamespace namespace Fluent { using System; @@ -134,17 +134,15 @@ private void FindKeyTips(FrameworkElement container, bool hide) if (keys != null || child is IKeyTipInformationProvider) { - if (groupBox != null) - { - this.GenerateAndAddGroupBoxKeyTipInformation(hide, keys, child, groupBox); - } - else + if (groupBox is null) { this.GenerateAndAddRegularKeyTipInformations(keys, child, hide); // Do not search deeper in the tree continue; } + + this.GenerateAndAddGroupBoxKeyTipInformation(hide, keys, child, groupBox); } var innerHide = hide || groupBox?.State == RibbonGroupBoxState.Collapsed; @@ -214,6 +212,13 @@ private static IList GetVisibleChildren(FrameworkElement eleme children = children.Concat(UIHelper.GetAllItemContainers(itemsControl)); } + // Don't show key tips for the selected content too early + if (element is RibbonTabControl ribbonTabControl + && ribbonTabControl.SelectedContent is FrameworkElement selectedContent) + { + children = children.Except(new[] { selectedContent }); + } + return children .Where(x => x.Visibility == Visibility.Visible) .Distinct() @@ -250,7 +255,7 @@ public void Attach() this.adornerLayer = GetAdornerLayer(this.oneOfAssociatedElements); - if (this.adornerLayer == null) + if (this.adornerLayer is null) { this.LogDebug("No adorner layer found"); this.isAttaching = false; @@ -337,7 +342,7 @@ private static AdornerLayer GetAdornerLayer(UIElement element) while (true) { - if (current == null) + if (current is null) { return null; } @@ -360,7 +365,7 @@ private static UIElement GetTopLevelElement(UIElement element) { var current = VisualTreeHelper.GetParent(element) as UIElement; - if (current == null) + if (current is null) { return element; } @@ -406,7 +411,7 @@ public bool Forward(string keys, bool click) this.LogTrace("Trying to forward keys \"{0}\"...", keys); var keyTipInformation = this.TryGetKeyTipInformation(keys); - if (keyTipInformation == null) + if (keyTipInformation is null) { this.LogTrace("Found no element for keys \"{0}\".", keys); return false; @@ -639,7 +644,7 @@ private void UpdateKeyTipPositions() // Dialog Launcher Button Exclusive Placement var keyTipSize = keyTipInformation.KeyTip.DesiredSize; var elementSize = keyTipInformation.VisualTarget.RenderSize; - if (rows == null) + if (rows is null) { continue; } @@ -691,7 +696,7 @@ private void UpdateKeyTipPositions() // InRibbonGallery Exclusive Placement var keyTipSize = keyTipInformation.KeyTip.DesiredSize; var elementSize = keyTipInformation.VisualTarget.RenderSize; - if (rows == null) + if (rows is null) { continue; } @@ -773,7 +778,7 @@ private static bool IsWithinRibbonToolbarInTwoLine(DependencyObject element) var ribbonToolBar = UIHelper.GetParent(element); var definition = ribbonToolBar?.GetCurrentLayoutDefinition(); - if (definition == null) + if (definition is null) { return false; } @@ -795,7 +800,7 @@ private static bool IsWithinQuickAccessToolbar(DependencyObject element) private static void SnapToRowsIfPresent(double[] rows, KeyTipInformation keyTipInformation, Point translatedPoint) { - if (rows == null) + if (rows is null) { return; } diff --git a/Fluent.Ribbon/Collections/CollectionSyncHelper.cs b/Fluent.Ribbon/Collections/CollectionSyncHelper.cs index 001858ec5..5814129b2 100644 --- a/Fluent.Ribbon/Collections/CollectionSyncHelper.cs +++ b/Fluent.Ribbon/Collections/CollectionSyncHelper.cs @@ -1,6 +1,7 @@ namespace Fluent.Collections { using System; + using System.Collections; using System.Collections.ObjectModel; using System.Collections.Specialized; @@ -12,7 +13,7 @@ public class CollectionSyncHelper /// /// Creates a new instance with as and as . /// - public CollectionSyncHelper(ObservableCollection source, ObservableCollection target) + public CollectionSyncHelper(ObservableCollection source, IList target) { this.Source = source ?? throw new ArgumentNullException(nameof(source)); this.Target = target ?? throw new ArgumentNullException(nameof(target)); @@ -30,7 +31,7 @@ public CollectionSyncHelper(ObservableCollection source, ObservableCollec /// /// The target collection. /// - public ObservableCollection Target { get; } + public IList Target { get; } /// /// Clears and then copies all items from to . diff --git a/Fluent.Ribbon/Controls/Ribbon.cs b/Fluent.Ribbon/Controls/Ribbon.cs index 17165e6f7..7651cea89 100644 --- a/Fluent.Ribbon/Controls/Ribbon.cs +++ b/Fluent.Ribbon/Controls/Ribbon.cs @@ -307,8 +307,8 @@ private static void OnContextMenuOpened(object sender, RoutedEventArgs e) { var ribbon = contextMenuOwner; - if (RibbonContextMenu == null - || ribbon == null) + if (RibbonContextMenu is null + || ribbon is null) { return; } @@ -495,6 +495,7 @@ private static void OnContextMenuOpened(object sender, RoutedEventArgs e) // Collection of tabs private ObservableCollection tabs; + private CollectionSyncHelper tabsSync; // Collection of toolbar items private ObservableCollection toolBarItems; @@ -824,52 +825,19 @@ public double QuickAccessToolBarHeight /// Gets collection of contextual tab groups /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] - public ObservableCollection ContextualGroups - { - get - { - if (this.contextualGroups == null) - { - this.contextualGroups = new ObservableCollection(); - } - - return this.contextualGroups; - } - } + public ObservableCollection ContextualGroups => this.contextualGroups ??= new ObservableCollection(); /// /// gets collection of ribbon tabs /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] - public ObservableCollection Tabs - { - get - { - if (this.tabs == null) - { - this.tabs = new ObservableCollection(); - } - - return this.tabs; - } - } + public ObservableCollection Tabs => this.tabs ??= new ObservableCollection(); /// /// Gets collection of toolbar items /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] - public ObservableCollection ToolBarItems - { - get - { - if (this.toolBarItems == null) - { - this.toolBarItems = new ObservableCollection(); - } - - return this.toolBarItems; - } - } + public ObservableCollection ToolBarItems => this.toolBarItems ??= new ObservableCollection(); /// /// Gets collection of quick access menu items @@ -879,7 +847,7 @@ public ObservableCollection QuickAccessItems { get { - if (this.quickAccessItems == null) + if (this.quickAccessItems is null) { this.quickAccessItems = new ObservableCollection(); this.quickAccessItems.CollectionChanged += this.OnQuickAccessItemsCollectionChanged; @@ -1221,7 +1189,7 @@ public ObservableCollection KeyTipKeys { get { - if (this.keyTipKeys == null) + if (this.keyTipKeys is null) { this.keyTipKeys = new ObservableCollection(); this.keyTipKeys.CollectionChanged += this.HandleKeyTipKeys_CollectionChanged; @@ -1303,7 +1271,7 @@ private static void OnShowQuickAccessBelowCommandExecuted(object sender, Execute { var ribbon = sender as Ribbon; - if (ribbon == null) + if (ribbon is null) { return; } @@ -1316,7 +1284,7 @@ private static void OnShowQuickAccessAboveCommandExecuted(object sender, Execute { var ribbon = sender as Ribbon; - if (ribbon == null) + if (ribbon is null) { return; } @@ -1368,7 +1336,7 @@ private static void OnCustomizeQuickAccessToolbarCommandCanExecute(object sender { var ribbon = sender as Ribbon; - if (ribbon == null) + if (ribbon is null) { return; } @@ -1381,7 +1349,7 @@ private static void OnCustomizeTheRibbonCommandCanExecute(object sender, CanExec { var ribbon = sender as Ribbon; - if (ribbon == null) + if (ribbon is null) { return; } @@ -1475,7 +1443,7 @@ private void OnSizeChanged(object sender, SizeChangedEventArgs e) private void MaintainIsCollapsed() { if (this.IsAutomaticCollapseEnabled == false - || this.ownerWindow == null) + || this.ownerWindow is null) { return; } @@ -1509,7 +1477,7 @@ public override void OnApplyTemplate() this.TabControl.SelectionChanged -= this.OnTabControlSelectionChanged; selectedTab = this.TabControl.SelectedItem as RibbonTabItem; - this.TabControl.ItemsSource = null; + this.tabsSync?.Target.Clear(); this.toolBarItemsSync?.Target.Clear(); } @@ -1520,7 +1488,7 @@ public override void OnApplyTemplate() { this.TabControl.SelectionChanged += this.OnTabControlSelectionChanged; - this.TabControl.ItemsSource = this.Tabs; + this.tabsSync = new CollectionSyncHelper(this.Tabs, this.TabControl.Items); this.TabControl.SelectedItem = selectedTab; @@ -1640,7 +1608,7 @@ private void DetachFromWindow() /// True if element in quick access toolbar public bool IsInQuickAccessToolBar(UIElement element) { - if (element == null) + if (element is null) { return false; } @@ -1654,7 +1622,7 @@ public bool IsInQuickAccessToolBar(UIElement element) /// Element public void AddToQuickAccessToolBar(UIElement element) { - if (element == null) + if (element is null) { return; } @@ -1665,12 +1633,12 @@ public void AddToQuickAccessToolBar(UIElement element) } // Do not add menu items without icon. - if (element is System.Windows.Controls.MenuItem menuItem && menuItem.Icon == null) + if (element is System.Windows.Controls.MenuItem menuItem && menuItem.Icon is null) { element = FindParentRibbonControl(element) as UIElement; } - if (element == null) + if (element is null) { return; } diff --git a/Fluent.Ribbon/Controls/RibbonTabControl.cs b/Fluent.Ribbon/Controls/RibbonTabControl.cs index 9c00f8135..eca2f4922 100644 --- a/Fluent.Ribbon/Controls/RibbonTabControl.cs +++ b/Fluent.Ribbon/Controls/RibbonTabControl.cs @@ -15,7 +15,6 @@ namespace Fluent using System.Windows.Input; using ControlzEx.Standard; using Fluent.Automation.Peers; - using Fluent.Collections; using Fluent.Extensions; using Fluent.Helpers; using Fluent.Internal;