www.pudn.com > CustomFormsDesigner.rar > MenuCommandServiceImpl.cs, change:2004-10-26,size:9595b


using System; 
using System.CodeDom; 
using System.Collections; 
using System.ComponentModel; 
using System.ComponentModel.Design; 
using System.ComponentModel.Design.Serialization; 
using System.Drawing; 
using System.Drawing.Design; 
using System.Windows.Forms; 
using System.Windows.Forms.Design; 
 
namespace FormDesigner.impls 
{ 
	/// IMenuCommandService implementation. 
	public class MenuCommandServiceImpl : System.ComponentModel.Design.IMenuCommandService 
	{ 
		// the host 
		private IDesignerHost host; 
		// commandId-command mapping 
		private IDictionary commands; 
		// menuItem-verb mapping 
		private IDictionary menuItemVerb; 
		// the global verbs collection.  
		private DesignerVerbCollection globalVerbs;  
		// we use the same context menu over-and-over 
		private ContextMenu contextMenu; 
		// we keep the lastSelectedComponent around  
		private IComponent lastSelectedComponent; 
 
		public MenuCommandServiceImpl(IDesignerHost host) 
		{ 
			this.host = host; 
			commands = new Hashtable(); 
			globalVerbs = new DesignerVerbCollection(); 
			menuItemVerb = new Hashtable(); 
			contextMenu = new ContextMenu(); 
			lastSelectedComponent = null; 
		} 
		#region Implementation of IMenuCommandService 
 
		/// called to add a MenuCommand 
		public void AddCommand(System.ComponentModel.Design.MenuCommand command) 
		{ 
			if (command == null) 
			{ 
				throw new ArgumentException("command"); 
			} 
			// don't add commands twice 
			if (FindCommand(command.CommandID) == null) 
			{ 
				commands.Add(command.CommandID, command); 
			} 
		} 
 
		/// called to remove a MenuCommand 
		public void RemoveCommand(System.ComponentModel.Design.MenuCommand command) 
		{ 
			if(command==null) 
			{ 
				throw new ArgumentException("command"); 
			} 
			commands.Remove(command.CommandID); 
		} 
 
		/// called when to add a global verb 
		public void AddVerb(System.ComponentModel.Design.DesignerVerb verb) 
		{ 
			if(verb==null) 
			{ 
				throw new ArgumentException("verb"); 
			} 
			globalVerbs.Add(verb); 
			// create a menu item for the verb and add it to the context menu 
			MenuItem menuItem = new MenuItem(verb.Text); 
			menuItem.Click += new EventHandler(MenuItemClickHandler); 
			menuItemVerb.Add(menuItem,verb); 
			contextMenu.MenuItems.Add(menuItem); 
		} 
		/// called to remove global verb 
		public void RemoveVerb(System.ComponentModel.Design.DesignerVerb verb) 
		{ 
			if(verb==null) 
			{ 
				throw new ArgumentException("verb"); 
			} 
			 
			globalVerbs.Remove(verb); 
 
			// find the menu item associated with the verb 
			MenuItem associatedMenuItem = null; 
			foreach(DictionaryEntry de in menuItemVerb) 
			{ 
				if(de.Value==verb) 
				{ 
					associatedMenuItem=de.Key as MenuItem; 
					break; 
				} 
			} 
			// if we found the verb's menu item, remove it 
			if(associatedMenuItem!=null) 
			{ 
				menuItemVerb.Remove(associatedMenuItem); 
			} 
			// remove the verb from the context menu too 
			contextMenu.MenuItems.Remove(associatedMenuItem); 
		} 
		/// returns the MenuCommand associated with the commandId. 
		public System.ComponentModel.Design.MenuCommand FindCommand(System.ComponentModel.Design.CommandID commandID) 
		{ 
			return commands[commandID] as MenuCommand; 
		} 
 
		/// called to invoke a command 
		public bool GlobalInvoke(System.ComponentModel.Design.CommandID commandID) 
		{ 
			bool result = false; 
			MenuCommand command = FindCommand(commandID); 
			if (command != null) 
			{ 
				command.Invoke(); 
				result = true; 
			} 
			return result; 
		} 
 
		/// called to show the context menu for the selected component. 
		public void ShowContextMenu(System.ComponentModel.Design.CommandID menuID, int x, int y) 
		{ 
			ISelectionService selectionService = host.GetService(typeof(ISelectionService)) as ISelectionService; 
			// get the primary component 
			IComponent primarySelection = selectionService.PrimarySelection as IComponent; 
			// if the he clicked on the same component again then just show the context 
			// menu. otherwise, we have to throw away the previous 
			// set of local menu items and create new ones for the newly 
			// selected component 
			if (lastSelectedComponent != primarySelection) 
			{ 
				// remove all non-global menu items from the context menu 
				ResetContextMenu(); 
				// get the designer 
				IDesigner designer = host.GetDesigner(primarySelection); 
				// not all controls need a desinger 
				if(designer!=null) 
				{ 
					// get designer's verbs 
					DesignerVerbCollection verbs = designer.Verbs; 
					foreach (DesignerVerb verb in verbs) 
					{ 
						// add new menu items to the context menu 
						CreateAndAddLocalVerb(verb); 
					} 
				} 
			} 
			// we only show designer context menus for controls 
			if(primarySelection is Control) 
			{ 
				Control comp = primarySelection as Control; 
				Point pt = comp.PointToScreen(new Point(0, 0)); 
				contextMenu.Show(comp, new Point(x - pt.X, y - pt.Y)); 
			} 
			// keep the selected component for next time 
			lastSelectedComponent = primarySelection; 
		} 
 
		/// returns the the current designer verbs 
		public System.ComponentModel.Design.DesignerVerbCollection Verbs 
		{ 
			get 
			{ 
				// create a new collection 
				DesignerVerbCollection availableVerbs = new DesignerVerbCollection(); 
				// add the global verbs 
				if(globalVerbs!=null && globalVerbs.Count>0) 
				{ 
					availableVerbs.AddRange(globalVerbs); 
				} 
				// now add the local verbs 
				ISelectionService selectionService = host.GetService(typeof(ISelectionService)) as ISelectionService; 
				IComponent primaryComponent = selectionService.PrimarySelection as IComponent; 
				if(primaryComponent!=null) 
				{ 
					IDesigner designer = host.GetDesigner(primaryComponent); 
					if(designer!=null && designer.Verbs!=null && designer.Verbs.Count>0) 
					{ 
						availableVerbs.AddRange(designer.Verbs); 
					} 
				} 
				return availableVerbs; 
			} 
		} 
 
		#endregion 
 
		/// called to invoke menu item verbs 
		private void MenuItemClickHandler(object sender, EventArgs e) 
		{ 
			// get the menu item 
			MenuItem menuItem = sender as MenuItem; 
			if(menuItem!=null) 
			{ 
				// get and invoke the verb 
				DesignerVerb verb = menuItemVerb[menuItem] as DesignerVerb; 
				if(verb!=null) 
				{ 
					try 
					{ 
						verb.Invoke(); 
					} 
					catch{} 
				} 
			} 
		} 
		/// removes all local verbs from the context menu  
		private void ResetContextMenu() 
		{ 
			if(contextMenu!=null && contextMenu.MenuItems!=null && contextMenu.MenuItems.Count>0) 
			{ 
				MenuItem[] menuItemArray = new MenuItem[contextMenu.MenuItems.Count]; 
				contextMenu.MenuItems.CopyTo(menuItemArray,0); 
				foreach(MenuItem menuItem in menuItemArray) 
				{ 
					// if its not in the global list, remove it 
					if(!IsInGlobalList(menuItem.Text)) 
					{ 
						contextMenu.MenuItems.Remove(menuItem); 
					} 
					// get rid of the menu item from the mapping 
					menuItemVerb.Remove(menuItem); 
				} 
			} 
		} 
		/// removes a local verb 
		private void RemoveLocalVerb(DesignerVerb verb) 
		{ 
			if(verb==null) 
			{ 
				throw new ArgumentException("verb"); 
			} 
			// get the associated menuItem  
			MenuItem menuItem = GetMenuItemForVerb(verb); 
			if(menuItem!=null) 
			{ 
				// undo mapping 
				menuItemVerb.Remove(menuItem); 
				// remove from context menu 
				contextMenu.MenuItems.Remove(menuItem); 
			}			 
		} 
		/// creats and adds a local verb 
		private void CreateAndAddLocalVerb(DesignerVerb verb) 
		{ 
			if(verb==null) 
			{ 
				throw new ArgumentException("verb"); 
			} 
			VerifyVerb(verb); 
			// create a menu item for the verb 
			MenuItem menuItem = new MenuItem(verb.Text); 
			// attach the menu item click listener 
			menuItem.Click += new EventHandler(MenuItemClickHandler); 
			// do the menuItem-verb mapping 
			menuItemVerb.Add(menuItem,verb); 
			// add to context menu  
			contextMenu.MenuItems.Add(menuItem); 
		} 
		/// returns the MenuItem associated with the verb 
		private MenuItem GetMenuItemForVerb(DesignerVerb verb) 
		{ 
			MenuItem menuItem = null; 
			if(menuItemVerb!=null && menuItemVerb.Count>0) 
			{ 
				foreach(DictionaryEntry de in menuItemVerb) 
				{ 
					DesignerVerb dv = de.Value as DesignerVerb; 
					if(dv==verb) 
					{ 
						menuItem = de.Key as MenuItem; 
						break; 
					} 
				} 
			} 
			return menuItem; 
		} 
		/// returns true if the verb is in the global verb collection 
		private bool IsInGlobalList(string verbText) 
		{ 
			bool found = false; 
			if(globalVerbs!=null && globalVerbs.Count>0) 
			{ 
				foreach(DesignerVerb dv in globalVerbs) 
				{ 
					if(string.Compare(dv.Text,verbText,true)==0) 
					{ 
						found=true; 
						break; 
					} 
				} 
			} 
			return found; 
		} 
		/// we can't add the same verb twice 
		private void VerifyVerb(DesignerVerb verb) 
		{ 
			if(verb==null) 
			{ 
				throw new ArgumentException("verb"); 
			} 
			// make sure the verb is not in the global list 
			if(globalVerbs!=null && globalVerbs.Count>0) 
			{ 
				foreach(DesignerVerb dv in globalVerbs) 
				{ 
					if(string.Compare(dv.Text,verb.Text,true)==0) 
					{ 
						throw new Exception("Cannot add the same verb twice."); 
					} 
				} 
			} 
			// now check the menuItemVerb mapping  
			if(menuItemVerb!=null && menuItemVerb.Count>0) 
			{ 
				foreach(DesignerVerb dv in menuItemVerb.Values) 
				{ 
					if(string.Compare(dv.Text,verb.Text,true)==0) 
					{ 
						throw new Exception("Cannot add the same verb twice."); 
					} 
				} 
			} 
		} 
	} 
}