| File: System\ComponentModel\Design\ToolStripContainerActionList.cs | Web Access |
| Project: src\winforms\src\System.Windows.Forms.Design\src\System.Windows.Forms.Design.csproj (System.Windows.Forms.Design) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; using System.ComponentModel.Design; using System.Windows.Forms.Design.Behavior; namespace System.Windows.Forms.Design; /// <summary> /// Describes the list of actions that can be performed for the ToolStripContainer control from the chrome panel. /// </summary> internal class ToolStripContainerActionList : DesignerActionList { private readonly ToolStripContainer _toolStripContainer; private readonly IDesignerHost? _designerHost; private readonly IServiceProvider? _serviceProvider; /// <summary> /// ToolStripContainer ActionList. /// </summary> public ToolStripContainerActionList(ToolStripContainer toolStripContainer) : base(toolStripContainer) { _toolStripContainer = toolStripContainer; _serviceProvider = _toolStripContainer.Site; _designerHost = _serviceProvider?.GetService<IDesignerHost>(); } /// <summary> /// Helper function to get the property on the component. /// </summary> private static object? GetProperty(Component component, string propertyName) { PropertyDescriptor? getProperty = TypeDescriptor.GetProperties(component)?[propertyName]; return getProperty?.GetValue(component); } /// <summary> /// Helper function to change the property on the component /// </summary> private void ChangeProperty(Component component, string propertyName, object value) { if (_designerHost is null) { return; } ToolStripPanel? panel = component as ToolStripPanel; ToolStripPanelDesigner? panelDesigner = _designerHost.GetDesigner(component) as ToolStripPanelDesigner; if (propertyName.Equals("Visible") && panel is not null) { foreach (Control control in panel.Controls) { PropertyDescriptor? visibleProperty = TypeDescriptor.GetProperties(control)["Visible"]; visibleProperty?.SetValue(control, value); } if (!(bool)value) { panel?.Padding = new Padding(0); if (panelDesigner?.ToolStripPanelSelectorGlyph is not null) { panelDesigner.ToolStripPanelSelectorGlyph.IsExpanded = false; } } } PropertyDescriptor? changingProperty = TypeDescriptor.GetProperties(component)[propertyName]; changingProperty?.SetValue(component, value); // Reset the Glyphs. SelectionManager? selectionManager = _serviceProvider?.GetService<SelectionManager>(); selectionManager?.Refresh(); // Invalidate the Window panelDesigner?.InvalidateGlyph(); } /// <summary> /// Checks if the <see cref="ToolStripContainer" /> is dock filled. /// </summary> private bool IsDockFilled { get { PropertyDescriptor? dockProperty = TypeDescriptor.GetProperties(_toolStripContainer)["Dock"]; return dockProperty is null || (DockStyle?)dockProperty.GetValue(_toolStripContainer) == DockStyle.Fill; } } /// <summary> /// Checks if the ToolStripContainer is a child control of the designerHost's rootComponent /// </summary> private bool ProvideReparent => _designerHost?.RootComponent is Control root && _toolStripContainer.Parent == root && IsDockFilled && root.Controls.Count > 1; /// <summary> /// Sets the Dock /// </summary> public void SetDockToForm() { if (_designerHost is null) { return; } // Change the Parent only if its not parented to the form. if (_designerHost.RootComponent is Control root && _toolStripContainer.Parent is null) { root.Controls.Add(_toolStripContainer); } // Set the dock prop to DockStyle.Fill if (!IsDockFilled) { PropertyDescriptor? dockProp = TypeDescriptor.GetProperties(_toolStripContainer)["Dock"]; dockProp?.SetValue(_toolStripContainer, DockStyle.Fill); } } /// <summary> /// Reparent the controls on the form. /// </summary> public void ReparentControls() { // Reparent the Controls only if the ToolStripContainer is a child of the RootComponent. if (_designerHost?.RootComponent is not Control root || _toolStripContainer.Parent != root || root.Controls.Count <= 1) { return; } Control newParent = _toolStripContainer.ContentPanel; PropertyDescriptor? autoScrollProp = TypeDescriptor.GetProperties(newParent)["AutoScroll"]; autoScrollProp?.SetValue(newParent, true); // create a transaction so this happens as an atomic unit. DesignerTransaction? changeParent = _designerHost.CreateTransaction(string.Format(SR._0_reparent_controls_transaction, nameof(ToolStripContainer))); try { IComponentChangeService? componentChangeService = _serviceProvider?.GetService<IComponentChangeService>(); Control[] childControls = new Control[root.Controls.Count]; root.Controls.CopyTo(childControls, 0); foreach (Control control in childControls) { if (control == _toolStripContainer || control is MdiClient) { continue; } // We should not reparent inherited Controls if (TypeDescriptor.GetAttributes(control)?[typeof(InheritanceAttribute)] is not InheritanceAttribute inheritanceAttribute || inheritanceAttribute.InheritanceLevel == InheritanceLevel.InheritedReadOnly) { continue; } newParent = control is ToolStrip ? GetParent(control) : _toolStripContainer.ContentPanel; PropertyDescriptor? controlsProp = TypeDescriptor.GetProperties(newParent)["Controls"]; Control? oldParent = control.Parent; if (oldParent is not null) { componentChangeService?.OnComponentChanging(oldParent, controlsProp); // Remove control from the old parent oldParent.Controls.Remove(control); } componentChangeService?.OnComponentChanging(newParent, controlsProp); // Finally add & relocate the control with the new parent newParent.Controls.Add(control); // Fire our component changed events if (componentChangeService is not null && oldParent is not null) { componentChangeService.OnComponentChanged(oldParent, controlsProp, oldValue: null, newValue: null); } // fire component changed on the newParent componentChangeService?.OnComponentChanged(newParent, controlsProp, oldValue: null, newValue: null); } } catch { changeParent?.Cancel(); changeParent = null; } finally { changeParent?.Commit(); changeParent = null; // Set the Selection on the new Parent, so that the selection is restored to the new item ISelectionService? selectionService = _serviceProvider?.GetService<ISelectionService>(); selectionService?.SetSelectedComponents(new IComponent[] { newParent }); } } private Control GetParent(Control control) { Control newParent = _toolStripContainer.ContentPanel; DockStyle dock = control.Dock; foreach (Control panel in _toolStripContainer.Controls) { if (panel is ToolStripPanel && panel.Dock == dock) { newParent = panel; break; } } return newParent; } /// <summary> /// Visibility of TopToolStripPanel. /// </summary> public bool TopVisible { get => (bool)(GetProperty(_toolStripContainer, nameof(ToolStripContainer.TopToolStripPanelVisible)) ?? false); set { if (value != TopVisible) { ChangeProperty(_toolStripContainer, "TopToolStripPanelVisible", value); } } } /// <summary> /// Visibility of BottomToolStripPanel. /// </summary> public bool BottomVisible { get => (bool)(GetProperty(_toolStripContainer, nameof(ToolStripContainer.BottomToolStripPanelVisible)) ?? false); set { if (value != BottomVisible) { ChangeProperty(_toolStripContainer, "BottomToolStripPanelVisible", value); } } } /// <summary> /// Visibility of LeftToolStripPanel. /// </summary> public bool LeftVisible { get => (bool)(GetProperty(_toolStripContainer, nameof(ToolStripContainer.LeftToolStripPanelVisible)) ?? false); set { if (value != LeftVisible) { ChangeProperty(_toolStripContainer, "LeftToolStripPanelVisible", value); } } } /// <summary> /// Visibility of RightToolStripPanel. /// </summary> public bool RightVisible { get => (bool)(GetProperty(_toolStripContainer, nameof(ToolStripContainer.RightToolStripPanelVisible)) ?? false); set { if (value != RightVisible) { ChangeProperty(_toolStripContainer, "RightToolStripPanelVisible", value); } } } /// <summary> /// Returns the control's action list items. /// </summary> public override DesignerActionItemCollection GetSortedActionItems() { DesignerActionItemCollection items = [ new DesignerActionHeaderItem(SR.ToolStripContainerActionList_Visible, SR.ToolStripContainerActionList_Show), new DesignerActionPropertyItem(nameof(TopVisible), SR.ToolStripContainerActionList_Top, SR.ToolStripContainerActionList_Show, SR.ToolStripContainerActionList_TopDesc), new DesignerActionPropertyItem(nameof(BottomVisible), SR.ToolStripContainerActionList_Bottom, SR.ToolStripContainerActionList_Show, SR.ToolStripContainerActionList_BottomDesc), new DesignerActionPropertyItem(nameof(LeftVisible), SR.ToolStripContainerActionList_Left, SR.ToolStripContainerActionList_Show, SR.ToolStripContainerActionList_LeftDesc), new DesignerActionPropertyItem(nameof(RightVisible), SR.ToolStripContainerActionList_Right, SR.ToolStripContainerActionList_Show, SR.ToolStripContainerActionList_RightDesc) ]; if (!IsDockFilled) { string displayName = _designerHost?.RootComponent is UserControl ? SR.DesignerShortcutDockInUserControl : SR.DesignerShortcutDockInForm; items.Add(new DesignerActionMethodItem( this, nameof(SetDockToForm), displayName)); } if (ProvideReparent) { items.Add(new DesignerActionMethodItem(this, nameof(ReparentControls), SR.DesignerShortcutReparentControls)); } return items; } }