Code:
/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / ndp / fx / src / Designer / WinForms / System / WinForms / Design / ToolStripMenuItemDesigner.cs / 5 / ToolStripMenuItemDesigner.cs
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//-----------------------------------------------------------------------------
/*
*/
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Windows.Forms.Design.ToolStripMenuItemDesigner..ctor()")]
namespace System.Windows.Forms.Design
{
using System.Design;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System;
using System.Security;
using System.Security.Permissions;
using System.Collections;
using System.ComponentModel.Design;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Design;
using System.Windows.Forms.Design;
using System.Windows.Forms.Design.Behavior;
using System.ComponentModel.Design.Serialization;
///
/// Designer for ToolStripMenuItems.
///
internal class ToolStripMenuItemDesigner : ToolStripDropDownItemDesigner
{
private const int GLYPHINSET=2;
//
// This is the typeHereNode that appears to the bottom and right
// of each commited ToolStripDropDownItem
//
private DesignerToolStripControlHost typeHereNode;
private ToolStripTemplateNode typeHereTemplateNode = null;
//
// This is the TemplateNode.EditorToolStrip. The editor ToolStrip is
// encapsulated in a ToolStripControlHost and then added as a
// ToolStripDropDownItem on the current ToolStripDropDownItems DropDown.
//
private DesignerToolStripControlHost commitedEditorNode;
//
// Actual InSitu Editor. This is created for every selected
// ToolStripDropDownItem and is DISPOSED immediately after the item
// comes out of InSitu edit Mode.
//
private ToolStripTemplateNode commitedTemplateNode;
//
// DesignerHost for current Component.
//
private IDesignerHost designerHost;
private ToolStripItem parentItem = null;
private ToolStripAdornerWindowService toolStripAdornerWindowService = null;
private ToolStripKeyboardHandlingService keyboardHandlingService = null;
//Make Selection service a class level member.. used a lot.
private ISelectionService selSvc = null;
//DesignerTrnasaction used for removing Items
private DesignerTransaction _pendingTransaction = null;
private bool fireComponentChanged = false;
//indicates that we are adding new MenuItem ..
private bool componentAddingFired = false;
//new item index
private int indexToInsertNewItem = -1;
//only used by DropDownMenu, DropDown or ContextMenuStrip.
private DesignerTransaction insertMenuItemTransaction;
// We want one parent transaction when the item is added by InSitu editing which is now supported only for MenuItems.
// This parent transaction would include
// - Adding the DummyItem
// - Swapping the DummyItem with the InsItu
// - Committing the new Item with the text entered in the Insitu.
private DesignerTransaction newMenuItemTransaction;
//DropDownToInvalidate
private Rectangle dropDownSizeToInvalidate = Rectangle.Empty;
//DropDownToInvalidate while ComponentRemove
private Rectangle boundsToInvalidateOnRemove = Rectangle.Empty;
private ToolStripDropDownGlyph rootControlGlyph;
private bool initialized = false;
// Hook on the Undoing and Undone Events...
private UndoEngine undoEngine = null;
private bool undoingCalled = false;
private bool addingDummyItem = false;
//custom DropDown
private ToolStripDropDown customDropDown = null;
private bool dropDownSet = false;
private SerializationStore serializedDataForDropDownItems = null;
private bool dropDownSetFailed = false;
///
/// The ToolStripDropDownItems are the associated components.
/// We want those to come with in any cut, copy opreations.
///
public override System.Collections.ICollection AssociatedComponents
{
get
{
ArrayList items = new ArrayList();
// Return the list only if the DropDown is AutoGenerated.
// else the DropDown property set/get will handle it.
if (MenuItem.DropDown.IsAutoGenerated)
{
foreach (ToolStripItem item in MenuItem.DropDownItems)
{
DesignerToolStripControlHost addNewItem = item as DesignerToolStripControlHost;
if (addNewItem == null)
{
items.Add(item);
}
}
}
return (ICollection)items;
}
}
///
/// ShadowProperty.
///
private bool CheckOnClick
{
get
{
return (bool)ShadowProperties["CheckOnClick"];
}
set
{
ShadowProperties["CheckOnClick"] = value;
}
}
///
/// ShadowProperty.
///
private bool DoubleClickEnabled
{
get
{
return (bool)ShadowProperties["DoubleClickEnabled"];
}
set
{
ShadowProperties["DoubleClickEnabled"] = value;
}
}
///
/// ShadowProperty.
///
private ToolStripDropDown DropDown
{
get
{
return customDropDown;
}
set
{
dropDownSetFailed = false;
if (IsParentDropDown(value))
{
dropDownSetFailed = true;
throw new ArgumentException(SR.GetString(SR.InvalidArgument,
"DropDown",
value.ToString()));
}
//Check if DropDown Exists .. and if yes then Close the DropDown
if (MenuItem.DropDown != null)
{
RemoveTypeHereNode(MenuItem);
// remove and destroy all the items...
if (MenuItem.DropDown.IsAutoGenerated && MenuItem.DropDownItems.Count > 0)
{
//Serialize all the DropDownItems for this Item....
ComponentSerializationService serializationService = GetService(typeof(ComponentSerializationService)) as ComponentSerializationService;
if (serializationService != null)
{
serializedDataForDropDownItems = serializationService.CreateStore();
foreach (ToolStripItem item in MenuItem.DropDownItems)
{
//Dont Serialize the DesignerToolStripControlHost...
if (!(item is DesignerToolStripControlHost))
{
serializationService.Serialize(serializedDataForDropDownItems, item);
}
}
//close the SerializationStore to Serialize Items..
serializedDataForDropDownItems.Close();
}
ToolStripItem[] items = new ToolStripItem[MenuItem.DropDownItems.Count];
MenuItem.DropDownItems.CopyTo(items, 0);
//base.RaiseComponentChanging(TypeDescriptor.GetProperties(MenuItem)["DropDownItems"]);
foreach (ToolStripItem item in items)
{
MenuItem.DropDownItems.Remove(item);
designerHost.DestroyComponent(item);
}
//base.RaiseComponentChanged(TypeDescriptor.GetProperties(MenuItem)["DropDownItems"], null, null);
}
MenuItem.HideDropDown();
}
// Set The DropDown
MenuItem.DropDown = value;
//Set the Shadow Property
customDropDown = value;
// If DropDown is Set to null and we have valid serializedData, then use it to recreate Items.
if (value == null && !dropDownSet && serializedDataForDropDownItems != null)
{
try
{
// turn off Adding/Added events listened to by the ToolStripDesigner...
ToolStripDesigner._autoAddNewItems = false;
// Add Dummy Node.
CreatetypeHereNode();
ComponentSerializationService serializationService = GetService(typeof(ComponentSerializationService)) as ComponentSerializationService;
if (serializationService != null)
{
serializationService.Deserialize(serializedDataForDropDownItems);
serializedDataForDropDownItems = null;
}
}
finally
{
// turn on Adding/Added events listened to by the ToolStripDesigner...
ToolStripDesigner._autoAddNewItems = true;
}
}
MenuItem.DropDown.OwnerItem = MenuItem;
//hook up to the Disposed event ...
MenuItem.DropDown.Disposed += new EventHandler(OnDropDownDisposed);
// show the dropDown.
if (MenuItem.Equals(selSvc.PrimarySelection))
{
//Add TypeHereNode & show the Dropdown
InitializeDropDown();
}
}
}
///
/// ToolStripEditorManager used this internal property to
/// Activate the editor.
///
internal override ToolStripTemplateNode Editor
{
get
{
if (base.Editor != null)
{
return base.Editor;
}
if (commitedTemplateNode != null)
{
return commitedTemplateNode;
}
return typeHereTemplateNode;
}
set
{
commitedTemplateNode = value;
}
}
///
/// True if the MenuItem is on ContextMenu.
///
private bool IsOnContextMenu
{
get
{
ToolStrip mainStrip = GetMainToolStrip();
if (mainStrip != null && mainStrip.Site != null && !(mainStrip is ContextMenuStrip))
{
return false;
}
return true;
}
}
///
/// Easy method for getting to the ToolStripDropDownItem
///
private ToolStripDropDownItem MenuItem
{
get
{
return ToolStripItem as ToolStripDropDownItem;
}
}
///
/// This property is true when the OwnerItem is selected during COPY & PASTE operations.
///
private bool MenuItemSelected
{
get
{
// check to see if the primary selection is the ToolStrip or one of it's children.
//
if (selSvc != null)
{
object selectedItem = selSvc.PrimarySelection;
ToolStripItem toolItem = null;
if (selectedItem == null)
{
if (KeyboardHandlingService != null)
{
selectedItem = KeyboardHandlingService.SelectedDesignerControl;
}
toolItem = selectedItem as ToolStripItem;
}
else
{
toolItem = selectedItem as ToolStripItem;
}
if (toolItem != null)
{
// We always need to return the current selection if we are adding a DummyNode...
if (designerHost != null)
{
ToolStripItemDesigner designer = designerHost.GetDesigner(toolItem) as ToolStripItemDesigner;
if (designer != null)
{
if (designer.dummyItemAdded)
{
return (toolItem == MenuItem);
}
}
}
// We need to return parent if we are on DropDown...
if (toolItem.IsOnDropDown && toolItem.Owner is ToolStripDropDown)
{
ToolStripDropDownItem parentItem = ((ToolStripDropDown)toolItem.Owner).OwnerItem as ToolStripDropDownItem;
return (parentItem == MenuItem);
}
else
{
return (toolItem == MenuItem);
}
}
else if (selectedItem is ContextMenuStrip && MenuItem.DropDown == selectedItem)
{
return true;
}
}
return false;
}
}
private ToolStripKeyboardHandlingService KeyboardHandlingService {
get {
if (keyboardHandlingService == null) {
keyboardHandlingService = GetService(typeof(ToolStripKeyboardHandlingService)) as ToolStripKeyboardHandlingService;
}
return keyboardHandlingService;
}
}
///
/// ParentComponent in case of MenuItems on the DropDown is the OwnerItem of the DropDown and not the ToolStripDropDown (since the DropDowns are not sited)
///
protected override IComponent ParentComponent
{
get
{
if (ToolStripItem != null)
{
if (!ToolStripItem.IsOnOverflow && ToolStripItem.IsOnDropDown)
{
ToolStripDropDown dropDown = MenuItem.Owner as ToolStripDropDown;
// If the dropDown is NOT AutoGenerated then its a dropdown
// the user has set or its a contextMenuStrip/ToolStripDropDownMenu/ToolStripDropDown
// that has been added from the ToolBox.
// In such a case dont return the ownerItem but the DropDown itself as the ParentComponent.
if (dropDown != null)
{
if (dropDown.IsAutoGenerated)
{
return dropDown.OwnerItem;
}
else
{
return dropDown;
}
}
}
return base.ParentComponent;
}
return null;
}
}
/////////////////////////////////////////////////////////////////////////////////////
//// ////
//// Methods ////
//// ////
/////////////////////////////////////////////////////////////////////////////////////
///
/// Adds the dummy node for InSitu Edit.
///
internal void AddNewTemplateNode(ToolStripDropDown dropDown)
{
//Check if the DropDown contains a typehereNode....
foreach (ToolStripItem currentItem in dropDown.Items)
{
if (currentItem is DesignerToolStripControlHost)
{
typeHereNode = (DesignerToolStripControlHost)currentItem;
}
}
if (typeHereNode != null)
{
dropDown.Items.Remove(typeHereNode);
}
//
// setup the MINIToolStrip host...
//
typeHereTemplateNode = new ToolStripTemplateNode(Component, SR.GetString(SR.ToolStripDesignerTemplateNodeEnterText), null);
int width = typeHereTemplateNode.EditorToolStrip.Width;
typeHereNode = new DesignerToolStripControlHost(typeHereTemplateNode.EditorToolStrip);
typeHereTemplateNode.ControlHost = typeHereNode;
typeHereNode.AutoSize = false;
typeHereNode.Width = width;
dropDown.Items.Add(typeHereNode);
}
// used by morphing in ToolStripItemDesigner ... hence internal method.
internal void AddItemBodyGlyph(ToolStripItem item)
{
if (item != null)
{
ToolStripItemDesigner dropDownItemDesigner = (ToolStripItemDesigner)designerHost.GetDesigner(item);
if (dropDownItemDesigner != null)
{
Rectangle bounds = dropDownItemDesigner.GetGlyphBounds();
System.Windows.Forms.Design.Behavior.Behavior toolStripBehavior = new ToolStripItemBehavior();
// Initialize Glyph
ToolStripItemGlyph bodyGlyphForddItem = new ToolStripItemGlyph(item, dropDownItemDesigner, bounds, toolStripBehavior);
//Set the glyph for the item .. so that we can remove it later....
dropDownItemDesigner.bodyGlyph = bodyGlyphForddItem;
//Add ItemGlyph to the Collection
if (toolStripAdornerWindowService != null)
{
toolStripAdornerWindowService.DropDownAdorner.Glyphs.Insert(0, bodyGlyphForddItem);
}
}
}
}
// Add individual item Body Glyphs
private void AddBodyGlyphs(ToolStripDropDownItem item)
{
if (item != null)
{
ToolStripMenuItemDesigner itemDesigner = (ToolStripMenuItemDesigner)designerHost.GetDesigner(item);
if (itemDesigner != null)
{
foreach (ToolStripItem ddItem in item.DropDownItems)
{
AddItemBodyGlyph(ddItem);
}
}
}
}
///
///
/// This is called by the TemplateNode to Commit the Edit.
/// This function creates a NEW ToolStripDropDownItem if we are committing
/// a dummy node or else just replaces the TEXT and IMAGE if we are changing
/// an existing MenuItem.
///
///
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
[SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")]
internal override void CommitEdit(Type type, string text, bool commit, bool enterKeyPressed, bool tabKeyPressed)
{
IsEditorActive = false;
if (!(MenuItem.Owner is ToolStripDropDown) && base.Editor != null) //we are on Base Menustrip !!
{
base.CommitEdit(type, text, commit, enterKeyPressed, tabKeyPressed);
}
else if (commit)
{
int index = -1;
bool dummyItem = dummyItemAdded;
dummyItemAdded = false;
//Invalidate DropDown..
MenuItem.DropDown.SuspendLayout();
if (commitedEditorNode != null) /// this means we have a valid node and we just changed some properties..
{
index = MenuItem.DropDownItems.IndexOf(commitedEditorNode);
ToolStripItem editedItem = (ToolStripItem)MenuItem.DropDownItems[index + 1];
// Remove TemplatENode
MenuItem.DropDown.Items.Remove(commitedEditorNode);
// Get rid of the templateNode...
if (commitedTemplateNode != null)
{
commitedTemplateNode.CloseEditor();
commitedTemplateNode = null;
}
if (commitedEditorNode != null)
{
commitedEditorNode.Dispose();
commitedEditorNode = null;
}
// If we have type "-" this means the user wants to add a Separator.
if (text == "-")
{
ToolStripItemDesigner itemDesigner = designerHost.GetDesigner(editedItem) as ToolStripItemDesigner;
if (itemDesigner != null)
{
try
{
editedItem = itemDesigner.MorphCurrentItem(typeof(ToolStripSeparator));
//Remove the ActionGlyph Added by morphing
RemoveItemBodyGlyph(editedItem);
}
catch
{
if (newMenuItemTransaction != null)
{
try
{
newMenuItemTransaction.Cancel();
}
catch //This will cause ROLLBACK and hence throw if the project is already in DEBUG and instuEdit was Active.
{
}
newMenuItemTransaction = null;
}
}
finally
{
if (newMenuItemTransaction != null)
{
newMenuItemTransaction.Commit();
newMenuItemTransaction = null;
}
}
}
}
else
{
// We are adding the item through INSITU for the first time
if (dummyItem)
{
try
{
dummyItemAdded = true;
CreateNewItem(type, index, text);
designerHost.DestroyComponent(editedItem);
// One place where we need to call this explicitly since the selection
// doesnt change.
//
if (enterKeyPressed)
{
typeHereNode.SelectControl();
}
}
catch
{
if (newMenuItemTransaction != null)
{
try
{
newMenuItemTransaction.Cancel();
}
catch //This will cause ROLLBACK and hence throw if the project is already in DEBUG and instuEdit was Active.
{
}
newMenuItemTransaction = null;
}
}
finally
{
if (newMenuItemTransaction != null)
{
newMenuItemTransaction.Commit();
newMenuItemTransaction = null;
}
dummyItemAdded = false;
}
}
else //We are editing item that was already present
{
// put the item back...
editedItem.Visible = true;
//create our transaction
DesignerTransaction designerTransaction = designerHost.CreateTransaction(SR.GetString(SR.ToolStripItemPropertyChangeTransaction));
try
{
//Change the properties
PropertyDescriptor textProp = TypeDescriptor.GetProperties(editedItem)["Text"];
string oldValue = (string)textProp.GetValue(editedItem);
if (textProp != null && text != oldValue)
{
textProp.SetValue(editedItem, text);
}
}
catch
{
if (designerTransaction != null)
{
designerTransaction.Cancel();
designerTransaction = null;
}
}
finally
{
if (designerTransaction != null)
{
designerTransaction.Commit();
designerTransaction = null;
}
}
}
}
}
else //if commitedEditorNode == null and we are in commitEdit then just add the new Item, since this item is added through dropDown.
{
//if no editorNode then we are commiting a NEW NODE...
index = MenuItem.DropDownItems.IndexOf(typeHereNode);
try
{
dummyItemAdded = true;
CreateNewItem(type, index, text);
}
finally
{
dummyItemAdded = false;
}
// One place where we need to call this explicitly since the selection
// doesnt change.
//
typeHereNode.SelectControl();
}
//Invalidate DropDown..
MenuItem.DropDown.ResumeLayout(true);
MenuItem.DropDown.PerformLayout();
//Reset the Glyphs after Item addition...
ResetGlyphs(MenuItem);
//set the selection to our new item only if item was commited via ENTER KEY in the Insitu Mode.
if (selSvc != null)
{
if (enterKeyPressed)
{
ToolStripItem nextItem = null;
if ((MenuItem.DropDownDirection == ToolStripDropDownDirection.AboveLeft ||
MenuItem.DropDownDirection == ToolStripDropDownDirection.AboveRight) && index >= 1)
{
nextItem = MenuItem.DropDownItems[index - 1];
}
else
{
nextItem = MenuItem.DropDownItems[index + 1];
}
if (KeyboardHandlingService != null)
{
if (nextItem != null)
{
ToolStripDropDownItem currentItem = MenuItem.DropDownItems[index] as ToolStripDropDownItem;
if (currentItem != null)
{
currentItem.HideDropDown();
}
}
if (nextItem == typeHereNode)
{
// Put Selection on the TypeHereNode.
KeyboardHandlingService.SelectedDesignerControl = nextItem;
selSvc.SetSelectedComponents(null, SelectionTypes.Replace);
}
else
{
KeyboardHandlingService.SelectedDesignerControl = null;
selSvc.SetSelectedComponents(new object[] { nextItem });
}
}
}
else if (tabKeyPressed) //just select this the new Item
{
selSvc.SetSelectedComponents(new object[] { MenuItem.DropDownItems[index] }, SelectionTypes.Replace);
}
}
}
else //we come here if we have not committed so revert our state...
{
if (commitedEditorNode != null) /// we just changed some properties which we want to revert...
{
MenuItem.DropDown.SuspendLayout();
bool dummyItem = dummyItemAdded;
dummyItemAdded = false;
int index = MenuItem.DropDownItems.IndexOf(commitedEditorNode);
ToolStripItem editedItem = (ToolStripItem)MenuItem.DropDownItems[index + 1];
MenuItem.DropDown.Items.Remove(commitedEditorNode);
// put the item back...
editedItem.Visible = true;
if (commitedTemplateNode != null)
{
commitedTemplateNode.CloseEditor();
commitedTemplateNode = null;
}
if (commitedEditorNode != null)
{
commitedEditorNode.Dispose();
commitedEditorNode = null;
}
if (dummyItem)
{
MenuItem.DropDownItems.Remove(editedItem);
try
{
designerHost.DestroyComponent(editedItem);
}
catch
{
if (newMenuItemTransaction != null)
{
try
{
newMenuItemTransaction.Cancel();
}
catch //This will cause ROLLBACK and hence throw if the project is already in DEBUG and instuEdit was Active.
{
}
newMenuItemTransaction = null;
}
}
editedItem = null;
}
// Required to do here...
MenuItem.DropDown.ResumeLayout();
//Remove the Glyphs so that Mouse Message go to the Editor
if (editedItem != null)
{
AddItemBodyGlyph(editedItem);
}
if (dummyItem)
{
SelectionManager selMgr = (SelectionManager)GetService(typeof(SelectionManager));
/// Since the operation is cancelled and there is no change of glyphs, Set SelectionManager.NeedRefresh to false so that it doesnt REFRESH,
/// when the transaction is cancelled.
selMgr.NeedRefresh = false;
if (newMenuItemTransaction != null)
{
try
{
dummyItemAdded = true;
newMenuItemTransaction.Cancel();
newMenuItemTransaction = null;
if (MenuItem.DropDownItems.Count == 0)
{
CreatetypeHereNode();
}
}
finally
{
dummyItemAdded = false;
}
}
dummyItem = false;
}
// Added for Separators...
MenuItem.DropDown.PerformLayout();
}
}
}
///
/// Creates the dummy node for InSitu Edit.
///
private void CreatetypeHereNode()
{
//Debug.Assert(typeHereNode == null, "Why is our dummy node valid?");
if (typeHereNode == null)
{
AddNewTemplateNode(MenuItem.DropDown);
//Add Text for Debugging Non Sited DropDown..
if (MenuItem.DropDown.Site == null)
{
MenuItem.DropDown.Text = MenuItem.Name + ".DropDown";
}
}
else if (typeHereNode != null && MenuItem.DropDownItems.IndexOf(typeHereNode) == -1)
{
MenuItem.DropDown.Items.Add(typeHereNode);
typeHereNode.Visible = true;
}
//Invalidate DropDown..
MenuItem.DropDown.PerformLayout();
}
///
///
/// This Function is called by EnterInSituEdit where in we Swap the typeHereNode by
/// the TemplateNode (the Insitu Editor).
/// Since the TemplateNode had a EditorToolStrip we can just HOST that ToolStrip
/// as a ToolStripContorlHost and add it to the DropDown.
///
///
private void CreateDummyMenuItem(ToolStripItem item, string text, Image image)
{
commitedTemplateNode = new ToolStripTemplateNode(Component, text, image);
commitedTemplateNode.ActiveItem = item;
int width = commitedTemplateNode.EditorToolStrip.Width;
commitedEditorNode = new DesignerToolStripControlHost(commitedTemplateNode.EditorToolStrip);
commitedEditorNode.AutoSize = false;
commitedEditorNode.Width = width;
}
///
/// This helper function creates a dummyItem for Insitu editing.
///
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
[SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")]
private ToolStripItem CreateDummyItem(Type t, int dummyIndex)
{
if (designerHost == null)
{
Debug.Fail("Couldn't get designer host!");
return null;
}
ToolStripItem newItem = null;
// For the "Upward DropDown" add at index +1...
if (MenuItem.DropDownDirection == ToolStripDropDownDirection.AboveLeft || MenuItem.DropDownDirection == ToolStripDropDownDirection.AboveRight)
{
dummyIndex++;
}
try
{
// turn off Adding/Added events listened to by the ToolStripDesigner...
ToolStripDesigner._autoAddNewItems = false;
//Store the index into a class level member so that the componentChanged can access it
indexToInsertNewItem = dummyIndex;
try
{
//create our transaction
if (newMenuItemTransaction == null)
{
newMenuItemTransaction = designerHost.CreateTransaction(SR.GetString(SR.ToolStripCreatingNewItemTransaction));
}
fireComponentChanged = true;
newItem = (ToolStripItem)designerHost.CreateComponent(t);
}
finally
{
fireComponentChanged = false;
}
ToolStripItemDesigner designer = designerHost.GetDesigner(newItem) as ToolStripItemDesigner;
try
{
// ToolStripItem designer tries to set the TEXT for the item in the InitializeNewComponent()
// But since we are create item thru InSitu .. we shouldnt do this.
designer.InternalCreate = true;
if (designer is ComponentDesigner)
{
((ComponentDesigner)designer).InitializeNewComponent(null);
}
}
finally
{
designer.InternalCreate = false;
}
}
catch (InvalidOperationException ex) {
CommitInsertTransaction(/*commit=*/false);
if (newMenuItemTransaction != null) {
newMenuItemTransaction.Cancel();
newMenuItemTransaction = null;
}
IUIService uiService = (IUIService)GetService(typeof(IUIService));
uiService.ShowError(ex.Message);
}
finally
{
// turn on Adding/Added events listened to by the ToolStripDesigner...
ToolStripDesigner._autoAddNewItems = true;
// Reset the index
indexToInsertNewItem = -1;
}
return newItem;
}
///
/// Asks the host to create a new DropDownItem, inserts the item
/// into the collection & selects it.
///
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
[SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")]
private ToolStripItem CreateNewItem(Type t, int dummyIndex, string newText)
{
if (designerHost == null)
{
Debug.Fail("Couldn't get designer host!");
return null;
}
ToolStripItem newItem = null;
// For the "Upward DropDown" add at index +1...
if (MenuItem.DropDownDirection == ToolStripDropDownDirection.AboveLeft || MenuItem.DropDownDirection == ToolStripDropDownDirection.AboveRight)
{
dummyIndex++;
}
//create our transaction
DesignerTransaction outerTransaction = designerHost.CreateTransaction(SR.GetString(SR.ToolStripCreatingNewItemTransaction));
try
{
// turn off Adding/Added events listened to by the ToolStripDesigner...
ToolStripDesigner._autoAddNewItems = false;
//Store the index into a class level member so that the componentChanged can access it
indexToInsertNewItem = dummyIndex;
try
{
fireComponentChanged = true;
newItem = (ToolStripItem)designerHost.CreateComponent(t, ToolStripDesigner.NameFromText(newText, t, MenuItem.Site));
}
finally
{
fireComponentChanged = false;
}
ToolStripItemDesigner designer = designerHost.GetDesigner(newItem) as ToolStripItemDesigner;
try
{
// ToolStripItem designer tries to set the TEXT for the item in the InitializeNewComponent()
// But since we are create item thru InSitu .. we shouldnt do this.
if (!string.IsNullOrEmpty(newText) || addingDummyItem)
{
designer.InternalCreate = true;
}
if (designer is ComponentDesigner)
{
((ComponentDesigner)designer).InitializeNewComponent(null);
}
}
finally
{
designer.InternalCreate = false;
}
//Set the Text and Image..
if (newItem != null)
{
PropertyDescriptor textProperty = TypeDescriptor.GetProperties(newItem)["Text"];
Debug.Assert(textProperty != null, "Could not find 'Text' property in ToolStripItem.");
if (textProperty != null && !string.IsNullOrEmpty(newText))
{
textProperty.SetValue(newItem, newText);
}
}
}
catch
{
//There might be scenarios where the ComponentAdding is fired but the Added doesnt get fired due to issues like VsW: 499796.
// Is such cases the InsertTransaction might be still active...
// So we need to cancel that too here.
CommitInsertTransaction(/*commit=*/ false);
if (outerTransaction != null)
{
outerTransaction.Cancel();
outerTransaction = null;
}
}
finally
{
if (outerTransaction != null)
{
outerTransaction.Commit();
outerTransaction = null;
}
// turn on Adding/Added events listened to by the ToolStripDesigner...
ToolStripDesigner._autoAddNewItems = true;
// Reset the index
indexToInsertNewItem = -1;
}
return newItem;
}
///
///
/// Helper function to find whether the passed in DropDownItems have same owner.
///
///
private bool CheckSameOwner(ToolStripDropDownItem lastSelected, ToolStripDropDownItem currentSelected)
{
if (lastSelected != null && currentSelected != null)
{
if (lastSelected.Owner is ToolStripDropDown && currentSelected.Owner is ToolStripDropDown)
{
ToolStripItem ownerLastSelected = ((ToolStripDropDown)(lastSelected.Owner)).OwnerItem;
ToolStripItem ownerCurrentSelected = ((ToolStripDropDown)(currentSelected.Owner)).OwnerItem;
return (ownerLastSelected == ownerCurrentSelected);
}
}
return false;
}
// internal method to commit any node.
internal void Commit()
{
if (commitedTemplateNode != null && commitedTemplateNode.Active)
{
//Get Index of the CommitedItem..
int index = MenuItem.DropDownItems.IndexOf(commitedEditorNode);
commitedTemplateNode.Commit(false, false);
if (index != -1 && MenuItem.DropDownItems.Count > index)
{
ToolStripDropDownItem newItem = MenuItem.DropDownItems[index] as ToolStripDropDownItem;
if (newItem != null)
{
newItem.HideDropDown();
}
}
}
else if (typeHereTemplateNode != null && typeHereTemplateNode.Active)
{
typeHereTemplateNode.Commit(false, false);
}
// COMMIT ALL THE THE PARENT CHAIN ....
ToolStripDropDownItem currentItem = MenuItem;
while (currentItem != null && currentItem.Owner is ToolStripDropDown)
{
currentItem = (ToolStripDropDownItem)((ToolStripDropDown)(currentItem.Owner)).OwnerItem;
if (currentItem != null)
{
ToolStripMenuItemDesigner itemDesigner = (ToolStripMenuItemDesigner)designerHost.GetDesigner(currentItem);
if (itemDesigner != null)
{
itemDesigner.Commit();
}
}
}
}
///
///
/// Disposes of this designer.
///
protected override void Dispose(bool disposing)
{
if (disposing)
{
//clean up
if (selSvc != null)
{
selSvc.SelectionChanged -= new EventHandler(this.OnSelectionChanged);
}
if (undoEngine != null)
{
undoEngine.Undoing -= new EventHandler(this.OnUndoing);
undoEngine.Undone -= new EventHandler(this.OnUndone);
}
if (MenuItem != null)
{
MenuItem.DropDown.Hide();
//Unhook the events...
UnHookEvents();
}
if (toolStripAdornerWindowService != null)
{
toolStripAdornerWindowService = null;
}
// unhook notifications.
//
IComponentChangeService componentChangeSvc = (IComponentChangeService)GetService(typeof(IComponentChangeService));
if (componentChangeSvc != null)
{
componentChangeSvc.ComponentRemoved -= new ComponentEventHandler(ComponentChangeSvc_ComponentRemoved);
componentChangeSvc.ComponentRemoving -= new ComponentEventHandler(ComponentChangeSvc_ComponentRemoving);
componentChangeSvc.ComponentAdding -= new ComponentEventHandler(ComponentChangeSvc_ComponentAdding);
componentChangeSvc.ComponentAdded -= new ComponentEventHandler(ComponentChangeSvc_ComponentAdded);
}
if (typeHereTemplateNode != null)
{
typeHereTemplateNode.RollBack();
typeHereTemplateNode.CloseEditor();
typeHereTemplateNode = null;
}
if (typeHereNode != null)
{
typeHereNode.Dispose();
typeHereNode = null;
}
if (commitedTemplateNode != null)
{
commitedTemplateNode.RollBack();
commitedTemplateNode.CloseEditor();
commitedTemplateNode = null;
}
if (commitedEditorNode != null)
{
commitedEditorNode.Dispose();
commitedEditorNode = null;
}
if (parentItem != null)
{
parentItem = null;
}
}
base.Dispose(disposing);
}
// When the dropDown is clicked; Commit any active insitu node.
private void DropDownClick(object sender, EventArgs e)
{
// Commit any InsituEdit Node.
if (KeyboardHandlingService != null && KeyboardHandlingService.TemplateNodeActive)
{
// If templateNode Active .. commit and Select it
KeyboardHandlingService.ActiveTemplateNode.CommitAndSelect();
}
}
// re-paint required to "validate" the glyphs
private void DropDownPaint(object sender, PaintEventArgs e)
{
//Select All requires the repaint of glyphs after the DropDown receives paint message.
if (selSvc != null && MenuItem != null)
{
foreach (ToolStripItem item in MenuItem.DropDownItems)
{
if (item.Visible && selSvc.GetComponentSelected(item))
{
ToolStripItemDesigner designer = designerHost.GetDesigner(item) as ToolStripItemDesigner;
if (designer != null)
{
Rectangle r = designer.GetGlyphBounds();
ToolStripDesignerUtils.GetAdjustedBounds(item, ref r);
r.Inflate(GLYPHINSET, GLYPHINSET);
//this will allow any Glyphs to re-paint
//after this control and its designer has painted
BehaviorService b = (BehaviorService)GetService(typeof(BehaviorService));
if (b != null)
{
b.ProcessPaintMessage(r);
}
}
}
// When you alt-tab from VS to any other application and come back
// and if the dropDown is open; then the templateNode doesnt paint.
// This happens when you have another control below the dropDown which paints over the controlhost
// so we need to refresh the TemplateNode in this case.
DesignerToolStripControlHost controlHost = item as DesignerToolStripControlHost;
if (controlHost != null)
{
controlHost.Control.Refresh();
}
}
}
}
// Invalidate the BehaviorService if the location changed.
private void DropDownLocationChanged(object sender, EventArgs e)
{
// this shoulnt get fired manytimes.. only in certain case...
// but in those cases its needed to REFRESH THE ENTIRE adornerWindow.
ToolStripDropDown dropDown = sender as ToolStripDropDown;
if (dropDown.Visible)
{
BehaviorService behaviorService = (BehaviorService)GetService(typeof(BehaviorService));
if (behaviorService != null)
{
behaviorService.Invalidate();
}
}
}
// Change the parent when the DropDown is opening.
private void DropDownItem_DropDownOpening(object sender, EventArgs e)
{
ToolStripDropDownItem ddi = sender as ToolStripDropDownItem;
if (toolStripAdornerWindowService != null)
{
ddi.DropDown.TopLevel = false;
ddi.DropDown.Parent = toolStripAdornerWindowService.ToolStripAdornerWindowControl;
}
}
// Add the DropDownGlyph when the dropDown is opened.
private void DropDownItem_DropDownOpened(object sender, EventArgs e)
{
//Add Glyphs...
ToolStripDropDownItem ddi = sender as ToolStripDropDownItem;
if (ddi != null)
{
ResetGlyphs(ddi);
}
// finally add Glyph for the "DropDown"
Control rootControl = ddi.DropDown;
if (rootControl != null)
{
ControlDesigner designer = designerHost.GetDesigner(designerHost.RootComponent) as ControlDesigner;
if (designer != null)
{
rootControlGlyph = new ToolStripDropDownGlyph(rootControl.Bounds, new DropDownBehavior(designer, this));
}
if (toolStripAdornerWindowService != null)
{
toolStripAdornerWindowService.DropDownAdorner.Glyphs.Add(rootControlGlyph);
}
}
}
// Remove the dropDownGlyph after the dropDown is closed.
private void DropDownItem_DropDownClosed(object sender, EventArgs e)
{
ToolStripDropDownItem ddi = sender as ToolStripDropDownItem;
if (ddi != null)
{
//Invaliate the ToolStripWindow.... for clearing the dropDowns
if (toolStripAdornerWindowService != null)
{
if (rootControlGlyph != null && toolStripAdornerWindowService.DropDownAdorner.Glyphs.Contains(rootControlGlyph))
{
toolStripAdornerWindowService.DropDownAdorner.Glyphs.Remove(rootControlGlyph);
}
}
//Remove body Glyphs...
InitializeBodyGlyphsForItems(false /*remove*/, ddi);
//Unhook all the Events
initialized = false;
UnHookEvents();
// Check if this is a Sited-DropDown
if (ddi.DropDown.Site != null || ddi.DropDownItems.Count == 1)
{
//Get Designer ... and call Remove on that Designer.
RemoveTypeHereNode(ddi);
}
else if (toolStripAdornerWindowService != null)
{
toolStripAdornerWindowService.Invalidate(ddi.DropDown.Bounds);
}
}
}
// invalidate the AdornerWindow when the DropDown resizes
private void DropDownResize(object sender, EventArgs e)
{
ToolStripDropDown dropDown = sender as ToolStripDropDown;
if (!dummyItemAdded)
{
if (dropDown != null && dropDown.Visible)
{
//Invalidate only if new Size is LESS than old Size...
if (toolStripAdornerWindowService != null && (dropDown.Width < dropDownSizeToInvalidate.Width || dropDown.Size.Height < dropDownSizeToInvalidate.Height))
{
using (Region invalidatingRegion = new Region(dropDownSizeToInvalidate))
{
invalidatingRegion.Exclude(dropDown.Bounds);
toolStripAdornerWindowService.Invalidate(invalidatingRegion);
//Invalidate BehaviorService AdornerWindow as well... but only the DropDownBounds
BehaviorService b = (BehaviorService)GetService(typeof(BehaviorService));
if (b != null)
{
b.Invalidate(invalidatingRegion);
}
}
}
}
if (toolStripAdornerWindowService != null)
{
if (rootControlGlyph != null && toolStripAdornerWindowService.DropDownAdorner.Glyphs.Contains(rootControlGlyph))
{
toolStripAdornerWindowService.DropDownAdorner.Glyphs.Remove(rootControlGlyph);
}
ControlDesigner designer = designerHost.GetDesigner(designerHost.RootComponent) as ControlDesigner;
if (designer != null)
{
rootControlGlyph = new ToolStripDropDownGlyph(dropDown.Bounds, new DropDownBehavior(designer, this));
}
toolStripAdornerWindowService.DropDownAdorner.Glyphs.Add(rootControlGlyph);
}
}
dropDownSizeToInvalidate = dropDown.Bounds;
}
///
/// Called when a menuItem wants to go into InSitu Editing Mode.
///
internal void EditTemplateNode(bool clicked)
{
// Refresh the state of the 'TypeHere' node to NotSelected state
typeHereNode.RefreshSelectionGlyph();
// Commit any InsituEdit Node.
if (KeyboardHandlingService != null && KeyboardHandlingService.TemplateNodeActive)
{
// If templateNode Active .. commit and Select it
KeyboardHandlingService.ActiveTemplateNode.CommitAndSelect();
}
// commit any existing insitu editor...
if (clicked)
{
// We should come here for a valid parent !!!
if (MenuItem == null)
{
return;
}
}
// always select the parent item...
// but dont redraw the control during this Selection Change as this causes flicker
try
{
ToolStripDesigner.editTemplateNode = true;
selSvc.SetSelectedComponents(new object[] { MenuItem }, SelectionTypes.Replace);
}
finally
{
ToolStripDesigner.editTemplateNode = false;
}
// Hide the DropDown of any previous Selection..
// First get the SelectedItem...
ToolStripDropDownItem selectedItem = null;
if (selSvc.PrimarySelection == null && KeyboardHandlingService != null)
{
ToolStripItem item = KeyboardHandlingService.SelectedDesignerControl as ToolStripItem;
if (item != null)
{
selectedItem = ((ToolStripDropDown)item.Owner).OwnerItem as ToolStripDropDownItem;
}
}
else
{
selectedItem = selSvc.PrimarySelection as ToolStripDropDownItem;
}
// Now Hide the DropDown and Refresh Glyphs...
if (selectedItem != null && selectedItem != MenuItem)
{
HideSiblingDropDowns(selectedItem);
}
MenuItem.DropDown.SuspendLayout();
dummyItemAdded = true;
int index = MenuItem.DropDownItems.IndexOf(typeHereNode);
ToolStripItem newDummyItem = null;
try
{
addingDummyItem = true;
newDummyItem = CreateDummyItem(typeof(ToolStripMenuItem), index);
}
catch (CheckoutException checkoutException)
{
if (checkoutException.Equals(CheckoutException.Canceled))
{
CommitInsertTransaction(/*commit=*/ false);
if (newMenuItemTransaction != null)
{
newMenuItemTransaction.Cancel();
newMenuItemTransaction = null;
}
}
else
{
throw;
}
}
finally
{
dummyItemAdded = (newDummyItem != null);
addingDummyItem = false;
}
MenuItem.DropDown.ResumeLayout();
if (newDummyItem != null)
{
ToolStripMenuItemDesigner newItemDesigner = designerHost.GetDesigner(newDummyItem) as ToolStripMenuItemDesigner;
if (newItemDesigner != null)
{
newItemDesigner.InitializeDropDown();
newItemDesigner.ShowEditNode(clicked);
}
}
}
///
/// Called from OnDoubleClickTimerTick to Enter in InsituMode
///
private void EnterInSituMode()
{
//we need to tell our parent that we want to enter insitu edit mode
if (MenuItem.Owner is ToolStripDropDown)
{
ToolStripItem ownerItem = ((ToolStripDropDown)(MenuItem.Owner)).OwnerItem;
//need to inform the owner tha we want to enter insitu mode
if (designerHost != null)
{
IDesigner designer = designerHost.GetDesigner(ownerItem);
if (designer is ToolStripMenuItemDesigner)
{
// Need to Add Dummy Node For Direct Insitu..
MenuItem.HideDropDown();
((ToolStripMenuItemDesigner)designer).EnterInSituEdit(MenuItem);
}
}
}
}
///
/// This method replaces the menItem with an in-situ TemplateNode.
///
internal void EnterInSituEdit(ToolStripItem toolItem)
{
MenuItem.DropDown.SuspendLayout();
//Remove the Glyphs so that Mouse Message go to the Editor
RemoveItemBodyGlyph(toolItem);
if (toolItem == null)
{
return;
}
// we can only one Active Editor at one time.
if (IsEditorActive)
{
return;
}
CreateDummyMenuItem(toolItem, toolItem.Text, toolItem.Image);
int index = MenuItem.DropDownItems.IndexOf(toolItem);
//swap in our insitu ToolStrip
MenuItem.DropDownItems.Insert(index, commitedEditorNode);
if (toolItem is ToolStripControlHost)
{
((ToolStripControlHost)toolItem).Control.Visible = false;
}
toolItem.Visible = false;
MenuItem.DropDown.ResumeLayout();
// Try Focusing the TextBox....
if (commitedTemplateNode != null)
{
commitedTemplateNode.FocusEditor(toolItem);
}
ToolStripDropDownItem dropDownItem = toolItem as ToolStripDropDownItem;
if (!(dropDownItem.Owner is ToolStripDropDownMenu) && dropDownItem != null && dropDownItem.Bounds.Width < commitedEditorNode.Bounds.Width)
{
dropDownItem.Width = commitedEditorNode.Width;
dropDownItem.DropDown.Location = new Point(dropDownItem.DropDown.Location.X + commitedEditorNode.Bounds.Width - dropDownItem.Bounds.Width, dropDownItem.DropDown.Location.Y);
}
IsEditorActive = true;
}
///
/// Get the Insertion Index to drop the current drag-drop item.
///
/// Returns the DropDown for this MenuItem else returns the Parent(Owner).
///
protected override Component GetOwnerForActionList()
{
return MenuItem;
}
// Helper Function to get the Main ToolStrip (MenuStrip);
internal override ToolStrip GetMainToolStrip()
{
ToolStripDropDown topmost = GetFirstDropDown(MenuItem);
ToolStripItem topMostItem = (topmost == null) ? null : topmost.OwnerItem;
if (topMostItem != null)
{
return topMostItem.Owner;
}
return MenuItem.Owner;
}
///
///
/// Helper function to Hide the Active Dropdown from the given DropDownItem.
///
// Standard 'catch all - rethrow critical' exception pattern
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
[SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")]
private void HideAllDropDowns(ToolStripDropDownItem item)
{
try
{
if (MenuItem.Owner is ToolStripDropDown)
{
ToolStripItem ownerItem = ((ToolStripDropDown)(MenuItem.Owner)).OwnerItem;
while (item != ownerItem)
{
if (item.DropDown.Visible)
{
item.HideDropDown();
}
if (item.Owner is ToolStripDropDown)
{
item = (ToolStripDropDownItem)((ToolStripDropDown)(item.Owner)).OwnerItem;
}
else
{
return;
}
}
}
}
catch (Exception e)
{
if (ClientUtils.IsCriticalException(e))
{
throw;
}
}
}
///
///
/// Helper function to Hide the Active Dropdown for all the siblings of the given DropDownItem.
///
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
[SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")]
private void HideSiblingDropDowns(ToolStripDropDownItem item)
{
try
{
ToolStripItem ownerItem = MenuItem;
while (item != ownerItem)
{
item.HideDropDown();
if (item.Owner is ToolStripDropDown)
{
item = (ToolStripDropDownItem)((ToolStripDropDown)(item.Owner)).OwnerItem;
}
else
{
return;
}
}
}
catch (Exception e)
{
if (ClientUtils.IsCriticalException(e))
{
throw;
}
}
}
///
/// This will listen to the necessary dropDown events... now we add the events on selection and unhook when the dropDown is closed.
///
internal void HookEvents()
{
if (MenuItem != null)
{
MenuItem.DropDown.Closing += new ToolStripDropDownClosingEventHandler(OnDropDownClosing);
MenuItem.DropDownOpening += new EventHandler(DropDownItem_DropDownOpening);
MenuItem.DropDownOpened += new EventHandler(DropDownItem_DropDownOpened);
MenuItem.DropDownClosed += new EventHandler(DropDownItem_DropDownClosed);
MenuItem.DropDown.Resize += new System.EventHandler(this.DropDownResize);
MenuItem.DropDown.ItemAdded += new ToolStripItemEventHandler(OnItemAdded);
MenuItem.DropDown.Paint += new PaintEventHandler(this.DropDownPaint);
MenuItem.DropDown.Click += new EventHandler(this.DropDownClick);
MenuItem.DropDown.LocationChanged += new EventHandler(this.DropDownLocationChanged);
}
}
///
///
/// Initializes the ToolStripDropDownItem Designer.
///
public override void Initialize(IComponent component)
{
base.Initialize(component);
// initialize the properties we will be shadowing
//
Visible = true;
DoubleClickEnabled = MenuItem.DoubleClickEnabled;
//hook our services
selSvc = (ISelectionService)GetService(typeof(ISelectionService));
if (selSvc != null)
{
selSvc.SelectionChanged += new EventHandler(this.OnSelectionChanged);
}
//hookup to the AdornerService..
toolStripAdornerWindowService = (ToolStripAdornerWindowService)GetService(typeof(ToolStripAdornerWindowService));
designerHost = (IDesignerHost)GetService(typeof(IDesignerHost));
// Hook All the Events
// HookEvents();
//Set the DoubleClickEnabled
MenuItem.DoubleClickEnabled = true;
// attach notifcations.
//
IComponentChangeService componentChangeSvc = (IComponentChangeService)GetService(typeof(IComponentChangeService));
if (componentChangeSvc != null)
{
componentChangeSvc.ComponentRemoved += new ComponentEventHandler(ComponentChangeSvc_ComponentRemoved);
componentChangeSvc.ComponentRemoving += new ComponentEventHandler(ComponentChangeSvc_ComponentRemoving);
componentChangeSvc.ComponentAdding += new ComponentEventHandler(ComponentChangeSvc_ComponentAdding);
componentChangeSvc.ComponentAdded += new ComponentEventHandler(ComponentChangeSvc_ComponentAdded);
}
if (undoEngine == null)
{
undoEngine = GetService(typeof(UndoEngine)) as UndoEngine;
if (undoEngine != null)
{
undoEngine.Undoing += new EventHandler(this.OnUndoing);
undoEngine.Undone += new EventHandler(this.OnUndone);
}
}
}
// internal since the Behavior uses this when the Items are moved on the DropDown.
internal void InitializeBodyGlyphsForItems(bool addGlyphs /* true for add */, ToolStripDropDownItem item)
{
if (addGlyphs)
{
AddBodyGlyphs(item);
}
else
{
RemoveBodyGlyphs(item);
}
}
///
/// Important function that initializes the dropDown with the typeHereNode , hooks the events and then shows the dropDown.
///
internal void InitializeDropDown()
{
ToolStrip main = GetMainToolStrip();
// Check if the TopMostItem is on normal dropdown or on the overflow.
ToolStripDropDown firstDropDown = GetFirstDropDown(MenuItem);
if (firstDropDown != null)
{
ToolStripItem topMostItem = firstDropDown.OwnerItem;
if ((topMostItem != null && topMostItem.GetCurrentParent() is ToolStripOverflow) && !main.CanOverflow)
{
return;
}
}
if (!initialized)
{
// Initialize the DropDown.
initialized = true;
// When the DropDown is Shared the ownerItem need not be the current MenuItem
// In Such a case hide the dropDown for current owner ... this will bring everything
// to a sane state..
ToolStripDropDownItem currentOwner = MenuItem.DropDown.OwnerItem as ToolStripDropDownItem;
if (currentOwner != null && currentOwner != MenuItem)
{
ToolStripMenuItemDesigner ownerdesigner = designerHost.GetDesigner(currentOwner) as ToolStripMenuItemDesigner;
if (ownerdesigner != null)
{
ownerdesigner.RemoveTypeHereNode(currentOwner);
}
currentOwner.HideDropDown();
}
// Check if this is a Sited-DropDown
if (MenuItem.DropDown.Site != null)
{
ToolStripDropDownDesigner designer = designerHost.GetDesigner(MenuItem.DropDown) as ToolStripDropDownDesigner;
if (designer != null)
{
designer.currentParent = MenuItem as ToolStripMenuItem;
}
}
CreatetypeHereNode();
MenuItem.DropDown.TopLevel = false;
//Allow Drag - Drop....
MenuItem.DropDown.AllowDrop = true;
HookEvents();
MenuItem.DropDown.AutoClose = false;
MenuItem.ShowDropDown();
ShowOwnerDropDown(MenuItem);
//Everytime you intitalize the dropDown Reset Glyphs
ResetGlyphs(MenuItem);
if (!IsOnContextMenu && !dummyItemAdded)
{
// Refer to VsW : 487943 : Required to show the SelectionBorder when the item is selected through the PropertyGrid or Doc outline.
SelectionManager selMgr = (SelectionManager)GetService(typeof(SelectionManager));
// used the cached value...
if (selMgr != null)
{
selMgr.Refresh();
}
}
}
}
private bool IsParentDropDown(ToolStripDropDown currentDropDown)
{
if (currentDropDown != null)
{
ToolStripDropDown startDropDown = MenuItem.Owner as ToolStripDropDown;
while (startDropDown != null && startDropDown != currentDropDown)
{
ToolStripDropDownItem ownerItem = startDropDown.OwnerItem as ToolStripDropDownItem;
if (ownerItem != null)
{
startDropDown = ownerItem.Owner as ToolStripDropDown;
}
else
{
startDropDown = null;
}
}
if (startDropDown == null)
{
return false;
}
return true;
}
return false;
}
///
///
/// This will morph the current item to the provided type "t" of the item...
///
///
internal override ToolStripItem MorphCurrentItem(Type t)
{
//Get the Hosting DropDown'd bounds
Rectangle hostingDropDownBounds = (MenuItem.GetCurrentParent()).Bounds;
//Get the currentItems DropDownBounds
Rectangle itemDropDownBounds = MenuItem.DropDown.Bounds;
//Remove body Glyphs...
InitializeBodyGlyphsForItems(false /*remove*/, MenuItem);
Rectangle boundstoInvalidate = Rectangle.Union(hostingDropDownBounds, itemDropDownBounds);
ToolStripAdornerWindowService toolStripservice = toolStripAdornerWindowService;
ToolStripItem newItem = base.MorphCurrentItem(t);
// We loose the ToolStripWindowService after Morphing... so use the cached one.
if (toolStripservice != null)
{
toolStripservice.Invalidate(boundstoInvalidate);
toolStripservice = null;
}
return newItem;
}
///
/// Fired after a component has been added. Here, we add it to the winbar and select it.
///
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
private void ComponentChangeSvc_ComponentAdded(object sender, ComponentEventArgs e)
{
ToolStripItem newItem = e.Component as ToolStripItem;
IComponentChangeService changeSvc = (IComponentChangeService)GetService(typeof(IComponentChangeService));
// make sure it's one of ours and on DropDown.
//
if (newItem != null && componentAddingFired && (MenuItemSelected || fireComponentChanged))
{
componentAddingFired = false;
try
{
if (IsOnContextMenu && MenuItem.DropDown.Site != null)
{
if (changeSvc != null) {
MemberDescriptor member = TypeDescriptor.GetProperties(MenuItem.DropDown)["Items"];
changeSvc.OnComponentChanging(MenuItem.DropDown, member);
}
}
else
{
base.RaiseComponentChanging(TypeDescriptor.GetProperties(MenuItem)["DropDownItems"]);
}
// Get the current count of ToolStripItems.
int count = MenuItem.DropDownItems.Count;
// In Cut / Copy and Paste the 'indexToInsertNewItem' is not Set and hence is -1...
// so check for that value...
if (indexToInsertNewItem != -1)
{
if (IsOnContextMenu && MenuItem.DropDown.Site != null)
{
MenuItem.DropDown.Items.Insert(indexToInsertNewItem, newItem);
}
else
{
MenuItem.DropDownItems.Insert(indexToInsertNewItem, newItem);
}
}
else
{
// Insert Item at the current Selection...
ToolStripItem selectedItem = selSvc.PrimarySelection as ToolStripItem;
if (selectedItem != null && selectedItem != MenuItem)
{
int index = MenuItem.DropDownItems.IndexOf(selectedItem);
if (MenuItem.DropDownDirection == ToolStripDropDownDirection.AboveLeft || MenuItem.DropDownDirection == ToolStripDropDownDirection.AboveRight)
{
// Add at the next Index in case of "Up-Directed" dropDown.
if (IsOnContextMenu && MenuItem.DropDown.Site != null)
{
MenuItem.DropDown.Items.Insert(index + 1, newItem);
}
else
{
MenuItem.DropDownItems.Insert(index + 1, newItem);
}
}
else
{
if (IsOnContextMenu && MenuItem.DropDown.Site != null)
{
MenuItem.DropDown.Items.Insert(index, newItem);
}
else
{
MenuItem.DropDownItems.Insert(index, newItem);
}
}
}
else
{
if (count > 0)
{
if (MenuItem.DropDownDirection != ToolStripDropDownDirection.AboveLeft && MenuItem.DropDownDirection != ToolStripDropDownDirection.AboveRight)
{
// ADD at Last but one, the last one being the TemplateNode always...
if (IsOnContextMenu && MenuItem.DropDown.Site != null)
{
MenuItem.DropDown.Items.Insert(count - 1, newItem);
}
else
{
MenuItem.DropDownItems.Insert(count - 1, newItem);
}
}
}
else //count == 0
{
if (IsOnContextMenu && MenuItem.DropDown.Site != null)
{
MenuItem.DropDown.Items.Add(newItem);
}
else
{
MenuItem.DropDownItems.Add(newItem);
}
}
}
}
// If the Item is added through Undo/Redo ONLY then select the item
if (undoingCalled)
{
if (selSvc != null)
{
selSvc.SetSelectedComponents(new IComponent[] { newItem } , SelectionTypes.Replace);
}
}
ResetGlyphs(MenuItem);
}
catch
{
CommitInsertTransaction(/*commit=*/false);
}
finally
{
if (IsOnContextMenu && MenuItem.DropDown.Site != null)
{
if (changeSvc != null) {
MemberDescriptor member = TypeDescriptor.GetProperties(MenuItem.DropDown)["Items"];
changeSvc.OnComponentChanged(MenuItem.DropDown, member, null, null);
}
}
else
{
base.RaiseComponentChanged(TypeDescriptor.GetProperties(MenuItem)["DropDownItems"], null, null);
}
CommitInsertTransaction(/*commit=*/true);
}
}
}
private void CommitInsertTransaction(bool commit) {
if (!IsOnContextMenu)
{
ToolStrip mainStrip = GetMainToolStrip();
ToolStripDesigner mainStripDesigner = designerHost.GetDesigner(mainStrip) as ToolStripDesigner;
if (mainStripDesigner != null && mainStripDesigner.InsertTansaction != null)
{
if (commit) {
mainStripDesigner.InsertTansaction.Commit();
}
else {
mainStripDesigner.InsertTansaction.Cancel();
}
mainStripDesigner.InsertTansaction = null;
}
}
else
{
if (insertMenuItemTransaction != null)
{
if (commit) {
insertMenuItemTransaction.Commit();
}
else {
insertMenuItemTransaction.Cancel();
}
insertMenuItemTransaction = null;
}
}
}
///
/// Checks if the component being added is a child ToolStripItem.
///
private void ComponentChangeSvc_ComponentAdding(object sender, ComponentEventArgs e)
{
//Dont do anything if CopyInProgress is true
if (KeyboardHandlingService != null && KeyboardHandlingService.CopyInProgress)
{
return;
}
if (e.Component is ToolStripItem && (MenuItemSelected || fireComponentChanged))
{
if (!IsOnContextMenu)
{
ToolStrip mainStrip = GetMainToolStrip();
ToolStripDesigner mainStripDesigner = designerHost.GetDesigner(mainStrip) as ToolStripDesigner;
if (mainStripDesigner != null && !mainStripDesigner.EditingCollection && mainStripDesigner.InsertTansaction == null)
{
componentAddingFired = true;
Debug.Assert(designerHost != null, "Why didn't we get a designer host?");
mainStripDesigner.InsertTansaction = designerHost.CreateTransaction(SR.GetString(SR.ToolStripInsertingIntoDropDownTransaction));
}
}
else //we are on ContextMenuStrip, ToolStripDropDown or ToolStripDropDownMenu....
{
ToolStripItem itemAdding = e.Component as ToolStripItem;
if (itemAdding != null && itemAdding.Owner == null)
{
componentAddingFired = true;
Debug.Assert(designerHost != null, "Why didn't we get a designer host?");
insertMenuItemTransaction = designerHost.CreateTransaction(SR.GetString(SR.ToolStripInsertingIntoDropDownTransaction));
}
}
}
}
///
/// After a ToolStripItem is removed, remove it from the ToolStrip and select the next item.
///
private void ComponentChangeSvc_ComponentRemoved(object sender, ComponentEventArgs e)
{
ToolStripItem itemToBeDeleted = e.Component as ToolStripItem;
if (itemToBeDeleted != null && itemToBeDeleted.IsOnDropDown)
{
//Get the ownerItem
ToolStripDropDownItem ownerItem = (ToolStripDropDownItem)((ToolStripDropDown)(itemToBeDeleted.Owner)).OwnerItem;
if (ownerItem != null && ownerItem == MenuItem)
{
int itemIndex = ownerItem.DropDownItems.IndexOf(itemToBeDeleted);
// send notifications.
//
try
{
if (itemIndex != -1)
{
ownerItem.DropDownItems.Remove(itemToBeDeleted);
base.RaiseComponentChanged(TypeDescriptor.GetProperties(ownerItem)["DropDownItems"], null, null);
}
}
finally
{
if (_pendingTransaction != null)
{
_pendingTransaction.Commit();
_pendingTransaction = null;
}
}
//Remove & Add the Glyphs
ResetGlyphs(ownerItem);
// select the next item or the ToolStrip itself.
//
if (ownerItem.DropDownItems.Count > 1)
{
itemIndex = Math.Min(ownerItem.DropDownItems.Count - 1, itemIndex);
itemIndex = Math.Max(0, itemIndex);
}
else
{
itemIndex = -1;
}
// Looks like we need to invalidate the entire
if (toolStripAdornerWindowService != null && boundsToInvalidateOnRemove != Rectangle.Empty)
{
using (Region regionToInvalidate = new Region(boundsToInvalidateOnRemove))
{
regionToInvalidate.Exclude(MenuItem.DropDown.Bounds);
toolStripAdornerWindowService.Invalidate(regionToInvalidate);
boundsToInvalidateOnRemove = Rectangle.Empty;
}
}
// Select the item only if Cut/Delete is pressed.
if (KeyboardHandlingService != null && KeyboardHandlingService.CutOrDeleteInProgress)
{
if (selSvc != null && !dummyItemAdded)
{
IComponent targetSelection = (itemIndex == -1) ? (IComponent)ownerItem : (IComponent)ownerItem.DropDownItems[itemIndex];
// if the TemplateNode becomes the targetSelection, then set the targetSelection to null.
if (targetSelection is DesignerToolStripControlHost)
{
KeyboardHandlingService.SelectedDesignerControl = targetSelection;
KeyboardHandlingService.OwnerItemAfterCut = MenuItem;
selSvc.SetSelectedComponents(null, SelectionTypes.Replace);
}
else
{
selSvc.SetSelectedComponents(new IComponent[] { targetSelection }, SelectionTypes.Replace);
}
}
}
}
}
}
///
/// Before a ToolStripItem is removed, open a transaction to batch the operation.
///
private void ComponentChangeSvc_ComponentRemoving(object sender, ComponentEventArgs e)
{
if (dummyItemAdded)
{
return;
}
ToolStripItem itemToBeDeleted = e.Component as ToolStripItem;
if (itemToBeDeleted != null && itemToBeDeleted.IsOnDropDown && itemToBeDeleted.Placement == ToolStripItemPlacement.Main)
{
//Get the ownerItem
ToolStripDropDownItem ownerItem = (ToolStripDropDownItem)((ToolStripDropDown)(itemToBeDeleted.Owner)).OwnerItem;
if (ownerItem != null && ownerItem == MenuItem)
{
RemoveItemBodyGlyph(itemToBeDeleted);
InitializeBodyGlyphsForItems(false, ownerItem);
boundsToInvalidateOnRemove = ownerItem.DropDown.Bounds;
//Check if the deleted item is a dropDownItem and its DropDown is Visible.
ToolStripDropDownItem dropDownItem = itemToBeDeleted as ToolStripDropDownItem;
if (dropDownItem != null)
{
boundsToInvalidateOnRemove = Rectangle.Union(boundsToInvalidateOnRemove, dropDownItem.DropDown.Bounds);
}
Debug.Assert(designerHost != null, "Why didn't we get a designer host?");
Debug.Assert(_pendingTransaction == null, "Adding item with pending transaction?");
try
{
_pendingTransaction = designerHost.CreateTransaction(SR.GetString(SR.ToolStripDesignerTransactionRemovingItem));
base.RaiseComponentChanging(TypeDescriptor.GetProperties(ownerItem)["DropDownItems"]);
}
catch
{
if (_pendingTransaction != null)
{
_pendingTransaction.Cancel();
_pendingTransaction = null;
}
}
}
}
}
///
///
/// Controls the dismissal of the drop down, here - we just cancel it
///
///
private void OnDropDownClosing(object sender, ToolStripDropDownClosingEventArgs e)
{
//always dismiss this so we don't collapse the dropdown when the user clicks @ design time
e.Cancel = (e.CloseReason == ToolStripDropDownCloseReason.ItemClicked);
}
///
/// When DropDown is disposed; nullify the dropDown.
///
private void OnDropDownDisposed(object sender, EventArgs e)
{
if (MenuItem != null)
{
if (MenuItem.DropDown != null)
{
MenuItem.DropDown.Disposed -= new EventHandler(OnDropDownDisposed);
}
// This is necessary when the MenuItem's DropDown property is SET to something other than the default DropDown.
MenuItem.DropDown = null;
}
}
///
/// When a item is added, re-arrange the elements to make sure that the templateNode is at the end..
///
private void OnItemAdded(object sender, ToolStripItemEventArgs e)
{
// Reshuffle the TemplateNode only for "Downward" dropdowns...
if (MenuItem.DropDownDirection != ToolStripDropDownDirection.AboveLeft && MenuItem.DropDownDirection != ToolStripDropDownDirection.AboveRight)
{
if (typeHereNode != null && (e.Item != typeHereNode))
{
int currentIndexOfEditor = MenuItem.DropDown.Items.IndexOf(typeHereNode);
if (currentIndexOfEditor >= 0 && currentIndexOfEditor < MenuItem.DropDown.Items.Count - 1)
{
// we now know the editor is there, but isnt currently at the end of the line.
// lets add it.
MenuItem.DropDown.ItemAdded -= new ToolStripItemEventHandler(OnItemAdded);
MenuItem.DropDown.SuspendLayout();
MenuItem.DropDown.Items.Remove(typeHereNode);
MenuItem.DropDown.Items.Add(typeHereNode);
MenuItem.DropDown.ResumeLayout();
MenuItem.DropDown.ItemAdded += new ToolStripItemEventHandler(OnItemAdded);
}
else
{
CreatetypeHereNode();
}
}
}
}
///
/// Called during Undo (this is used for DropDown Property)
///
private void OnUndone(object source, EventArgs e)
{
if (undoingCalled)
{
// If we have Undone the SETTING of DropDown Revert back to Original state.
if (dropDownSet && MenuItem.DropDown.IsAutoGenerated)
{
ToolStrip mainStrip = GetMainToolStrip();
ToolStripDesigner mainStripDesigner = designerHost.GetDesigner(mainStrip) as ToolStripDesigner;
if (mainStripDesigner != null && mainStripDesigner.CacheItems)
{
foreach (ToolStripItem item in mainStripDesigner.Items)
{
MenuItem.DropDownItems.Insert(0, item);
}
mainStripDesigner.CacheItems = false;
}
ResetGlyphs(MenuItem);
}
// since the dropDown is closed during UnDoing .. we need to re-open the dropDown in Undone.
if (MenuItem != null && selSvc.GetComponentSelected(MenuItem))
{
InitializeDropDown();
MenuItem.DropDown.PerformLayout();
}
undoingCalled = false;
dropDownSet = false;
}
// After Redo-Undo Glyphs are broken.
if (selSvc.GetComponentSelected(MenuItem) && !dropDownSetFailed)
{
InitializeDropDown();
}
}
///
/// Called during Undo (this is used for DropDown Property)
///
private void OnUndoing(object source, EventArgs e)
{
if (dummyItemAdded)
{
return;
}
if (!IsOnContextMenu && MenuItem.DropDown.Visible)
{
MenuItem.HideDropDown();
if (!MenuItem.DropDown.IsAutoGenerated)
{
dropDownSet = true;
ToolStrip mainStrip = GetMainToolStrip();
ToolStripDesigner mainStripDesigner = designerHost.GetDesigner(mainStrip) as ToolStripDesigner;
if (mainStripDesigner != null)
{
mainStripDesigner.CacheItems = true;
mainStripDesigner.Items.Clear();
}
}
undoingCalled = true;
}
}
///
///
/// Once a menuitem designer has selection - be sure to expand and collapse
/// all necessary child/parent items
/// Implements the Selection Paint Logic by adding Text to Tag property.
/// Also Hides Unnecessary DropDowns.
///
private void OnSelectionChanged(object sender, EventArgs e)
{
//determine if we are selected
if (MenuItem == null)
{
return;
}
ISelectionService selectionSvc = sender as ISelectionService;
Debug.Assert(selectionSvc != null, "No Selection Service !!");
if (selectionSvc == null)
{
return;
}
//ALWAYS COMMIT!!!
if (commitedTemplateNode != null && commitedTemplateNode.Active)
{
commitedTemplateNode.Commit(false, false);
}
else if (typeHereTemplateNode != null && typeHereTemplateNode.Active)
{
typeHereTemplateNode.Commit(false, false);
}
if (MenuItem.Equals(selectionSvc.PrimarySelection))
{
ArrayList origSel = ToolStripDesignerUtils.originalSelComps;
if (origSel != null)
{
ToolStripDesignerUtils.InvalidateSelection(origSel, MenuItem, MenuItem.Site, false /*shift pressed*/);
}
if (IsOnContextMenu && !MenuItem.Owner.Visible)
{
ToolStripDropDown firstDropDown = GetFirstDropDown(MenuItem);
ToolStripDropDownDesigner firstDropDownDesigner = designerHost.GetDesigner(firstDropDown) as ToolStripDropDownDesigner;
if (firstDropDownDesigner != null)
{
InitializeDropDown();
firstDropDownDesigner.ShowMenu();
firstDropDownDesigner.AddSelectionGlyphs();
}
}
else
{
InitializeDropDown();
}
//Cache original selection
ICollection originalSelComps = null;
if (selSvc != null)
{
originalSelComps = selectionSvc.GetSelectedComponents();
}
// Add the TemplateNode to the Selection if it is currently Selected as the GetSelectedComponents wont do it for us.
origSel = new ArrayList(originalSelComps);
if (origSel.Count == 0)
{
if (KeyboardHandlingService != null && KeyboardHandlingService.SelectedDesignerControl != null)
{
origSel.Add(KeyboardHandlingService.SelectedDesignerControl);
}
}
if (origSel.Count > 0)
{
ToolStripDesignerUtils.originalSelComps = origSel;
}
}
else
{
object selectedObj = ((ISelectionService)sender).PrimarySelection;
if (selectedObj == null)
{
if (KeyboardHandlingService != null)
{
selectedObj = KeyboardHandlingService.SelectedDesignerControl;
}
}
ToolStripItem currentSelection = selectedObj as ToolStripItem;
if (currentSelection != null)
{
ToolStripDropDown parent = currentSelection.Owner as ToolStripDropDown;
while (parent != null)
{
if (parent.OwnerItem == MenuItem || parent.OwnerItem == null)
{
return;
}
else
{
parent = ((ToolStripItem)(parent.OwnerItem)).Owner as ToolStripDropDown;
}
}
}
if (MenuItem.DropDown.Visible)
{
// CASE : Check if the DropDown Selected is the one assigned to this MenuItem's DropDown property.
// If MenuItem.DropDown matches the currentSelection or is the First Dropdown of any selection THEN return
ToolStripDropDown selectedDropDown = selectedObj as ToolStripDropDown;
if (selectedDropDown != null && MenuItem.DropDown == selectedDropDown)
{
return;
}
else
{
// Any ToolStripItem on the DropDown OR any of its Child DropDowns
ToolStripItem item = selectedObj as ToolStripItem;
if (item != null)
{
ToolStripDropDown parent = item.Owner as ToolStripDropDown;
while (parent != null)
{
if (parent == MenuItem.DropDown)
{
return;
}
else
{
parent = ((ToolStripItem)(parent.OwnerItem)).Owner as ToolStripDropDown;
}
}
}
}
// Close your own dropDown...
if (MenuItem.DropDown.OwnerItem == MenuItem)
{
MenuItem.HideDropDown();
}
}
}
}
///
///
/// Allows a designer to filter the set of properties
/// the component it is designing will expose through the
/// TypeDescriptor object. This method is called
/// immediately before its corresponding "Post" method.
/// If you are overriding this method you should call
/// the base implementation before you perform your own
/// filtering.
///
protected override void PreFilterProperties(IDictionary properties)
{
base.PreFilterProperties(properties);
// Handle shadowed properties
//
string[] shadowProps = new string[] {
"Visible",
"DoubleClickEnabled",
"CheckOnClick",
"DropDown"
};
PropertyDescriptor prop;
Attribute[] empty = new Attribute[0];
for (int i = 0; i < shadowProps.Length; i++)
{
prop = (PropertyDescriptor)properties[shadowProps[i]];
if (prop != null)
{
properties[shadowProps[i]] = TypeDescriptor.CreateProperty(typeof(ToolStripMenuItemDesigner), prop, empty);
}
}
}
//
// Resets the ToolStripMenuItem DoubleClickEnabled to be the default visible
//
private void ResetDoubleClickEnabled()
{
DoubleClickEnabled = false;
}
//
// Resets the ToolStripMenuItem CheckOnClick to be the default visible
//
private void ResetCheckOnClick()
{
CheckOnClick = false;
}
//
// Resets the ToolStripMenuItem CheckOnClick to be the default visible
//
private void ResetDropDown()
{
DropDown = null;
}
//
// Resets the ToolStripMenuItem Visible to be the default visible
//
private void ResetVisible()
{
Visible = true;
}
//
// Restores the ToolStripMenuItem Visible to be the value set in the property grid.
//
private void RestoreVisible()
{
MenuItem.Visible = Visible;
}
//
// Removes the TypeHere node when the DropDownCloses.
//
internal void RemoveTypeHereNode(ToolStripDropDownItem ownerItem)
{
//This will cause the DropDown to Relayout
// so that during the DropDownClosed event we wont have proper Bounds to Invalidate
// the ToolStripAdorner...
// So for this case do it here...
Rectangle bounds = ownerItem.DropDown.Bounds;
if (ownerItem.DropDownItems.Count > 0 && ownerItem.DropDownItems[0] is DesignerToolStripControlHost)
{
ownerItem.DropDownItems.RemoveAt(0);
}
if (typeHereTemplateNode != null && typeHereTemplateNode.Active)
{
typeHereTemplateNode.RollBack();
typeHereTemplateNode.CloseEditor();
typeHereTemplateNode = null;
}
if (typeHereNode != null)
{
typeHereNode.Dispose();
typeHereNode = null;
}
if (toolStripAdornerWindowService != null)
{
toolStripAdornerWindowService.Invalidate(bounds);
}
}
///
///
/// This private function is called to ROLLBACK the current
/// Insitu editing mode.
///
///
private void RollBack()
{
if (commitedEditorNode != null)
{
int index = MenuItem.DropDownItems.IndexOf(commitedEditorNode);
Debug.Assert(index != -1, "Invalid Index");
ToolStripDropDownItem editedItem = (ToolStripDropDownItem)MenuItem.DropDownItems[index + 1];
if (editedItem != null)
{
editedItem.Visible = true;
}
MenuItem.DropDown.Items.Remove(commitedEditorNode);
if (commitedTemplateNode != null)
{
commitedTemplateNode.RollBack();
commitedTemplateNode.CloseEditor();
commitedTemplateNode = null;
}
if (commitedEditorNode != null)
{
commitedEditorNode.Dispose();
commitedEditorNode = null;
}
}
}
///
/// Remove Body glyphs when the dropDown is closed.
///
private void RemoveBodyGlyphs(ToolStripDropDownItem item)
{
if (item != null)
{
foreach (ToolStripItem ddItem in item.DropDownItems)
{
ToolStripItemDesigner dropDownItemDesigner = (ToolStripItemDesigner)designerHost.GetDesigner(ddItem);
if (dropDownItemDesigner != null)
{
ControlBodyGlyph glyph = dropDownItemDesigner.bodyGlyph;
if (glyph != null && toolStripAdornerWindowService != null && toolStripAdornerWindowService.DropDownAdorner.Glyphs.Contains(glyph))
{
toolStripAdornerWindowService.DropDownAdorner.Glyphs.Remove(glyph);
dropDownItemDesigner.bodyGlyph = null;
}
}
}
}
}
///
/// Remove glyphs per item
///
internal void RemoveItemBodyGlyph(ToolStripItem item)
{
if (item != null)
{
ToolStripItemDesigner itemDesigner = (ToolStripItemDesigner)designerHost.GetDesigner(item);
if (itemDesigner != null)
{
ControlBodyGlyph glyph = itemDesigner.bodyGlyph;
if (glyph != null && toolStripAdornerWindowService != null && toolStripAdornerWindowService.DropDownAdorner.Glyphs.Contains(glyph))
{
toolStripAdornerWindowService.DropDownAdorner.Glyphs.Remove(glyph);
itemDesigner.bodyGlyph = null;
}
}
}
}
///
/// Helper function to remove and then re-add the glyphs.
///
internal void ResetGlyphs(ToolStripDropDownItem item)
{
//Reset the glyphs only if the DropDown is visible.
if (item.DropDown.Visible)
{
InitializeBodyGlyphsForItems(false, item);
InitializeBodyGlyphsForItems(true, item);
}
}
///
/// Set the Selection after a insitu edit is complete.
///
internal override bool SetSelection(bool enterKeyPressed)
{
if (enterKeyPressed)
{
if (!initialized)
{
InitializeDropDown();
}
//set the selection to our new item
if (selSvc != null)
{
if (KeyboardHandlingService != null)
{
int count = 0;
if (MenuItem.DropDownDirection != ToolStripDropDownDirection.AboveLeft && MenuItem.DropDownDirection != ToolStripDropDownDirection.AboveRight)
{
// index to the last item.
count = MenuItem.DropDownItems.Count;
count--;
}
selSvc.SetSelectedComponents(new object[] { MenuItem }, SelectionTypes.Replace);
if (count >= 0)
{
KeyboardHandlingService.SelectedDesignerControl = MenuItem.DropDownItems[count];
selSvc.SetSelectedComponents(null, SelectionTypes.Replace);
}
}
}
return true;
}
return false;
}
///
/// Returns true if the visible property should be persisted in code gen.
///
private bool ShouldSerializeDoubleClickEnabled()
{
return (bool)ShadowProperties["DoubleClickEnabled"];
}
///
/// Returns true if the CheckOnClick property should be persisted in code gen.
///
private bool ShouldSerializeCheckOnClick()
{
return (bool)ShadowProperties["CheckOnClick"];
}
///
/// Returns true if the CheckOnClick property should be persisted in code gen.
///
private bool ShouldSerializeDropDown()
{
return (customDropDown != null);
}
///
/// Returns true if the visible property should be persisted in code gen.
///
private bool ShouldSerializeVisible()
{
return !Visible;
}
///
///
/// This Function is called thru the ToolStripEditorManager which is listening for the
/// F2 command.
///
///
internal override void ShowEditNode(bool clicked)
{
if (MenuItem == null)
{
return;
}
try
{
if (MenuItem.Owner is ToolStripDropDown)
{
this.parentItem = ((ToolStripDropDown)(MenuItem.Owner)).OwnerItem;
//need to inform the owner tha we want to enter insitu mode
if (designerHost != null)
{
IDesigner designer = designerHost.GetDesigner(parentItem);
if (designer is ToolStripMenuItemDesigner)
{
((ToolStripMenuItemDesigner)designer).EnterInSituEdit(MenuItem);
}
}
}
// We come here for TOP LEVEL MENUITEM .. So call base version...
else
{
base.ShowEditNode(clicked);
}
}
catch (CheckoutException checkoutException)
{
// Do not crash on canceled checkout
if (checkoutException.Equals(CheckoutException.Canceled))
{
return;
}
else
{
throw;
}
}
}
///
///
/// This Function would select all items starting form oldSelection to the Current MenuItem.
///
///
private void SelectItems(ToolStripDropDownItem oldSelection, ISelectionService selSvc)
{
ToolStripDropDown ownerDropDown = (ToolStripDropDown)MenuItem.Owner;
int maxIndex = Math.Max(ownerDropDown.Items.IndexOf(oldSelection), ownerDropDown.Items.IndexOf(MenuItem));
int minIndex = Math.Min(ownerDropDown.Items.IndexOf(oldSelection), ownerDropDown.Items.IndexOf(MenuItem));
ToolStripItem[] selectedItems = new ToolStripItem[maxIndex - minIndex + 1];
int i = 0;
while (minIndex <= maxIndex)
{
selectedItems[i] = ownerDropDown.Items[minIndex];
//((ToolStripDropDownItem)selectedItems[i]).HideDropDown();
i++;
minIndex++;
}
selSvc.SetSelectedComponents(selectedItems);
}
///
///
/// Shows ALL the owner DropDowns if passed in MenuItem is Selected
///
///
internal void ShowOwnerDropDown(ToolStripDropDownItem currentSelection)
{
// We MIGHT HAVE TO START TOP - DOWN Instead of BOTTOM-UP.
// Sometimes we DONT get the Owner POPUP and hence all the popup are parented to
// Wrong guy.
while (currentSelection != null && currentSelection.Owner is ToolStripDropDown)
{
currentSelection = (ToolStripDropDownItem)((ToolStripDropDown)(currentSelection.Owner)).OwnerItem;
if (currentSelection != null && !currentSelection.DropDown.Visible)
{
ToolStripMenuItemDesigner currentSelectionDesigner = designerHost.GetDesigner(currentSelection) as ToolStripMenuItemDesigner;
if (currentSelectionDesigner != null)
{
currentSelectionDesigner.InitializeDropDown();
}
}
}
}
///
/// This will listen to the necessary dropDown events... now we add the events on selection and unhook when the dropDown is closed.
///
internal void UnHookEvents()
{
if (MenuItem != null)
{
MenuItem.DropDown.Closing -= new ToolStripDropDownClosingEventHandler(OnDropDownClosing);
MenuItem.DropDownOpening -= new EventHandler(DropDownItem_DropDownOpening);
MenuItem.DropDownOpened -= new EventHandler(DropDownItem_DropDownOpened);
MenuItem.DropDownClosed -= new EventHandler(DropDownItem_DropDownClosed);
MenuItem.DropDown.Resize -= new System.EventHandler(this.DropDownResize);
MenuItem.DropDown.ItemAdded -= new ToolStripItemEventHandler(OnItemAdded);
MenuItem.DropDown.Paint -= new PaintEventHandler(this.DropDownPaint);
MenuItem.DropDown.LocationChanged -= new EventHandler(this.DropDownLocationChanged);
MenuItem.DropDown.Click -= new EventHandler(this.DropDownClick);
}
}
///
/// The glyph we put over the items. Basically this sets the hit-testable area of the item itself.
///
internal class ToolStripDropDownGlyph : Glyph
{
private Rectangle _bounds;
internal ToolStripDropDownGlyph(Rectangle bounds, System.Windows.Forms.Design.Behavior.Behavior b)
: base(b)
{
_bounds = bounds;
}
///
///
/// Abstract method that forces Glyph implementations to provide
/// hit test logic. Given any point - if the Glyph has decided to
/// be involved with that location, the Glyph will need to return
/// a valid Cursor. Otherwise, returning null will cause the
/// the BehaviorService to simply ignore it.
///
public override Cursor GetHitTest(Point p)
{
if (_bounds.Contains(p))
{
return Cursors.Default;
}
return null;
}
///
///
/// Overrides Glyph::Paint - this implementation does nothing.
///
public override void Paint(PaintEventArgs pe)
{
}
}
///
/// The transparent behavior on top of the DropDownGlyphs.
///
internal class DropDownBehavior : ControlDesigner.TransparentBehavior
{
///
///
/// Constructor that accepts the related ControlDesigner.
///
private ToolStripMenuItemDesigner menuItemDesigner;
internal DropDownBehavior(ControlDesigner designer, ToolStripMenuItemDesigner menuItemDesigner)
: base(designer)
{
this.menuItemDesigner = menuItemDesigner;
}
///
/// Drag drop support on the DropDown...
///
public override void OnDragEnter(Glyph g, DragEventArgs e)
{
ToolStripItemDataObject data = e.Data as ToolStripItemDataObject;
if (data != null)
{
e.Effect = (Control.ModifierKeys == Keys.Control) ? DragDropEffects.Copy : DragDropEffects.Move;
}
else
{
base.OnDragEnter(g, e);
}
}
///
/// Drag drop support on the DropDown...
///
public override void OnDragOver(Glyph g, DragEventArgs e)
{
ToolStripItemDataObject data = e.Data as ToolStripItemDataObject;
if (data != null)
{
e.Effect = (Control.ModifierKeys == Keys.Control) ? DragDropEffects.Copy : DragDropEffects.Move;
}
else
{
base.OnDragOver(g, e);
}
}
///
/// Drag drop support on the DropDown...
///
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
public override void OnDragDrop(Glyph g, DragEventArgs e)
{
ToolStripItemDataObject data = e.Data as ToolStripItemDataObject;
if (data != null)
{
ToolStripItem primaryItem = data.PrimarySelection;
IDesignerHost host = (IDesignerHost)primaryItem.Site.GetService(typeof(IDesignerHost));
ToolStripDropDown parentToolStrip = primaryItem.GetCurrentParent() as ToolStripDropDown;
ToolStripDropDownItem ownerItem = null;
if (parentToolStrip != null)
{
ownerItem = parentToolStrip.OwnerItem as ToolStripDropDownItem;
}
Debug.Assert(ownerItem != null, "How can ownerItem be null for a menu item on a dropdown?");
if (ownerItem != null && host != null)
{
string transDesc;
ArrayList components = data.DragComponents;
int primaryIndex = -1;
bool copy = (e.Effect == DragDropEffects.Copy);
if (components.Count == 1)
{
string name = TypeDescriptor.GetComponentName(components[0]);
if (name == null || name.Length == 0)
{
name = components[0].GetType().Name;
}
transDesc = SR.GetString(copy ? SR.BehaviorServiceCopyControl : SR.BehaviorServiceMoveControl, name);
}
else
{
transDesc = SR.GetString(copy ? SR.BehaviorServiceCopyControls : SR.BehaviorServiceMoveControls, components.Count);
}
// create a transaction so this happens as an atomic unit.
DesignerTransaction changeParent = host.CreateTransaction(transDesc);
try
{
IComponentChangeService changeSvc = (IComponentChangeService)primaryItem.Site.GetService(typeof(IComponentChangeService));
if (changeSvc != null)
changeSvc.OnComponentChanging(ownerItem, TypeDescriptor.GetProperties(ownerItem)["DropDownItems"]);
// If we are copying, then we want to make a copy of the components we are dragging
if (copy)
{
// Remember the primary selection if we had one
if (primaryItem != null)
{
primaryIndex = components.IndexOf(primaryItem);
}
ToolStripKeyboardHandlingService keyboardHandlingService = (ToolStripKeyboardHandlingService)primaryItem.Site.GetService(typeof(ToolStripKeyboardHandlingService));
if (keyboardHandlingService != null)
{
keyboardHandlingService.CopyInProgress = true;
}
components = DesignerUtils.CopyDragObjects(components, primaryItem.Site) as ArrayList;
if (keyboardHandlingService != null)
{
keyboardHandlingService.CopyInProgress = false;
}
if (primaryIndex != -1)
{
primaryItem = components[primaryIndex] as ToolStripItem;
}
}
if (e.Effect == DragDropEffects.Move || copy)
{
// Add the item.
foreach (ToolStripItem toolItem in components)
{
parentToolStrip.Items.Add(toolItem);
}
// Open the DropDown for the PrimarySelection before the DRAG-DROP operation.
ToolStripDropDownItem dropDownItem = primaryItem as ToolStripDropDownItem;
if (dropDownItem != null)
{
ToolStripMenuItemDesigner dropDownItemDesigner = host.GetDesigner(dropDownItem) as ToolStripMenuItemDesigner;
if (dropDownItemDesigner != null)
{
dropDownItemDesigner.InitializeDropDown();
}
}
//Set the Selection ..
menuItemDesigner.selSvc.SetSelectedComponents(new IComponent[] { primaryItem }, SelectionTypes.Primary | SelectionTypes.Replace);
}
if (changeSvc != null)
{
changeSvc.OnComponentChanged(ownerItem, TypeDescriptor.GetProperties(ownerItem)["DropDownItems"], null, null);
}
//fire extra changing/changed events so that the order is "restored" after undo/redo
if (copy)
{
if (changeSvc != null)
{
changeSvc.OnComponentChanging(ownerItem, TypeDescriptor.GetProperties(ownerItem)["DropDownItems"]);
changeSvc.OnComponentChanged(ownerItem, TypeDescriptor.GetProperties(ownerItem)["DropDownItems"], null, null);
}
}
//If Parent is DropDown... we have to manage the Glyphs ....
if (ownerItem != null)
{
ToolStripMenuItemDesigner ownerDesigner = host.GetDesigner(ownerItem) as ToolStripMenuItemDesigner;
if (ownerDesigner != null)
{
ownerDesigner.InitializeBodyGlyphsForItems(false, ownerItem);
ownerDesigner.InitializeBodyGlyphsForItems(true, ownerItem);
}
}
// Refresh the BehaviorService.
BehaviorService bSvc = (BehaviorService)primaryItem.Site.GetService(typeof(BehaviorService));
if (bSvc != null)
{
bSvc.SyncSelection();
}
}
catch
{
if (changeParent != null)
{
changeParent.Cancel();
changeParent = null;
}
}
finally
{
if (changeParent != null)
changeParent.Commit();
changeParent = null;
}
}
}
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- OperationAbortedException.cs
- PersonalizablePropertyEntry.cs
- _NegoStream.cs
- XmlElementAttribute.cs
- ResXResourceReader.cs
- EnvironmentPermission.cs
- RadioButtonRenderer.cs
- XmlNodeList.cs
- ProfileSettings.cs
- ListCommandEventArgs.cs
- ConvertBinder.cs
- Stylus.cs
- MenuItemBindingCollection.cs
- ConfigXmlWhitespace.cs
- IntPtr.cs
- clipboard.cs
- XamlSerializer.cs
- EntityDataSourceColumn.cs
- Subordinate.cs
- TextDecoration.cs
- TextTreeObjectNode.cs
- PackageFilter.cs
- EventTrigger.cs
- WsatAdminException.cs
- DataGridViewBindingCompleteEventArgs.cs
- XamlRtfConverter.cs
- DataGridItemAttachedStorage.cs
- CachedRequestParams.cs
- _ListenerResponseStream.cs
- XmlSchemaAny.cs
- wmiprovider.cs
- WebPartEditorOkVerb.cs
- StreamWriter.cs
- ImageCodecInfoPrivate.cs
- MissingFieldException.cs
- DefaultValueConverter.cs
- RealProxy.cs
- XPathNodePointer.cs
- _DigestClient.cs
- Bits.cs
- OleDbTransaction.cs
- ToolStripOverflow.cs
- WebPartConnectionsDisconnectVerb.cs
- MultiPartWriter.cs
- FontFamilyValueSerializer.cs
- Manipulation.cs
- ServiceModelSecurityTokenTypes.cs
- XmlDictionaryWriter.cs
- SqlParameter.cs
- ViewValidator.cs
- TickBar.cs
- TransformerConfigurationWizardBase.cs
- EventRouteFactory.cs
- XmlWrappingReader.cs
- TemplateKeyConverter.cs
- MembershipSection.cs
- TypeResolver.cs
- ExcCanonicalXml.cs
- XPathBuilder.cs
- WorkflowEnvironment.cs
- UIElement.cs
- HierarchicalDataBoundControlAdapter.cs
- ListViewItemEventArgs.cs
- TriggerBase.cs
- documentsequencetextcontainer.cs
- GridToolTip.cs
- IgnoreSectionHandler.cs
- FileStream.cs
- CreateUserWizardAutoFormat.cs
- Assert.cs
- ConditionChanges.cs
- xmlglyphRunInfo.cs
- MoveSizeWinEventHandler.cs
- QueryContinueDragEventArgs.cs
- HtmlInputButton.cs
- DocumentCollection.cs
- EntityDataReader.cs
- SQLInt16.cs
- TypeToken.cs
- ConsoleTraceListener.cs
- ExtendedPropertyCollection.cs
- IndexedGlyphRun.cs
- SessionEndingCancelEventArgs.cs
- CollectionEditorDialog.cs
- SoapInteropTypes.cs
- cookie.cs
- AppDomainProtocolHandler.cs
- InvalidDataException.cs
- FaultDescriptionCollection.cs
- assertwrapper.cs
- EntityDataSourceEntitySetNameItem.cs
- CatalogZone.cs
- ChangeConflicts.cs
- Transform3D.cs
- PriorityBindingExpression.cs
- TextTreeUndo.cs
- RoleManagerModule.cs
- CacheEntry.cs
- DataGridViewToolTip.cs
- ThicknessAnimation.cs