1 //
2 // System.ComponentModel.Design.MenuCommandService.cs
3 //
4 // Author:
5 //      Atsushi Enomoto  <atsushi@ximian.com>
6 //	Ivan N. Zlatev   <contact@i-nz.net>
7 //
8 // Copyright (C) 2007 Novell, Inc
9 // Copyright (C) Ivan N. Zlatev
10 //
11 
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32 
33 
34 using System;
35 using System.Collections;
36 using System.Collections.Generic;
37 using System.ComponentModel.Design;
38 using System.ComponentModel;
39 
40 namespace System.ComponentModel.Design
41 {
42 	public class MenuCommandService : IMenuCommandService, IDisposable
43 	{
44 		private IServiceProvider _serviceProvider;
45 		private DesignerVerbCollection _globalVerbs;
46 		private DesignerVerbCollection _verbs;
47 		private Dictionary <CommandID, MenuCommand> _commands;
48 
MenuCommandService(IServiceProvider serviceProvider)49 		public MenuCommandService (IServiceProvider serviceProvider)
50 		{
51 			if (serviceProvider == null)
52 				throw new ArgumentNullException ("serviceProvider");
53 			_serviceProvider = serviceProvider;
54 			ISelectionService selectionSvc = _serviceProvider.GetService (typeof (ISelectionService)) as ISelectionService;
55 			if (selectionSvc != null)
56 				selectionSvc.SelectionChanged += OnSelectionChanged;
57 		}
58 
OnSelectionChanged(object sender, EventArgs arg)59 		private void OnSelectionChanged (object sender, EventArgs arg)
60 		{
61 			this.OnCommandsChanged (new MenuCommandsChangedEventArgs (MenuCommandsChangedType.CommandChanged, null));
62 			// The commands will be updated whenever they are requested/modified.
63 		}
64 
65 		public event MenuCommandsChangedEventHandler MenuCommandsChanged;
66 
67 		public virtual DesignerVerbCollection Verbs {
68 			get {
69 				this.EnsureVerbs ();
70 				return _verbs;
71 			}
72 		}
73 
AddCommand(MenuCommand command)74 		public virtual void AddCommand (MenuCommand command)
75 		{
76 			if (command == null)
77 				throw new ArgumentNullException ("command");
78 
79 			if (_commands == null)
80 				_commands = new Dictionary <CommandID, MenuCommand> ();
81 			_commands.Add (command.CommandID, command);
82 			this.OnCommandsChanged (new MenuCommandsChangedEventArgs (MenuCommandsChangedType.CommandAdded, command));
83 		}
84 
AddVerb(DesignerVerb verb)85 		public virtual void AddVerb (DesignerVerb verb)
86 		{
87 			if (verb == null)
88 				throw new ArgumentNullException ("verb");
89 			this.EnsureVerbs ();
90 			if (!_verbs.Contains (verb)) {
91 				if (_globalVerbs == null)
92 					_globalVerbs = new DesignerVerbCollection ();
93 				_globalVerbs.Add (verb);
94 			}
95 			this.OnCommandsChanged (new MenuCommandsChangedEventArgs (MenuCommandsChangedType.CommandAdded, verb));
96 		}
97 
Dispose()98 		public void Dispose ()
99 		{
100 			Dispose (true);
101 		}
102 
Dispose(bool disposing)103 		protected virtual void Dispose (bool disposing)
104 		{
105 			if (disposing) {
106 				if (_globalVerbs != null) {
107 					_globalVerbs.Clear ();
108 					_globalVerbs = null;
109 				}
110 				if (_verbs != null) {
111 					_verbs.Clear ();
112 					_verbs = null;
113 				}
114 				if (_commands != null) {
115 					_commands.Clear ();
116 					_commands = null;
117 				}
118 				if (_serviceProvider != null) {
119 					ISelectionService selectionSvc = _serviceProvider.GetService (typeof (ISelectionService)) as ISelectionService;
120 					if (selectionSvc != null)
121 						selectionSvc.SelectionChanged -= OnSelectionChanged;
122 					_serviceProvider = null;
123 				}
124 			}
125 		}
126 
EnsureVerbs()127 		protected void EnsureVerbs ()
128 		{
129 			DesignerVerbCollection selectionVerbs = null;
130 
131 			ISelectionService selectionSvc = this.GetService (typeof (ISelectionService)) as ISelectionService;
132 			IDesignerHost host = this.GetService (typeof (IDesignerHost)) as IDesignerHost;
133 			if (selectionSvc != null && host != null && selectionSvc.SelectionCount == 1) {
134 				IComponent primarySelection = selectionSvc.PrimarySelection as IComponent;
135 				if (primarySelection != null) {
136 					IDesigner designer = host.GetDesigner (primarySelection);
137 					if (designer != null)
138 						selectionVerbs = designer.Verbs;
139 				}
140 			}
141 
142 			// Designer provided verbs have the higher precedence than the global
143 			//
144 			Dictionary <string, DesignerVerb> allVerbs = new Dictionary <string, DesignerVerb> ();
145 			if (_globalVerbs != null) {
146 				foreach (DesignerVerb verb in _globalVerbs)
147 					allVerbs[verb.Text] = verb;
148 			}
149 			if (selectionVerbs != null) {
150 				foreach (DesignerVerb verb in selectionVerbs)
151 					allVerbs[verb.Text] = verb;
152 			}
153 
154 			if (_verbs == null)
155 				_verbs = new DesignerVerbCollection ();
156 			else
157 				_verbs.Clear ();
158 
159 			foreach (DesignerVerb verb in allVerbs.Values)
160 				_verbs.Add (verb);
161 		}
162 
FindCommand(Guid guid, int id)163 		protected MenuCommand FindCommand (Guid guid, int id)
164 		{
165 			return this.FindCommand (new CommandID (guid, id));
166 		}
167 
FindCommand(CommandID commandID)168 		public MenuCommand FindCommand (CommandID commandID)
169 		{
170 			if (commandID == null)
171 				throw new ArgumentNullException ("commandID");
172 
173 			MenuCommand command = null;
174 			if (_commands != null)
175 				_commands.TryGetValue (commandID, out command);
176 			if (command == null) {
177 				this.EnsureVerbs ();
178 				foreach (DesignerVerb verb in _verbs) {
179 					if (verb.CommandID.Equals (commandID)) {
180 						command = (MenuCommand) verb;
181 						break;
182 					}
183 				}
184 			}
185 			return command;
186 		}
187 
GetCommandList(Guid guid)188 		protected ICollection GetCommandList (Guid guid)
189 		{
190 			List<MenuCommand> list = new List<MenuCommand> ();
191 			if (_commands != null) {
192 				foreach (MenuCommand command in _commands.Values) {
193 					if (command.CommandID.Guid == guid)
194 						list.Add (command);
195 				}
196 			}
197 			return list;
198 		}
199 
GlobalInvoke(CommandID commandID)200 		public virtual bool GlobalInvoke (CommandID commandID)
201 		{
202 			if (commandID == null)
203 				throw new ArgumentNullException ("commandID");
204 
205 			MenuCommand command = this.FindCommand (commandID);
206 			if (command != null) {
207 				command.Invoke ();
208 				return true;
209 			}
210 			return false;
211 		}
212 
GlobalInvoke(CommandID commandId, object arg)213 		public virtual bool GlobalInvoke (CommandID commandId, object arg)
214 		{
215 			if (commandId == null)
216 				throw new ArgumentNullException ("commandId");
217 
218 			MenuCommand command = this.FindCommand (commandId);
219 			if (command != null) {
220 				command.Invoke (arg);
221 				return true;
222 			}
223 			return false;
224 		}
225 
OnCommandsChanged(MenuCommandsChangedEventArgs e)226 		protected virtual void OnCommandsChanged (MenuCommandsChangedEventArgs e)
227 		{
228 			if (MenuCommandsChanged != null)
229 				MenuCommandsChanged (this, e);
230 		}
231 
RemoveCommand(MenuCommand command)232 		public virtual void RemoveCommand (MenuCommand command)
233 		{
234 			if (command == null)
235 				throw new ArgumentNullException ("command");
236 			if (_commands != null)
237 				_commands.Remove (command.CommandID);
238 
239 			this.OnCommandsChanged (new MenuCommandsChangedEventArgs (MenuCommandsChangedType.CommandRemoved, null));
240 		}
241 
RemoveVerb(DesignerVerb verb)242 		public virtual void RemoveVerb (DesignerVerb verb)
243 		{
244 			if (verb == null)
245 				throw new ArgumentNullException ("verb");
246 
247 			if (_globalVerbs.Contains (verb))
248 				_globalVerbs.Remove (verb);
249 
250 			this.OnCommandsChanged (new MenuCommandsChangedEventArgs (MenuCommandsChangedType.CommandRemoved, verb));
251 		}
252 
ShowContextMenu(CommandID menuID, int x, int y)253 		public virtual void ShowContextMenu (CommandID menuID, int x, int y)
254 		{
255 		}
256 
GetService(Type serviceType)257 		protected object GetService (Type serviceType)
258 		{
259 			if (_serviceProvider != null)
260 				return _serviceProvider.GetService (serviceType);
261 			return null;
262 		}
263 	}
264 }
265