DesignerHost.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. //
  2. // System.ComponentModel.Design.DesignerHost
  3. //
  4. // Authors:
  5. // Ivan N. Zlatev (contact i-nZ.net)
  6. //
  7. // (C) 2006-2007 Ivan N. Zlatev
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining
  10. // a copy of this software and associated documentation files (the
  11. // "Software"), to deal in the Software without restriction, including
  12. // without limitation the rights to use, copy, modify, merge, publish,
  13. // distribute, sublicense, and/or sell copies of the Software, and to
  14. // permit persons to whom the Software is furnished to do so, subject to
  15. // the following conditions:
  16. //
  17. // The above copyright notice and this permission notice shall be
  18. // included in all copies or substantial portions of the Software.
  19. //
  20. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  21. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  22. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  23. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  24. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  25. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  26. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27. //
  28. #if NET_2_0
  29. using System;
  30. using System.Collections;
  31. using System.ComponentModel;
  32. using System.ComponentModel.Design.Serialization;
  33. using System.Windows.Forms.Design;
  34. using System.Reflection;
  35. namespace System.ComponentModel.Design
  36. {
  37. // A container for components and their designers
  38. //
  39. internal sealed class DesignerHost : Container, IDesignerLoaderHost, IDesignerHost, IServiceProvider, IComponentChangeService
  40. {
  41. #region DesignerHostTransaction : DesignerTransaction
  42. private enum TransactionAction
  43. {
  44. Commit,
  45. Cancel
  46. }
  47. private sealed class DesignerHostTransaction : DesignerTransaction
  48. {
  49. DesignerHost _designerHost;
  50. public DesignerHostTransaction (DesignerHost host, string description) : base (description)
  51. {
  52. _designerHost = host;
  53. }
  54. protected override void OnCancel ()
  55. {
  56. _designerHost.OnTransactionClosing (this, TransactionAction.Cancel);
  57. _designerHost.OnTransactionClosed (this, TransactionAction.Cancel);
  58. }
  59. protected override void OnCommit ()
  60. {
  61. _designerHost.OnTransactionClosing (this, TransactionAction.Commit);
  62. _designerHost.OnTransactionClosed (this, TransactionAction.Commit);
  63. }
  64. } // DesignerHostTransaction
  65. #endregion
  66. private IServiceProvider _serviceProvider;
  67. private Hashtable _designers;
  68. private Stack _transactions;
  69. private IServiceContainer _serviceContainer;
  70. private bool _loading;
  71. public DesignerHost (IServiceProvider serviceProvider)
  72. {
  73. if (serviceProvider == null)
  74. throw new ArgumentNullException ("serviceProvider");
  75. _serviceProvider = serviceProvider;
  76. _serviceContainer = serviceProvider.GetService (typeof (IServiceContainer)) as IServiceContainer;
  77. _designers = new Hashtable ();
  78. _transactions = new Stack ();
  79. _loading = true;
  80. }
  81. #region IContainer
  82. // XXX: More validation here?
  83. // (e.g: Make use of a potentially existing INameCreationService)
  84. //
  85. public override void Add (IComponent component, string name)
  86. {
  87. AddPreProcess (component, name);
  88. base.Add (component, name);
  89. AddPostProcess (component, name);
  90. }
  91. internal void AddPreProcess (IComponent component, string name)
  92. {
  93. if (ComponentAdding != null)
  94. ComponentAdding (this, new ComponentEventArgs (component));
  95. }
  96. internal void AddPostProcess (IComponent component, string name)
  97. {
  98. IDesigner designer;
  99. if (_rootComponent == null) {
  100. _rootComponent = component;
  101. designer = this.CreateDesigner (component, true);
  102. }
  103. else {
  104. designer = this.CreateDesigner (component, false);
  105. }
  106. if (designer != null) {
  107. _designers[component] = designer;
  108. designer.Initialize (component);
  109. } else {
  110. IUIService uiService = GetService (typeof (IUIService)) as IUIService;
  111. if (uiService != null) {
  112. uiService.ShowError ("Unable to load a designer for component type '" +
  113. component.GetType ().Name + "'");
  114. }
  115. this.DestroyComponent (component);
  116. }
  117. // Activate the host and design surface once the root component is added to
  118. // the container and its designer is loaded and added to the designers collection
  119. if (component == _rootComponent)
  120. this.Activate ();
  121. if (component is IExtenderProvider) {
  122. IExtenderProviderService service = this.GetService (typeof (IExtenderProviderService)) as IExtenderProviderService;
  123. if (service != null)
  124. service.AddExtenderProvider ((IExtenderProvider) component);
  125. }
  126. if (ComponentAdded != null)
  127. ComponentAdded (this, new ComponentEventArgs (component));
  128. }
  129. public override void Remove (IComponent component)
  130. {
  131. RemovePreProcess (component);
  132. base.Remove (component);
  133. RemovePostProcess (component);
  134. }
  135. internal void RemovePreProcess (IComponent component)
  136. {
  137. if (ComponentRemoving != null)
  138. ComponentRemoving (this, new ComponentEventArgs (component));
  139. IDesigner designer = _designers[component] as IDesigner;
  140. if (designer != null)
  141. designer.Dispose ();
  142. _designers.Remove (component);
  143. if (component == _rootComponent)
  144. _rootComponent = null;
  145. if (component is IExtenderProvider) {
  146. IExtenderProviderService service = GetService (typeof (IExtenderProviderService)) as IExtenderProviderService;
  147. if (service != null)
  148. service.RemoveExtenderProvider ((IExtenderProvider) component);
  149. }
  150. }
  151. internal void RemovePostProcess (IComponent component)
  152. {
  153. if (ComponentRemoved != null)
  154. ComponentRemoved (this, new ComponentEventArgs (component));
  155. }
  156. protected override ISite CreateSite (IComponent component, string name)
  157. {
  158. if (name == null) {
  159. INameCreationService nameService = this.GetService (typeof (INameCreationService)) as INameCreationService;
  160. if (nameService != null)
  161. name = nameService.CreateName (this, component.GetType ());
  162. }
  163. return new DesignModeSite (component, name, this, this);
  164. }
  165. #endregion
  166. #region IDesignerHost
  167. private IComponent _rootComponent;
  168. public IContainer Container {
  169. get { return this; }
  170. }
  171. public bool InTransaction {
  172. get {
  173. if (_transactions != null && _transactions.Count > 0)
  174. return true;
  175. return false;
  176. }
  177. }
  178. public bool Loading {
  179. get { return _loading; }
  180. }
  181. public IComponent RootComponent {
  182. get { return _rootComponent; }
  183. }
  184. public string RootComponentClassName {
  185. get {
  186. if (_rootComponent != null)
  187. return ((object)_rootComponent).GetType ().AssemblyQualifiedName;
  188. return null;
  189. }
  190. }
  191. public string TransactionDescription {
  192. get {
  193. if (_transactions != null && _transactions.Count > 0)
  194. return ((DesignerHostTransaction) _transactions.Peek()).Description;
  195. return null;
  196. }
  197. }
  198. // GUI loading in the designer should be done after the Activated event is raised.
  199. //
  200. public void Activate ()
  201. {
  202. ISelectionService selectionService = GetService (typeof (ISelectionService)) as ISelectionService;
  203. // Set the Primary Selection to be the root component
  204. //
  205. if (selectionService != null)
  206. selectionService.SetSelectedComponents (new IComponent[] { _rootComponent });
  207. if (Activated != null)
  208. Activated (this, EventArgs.Empty);
  209. }
  210. public IComponent CreateComponent (Type componentClass)
  211. {
  212. return CreateComponent (componentClass, null);
  213. }
  214. public IComponent CreateComponent (Type componentClass, string name)
  215. {
  216. if (componentClass == null)
  217. throw new ArgumentNullException ("componentClass");
  218. else if (!typeof(IComponent).IsAssignableFrom(componentClass))
  219. throw new ArgumentException ("componentClass");
  220. IComponent component = this.CreateInstance (componentClass) as IComponent;
  221. this.Add (component, name);
  222. return component;
  223. }
  224. internal object CreateInstance (Type type)
  225. {
  226. if (type == null)
  227. throw new System.ArgumentNullException ("type");
  228. // FIXME: Should I use TypeDescriptor.CreateInstance() for 2.0 ?
  229. //
  230. return Activator.CreateInstance (type, BindingFlags.CreateInstance | BindingFlags.Public
  231. | BindingFlags.Instance, null, null, null);
  232. }
  233. internal IDesigner CreateDesigner (IComponent component, bool rootDesigner)
  234. {
  235. if (component == null)
  236. throw new System.ArgumentNullException ("component");
  237. if (rootDesigner) {
  238. //return TypeDescriptor.CreateDesigner (component, typeof (IRootDesigner));
  239. return this.CreateDesigner (component, typeof (IRootDesigner));
  240. }
  241. else {
  242. //return TypeDescriptor.CreateDesigner (component, typeof (IDesigner));
  243. return this.CreateDesigner (component, typeof (IDesigner));
  244. }
  245. }
  246. // Since most of the specific designers are missing this temporary method
  247. // will fallback to the first available designer type in the type's base types
  248. //
  249. private IDesigner CreateDesigner (IComponent component, Type designerBaseType)
  250. {
  251. IDesigner instance = null;
  252. AttributeCollection attributes = TypeDescriptor.GetAttributes (component);
  253. foreach (Attribute attribute in attributes) {
  254. DesignerAttribute designerAttr = attribute as DesignerAttribute;
  255. if (designerAttr != null &&
  256. (designerBaseType.FullName == designerAttr.DesignerBaseTypeName ||
  257. designerBaseType.AssemblyQualifiedName == designerAttr.DesignerBaseTypeName)) {
  258. Type type = Type.GetType (designerAttr.DesignerTypeName);
  259. if (type == null && designerBaseType == typeof (IRootDesigner))
  260. type = typeof (System.Windows.Forms.Design.DocumentDesigner);
  261. if (type != null)
  262. instance = (IDesigner) Activator.CreateInstance (type);
  263. break;
  264. }
  265. }
  266. if (instance == null) {
  267. Type baseType = component.GetType ().BaseType;
  268. do {
  269. attributes = TypeDescriptor.GetAttributes (baseType);
  270. foreach (Attribute attribute in attributes) {
  271. DesignerAttribute designerAttr = attribute as DesignerAttribute;
  272. if (designerAttr != null &&
  273. (designerBaseType.FullName == designerAttr.DesignerBaseTypeName ||
  274. designerBaseType.AssemblyQualifiedName == designerAttr.DesignerBaseTypeName)) {
  275. Type type = Type.GetType (designerAttr.DesignerTypeName);
  276. if (type != null)
  277. instance = (IDesigner) Activator.CreateInstance (type);
  278. break;
  279. }
  280. }
  281. baseType = baseType.BaseType;
  282. } while (instance == null && baseType != null);
  283. }
  284. return instance;
  285. }
  286. public void DestroyComponent (IComponent component)
  287. {
  288. if (component.Site != null && component.Site.Container == this) {
  289. OnComponentChanging (component, null);
  290. this.Remove (component); // takes care for the designer as well
  291. component.Dispose ();
  292. OnComponentChanged (component, null, null, null);
  293. }
  294. }
  295. public IDesigner GetDesigner (IComponent component)
  296. {
  297. if (component == null)
  298. throw new ArgumentNullException ("component");
  299. return _designers[component] as IDesigner;
  300. }
  301. public DesignerTransaction CreateTransaction ()
  302. {
  303. return CreateTransaction (null);
  304. }
  305. public DesignerTransaction CreateTransaction (string description)
  306. {
  307. if (TransactionOpening != null)
  308. TransactionOpening (this, EventArgs.Empty);
  309. DesignerHostTransaction transaction = new DesignerHostTransaction (this, description);
  310. _transactions.Push (transaction);
  311. if (TransactionOpened != null)
  312. TransactionOpened (this, EventArgs.Empty);
  313. return transaction;
  314. }
  315. public Type GetType (string typeName)
  316. {
  317. Type result;
  318. ITypeResolutionService s = GetService (typeof (ITypeResolutionService)) as ITypeResolutionService;
  319. if (s != null)
  320. result = s.GetType (typeName);
  321. else
  322. result = Type.GetType (typeName);
  323. return result;
  324. }
  325. // Take care of disposing the designer the base.Dispose will cleanup
  326. // the components.
  327. //
  328. protected override void Dispose (bool disposing)
  329. {
  330. Unload ();
  331. base.Dispose (disposing);
  332. }
  333. public event EventHandler Activated;
  334. public event EventHandler Deactivated;
  335. public event EventHandler LoadComplete;
  336. public event DesignerTransactionCloseEventHandler TransactionClosed;
  337. public event DesignerTransactionCloseEventHandler TransactionClosing;
  338. public event EventHandler TransactionOpened;
  339. public event EventHandler TransactionOpening;
  340. private void OnTransactionClosing (DesignerHostTransaction raiser, TransactionAction action)
  341. {
  342. bool commit = false;
  343. bool lastTransaction = false;
  344. if (_transactions.Peek () != raiser)
  345. throw new InvalidOperationException ("Current transaction differs from the one a commit was requested for.");
  346. if (_transactions.Count == 1)
  347. lastTransaction = true;
  348. if (action == TransactionAction.Commit)
  349. commit = true;
  350. if (TransactionClosing != null)
  351. TransactionClosing (this, new DesignerTransactionCloseEventArgs (commit, lastTransaction));
  352. }
  353. private void OnTransactionClosed (DesignerHostTransaction raiser, TransactionAction action)
  354. {
  355. bool commit = false;
  356. bool lastTransaction = false;
  357. if (_transactions.Peek () != raiser)
  358. throw new InvalidOperationException ("Current transaction differs from the one a commit was requested for.");
  359. if (_transactions.Count == 1)
  360. lastTransaction = true;
  361. if (action == TransactionAction.Commit)
  362. commit = true;
  363. _transactions.Pop ();
  364. if (TransactionClosed != null)
  365. TransactionClosed (this, new DesignerTransactionCloseEventArgs (commit, lastTransaction));
  366. }
  367. #endregion
  368. #region IDesignerLoaderHost
  369. internal event LoadedEventHandler DesignerLoaderHostLoaded;
  370. internal event EventHandler DesignerLoaderHostLoading;
  371. internal event EventHandler DesignerLoaderHostUnloading;
  372. internal event EventHandler DesignerLoaderHostUnloaded;
  373. public void EndLoad (string rootClassName, bool successful, ICollection errorCollection)
  374. {
  375. if (DesignerLoaderHostLoaded != null)
  376. DesignerLoaderHostLoaded (this, new LoadedEventArgs (successful, errorCollection));
  377. if (LoadComplete != null)
  378. LoadComplete (this, EventArgs.Empty);
  379. _loading = false; // _loading = true is set by the ctor
  380. }
  381. // BasicDesignerLoader invokes this.Reload, then invokes BeginLoad on itself,
  382. // then when loading it the loader is done it ends up in this.EndLoad.
  383. // At the end of the day Reload is more like Unload.
  384. //
  385. public void Reload ()
  386. {
  387. _loading = true;
  388. Unload ();
  389. if (DesignerLoaderHostLoading != null)
  390. DesignerLoaderHostLoading (this, EventArgs.Empty);
  391. }
  392. private void Unload ()
  393. {
  394. if (DesignerLoaderHostUnloading != null)
  395. DesignerLoaderHostUnloading (this, EventArgs.Empty);
  396. IComponent[] components = new IComponent[this.Components.Count];
  397. this.Components.CopyTo (components, 0);
  398. foreach (IComponent component in components)
  399. this.Remove (component);
  400. _transactions.Clear ();
  401. if (DesignerLoaderHostUnloaded != null)
  402. DesignerLoaderHostUnloaded (this, EventArgs.Empty);
  403. }
  404. #endregion
  405. #region IComponentChangeService
  406. public event ComponentEventHandler ComponentAdded;
  407. public event ComponentEventHandler ComponentAdding;
  408. public event ComponentChangedEventHandler ComponentChanged;
  409. public event ComponentChangingEventHandler ComponentChanging;
  410. public event ComponentEventHandler ComponentRemoved;
  411. public event ComponentEventHandler ComponentRemoving;
  412. public event ComponentRenameEventHandler ComponentRename;
  413. public void OnComponentChanged (object component, MemberDescriptor member, object oldValue, object newValue)
  414. {
  415. if (ComponentChanged != null)
  416. ComponentChanged (this, new ComponentChangedEventArgs (component, member, oldValue, newValue));
  417. }
  418. public void OnComponentChanging (object component, MemberDescriptor member)
  419. {
  420. if (ComponentChanging != null)
  421. ComponentChanging (this, new ComponentChangingEventArgs (component, member));
  422. }
  423. internal void OnComponentRename (object component, string oldName, string newName)
  424. {
  425. if (ComponentRename != null)
  426. ComponentRename (this, new ComponentRenameEventArgs (component, oldName, newName));
  427. }
  428. #endregion
  429. #region IServiceContainer
  430. // Wrapper around the DesignSurface service container
  431. //
  432. public void AddService (Type serviceType, object serviceInstance)
  433. {
  434. _serviceContainer.AddService (serviceType, serviceInstance);
  435. }
  436. public void AddService (Type serviceType, object serviceInstance, bool promote)
  437. {
  438. _serviceContainer.AddService (serviceType, serviceInstance, promote);
  439. }
  440. public void AddService (Type serviceType, ServiceCreatorCallback callback)
  441. {
  442. _serviceContainer.AddService (serviceType, callback);
  443. }
  444. public void AddService (Type serviceType, ServiceCreatorCallback callback, bool promote)
  445. {
  446. _serviceContainer.AddService (serviceType, callback, promote);
  447. }
  448. public void RemoveService (Type serviceType)
  449. {
  450. _serviceContainer.RemoveService (serviceType);
  451. }
  452. public void RemoveService (Type serviceType, bool promote)
  453. {
  454. _serviceContainer.RemoveService (serviceType, promote);
  455. }
  456. #endregion
  457. #region IServiceProvider
  458. public new object GetService (Type serviceType)
  459. {
  460. if (_serviceProvider != null)
  461. return _serviceProvider.GetService (serviceType);
  462. return null;
  463. }
  464. #endregion
  465. }
  466. }
  467. #endif