DesignerHost.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  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.Reflection;
  34. namespace System.ComponentModel.Design
  35. {
  36. // A container for components and their designers
  37. //
  38. internal sealed class DesignerHost : Container, IDesignerLoaderHost, IDesignerHost, IServiceProvider, IComponentChangeService
  39. {
  40. #region DesignerHostTransaction : DesignerTransaction
  41. private sealed class DesignerHostTransaction : DesignerTransaction
  42. {
  43. DesignerHost _designerHost;
  44. public DesignerHostTransaction (DesignerHost host, string description) : base (description)
  45. {
  46. _designerHost = host;
  47. }
  48. protected override void OnCancel ()
  49. {
  50. _designerHost.OnTransactionClosing (this, false);
  51. _designerHost.OnTransactionClosed (this, false);
  52. }
  53. protected override void OnCommit ()
  54. {
  55. _designerHost.OnTransactionClosing (this, true);
  56. _designerHost.OnTransactionClosed (this, true);
  57. }
  58. } // DesignerHostTransaction
  59. #endregion
  60. private IServiceProvider _serviceProvider;
  61. private Hashtable _designers;
  62. private Stack _transactions;
  63. private IServiceContainer _serviceContainer;
  64. private bool _loading;
  65. public DesignerHost (IServiceProvider serviceProvider)
  66. {
  67. if (serviceProvider == null)
  68. throw new ArgumentNullException ("serviceProvider");
  69. _serviceProvider = serviceProvider;
  70. _serviceContainer = serviceProvider.GetService (typeof (IServiceContainer)) as IServiceContainer;
  71. _designers = new Hashtable ();
  72. _transactions = new Stack ();
  73. _loading = true;
  74. }
  75. #region IContainer
  76. // XXX: More validation here?
  77. // (e.g: Make use of a potentially existing INameCreationService)
  78. //
  79. public override void Add (IComponent component, string name)
  80. {
  81. AddPreProcess (component, name);
  82. base.Add (component, name);
  83. AddPostProcess (component, name);
  84. }
  85. internal void AddPreProcess (IComponent component, string name)
  86. {
  87. if (ComponentAdding != null)
  88. ComponentAdding (this, new ComponentEventArgs (component));
  89. }
  90. internal void AddPostProcess (IComponent component, string name)
  91. {
  92. IDesigner designer;
  93. if (_rootComponent == null) {
  94. _rootComponent = component;
  95. designer = this.CreateDesigner (component, true);
  96. }
  97. else {
  98. designer = this.CreateDesigner (component, false);
  99. }
  100. if (designer != null) {
  101. _designers[component] = designer;
  102. designer.Initialize (component);
  103. } else {
  104. Console.WriteLine ("Unable to load a designer for " + component.GetType ().FullName);
  105. }
  106. // Activate the host and design surface once the root component is added to
  107. // the container and its designer is loaded and added to the designers collection
  108. if (component == _rootComponent)
  109. this.Activate ();
  110. if (component is IExtenderProvider) {
  111. IExtenderProviderService service = this.GetService (typeof (IExtenderProviderService)) as IExtenderProviderService;
  112. if (service != null)
  113. service.AddExtenderProvider ((IExtenderProvider) component);
  114. }
  115. if (ComponentAdded != null)
  116. ComponentAdded (this, new ComponentEventArgs (component));
  117. }
  118. public override void Remove (IComponent component)
  119. {
  120. RemovePreProcess (component);
  121. base.Remove (component);
  122. RemovePostProcess (component);
  123. }
  124. internal void RemovePreProcess (IComponent component)
  125. {
  126. if (ComponentRemoving != null)
  127. ComponentRemoving (this, new ComponentEventArgs (component));
  128. IDesigner designer = _designers[component] as IDesigner;
  129. if (designer != null)
  130. designer.Dispose ();
  131. _designers.Remove (component);
  132. if (component == _rootComponent)
  133. _rootComponent = null;
  134. if (component is IExtenderProvider) {
  135. IExtenderProviderService service = GetService (typeof (IExtenderProviderService)) as IExtenderProviderService;
  136. if (service != null)
  137. service.RemoveExtenderProvider ((IExtenderProvider) component);
  138. }
  139. }
  140. internal void RemovePostProcess (IComponent component)
  141. {
  142. if (ComponentRemoved != null)
  143. ComponentRemoved (this, new ComponentEventArgs (component));
  144. }
  145. protected override ISite CreateSite (IComponent component, string name)
  146. {
  147. if (name == null) {
  148. INameCreationService nameService = this.GetService (typeof (INameCreationService)) as INameCreationService;
  149. if (nameService != null)
  150. name = nameService.CreateName (this, component.GetType ());
  151. }
  152. return new DesignModeSite (component, name, this, this);
  153. }
  154. #endregion
  155. #region IDesignerHost
  156. private IComponent _rootComponent;
  157. public IContainer Container {
  158. get { return this; }
  159. }
  160. public bool InTransaction {
  161. get {
  162. if (_transactions != null && _transactions.Count > 0)
  163. return true;
  164. return false;
  165. }
  166. }
  167. public bool Loading {
  168. get { return _loading; }
  169. }
  170. public IComponent RootComponent {
  171. get { return _rootComponent; }
  172. }
  173. public string RootComponentClassName {
  174. get {
  175. if (_rootComponent != null)
  176. return ((object)_rootComponent).GetType ().AssemblyQualifiedName;
  177. return null;
  178. }
  179. }
  180. public string TransactionDescription {
  181. get {
  182. if (_transactions != null && _transactions.Count > 0)
  183. return ((DesignerHostTransaction) _transactions.Peek()).Description;
  184. return null;
  185. }
  186. }
  187. // GUI loading in the designer should be done after the Activated event is raised.
  188. //
  189. public void Activate ()
  190. {
  191. ISelectionService selectionService = GetService (typeof (ISelectionService)) as ISelectionService;
  192. // Set the Primary Selection to be the root component
  193. //
  194. if (selectionService != null)
  195. selectionService.SetSelectedComponents (new IComponent[] { _rootComponent });
  196. if (Activated != null)
  197. Activated (this, EventArgs.Empty);
  198. }
  199. public IComponent CreateComponent (Type componentClass)
  200. {
  201. return CreateComponent (componentClass, null);
  202. }
  203. public IComponent CreateComponent (Type componentClass, string name)
  204. {
  205. if (componentClass == null)
  206. throw new ArgumentNullException ("componentClass");
  207. else if (!typeof(IComponent).IsAssignableFrom(componentClass))
  208. throw new ArgumentException ("componentClass");
  209. IComponent component = this.CreateInstance (componentClass) as IComponent;
  210. this.Add (component, name);
  211. return component;
  212. }
  213. internal object CreateInstance (Type type)
  214. {
  215. if (type == null)
  216. throw new System.ArgumentNullException ("type");
  217. // FIXME: Should I use TypeDescriptor.CreateInstance() for 2.0 ?
  218. //
  219. return Activator.CreateInstance (type, BindingFlags.CreateInstance | BindingFlags.Public
  220. | BindingFlags.Instance, null, null, null);
  221. }
  222. internal IDesigner CreateDesigner (IComponent component, bool rootDesigner)
  223. {
  224. if (component == null)
  225. throw new System.ArgumentNullException ("component");
  226. if (rootDesigner) {
  227. //return TypeDescriptor.CreateDesigner (component, typeof (IRootDesigner));
  228. return this.CreateDesigner (component, typeof (IRootDesigner));
  229. }
  230. else {
  231. //return TypeDescriptor.CreateDesigner (component, typeof (IDesigner));
  232. return this.CreateDesigner (component, typeof (IDesigner));
  233. }
  234. }
  235. // Since most of the specific designers are missing this temporary method
  236. // will fallback to the first available designer type in the type's base types
  237. //
  238. private IDesigner CreateDesigner (IComponent component, Type designerBaseType)
  239. {
  240. IDesigner instance = null;
  241. AttributeCollection attributes = TypeDescriptor.GetAttributes (component);
  242. foreach (Attribute attribute in attributes) {
  243. DesignerAttribute designerAttr = attribute as DesignerAttribute;
  244. if (designerAttr != null &&
  245. (designerBaseType.FullName == designerAttr.DesignerBaseTypeName ||
  246. designerBaseType.AssemblyQualifiedName == designerAttr.DesignerBaseTypeName)) {
  247. Type type = Type.GetType (designerAttr.DesignerTypeName);
  248. if (type == null && designerBaseType == typeof (IRootDesigner))
  249. type = typeof (System.Windows.Forms.Design.DocumentDesigner);
  250. if (type != null)
  251. instance = (IDesigner) Activator.CreateInstance (type);
  252. break;
  253. }
  254. }
  255. if (instance == null) {
  256. Type baseType = component.GetType ().BaseType;
  257. do {
  258. attributes = TypeDescriptor.GetAttributes (baseType);
  259. foreach (Attribute attribute in attributes) {
  260. DesignerAttribute designerAttr = attribute as DesignerAttribute;
  261. if (designerAttr != null &&
  262. (designerBaseType.FullName == designerAttr.DesignerBaseTypeName ||
  263. designerBaseType.AssemblyQualifiedName == designerAttr.DesignerBaseTypeName)) {
  264. Type type = Type.GetType (designerAttr.DesignerTypeName);
  265. if (type != null)
  266. instance = (IDesigner) Activator.CreateInstance (type);
  267. break;
  268. }
  269. }
  270. baseType = baseType.BaseType;
  271. } while (instance == null && baseType != null);
  272. }
  273. return instance;
  274. }
  275. public void DestroyComponent (IComponent component)
  276. {
  277. if (component.Site != null && component.Site.Container == this) {
  278. OnComponentChanging (component, null);
  279. this.Remove (component); // takes care for the designer as well
  280. component.Dispose ();
  281. OnComponentChanged (component, null, null, null);
  282. }
  283. }
  284. public IDesigner GetDesigner (IComponent component)
  285. {
  286. if (component == null)
  287. throw new ArgumentNullException ("component");
  288. return _designers[component] as IDesigner;
  289. }
  290. public DesignerTransaction CreateTransaction ()
  291. {
  292. return CreateTransaction (null);
  293. }
  294. public DesignerTransaction CreateTransaction (string description)
  295. {
  296. if (TransactionOpening != null)
  297. TransactionOpening (this, EventArgs.Empty);
  298. DesignerHostTransaction transaction = new DesignerHostTransaction (this, description);
  299. _transactions.Push (transaction);
  300. if (TransactionOpened != null)
  301. TransactionOpened (this, EventArgs.Empty);
  302. return transaction;
  303. }
  304. public Type GetType (string typeName)
  305. {
  306. Type result;
  307. ITypeResolutionService s = GetService (typeof (ITypeResolutionService)) as ITypeResolutionService;
  308. if (s != null)
  309. result = s.GetType (typeName);
  310. else
  311. result = Type.GetType (typeName);
  312. return result;
  313. }
  314. // Take care of disposing the designer the base.Dispose will cleanup
  315. // the components.
  316. //
  317. protected override void Dispose (bool disposing)
  318. {
  319. Unload ();
  320. base.Dispose (disposing);
  321. }
  322. public event EventHandler Activated;
  323. public event EventHandler Deactivated;
  324. public event EventHandler LoadComplete;
  325. public event DesignerTransactionCloseEventHandler TransactionClosed;
  326. public event DesignerTransactionCloseEventHandler TransactionClosing;
  327. public event EventHandler TransactionOpened;
  328. public event EventHandler TransactionOpening;
  329. private void OnTransactionClosing (DesignerHostTransaction raiser, bool commit)
  330. {
  331. bool lastTransaction = false;
  332. if (_transactions.Count > 0 && _transactions.Peek() == raiser)
  333. lastTransaction = true;
  334. if (TransactionClosing != null)
  335. TransactionClosing (this, new DesignerTransactionCloseEventArgs (commit, lastTransaction));
  336. }
  337. private void OnTransactionClosed (DesignerHostTransaction raiser, bool commit)
  338. {
  339. bool lastTransaction = false;
  340. if (_transactions.Count > 0 && _transactions.Peek() == raiser) {
  341. lastTransaction = true;
  342. _transactions.Pop ();
  343. }
  344. if (TransactionClosed != null)
  345. TransactionClosed (this, new DesignerTransactionCloseEventArgs (commit, lastTransaction));
  346. }
  347. #endregion
  348. #region IDesignerLoaderHost
  349. internal event LoadedEventHandler DesignerLoaderHostLoaded;
  350. internal event EventHandler DesignerLoaderHostLoading;
  351. internal event EventHandler DesignerLoaderHostUnloading;
  352. internal event EventHandler DesignerLoaderHostUnloaded;
  353. public void EndLoad (string rootClassName, bool successful, ICollection errorCollection)
  354. {
  355. if (DesignerLoaderHostLoaded != null)
  356. DesignerLoaderHostLoaded (this, new LoadedEventArgs (successful, errorCollection));
  357. if (LoadComplete != null)
  358. LoadComplete (this, EventArgs.Empty);
  359. _loading = false; // _loading = true is set by the ctor
  360. }
  361. // BasicDesignerLoader invokes this.Reload, then invokes BeginLoad on itself,
  362. // then when loading it the loader is done it ends up in this.EndLoad.
  363. // At the end of the day Reload is more like Unload.
  364. //
  365. public void Reload ()
  366. {
  367. _loading = true;
  368. Unload ();
  369. if (DesignerLoaderHostLoading != null)
  370. DesignerLoaderHostLoading (this, EventArgs.Empty);
  371. }
  372. private void Unload ()
  373. {
  374. if (DesignerLoaderHostUnloading != null)
  375. DesignerLoaderHostUnloading (this, EventArgs.Empty);
  376. IComponent[] components = new IComponent[this.Components.Count];
  377. this.Components.CopyTo (components, 0);
  378. foreach (IComponent component in components)
  379. this.Remove (component);
  380. _transactions.Clear ();
  381. if (DesignerLoaderHostUnloaded != null)
  382. DesignerLoaderHostUnloaded (this, EventArgs.Empty);
  383. }
  384. #endregion
  385. #region IComponentChangeService
  386. public event ComponentEventHandler ComponentAdded;
  387. public event ComponentEventHandler ComponentAdding;
  388. public event ComponentChangedEventHandler ComponentChanged;
  389. public event ComponentChangingEventHandler ComponentChanging;
  390. public event ComponentEventHandler ComponentRemoved;
  391. public event ComponentEventHandler ComponentRemoving;
  392. public event ComponentRenameEventHandler ComponentRename;
  393. public void OnComponentChanged (object component, MemberDescriptor member, object oldValue, object newValue)
  394. {
  395. if (ComponentChanged != null)
  396. ComponentChanged (this, new ComponentChangedEventArgs (component, member, oldValue, newValue));
  397. }
  398. public void OnComponentChanging (object component, MemberDescriptor member)
  399. {
  400. if (ComponentChanging != null)
  401. ComponentChanging (this, new ComponentChangingEventArgs (component, member));
  402. }
  403. internal void OnComponentRename (object component, string oldName, string newName)
  404. {
  405. if (ComponentRename != null)
  406. ComponentRename (this, new ComponentRenameEventArgs (component, oldName, newName));
  407. }
  408. #endregion
  409. #region IServiceContainer
  410. // Wrapper around the DesignSurface service container
  411. //
  412. public void AddService (Type serviceType, object serviceInstance)
  413. {
  414. _serviceContainer.AddService (serviceType, serviceInstance);
  415. }
  416. public void AddService (Type serviceType, object serviceInstance, bool promote)
  417. {
  418. _serviceContainer.AddService (serviceType, serviceInstance, promote);
  419. }
  420. public void AddService (Type serviceType, ServiceCreatorCallback callback)
  421. {
  422. _serviceContainer.AddService (serviceType, callback);
  423. }
  424. public void AddService (Type serviceType, ServiceCreatorCallback callback, bool promote)
  425. {
  426. _serviceContainer.AddService (serviceType, callback, promote);
  427. }
  428. public void RemoveService (Type serviceType)
  429. {
  430. _serviceContainer.RemoveService (serviceType);
  431. }
  432. public void RemoveService (Type serviceType, bool promote)
  433. {
  434. _serviceContainer.RemoveService (serviceType, promote);
  435. }
  436. #endregion
  437. #region IServiceProvider
  438. public new object GetService (Type serviceType)
  439. {
  440. if (_serviceProvider != null)
  441. return _serviceProvider.GetService (serviceType);
  442. return null;
  443. }
  444. #endregion
  445. }
  446. }
  447. #endif