File: Microsoft\Windows\Controls\Ribbon\RibbonContextualTabGroup.cs
Web Access
Project: src\src\Microsoft.DotNet.Wpf\src\System.Windows.Controls.Ribbon\System.Windows.Controls.Ribbon_dxtfdo3u_wpftmp.csproj (System.Windows.Controls.Ribbon)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
 
#region Using declarations
 
using System.Collections;
using System.Collections.Generic;
using System.Windows.Automation;
using System.Windows.Automation.Peers;
using System.Windows.Input;
using System.Windows.Markup;
#if RIBBON_IN_FRAMEWORK
using Microsoft.Windows.Controls;
 
#if RIBBON_IN_FRAMEWORK
namespace System.Windows.Controls.Ribbon
#else
namespace Microsoft.Windows.Controls.Ribbon
#endif
{
#else
    using Microsoft.Windows.Automation.Peers;
#endif
 
    #endregion
 
    /// <summary>
    ///     Item container for RibbonContextualTabGroupItemsControl
    /// </summary>
    [ContentProperty("Header")]
    public class RibbonContextualTabGroup : Control
    {
        #region Fields
        
        internal const double TabHeaderSeparatorHeightDelta = 4.0;
 
        private TabsEnumerable _tabs = null;
        
        #endregion
 
        #region Constructors
 
        /// <summary>
        ///   Initializes static members of the RibbonContextualTabGroup class.  Also
        ///   overrides the default style.
        /// </summary>
        static RibbonContextualTabGroup()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(RibbonContextualTabGroup), new FrameworkPropertyMetadata(typeof(RibbonContextualTabGroup)));
            VisibilityProperty.OverrideMetadata(typeof(RibbonContextualTabGroup), new FrameworkPropertyMetadata(Visibility.Collapsed, new PropertyChangedCallback(OnVisibilityChanged), new CoerceValueCallback(CoerceVisibility)));
            FocusableProperty.OverrideMetadata(typeof(RibbonContextualTabGroup), new FrameworkPropertyMetadata(false));
#if RIBBON_IN_FRAMEWORK
            AutomationProperties.IsOffscreenBehaviorProperty.OverrideMetadata(typeof(RibbonContextualTabGroup), new FrameworkPropertyMetadata(IsOffscreenBehavior.FromClip));
#endif
        }
 
        #endregion
 
        #region Public Properties
 
        /// <summary>
        ///     The DependencyProperty for the Header property.
        ///     Flags:              None
        ///     Default Value:      null
        /// </summary>
        public static readonly DependencyProperty HeaderProperty =
                DependencyProperty.Register(
                        "Header",
                        typeof(object),
                        typeof(RibbonContextualTabGroup),
                        new FrameworkPropertyMetadata(
                                (object) null,
                                new PropertyChangedCallback(OnHeaderChanged)));
 
 
        /// <summary>
        ///     Header is the data used to for the header of each item in the control.
        /// </summary>
        public object Header
        {
            get { return GetValue(HeaderProperty); }
            set { SetValue(HeaderProperty, value); }
        }
 
        /// <summary>
        ///     Called when HeaderProperty is invalidated on "d."
        /// </summary>
        private static void OnHeaderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            RibbonContextualTabGroup ctrl = (RibbonContextualTabGroup) d;
            ctrl.OnHeaderChanged(e.OldValue, e.NewValue);
        }
 
        /// <summary>
        ///     This method is invoked when the Header property changes.
        /// </summary>
        /// <param name="oldHeader">The old value of the Header property.</param>
        /// <param name="newHeader">The new value of the Header property.</param>
        protected virtual void OnHeaderChanged(object oldHeader, object newHeader)
        {
            RemoveLogicalChild(oldHeader);
            AddLogicalChild(newHeader);
            UpdateTabs(false /* clear */);
        }
 
        /// <summary>
        ///     The DependencyProperty for the HeaderTemplate property.
        ///     Flags:              Can be used in style rules
        ///     Default Value:      null
        /// </summary>
        public static readonly DependencyProperty HeaderTemplateProperty =
                DependencyProperty.Register(
                        "HeaderTemplate",
                        typeof(DataTemplate),
                        typeof(RibbonContextualTabGroup),
                        new FrameworkPropertyMetadata(
                                (DataTemplate) null));
 
        /// <summary>
        ///     HeaderTemplate is the template used to display the <seealso cref="Header"/>.
        /// </summary>
        public DataTemplate HeaderTemplate
        {
            get { return (DataTemplate) GetValue(HeaderTemplateProperty); }
            set { SetValue(HeaderTemplateProperty, value); }
        }
 
 
        /// <summary>
        ///     The DependencyProperty for the HeaderTemplateSelector property.
        ///     Flags:              none
        ///     Default Value:      null
        /// </summary>
        public static readonly DependencyProperty HeaderTemplateSelectorProperty =
                DependencyProperty.Register(
                        "HeaderTemplateSelector",
                        typeof(DataTemplateSelector),
                        typeof(RibbonContextualTabGroup),
                        new FrameworkPropertyMetadata(
                                (DataTemplateSelector) null));
 
        /// <summary>
        ///     HeaderTemplateSelector allows the application writer to provide custom logic
        ///     for choosing the template used to display the <seealso cref="Header"/>.
        /// </summary>
        /// <remarks>
        ///     This property is ignored if <seealso cref="HeaderTemplate"/> is set.
        /// </remarks>
        public DataTemplateSelector HeaderTemplateSelector
        {
            get { return (DataTemplateSelector) GetValue(HeaderTemplateSelectorProperty); }
            set { SetValue(HeaderTemplateSelectorProperty, value); }
        }
 
        /// <summary>
        ///     The DependencyProperty for the HeaderStringFormat property.
        ///     Flags:              None
        ///     Default Value:      null
        /// </summary>
        public static readonly DependencyProperty HeaderStringFormatProperty =
                DependencyProperty.Register(
                        "HeaderStringFormat",
                        typeof(String),
                        typeof(RibbonContextualTabGroup),
                        new FrameworkPropertyMetadata(
                                (String) null));
 
 
        /// <summary>
        ///     HeaderStringFormat is the format used to display the header content as a string.
        ///     This arises only when no template is available.
        /// </summary>
        public String HeaderStringFormat
        {
            get { return (String) GetValue(HeaderStringFormatProperty); }
            set { SetValue(HeaderStringFormatProperty, value); }
        }
 
        /// <summary>
        ///     DependencyProperty for Ribbon property.
        /// </summary>
        public static readonly DependencyProperty RibbonProperty =
            RibbonControlService.RibbonProperty.AddOwner(typeof(RibbonContextualTabGroup));
 
        /// <summary>
        ///     This property is used to access Ribbon
        /// </summary>
        public Ribbon Ribbon
        {
            get { return RibbonControlService.GetRibbon(this); }
        }
 
        #endregion
 
        #region Internal Properties
 
        /// <summary>
        ///   Gets or sets a value indicating whether the contextual tab group's label should be shown.
        /// </summary>
        internal bool ShowLabelToolTip
        {
            get { return RibbonHelper.GetIsContentTooltip(VisualChild, Header); }
            set { RibbonHelper.SetContentAsToolTip(this, VisualChild, Header, value); }
        }
 
        private FrameworkElement VisualChild
        {
            get
            {
                return VisualChildrenCount == 0 ? null : (GetVisualChild(0) as FrameworkElement);
            }
        }
 
        internal IEnumerable<RibbonTab> Tabs
        {
            get
            {
                if (_tabs == null)
                {
                    _tabs = new TabsEnumerable(this);
                }
                return _tabs;
            }
        }
 
        internal RibbonTab FirstVisibleTab
        {
            get
            {
                IEnumerable<RibbonTab> tabs = Tabs;
                if (tabs != null)
                {
                    foreach (RibbonTab tab in tabs)
                    {
                        if (tab.Visibility == Visibility.Visible)
                        {
                            return tab;
                        }
                    }
                }
                return null;
            }
        }
 
        /// <summary>
        ///   Gets or sets the sum of DesiredSize.Width of TabHeaders of this group. 
        /// </summary>
        internal double TabsDesiredWidth
        {
            get;
            set;
        }
 
        /// <summary>
        /// Gets or sets the width required to display the full Header without trimming. 
        /// </summary>
        internal double IdealDesiredWidth
        {
            get;
            set;
        }
 
        /// <summary>
        /// Gets or sets Padding to be added to each TabHeader in this group, 
        /// such that ContextualTabGroupHeader can be displayed in its full length.
        /// Its computed as (IdealDesiredWidth - TabsDesiredWidth)/ (Number of visible Tabs in this group)
        /// </summary>
        internal double DesiredExtraPaddingPerTab
        {
            get;
            set;
        }
 
        /// <summary>
        ///  Gets or sets the arrange width of the contextual tab group.
        /// </summary>
        internal double ArrangeWidth
        {
            get;
            set;
        }
 
        /// <summary>
        ///   Gets or sets the arrange x-coordinate of the contextual tab group.
        /// </summary>
        internal double ArrangeX
        {
            get;
            set;
        }
 
        #endregion
 
        #region Protected Methods
 
        protected override AutomationPeer OnCreateAutomationPeer()
        {
            return new RibbonContextualTabGroupAutomationPeer(this);
        }
 
        /// <summary>
        ///   Callback for mouse down.  Captures/Releases the mouse depending on whether
        ///   the tab group was clicked.
        /// </summary>
        /// <param name="e">The event data.</param>
        protected override void OnMouseDown(MouseButtonEventArgs e)
        {
            if (e.ClickCount == 1 || e.ChangedButton == MouseButton.Right )
            {
                this.CaptureMouse();
                if (this.IsMouseCaptured)
                {
                    // Though we have already checked this state, our call to CaptureMouse
                    // could also end up changing the state, so we check it again.
                    if (e.ButtonState != MouseButtonState.Pressed)
                    {
                        // Release capture since we decided not to press the button.
                        this.ReleaseMouseCapture();
                    }
                }
                e.Handled = true;
            }
            else if( e.ClickCount == 2 && e.ChangedButton == MouseButton.Left)
            {
                // On DoubleClick maximize/restore the window
                RibbonWindow ribbonWindow = Window.GetWindow(this) as RibbonWindow; 
                if( ribbonWindow != null )
                {
#if RIBBON_IN_FRAMEWORK
                    if (SystemCommands.MaximizeWindowCommand.CanExecute(null, ribbonWindow))
                    {
                        SystemCommands.MaximizeWindowCommand.Execute( /*parameter*/ null, /* target*/ ribbonWindow);
                        e.Handled = true;
                    }
                    else if (SystemCommands.RestoreWindowCommand.CanExecute(null, ribbonWindow))
                    {
                        SystemCommands.RestoreWindowCommand.Execute(/*parameter*/ null, /* target*/ ribbonWindow);
                        e.Handled = true;
                    }
#else
                    if (Microsoft.Windows.Shell.SystemCommands.MaximizeWindowCommand.CanExecute(null, ribbonWindow))
                    {
                        Microsoft.Windows.Shell.SystemCommands.MaximizeWindowCommand.Execute( /*parameter*/ null, /* target*/ ribbonWindow);
                        e.Handled = true;
                    }
                    else if (Microsoft.Windows.Shell.SystemCommands.RestoreWindowCommand.CanExecute(null, ribbonWindow))
                    {
                        Microsoft.Windows.Shell.SystemCommands.RestoreWindowCommand.Execute(/*parameter*/ null, /* target*/ ribbonWindow);
                        e.Handled = true;
                    }
#endif
                }
            }
 
            base.OnMouseDown(e);
        }
 
        /// <summary>
        ///   Callback for mouse up, releases mouse capture and sends click notifications.
        /// </summary>
        /// <param name="e">The event data.</param>
        protected override void OnMouseUp(MouseButtonEventArgs e)
        {
            if (this.IsMouseCaptured)
            {
                this.ReleaseMouseCapture();
                if (IsMouseOver)
                {
                    if (e.ChangedButton == MouseButton.Left && this.Ribbon != null)
                    {
                        // Selects the first tab in this contextual group.
                        this.Ribbon.NotifyMouseClickedOnContextualTabGroup(this);
                        e.Handled = true;
                    }
                    else if (e.ChangedButton == MouseButton.Right)
                    {
                        // Show SystemMenu
                        RibbonWindow ribbonWindow = Window.GetWindow(this) as RibbonWindow;
                        if (ribbonWindow != null)
                        {
#if RIBBON_IN_FRAMEWORK
                            if (SystemCommands.ShowSystemMenuCommand.CanExecute(null, ribbonWindow))
                            {
                                SystemCommands.ShowSystemMenuCommand.Execute( /*parameter*/ null, /* target*/ ribbonWindow);
                                e.Handled = true;
                            }
#else
                            if (Microsoft.Windows.Shell.SystemCommands.ShowSystemMenuCommand.CanExecute(null, ribbonWindow))
                            {
                                Microsoft.Windows.Shell.SystemCommands.ShowSystemMenuCommand.Execute( /*parameter*/ null, /* target*/ ribbonWindow);
                                e.Handled = true;
                            }
#endif
                        }
                    }
                }
            }
 
            base.OnMouseUp(e);
        }
 
        #endregion
 
        #region Private Methods
 
        internal void PrepareTabGroupHeader(object item,
                                        DataTemplate itemTemplate,
                                        DataTemplateSelector itemTemplateSelector,
                                        string itemStringFormat)
        {
            UpdateTabs(false /* clear */);
 
            if (item != this)
            {
                // copy styles from the ItemsControl
                if (PropertyHelper.IsDefaultValue(this, HeaderProperty))
                {
                    Header = item;
                }
                if (itemTemplate != null)
                    SetValue(HeaderTemplateProperty, itemTemplate);
                if (itemTemplateSelector != null)
                    SetValue(HeaderTemplateSelectorProperty, itemTemplateSelector);
                if (itemStringFormat != null)
                    SetValue(HeaderStringFormatProperty, itemStringFormat);
            }
        }
 
        internal void ClearTabGroupHeader()
        {
            UpdateTabs(true /* clear */);
        }
 
        private static object CoerceVisibility(DependencyObject d, object baseValue)
        {
            // Always coerce Hidden to Collapsed
            if ((Visibility)baseValue == Visibility.Hidden)
                return Visibility.Collapsed;
            return baseValue;
        }
 
        /// <summary>
        ///   Callback for Visibility property changed.  
        /// </summary>
        /// <param name="sender">The RibbonContextualTabGroup whose Visibility property changed.</param>
        /// <param name="e">The event data.</param>
        private static void OnVisibilityChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ((RibbonContextualTabGroup)sender).CoerceTabsVisibility();
        }
 
        private void UpdateTabs(bool clear)
        {
            if (Ribbon != null)
            {
                for (int i = 0; i < Ribbon.Items.Count; i++)
                {
                    RibbonTab tab = Ribbon.ItemContainerGenerator.ContainerFromIndex(i) as RibbonTab;
                    if (tab != null && tab.IsContextualTab && Object.Equals(tab.ContextualTabGroupHeader, Header))
                    {
                        if (!clear)
                        {
                            if (tab.ContextualTabGroup == null)
                            {
                                tab.ContextualTabGroup = this;
                                tab.CoerceValue(VisibilityProperty);
                            }
                        }
                        else
                        {
                            tab.CoerceValue(VisibilityProperty);
                            tab.ContextualTabGroup = null;
                        }
                    }
                }
            }
        }
 
        private void CoerceTabsVisibility()
        {
            IEnumerable<RibbonTab> tabs = Tabs;
            if (tabs != null)
            {
                foreach (RibbonTab tab in tabs)
                {
                    tab.CoerceValue(VisibilityProperty);
                }
            }
        }
 
        #endregion
 
        #region Tabs
 
        private class TabsEnumerable : IEnumerable<RibbonTab>
        {
            #region Constructor And Properties
 
            public TabsEnumerable(RibbonContextualTabGroup tabGroup)
            {
                ContextualTabGroup = tabGroup;
            }
 
            private RibbonContextualTabGroup ContextualTabGroup
            {
                get;
                set;
            }
 
            #endregion
 
            #region IEnumerable<RibbonTab> Members
 
            public IEnumerator<RibbonTab> GetEnumerator()
            {
                Ribbon ribbon = ContextualTabGroup.Ribbon;
                if (ribbon != null)
                {
                    int itemCount = ribbon.Items.Count;
                    for (int i = 0; i < itemCount; i++)
                    {
                        RibbonTab tab = ribbon.ItemContainerGenerator.ContainerFromIndex(i) as RibbonTab;
                        if (tab != null &&
                            tab.IsContextualTab &&
                            object.ReferenceEquals(ContextualTabGroup, tab.ContextualTabGroup))
                        {
                            yield return tab;
                        }
                    }
                }
            }
 
            #endregion
 
            #region IEnumerable Members
 
            IEnumerator IEnumerable.GetEnumerator()
            {
                return this.GetEnumerator();
            }
 
            #endregion
        }
 
        #endregion
    }
}