2008-06-28 Ivan N. Zlatev <contact@i-nz.net>
[mono.git] / mcs / class / System.Design / System.ComponentModel.Design / DesignSurfaceManager.cs
1 //
2 // System.ComponentModel.Design.DesignSurfaceManager
3 //
4 // Authors:      
5 //        Ivan N. Zlatev (contact i-nZ.net)
6 //
7 // (C) 2006 Ivan N. Zlatev
8
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.
28 //
29
30 #if NET_2_0
31
32 using System;
33 using System.ComponentModel;
34 using System.Collections;
35
36 namespace System.ComponentModel.Design
37 {
38
39         public class DesignSurfaceManager : IServiceProvider, IDisposable
40         {
41
42                 private class MergedServiceProvider : IServiceProvider
43                 {
44                         private IServiceProvider _primaryProvider;
45                         private IServiceProvider _secondaryProvider;
46                         
47                         public MergedServiceProvider (IServiceProvider primary, IServiceProvider secondary)
48                         {
49                                 if (primary == null)
50                                         throw new ArgumentNullException ("primary");
51                                 if (secondary == null)
52                                         throw new ArgumentNullException ("secondary");
53                                 
54                                 _primaryProvider = primary;
55                                 _secondaryProvider = secondary;
56                         }
57
58                         public object GetService (Type service)
59                         {
60                                 object result = _primaryProvider.GetService (service);
61                                 if (result == null)
62                                         result = _secondaryProvider.GetService (service);
63
64                                 return result;
65                         }
66                         
67                 } // MergedServiceProvider
68
69                 
70                 private IServiceProvider _parentProvider;
71                 private ServiceContainer _serviceContainer;
72                 
73                 public DesignSurfaceManager () : this (null)
74                 {
75                 }
76
77                 public DesignSurfaceManager (IServiceProvider serviceProvider)
78                 {
79                         _parentProvider = serviceProvider;
80                         this.ServiceContainer.AddService (typeof (IDesignerEventService), new DesignerEventService ());
81                 }
82
83                 // The CreateDesignSurfaceCore method is called by both CreateDesignSurface methods.
84                 // It is the implementation that actually creates the design surface. The default
85                 // implementation just returns a new DesignSurface. You may override this method to provide
86                 // a custom object that derives from the DesignSurface class.
87                 //
88                 protected virtual DesignSurface CreateDesignSurfaceCore (IServiceProvider parentProvider)
89                 {
90                         DesignSurface surface = new DesignSurface (parentProvider);
91                         OnDesignSurfaceCreated (surface);
92                         return surface;
93                 }
94                 
95                 public DesignSurface CreateDesignSurface ()
96                 {
97                         return CreateDesignSurfaceCore (this);  
98                 }
99
100                 // MSDN: parentProvider - A parent service provider. A new merged service provider will be created that
101                 // will first ask this provider for a service, and then delegate any failures to the design surface
102                 // manager object. This merged provider will be passed into the CreateDesignSurfaceCore method.
103                 //
104                 public DesignSurface CreateDesignSurface (IServiceProvider parentProvider)
105                 {
106                         if (parentProvider == null)
107                                 throw new ArgumentNullException ("parentProvider");
108                         
109                         return CreateDesignSurfaceCore (new MergedServiceProvider (parentProvider, this));
110                 }
111                 
112                 public virtual DesignSurface ActiveDesignSurface {
113                         get {
114                                 DesignerEventService eventService = GetService (typeof (IDesignerEventService)) as DesignerEventService;
115                                 if (eventService != null) {
116                                         IDesignerHost designer = eventService.ActiveDesigner;
117                                         if (designer != null)
118                                                 return designer.GetService (typeof (DesignSurface)) as DesignSurface;
119                                 }
120                                 return null;
121                         }
122                         set {
123                                 if (value != null) {
124                                         DesignSurface oldSurface = null;
125                                 
126                                         // get current surface
127                                         DesignerEventService eventService = GetService (typeof (IDesignerEventService)) as DesignerEventService;
128                                         if (eventService != null) {
129                                                 IDesignerHost designer = eventService.ActiveDesigner;
130                                                 if (designer != null)
131                                                         oldSurface = designer.GetService (typeof (DesignSurface)) as DesignSurface;
132                                         }
133                                         
134                                         ISelectionService selectionService = null;
135                                         
136                                         if (oldSurface != value) {
137                                                 // unsubscribe from current's selectionchanged
138                                                 if (oldSurface != null) {
139                                                         selectionService = oldSurface.GetService (typeof (ISelectionService)) as ISelectionService;
140                                                         if (selectionService != null)
141                                                                 selectionService.SelectionChanged -= new EventHandler (OnSelectionChanged);
142                                                 }
143                                                 // subscribe to new's selectionchanged
144                                                 selectionService = value.GetService (typeof (ISelectionService)) as ISelectionService;
145                                                 if (selectionService != null)
146                                                         selectionService.SelectionChanged += new EventHandler (OnSelectionChanged);
147                                                 
148                                                 // set it
149                                                 eventService.ActiveDesigner = value.GetService (typeof (IDesignerHost)) as IDesignerHost;
150                                                 
151                                                 // fire event
152                                                 if (this.ActiveDesignSurfaceChanged != null)
153                                                         this.ActiveDesignSurfaceChanged (this, new ActiveDesignSurfaceChangedEventArgs (oldSurface, value));
154                                         }
155                                 }
156                         }
157                 }
158                 
159                 public DesignSurfaceCollection DesignSurfaces {
160                         get {
161                                 DesignerEventService eventService = GetService (typeof (IDesignerEventService)) as DesignerEventService;
162                                 if (eventService != null) 
163                                         return new DesignSurfaceCollection (eventService.Designers);
164
165                                 return new DesignSurfaceCollection (null);
166                         }
167                 }
168                 
169                 protected ServiceContainer ServiceContainer {
170                         get {
171                                 if (_serviceContainer == null)
172                                         _serviceContainer = new ServiceContainer (_parentProvider);
173
174                                 return _serviceContainer;
175                         }
176                 }
177                                 
178                 // MSDN2 says those events are mapped through the IDesignerEventService,
179                 // but I preferd not to do that. Should not cause compitability issues.
180                 //
181                 // 
182                 // The SelectionChanged is fired only for a changed component selection on the
183                 // active designersurface.
184                 //
185                 public event EventHandler SelectionChanged;      
186                 public event DesignSurfaceEventHandler DesignSurfaceDisposed;
187                 public event DesignSurfaceEventHandler DesignSurfaceCreated;
188                 public event ActiveDesignSurfaceChangedEventHandler ActiveDesignSurfaceChanged;
189                 
190                 private void OnSelectionChanged (object sender, EventArgs args)
191                 {
192                         if (SelectionChanged != null)
193                                 SelectionChanged (this, EventArgs.Empty);
194                         
195                         DesignerEventService eventService = GetService (typeof (IDesignerEventService)) as DesignerEventService;
196                         if (eventService != null)
197                                 eventService.RaiseSelectionChanged ();
198                 }
199                 
200                 private void OnDesignSurfaceCreated (DesignSurface surface)
201                 {
202                         if (DesignSurfaceCreated != null)
203                                 DesignSurfaceCreated (this, new DesignSurfaceEventArgs (surface));
204                         
205                         // monitor disposing
206                         surface.Disposed += new EventHandler (OnDesignSurfaceDisposed);
207                         
208                         DesignerEventService eventService = GetService (typeof (IDesignerEventService)) as DesignerEventService;
209                         if (eventService != null)
210                                 eventService.RaiseDesignerCreated (surface.GetService (typeof (IDesignerHost)) as IDesignerHost);
211                 }
212
213                 private void OnDesignSurfaceDisposed (object sender, EventArgs args)
214                 {
215                         DesignSurface surface = (DesignSurface) sender;
216                         
217                         surface.Disposed -= new EventHandler (OnDesignSurfaceDisposed);
218                         
219                         if (DesignSurfaceDisposed != null)
220                                 DesignSurfaceDisposed (this, new DesignSurfaceEventArgs (surface));
221                         
222                         DesignerEventService eventService = GetService (typeof (IDesignerEventService)) as DesignerEventService;
223                         if (eventService != null)
224                                 eventService.RaiseDesignerDisposed (surface.GetService (typeof (IDesignerHost)) as IDesignerHost);
225                                 
226                 }
227                 
228                 public object GetService (Type service)
229                 {
230                         if (_serviceContainer != null)
231                                 return _serviceContainer.GetService (service);
232
233                         return null;
234                 }
235
236                 public void Dispose ()
237                 {
238                         Dispose (true);
239                 }
240
241                 protected virtual void Dispose (bool disposing)
242                 {
243                         if (disposing && _serviceContainer != null) {
244                                 _serviceContainer.Dispose ();
245                                 _serviceContainer = null;
246                         }
247                 }
248         }
249
250 }
251 #endif