|
// 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.Drawing;
namespace System.Windows.Forms.Design;
/// <summary>
/// This class is going to replace the shell contextMenu and uses the ContextMenuStrip.
/// The ContextMenuStrip contains groups and groupOrder which it uses to add items to itself.
/// ControlDesigners can add custom items to the contextMenu, using the new member to the
/// group and add the groupOrder to the ContextMenu.
/// </summary>
internal class BaseContextMenuStrip : GroupedContextMenuStrip
{
private readonly IServiceProvider _serviceProvider;
private ToolStripMenuItem? _selectionMenuItem;
public BaseContextMenuStrip(IServiceProvider provider) : base()
{
_serviceProvider = provider;
// Now initialize the contextMenu
InitializeContextMenu();
}
/// <summary>
/// Helper function to add the "View Code" menuItem.
/// </summary>
private void AddCodeMenuItem()
{
StandardCommandToolStripMenuItem codeMenuItem = new(StandardCommands.ViewCode, SR.ContextMenuViewCode, "viewcode", _serviceProvider);
Groups[StandardGroups.Code].Items.Add(codeMenuItem);
}
/// <summary>
/// Helper function to add the "SendToBack/BringToFront" menuItem.
/// </summary>
private void AddZorderMenuItem()
{
StandardCommandToolStripMenuItem ZOrderMenuItem = new(StandardCommands.BringToFront, SR.ContextMenuBringToFront, "bringToFront", _serviceProvider);
Groups[StandardGroups.ZORder].Items.Add(ZOrderMenuItem);
ZOrderMenuItem = new StandardCommandToolStripMenuItem(StandardCommands.SendToBack, SR.ContextMenuSendToBack, "sendToBack", _serviceProvider);
Groups[StandardGroups.ZORder].Items.Add(ZOrderMenuItem);
}
/// <summary>
/// Helper function to add the "Alignment" menuItem.
/// </summary>
private void AddGridMenuItem()
{
StandardCommandToolStripMenuItem gridMenuItem = new(StandardCommands.AlignToGrid, SR.ContextMenuAlignToGrid, "alignToGrid", _serviceProvider);
Groups[StandardGroups.Grid].Items.Add(gridMenuItem);
}
/// <summary>
/// Helper function to add the "Locked" menuItem.
/// </summary>
private void AddLockMenuItem()
{
StandardCommandToolStripMenuItem lockMenuItem = new(StandardCommands.LockControls, SR.ContextMenuLockControls, "lockControls", _serviceProvider);
Groups[StandardGroups.Lock].Items.Add(lockMenuItem);
}
/// <summary>
/// Helper function to add the Select Parent menuItem.
/// </summary>
private void RefreshSelectionMenuItem()
{
int index = -1;
if (_selectionMenuItem is not null)
{
index = Items.IndexOf(_selectionMenuItem);
Groups[StandardGroups.Selection].Items.Remove(_selectionMenuItem);
Items.Remove(_selectionMenuItem);
}
List<Component> parentControls = [];
int nParentControls = 0;
// Get the currently selected Control
if (_serviceProvider.GetService(typeof(ISelectionService)) is ISelectionService selectionService && _serviceProvider.GetService(typeof(IDesignerHost)) is IDesignerHost host)
{
IComponent root = host.RootComponent;
Debug.Assert(root is not null, "Null root component. Will be unable to build selection menu");
if (selectionService.PrimarySelection is Control selectedControl && root is not null && selectedControl != root)
{
Control? parentControl = selectedControl.Parent;
while (parentControl is not null)
{
if (parentControl.Site is not null)
{
parentControls.Add(parentControl);
nParentControls++;
}
if (parentControl == root)
{
break;
}
parentControl = parentControl.Parent;
}
}
else if (selectionService.PrimarySelection is ToolStripItem selectedItem)
{
if (host.GetDesigner(selectedItem) is ToolStripItemDesigner itemDesigner)
{
parentControls = itemDesigner.AddParentTree();
nParentControls = parentControls.Count;
}
}
}
if (nParentControls > 0)
{
_selectionMenuItem = new ToolStripMenuItem();
if (_serviceProvider.GetService(typeof(IUIService)) is IUIService uis)
{
_selectionMenuItem.DropDown.Renderer = (ToolStripProfessionalRenderer)uis.Styles["VsRenderer"]!;
// Set the right Font
_selectionMenuItem.DropDown.Font = (Font)uis.Styles["DialogFont"]!;
if (uis.Styles["VsColorPanelText"] is Color color)
{
_selectionMenuItem.DropDown.ForeColor = color;
}
}
_selectionMenuItem.Text = SR.ContextMenuSelect;
foreach (Component parent in parentControls)
{
ToolStripMenuItem selectListItem = new SelectToolStripMenuItem(parent, _serviceProvider);
_selectionMenuItem.DropDownItems.Add(selectListItem);
}
Groups[StandardGroups.Selection].Items.Add(_selectionMenuItem);
// Re-add the newly refreshed item.
if (index != -1)
{
Items.Insert(index, _selectionMenuItem);
}
}
}
/// <summary>
/// Helper function to add the Verbs.
/// </summary>
private void AddVerbMenuItem()
{
// Add Designer Verbs..
if (_serviceProvider.TryGetService(out IMenuCommandService? menuCommandService))
{
DesignerVerbCollection verbCollection = menuCommandService.Verbs;
foreach (DesignerVerb verb in verbCollection)
{
DesignerVerbToolStripMenuItem verbItem = new(verb);
Groups[StandardGroups.Verbs].Items.Add(verbItem);
}
}
}
/// <summary>
/// Helper function to add the "Cut/Copy/Paste/Delete" menuItem.
/// </summary>
private void AddEditMenuItem()
{
StandardCommandToolStripMenuItem stdMenuItem = new(StandardCommands.Cut, SR.ContextMenuCut, "cut", _serviceProvider);
Groups[StandardGroups.Edit].Items.Add(stdMenuItem);
stdMenuItem = new StandardCommandToolStripMenuItem(StandardCommands.Copy, SR.ContextMenuCopy, "copy", _serviceProvider);
Groups[StandardGroups.Edit].Items.Add(stdMenuItem);
stdMenuItem = new StandardCommandToolStripMenuItem(StandardCommands.Paste, SR.ContextMenuPaste, "paste", _serviceProvider);
Groups[StandardGroups.Edit].Items.Add(stdMenuItem);
stdMenuItem = new StandardCommandToolStripMenuItem(StandardCommands.Delete, SR.ContextMenuDelete, "delete", _serviceProvider);
Groups[StandardGroups.Edit].Items.Add(stdMenuItem);
}
/// <summary>
/// Helper function to add the "Properties" menuItem.
/// </summary>
private void AddPropertiesMenuItem()
{
StandardCommandToolStripMenuItem stdMenuItem = new(StandardCommands.DocumentOutline, SR.ContextMenuDocumentOutline, "", _serviceProvider);
Groups[StandardGroups.Properties].Items.Add(stdMenuItem);
stdMenuItem = new StandardCommandToolStripMenuItem(MenuCommands.DesignerProperties, SR.ContextMenuProperties, "properties", _serviceProvider);
Groups[StandardGroups.Properties].Items.Add(stdMenuItem);
}
/// <summary>
/// Basic Initialize method.
/// </summary>
private void InitializeContextMenu()
{
Name = "designerContextMenuStrip";
if (_serviceProvider.TryGetService(out IUIService? uis))
{
Renderer = (ToolStripProfessionalRenderer)uis.Styles["VsRenderer"]!;
if (uis.Styles["VsColorPanelText"] is Color color)
{
ForeColor = color;
}
}
GroupOrdering.AddRange([
StandardGroups.Code,
StandardGroups.ZORder,
StandardGroups.Grid,
StandardGroups.Lock,
StandardGroups.Verbs,
StandardGroups.Custom,
StandardGroups.Selection,
StandardGroups.Edit,
StandardGroups.Properties]);
// ADD MENUITEMS
AddCodeMenuItem();
AddZorderMenuItem();
AddGridMenuItem();
AddLockMenuItem();
AddVerbMenuItem();
RefreshSelectionMenuItem();
AddEditMenuItem();
AddPropertiesMenuItem();
}
/// <summary>
/// Public function that allows the individual MenuItems to get refreshed each time the ContextMenu is opened.
/// </summary>
public override void RefreshItems()
{
if (_serviceProvider.TryGetService(out IUIService? uis))
{
Font = (Font)uis.Styles["DialogFont"]!;
}
foreach (ToolStripItem item in Items)
{
if (item is StandardCommandToolStripMenuItem stdItem)
{
stdItem.RefreshItem();
}
}
RefreshSelectionMenuItem();
}
/// <summary>
/// A ToolStripMenuItem that gets added for the "Select" menuitem.
/// </summary>
private class SelectToolStripMenuItem : ToolStripMenuItem
{
private readonly Component? _comp;
private readonly IServiceProvider _serviceProvider;
private readonly Type _itemType;
private bool _cachedImage;
private Image? _image;
private static readonly string s_systemWindowsFormsNamespace = typeof(ToolStripItem).Namespace!;
public SelectToolStripMenuItem(Component c, IServiceProvider provider)
{
_comp = c;
_serviceProvider = provider;
// Get NestedSiteName...
string? compName = null;
if (_comp is not null && _comp.Site is { } site)
{
if (site is INestedSite nestedSite && !string.IsNullOrEmpty(nestedSite.FullName))
{
compName = nestedSite.FullName;
}
else if (!string.IsNullOrEmpty(site.Name))
{
compName = site.Name;
}
}
Text = string.Format(SR.ToolStripSelectMenuItem, compName);
_itemType = c.GetType();
}
public override Image? Image
{
get
{
// Defer loading the image until we're sure we need it
if (!_cachedImage)
{
_cachedImage = true;
// else attempt to get the resource from a known place in the manifest.
// if and only if the namespace of the type is System.Windows.Forms.
// else attempt to get the resource from a known place in the manifest
if (_itemType.Namespace == s_systemWindowsFormsNamespace)
{
_image = ToolboxBitmapAttribute.GetImageFromResource(_itemType, imageName: null, large: false);
}
// if all else fails, throw up a default image.
_image ??= ToolboxBitmapAttribute.GetImageFromResource(_comp!.GetType(), imageName: null, large: false);
}
return _image;
}
set
{
_image = value;
_cachedImage = true;
}
}
/// <summary>
/// Items OnClick event, to select the Parent Control.
/// </summary>
protected override void OnClick(EventArgs e)
{
if (_comp is not null && _serviceProvider.TryGetService(out ISelectionService? selectionService))
{
selectionService.SetSelectedComponents(new object[] { _comp }, SelectionTypes.Replace);
}
}
}
}
|