123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408 |
- // some code fetch from system.windows.controls.ribbon.
- using System;
- using System.Collections.ObjectModel;
- using System.Collections.Specialized;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Controls.Primitives;
- using System.Windows.Input;
- using HandyControl.Data;
- using HandyControl.Interactivity;
- using HandyControl.Tools.Extension;
- namespace HandyControl.Controls
- {
- // TODO: this control is a work-in-progress, it needs to support things like automatic resizing.
- [TemplatePart(Name = TabHeaderItemsControl, Type = typeof(ItemsControl))]
- [TemplatePart(Name = RootPanel, Type = typeof(Panel))]
- [TemplatePart(Name = ContentPanel, Type = typeof(Panel))]
- public class Ribbon : Selector
- {
- private const string TabHeaderItemsControl = "PART_TabHeaderItemsControl";
- private const string RootPanel = "PART_RootPanel";
- private const string ContentPanel = "PART_ContentPanel";
- private ItemsControl _tabHeaderItemsControl;
- private Panel _rootPanel;
- private Panel _contentPanel;
- private System.Windows.Window _window;
- private readonly ObservableCollection<object> _tabHeaderItemsSource = new();
- internal ItemsControl RibbonTabHeaderItemsControl => _tabHeaderItemsControl;
- public Ribbon()
- {
- SetRibbon(this, this);
- Loaded += Ribbon_Loaded;
- Unloaded += Ribbon_Unloaded;
- ItemContainerGenerator.StatusChanged += OnItemContainerGeneratorStatusChanged;
- CommandBindings.Add(new CommandBinding(ControlCommands.Switch, IsMinimizedSwitchButton_OnClick));
- }
- internal static readonly DependencyProperty RibbonProperty = DependencyProperty.RegisterAttached(
- "Ribbon", typeof(Ribbon), typeof(Ribbon),
- new FrameworkPropertyMetadata(default(Ribbon), FrameworkPropertyMetadataOptions.Inherits));
- internal static void SetRibbon(DependencyObject element, Ribbon value)
- => element.SetValue(RibbonProperty, value);
- internal static Ribbon GetRibbon(DependencyObject element)
- => (Ribbon) element.GetValue(RibbonProperty);
- public static readonly DependencyProperty IsDropDownOpenProperty = DependencyProperty.Register(
- nameof(IsDropDownOpen), typeof(bool), typeof(Ribbon), new PropertyMetadata(ValueBoxes.TrueBox, OnIsDropDownOpenChanged));
- private static void OnIsDropDownOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- ((Ribbon) d).OnIsDropDownOpenChanged((bool) e.NewValue);
- }
- private void OnIsDropDownOpenChanged(bool isDropDownOpen)
- {
- if (_contentPanel == null)
- {
- return;
- }
- SwitchCurrentTabContentVisibility(isDropDownOpen);
- _contentPanel.Show(isDropDownOpen);
- }
- public bool IsDropDownOpen
- {
- get => (bool) GetValue(IsDropDownOpenProperty);
- set => SetValue(IsDropDownOpenProperty, value);
- }
- public static readonly DependencyProperty IsMinimizedProperty = DependencyProperty.Register(
- nameof(IsMinimized), typeof(bool), typeof(Ribbon), new PropertyMetadata(ValueBoxes.FalseBox));
- public bool IsMinimized
- {
- get => (bool) GetValue(IsMinimizedProperty);
- set => SetValue(IsMinimizedProperty, value);
- }
- public static readonly DependencyProperty ContentHeightProperty = DependencyProperty.Register(
- nameof(ContentHeight), typeof(double), typeof(Ribbon), new PropertyMetadata(default(double)));
- public double ContentHeight
- {
- get => (double) GetValue(ContentHeightProperty);
- set => SetValue(ContentHeightProperty, value);
- }
- public static readonly DependencyProperty PrefixContentProperty = DependencyProperty.Register(
- nameof(PrefixContent), typeof(object), typeof(Ribbon), new PropertyMetadata(default(object)));
- public object PrefixContent
- {
- get => GetValue(PrefixContentProperty);
- set => SetValue(PrefixContentProperty, value);
- }
- public static readonly DependencyProperty PostfixContentProperty = DependencyProperty.Register(
- nameof(PostfixContent), typeof(object), typeof(Ribbon), new PropertyMetadata(default(object)));
- public object PostfixContent
- {
- get => GetValue(PostfixContentProperty);
- set => SetValue(PostfixContentProperty, value);
- }
- public override void OnApplyTemplate()
- {
- base.OnApplyTemplate();
- _tabHeaderItemsControl = GetTemplateChild(TabHeaderItemsControl) as ItemsControl;
- if (_tabHeaderItemsControl is { ItemsSource: null })
- {
- _tabHeaderItemsControl.ItemsSource = _tabHeaderItemsSource;
- }
- _rootPanel = GetTemplateChild(RootPanel) as Panel;
- _contentPanel = GetTemplateChild(ContentPanel) as Panel;
- if (IsMinimized)
- {
- _rootPanel.SetCurrentValue(HeightProperty, _tabHeaderItemsControl.ActualHeight);
- }
- if (!IsDropDownOpen)
- {
- _contentPanel.SetCurrentValue(HeightProperty, .0);
- }
- }
- internal void ResetSelection()
- {
- SelectedIndex = -1;
- InitializeSelection();
- }
- internal void NotifyMouseClickedOnTabHeader(RibbonTabHeader tabHeader, MouseButtonEventArgs e)
- {
- if (_tabHeaderItemsControl == null)
- {
- return;
- }
- var selectedIndex = _tabHeaderItemsControl.ItemContainerGenerator.IndexFromContainer(tabHeader);
- if (e.ClickCount == 1)
- {
- var currentSelectedIndex = SelectedIndex;
- if (currentSelectedIndex < 0 || currentSelectedIndex != selectedIndex)
- {
- SelectedIndex = selectedIndex;
- if (IsMinimized)
- {
- IsDropDownOpen = true;
- }
- }
- else
- {
- if (IsMinimized)
- {
- IsDropDownOpen = !IsDropDownOpen;
- if (!IsDropDownOpen)
- {
- SelectedIndex = -1;
- }
- }
- }
- }
- else if (e.ClickCount == 2)
- {
- IsMinimized = !IsMinimized;
- IsDropDownOpen = !IsMinimized;
- if (IsMinimized && !IsDropDownOpen)
- {
- SelectedIndex = -1;
- }
- else
- {
- SelectedIndex = selectedIndex;
- }
- }
- }
- internal void NotifyTabHeaderChanged()
- {
- if (ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated)
- {
- return;
- }
- RefreshHeaderCollection();
- }
- protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
- {
- base.OnItemsChanged(e);
- if (e.Action == NotifyCollectionChangedAction.Remove ||
- e.Action == NotifyCollectionChangedAction.Replace ||
- e.Action == NotifyCollectionChangedAction.Reset)
- {
- InitializeSelection();
- }
- if ((ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated ||
- e.Action != NotifyCollectionChangedAction.Move) && e.Action != NotifyCollectionChangedAction.Remove)
- {
- return;
- }
- RefreshHeaderCollection();
- }
- protected override DependencyObject GetContainerForItemOverride() => new RibbonTab();
- protected override bool IsItemItsOwnContainerOverride(object item) => item is RibbonTab;
- protected override void OnSelectionChanged(SelectionChangedEventArgs e)
- {
- base.OnSelectionChanged(e);
- if (e.AddedItems is not { Count: > 0 })
- {
- return;
- }
- SelectedItem = e.AddedItems[0];
- }
- private void OnPreviewMouseButton(MouseButtonEventArgs e)
- {
- var postion = e.GetPosition(this);
- if (InputHitTest(postion) == null)
- {
- if (IsMinimized && IsDropDownOpen)
- {
- IsDropDownOpen = false;
- SelectedIndex = -1;
- }
- }
- }
- private void Ribbon_Loaded(object sender, RoutedEventArgs e)
- {
- _window = System.Windows.Window.GetWindow(this);
- if (_window != null)
- {
- _window.Deactivated += Window_Deactivated;
- _window.PreviewMouseLeftButtonDown += Window_PreviewMouseLeftButtonDown;
- _window.PreviewMouseLeftButtonUp += Window_PreviewMouseLeftButtonUp;
- _window.PreviewMouseRightButtonDown += Window_PreviewMouseRightButtonDown;
- _window.PreviewMouseRightButtonUp += Window_PreviewMouseRightButtonUp;
- }
- }
- private void Ribbon_Unloaded(object sender, RoutedEventArgs e)
- {
- if (_window != null)
- {
- _window.Deactivated -= Window_Deactivated;
- }
- }
- private void Window_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) => OnPreviewMouseButton(e);
- private void Window_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) => OnPreviewMouseButton(e);
- private void Window_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e) => OnPreviewMouseButton(e);
- private void Window_PreviewMouseRightButtonUp(object sender, MouseButtonEventArgs e) => OnPreviewMouseButton(e);
- private void Window_Deactivated(object sender, EventArgs e)
- {
- if (IsMinimized && IsDropDownOpen)
- {
- IsDropDownOpen = false;
- SelectedIndex = -1;
- }
- }
- private void IsMinimizedSwitchButton_OnClick(object sender, ExecutedRoutedEventArgs e)
- {
- IsDropDownOpen = !IsMinimized;
- if (!IsDropDownOpen)
- {
- SelectedIndex = -1;
- }
- }
- private void OnItemContainerGeneratorStatusChanged(object sender, EventArgs e)
- {
- if (ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated)
- {
- return;
- }
- InitializeSelection();
- RefreshHeaderCollection();
- }
- private int GetFirstVisibleTabIndex()
- {
- var count = Items.Count;
- for (var index = 0; index < count; ++index)
- {
- if (ItemContainerGenerator.ContainerFromIndex(index) is RibbonTab { IsVisible: true })
- {
- return index;
- }
- }
- return -1;
- }
- private void SwitchCurrentTabContentVisibility(bool isVisible)
- {
- var tab = GetCurrentTab();
- tab?.SwitchContentVisibility(isVisible);
- }
- private RibbonTab GetCurrentTab()
- {
- var index = SelectedIndex;
- if (index == -1)
- {
- return null;
- }
- if (ItemContainerGenerator.ContainerFromIndex(index) is RibbonTab ribbonTab)
- {
- return ribbonTab;
- }
- return null;
- }
- private void InitializeSelection()
- {
- if (!IsDropDownOpen)
- {
- SelectedIndex = -1;
- return;
- }
- if (SelectedIndex >= 0 || Items.Count <= 0)
- {
- return;
- }
- var firstVisibleTabIndex = GetFirstVisibleTabIndex();
- if (firstVisibleTabIndex < 0)
- {
- return;
- }
- SelectedIndex = firstVisibleTabIndex;
- }
- private void RefreshHeaderCollection()
- {
- var itemsCount = Items.Count;
- for (var index = 0; index < itemsCount; ++index)
- {
- object header = null;
- if (ItemContainerGenerator.ContainerFromIndex(index) is RibbonTab ribbonTab)
- {
- header = ribbonTab.Header;
- }
- header ??= string.Empty;
- if (index >= _tabHeaderItemsSource.Count)
- {
- _tabHeaderItemsSource.Add(header);
- }
- else
- {
- _tabHeaderItemsSource[index] = header;
- }
- }
- var headerCount = _tabHeaderItemsSource.Count;
- for (var index = 0; index < headerCount - itemsCount; ++index)
- {
- _tabHeaderItemsSource.RemoveAt(itemsCount);
- }
- }
- }
- }
|