2 // System.ComponentModel.Design.Serialization.BasicDesignerLoader
5 // Ivan N. Zlatev (contact i-nZ.net)
7 // (C) 2007 Ivan N. Zlatev
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:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
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.
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
44 protected enum ReloadOptions
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;
68 _notificationsEnabled
= 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
)
87 throw new ArgumentNullException ("host");
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.
97 IDisposable session
= _serializationMananger
.CreateSession ();
99 IDesignerLoaderService loader
= _host
.GetService (typeof (IDesignerLoaderService
)) as IDesignerLoaderService
;
101 if (loader
!= null) {
102 _dependenciesCount
= -1;
103 loader
.AddLoadDependency ();
108 bool successful
= true;
111 PerformLoad (_serializationMananger
);
112 } catch (Exception e
) {
114 _serializationMananger
.Errors
.Add (e
);
118 loader
.DependentLoadComplete (successful
, _serializationMananger
.Errors
);
120 OnEndLoad (successful
, _serializationMananger
.Errors
);
125 protected abstract void PerformLoad (IDesignerSerializationManager serializationManager
);
127 protected virtual void OnBeginLoad ()
132 protected virtual void OnEndLoad (bool successful
, ICollection errors
)
134 _host
.EndLoad (_baseComponentClassName
, successful
, errors
);
138 EnableComponentNotification (true);
140 if (_reloadScheduled
) { // we are reloading
141 bool modify
= ((_reloadOptions
& ReloadOptions
.ModifyOnError
) == ReloadOptions
.ModifyOnError
);
144 this.Modified
= true;
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
{
167 throw new InvalidOperationException ("host not initialized");
168 return _serializationMananger
.PropertyProvider
;
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
)
184 throw new InvalidOperationException ("host not initialized");
186 IComponentChangeService service
= _host
.GetService (typeof (IComponentChangeService
)) as IComponentChangeService
;
187 if (service
!= null && _notificationsEnabled
!= 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
);
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
)
227 private void OnComponentRemoving (object sender
, ComponentEventArgs args
)
229 if (!_loading
&& _loaded
)
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
)
245 private void OnComponentRename (object sender
, ComponentRenameEventArgs args
)
247 if (!_loading
&& _loaded
) {
249 this.Modified
= true;
253 public override void Flush ()
256 throw new InvalidOperationException ("host not initialized");
258 if (!_flushing
&& this.Modified
) {
260 using ((IDisposable
)_serializationMananger
.CreateSession ()) {
262 PerformFlush (_serializationMananger
);
263 } catch (Exception e
) {
264 _serializationMananger
.Errors
.Add (e
);
265 ReportFlushErrors (_serializationMananger
.Errors
);
272 protected abstract void PerformFlush (IDesignerSerializationManager serializationManager
);
274 // MSDN: The default implementation always returns true.
275 protected virtual bool IsReloadNeeded ()
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
);
299 Application
.Idle
+= new EventHandler (OnIdle
);
303 private void OnIdle (object sender
, EventArgs args
)
305 Application
.Idle
-= new EventHandler (OnIdle
);
309 private void ReloadCore ()
311 bool flush
= !((_reloadOptions
& ReloadOptions
.NoFlush
) == ReloadOptions
.NoFlush
);
317 BeginLoad (_host
); // calls EndLoad, which will check for ReloadOptions.ModifyOnError
318 _reloadScheduled
= false;
321 private void Unload ()
325 EnableComponentNotification (false);
327 _baseComponentClassName
= null;
332 // The default implementation of ReportFlushErrors raises the last exception in the collection.
334 protected virtual void ReportFlushErrors (ICollection errors
)
337 foreach (object o
in errors
)
339 throw (Exception
)last
;
342 // Must be called during PerformLoad by subclasses.
343 protected void SetBaseComponentClassName (string name
)
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;
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
);
382 protected object GetService (Type serviceType
)
385 return _host
.GetService (serviceType
);
389 public override void Dispose ()
391 this.LoaderHost
.RemoveService (typeof (IDesignerLoaderService
));