2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / class / System.Design / System.ComponentModel.Design.Serialization / BasicDesignerLoader.cs
blob5661e7381705e86f1a92c5b33c83d829a2493fe6
1 //
2 // System.ComponentModel.Design.Serialization.BasicDesignerLoader
3 //
4 // Authors:
5 // Ivan N. Zlatev (contact i-nZ.net)
6 //
7 // (C) 2007 Ivan N. Zlatev
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 #if NET_2_0
32 using System;
33 using System.Collections;
34 using System.ComponentModel;
35 using System.ComponentModel.Design;
36 using System.Windows.Forms;
38 namespace System.ComponentModel.Design.Serialization
40 public abstract class BasicDesignerLoader : DesignerLoader, IDesignerLoaderService
43 [Flags]
44 protected enum ReloadOptions
46 Default,
47 Force,
48 ModifyOnError,
49 NoFlush
52 private bool _loaded;
53 private bool _loading;
54 private IDesignerLoaderHost _host;
55 private int _dependenciesCount;
56 private bool _notificationsEnabled;
57 private bool _modified;
58 private string _baseComponentClassName;
59 private DesignerSerializationManager _serializationMananger;
60 private bool _flushing;
61 private bool _reloadScheduled;
62 private ReloadOptions _reloadOptions;
64 protected BasicDesignerLoader ()
66 _loading = _loaded = _flushing = _reloadScheduled = false;
67 _host = null;
68 _notificationsEnabled = false;
69 _modified = false;
70 _dependenciesCount = 0;
73 protected virtual void Initialize ()
75 _serializationMananger = new DesignerSerializationManager (_host);
77 DesignSurfaceServiceContainer serviceContainer = _host.GetService (typeof (IServiceContainer)) as DesignSurfaceServiceContainer;
78 if (serviceContainer != null) {
79 serviceContainer.AddService (typeof (IDesignerLoaderService), (IDesignerLoaderService) this);
80 serviceContainer.AddNonReplaceableService (typeof (IDesignerSerializationManager), _serializationMananger);
84 public override void BeginLoad (IDesignerLoaderHost host)
86 if (host == null)
87 throw new ArgumentNullException ("host");
88 if (_loaded)
89 throw new InvalidOperationException ("Already loaded.");
90 if (_host != null && _host != host)
91 throw new InvalidOperationException ("Trying to load with a different host");
93 if (_host == null) { // beingload is called on reload - no need to initialize twice.
94 _host = host;
95 Initialize ();
97 IDisposable session = _serializationMananger.CreateSession ();
99 IDesignerLoaderService loader = _host.GetService (typeof (IDesignerLoaderService)) as IDesignerLoaderService;
101 if (loader != null) {
102 _dependenciesCount = -1;
103 loader.AddLoadDependency ();
104 } else {
105 OnBeginLoad ();
108 bool successful = true;
110 try {
111 PerformLoad (_serializationMananger);
112 } catch (Exception e) {
113 successful = false;
114 _serializationMananger.Errors.Add (e);
117 if (loader != null)
118 loader.DependentLoadComplete (successful, _serializationMananger.Errors);
119 else
120 OnEndLoad (successful, _serializationMananger.Errors);
122 session.Dispose ();
125 protected abstract void PerformLoad (IDesignerSerializationManager serializationManager);
127 protected virtual void OnBeginLoad ()
129 _loading = true;
132 protected virtual void OnEndLoad (bool successful, ICollection errors)
134 _host.EndLoad (_baseComponentClassName, successful, errors);
136 if (successful) {
137 _loaded = true;
138 EnableComponentNotification (true);
139 } else {
140 if (_reloadScheduled) { // we are reloading
141 bool modify = ((_reloadOptions & ReloadOptions.ModifyOnError) == ReloadOptions.ModifyOnError);
142 if (modify) {
143 OnModifying ();
144 this.Modified = true;
148 _loading = false;
151 public override bool Loading {
152 get { return _loading; }
155 protected IDesignerLoaderHost LoaderHost {
156 get { return _host; }
159 protected virtual bool Modified {
160 get { return _modified; }
161 set { _modified = value; }
164 protected object PropertyProvider {
165 get {
166 if (!_loaded)
167 throw new InvalidOperationException ("host not initialized");
168 return _serializationMananger.PropertyProvider;
170 set {
171 if (!_loaded)
172 throw new InvalidOperationException ("host not initialized");
173 _serializationMananger.PropertyProvider = value;
177 protected bool ReloadPending {
178 get { return _reloadScheduled; }
181 protected virtual bool EnableComponentNotification (bool enable)
183 if (!_loaded)
184 throw new InvalidOperationException ("host not initialized");
186 IComponentChangeService service = _host.GetService (typeof (IComponentChangeService)) as IComponentChangeService;
187 if (service != null && _notificationsEnabled != enable) {
188 if (enable) {
189 service.ComponentAdding += new ComponentEventHandler (OnComponentAdding);
190 service.ComponentAdded += new ComponentEventHandler (OnComponentAdded);
191 service.ComponentRemoving += new ComponentEventHandler (OnComponentRemoving);
192 service.ComponentRemoved += new ComponentEventHandler (OnComponentRemoved);
193 service.ComponentChanging += new ComponentChangingEventHandler (OnComponentChanging);
194 service.ComponentChanged += new ComponentChangedEventHandler (OnComponentChanged);
195 service.ComponentRename += new ComponentRenameEventHandler (OnComponentRename);
196 } else {
197 service.ComponentAdding -= new ComponentEventHandler (OnComponentAdding);
198 service.ComponentAdded -= new ComponentEventHandler (OnComponentAdded);
199 service.ComponentRemoving -= new ComponentEventHandler (OnComponentRemoving);
200 service.ComponentRemoved -= new ComponentEventHandler (OnComponentRemoved);
201 service.ComponentChanging -= new ComponentChangingEventHandler (OnComponentChanging);
202 service.ComponentChanged -= new ComponentChangedEventHandler (OnComponentChanged);
203 service.ComponentRename -= new ComponentRenameEventHandler (OnComponentRename);
206 return _notificationsEnabled == true ? true : false;
209 private void OnComponentAdded (object sender, ComponentEventArgs args)
211 if (!_loading && _loaded)
212 this.Modified = true;
215 private void OnComponentRemoved (object sender, ComponentEventArgs args)
217 if (!_loading && _loaded)
218 this.Modified = true;
221 private void OnComponentAdding (object sender, ComponentEventArgs args)
223 if (!_loading && _loaded)
224 OnModifying ();
227 private void OnComponentRemoving (object sender, ComponentEventArgs args)
229 if (!_loading && _loaded)
230 OnModifying ();
233 private void OnComponentChanged (object sender, ComponentChangedEventArgs args)
235 if (!_loading && _loaded)
236 this.Modified = true;
239 private void OnComponentChanging (object sender, ComponentChangingEventArgs args)
241 if (!_loading && _loaded)
242 OnModifying ();
245 private void OnComponentRename (object sender, ComponentRenameEventArgs args)
247 if (!_loading && _loaded) {
248 OnModifying ();
249 this.Modified = true;
253 public override void Flush ()
255 if (!_loaded)
256 throw new InvalidOperationException ("host not initialized");
258 if (!_flushing && this.Modified) {
259 _flushing = true;
260 using ((IDisposable)_serializationMananger.CreateSession ()) {
261 try {
262 PerformFlush (_serializationMananger);
263 } catch (Exception e) {
264 _serializationMananger.Errors.Add (e);
265 ReportFlushErrors (_serializationMananger.Errors);
268 _flushing = false;
272 protected abstract void PerformFlush (IDesignerSerializationManager serializationManager);
274 // MSDN: The default implementation always returns true.
275 protected virtual bool IsReloadNeeded ()
277 return true;
281 protected virtual void OnBeginUnload ()
285 protected virtual void OnModifying ()
289 // MSDN: reloads are performed at idle time
290 protected void Reload (ReloadOptions flags)
292 if (!_reloadScheduled) {
293 _reloadScheduled = true;
294 _reloadOptions = flags;
295 bool force = ((flags & ReloadOptions.Force) == ReloadOptions.Force);
296 if (force)
297 ReloadCore ();
298 else
299 Application.Idle += new EventHandler (OnIdle);
303 private void OnIdle (object sender, EventArgs args)
305 Application.Idle -= new EventHandler (OnIdle);
306 ReloadCore ();
309 private void ReloadCore ()
311 bool flush = !((_reloadOptions & ReloadOptions.NoFlush) == ReloadOptions.NoFlush);
313 if (flush)
314 Flush ();
315 Unload ();
316 _host.Reload ();
317 BeginLoad (_host); // calls EndLoad, which will check for ReloadOptions.ModifyOnError
318 _reloadScheduled = false;
321 private void Unload ()
323 if (_loaded) {
324 OnBeginUnload ();
325 EnableComponentNotification (false);
326 _loaded = false;
327 _baseComponentClassName = null;
332 // The default implementation of ReportFlushErrors raises the last exception in the collection.
334 protected virtual void ReportFlushErrors (ICollection errors)
336 object last = null;
337 foreach (object o in errors)
338 last = o;
339 throw (Exception)last;
342 // Must be called during PerformLoad by subclasses.
343 protected void SetBaseComponentClassName (string name)
345 if (name == null)
346 throw new ArgumentNullException ("name");
347 _baseComponentClassName = name;
350 #region IDesignerLoaderService implementation
352 void IDesignerLoaderService.AddLoadDependency ()
354 _dependenciesCount++;
355 if (_dependenciesCount == 0) {
356 _dependenciesCount = 1;
357 OnBeginLoad ();
361 void IDesignerLoaderService.DependentLoadComplete (bool successful, ICollection errorCollection)
363 if (_dependenciesCount == 0)
364 throw new InvalidOperationException ("dependencies == 0");
366 _dependenciesCount--;
367 if (_dependenciesCount == 0) {
368 OnEndLoad (successful, errorCollection);
372 bool IDesignerLoaderService.Reload ()
374 if (_dependenciesCount == 0) {
375 this.Reload (ReloadOptions.Force);
376 return true;
378 return false;
380 #endregion
382 protected object GetService (Type serviceType)
384 if (_host != null)
385 return _host.GetService (serviceType);
386 return null;
389 public override void Dispose ()
391 this.LoaderHost.RemoveService (typeof (IDesignerLoaderService));
392 Unload ();
397 #endif