Merge pull request #347 from JamesB7/master
[mono.git] / mcs / class / System / System.ComponentModel / NestedContainer.cs
1 //
2 // System.ComponentModel.NestedContainer
3 //
4 // Authors:             
5 //              Ivan N. Zlatev (contact i-nZ.net)
6 //
7 // (C) 2006-2007 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 using System;
31 using System.Collections;
32 using System.ComponentModel;
33 using System.ComponentModel.Design;
34
35 namespace System.ComponentModel
36 {
37         // Differences compared to Container:
38         // * Site's DesignMode property is routed through the owning component's site. Note that even though MSDN 
39         //   says that GetService is routed as well, it actually isn't. The unit tests proof that.
40         // * According to MSDN the site's Name property is a qualified name that includes the owning component's name followed by a
41         //      period (.) and the child component's name. It is not again according to the tests.
42         // * GetService provides support for the INestedContainer as a service.
43         // * When the owning component is disposed, the container is disposed as well.
44         
45         public class NestedContainer : Container, INestedContainer, IContainer, IDisposable
46         {
47
48 #region Site : INestedSite, ISite, IServiceProvider
49
50                 private class Site : INestedSite, ISite, IServiceProvider
51                 {                
52
53                         private IComponent _component;
54                         private NestedContainer _nestedContainer;
55                         private string _siteName;
56                         
57                         public Site (IComponent component, NestedContainer container, string name)
58                         {
59                                 _component = component;
60                                 _nestedContainer = container;
61                                 _siteName = name;
62                         }
63                         
64                         public IComponent Component {
65                                 get { return _component; }
66                         }
67
68                         public IContainer Container {
69                                 get { return _nestedContainer; }
70                         }
71
72                         public bool DesignMode {
73                                 get {
74                                         if (_nestedContainer.Owner != null
75                                                 && _nestedContainer.Owner.Site != null) {
76
77                                                 return _nestedContainer.Owner.Site.DesignMode;
78                                         }
79                                         else {
80                                                 return false;
81                                         }
82                                 }
83                         }
84
85                         public string Name {
86                                 get { return _siteName; }                               
87                                 set { _siteName = value; }
88                         }
89
90                         // [owner].[component]
91                         //
92                         public string FullName {
93                                 get {
94                                         if (_siteName == null) {
95                                                 return null;
96                                         }
97                                         if (_nestedContainer.OwnerName == null) {
98                                                 return _siteName;
99                                         }
100
101                                         return _nestedContainer.OwnerName + "." + _siteName;
102                                 }
103                         }
104
105                         public virtual object GetService (Type service)
106                         {
107                                 if (service == typeof (ISite)) {
108                                         return this; 
109                                 }
110                                 
111                                 return _nestedContainer.GetService (service);
112                         }
113                 } // Site
114
115 #endregion
116
117                 
118                 
119                 private IComponent _owner;
120                 
121                 
122                 public NestedContainer (IComponent owner)
123                 {
124                         if (owner == null)
125                                 throw new ArgumentNullException ("owner");
126
127                         _owner = owner;
128                         _owner.Disposed += new EventHandler (OnOwnerDisposed);
129                 }
130                 
131                 public IComponent Owner {
132                         get { return _owner; }
133                 }
134
135                 protected virtual string OwnerName {
136                         get {
137                                 if (_owner.Site is INestedSite)
138                                         return ((INestedSite) _owner.Site).FullName;
139                                 if (_owner == null || _owner.Site == null)
140                                         return null;
141                         
142                                 return _owner.Site.Name;
143                         }
144                 }               
145
146                 protected override ISite CreateSite (IComponent component, string name)
147                 {
148                         if (component == null)
149                                 throw new ArgumentNullException("component");
150                         
151                         return new NestedContainer.Site (component, this, name);
152                 }
153                 
154                 protected override object GetService (Type service)
155                 {
156                         if (service == typeof (INestedContainer))
157                                 return this;
158                         
159                         return base.GetService (service);
160                 }
161
162                 protected override void Dispose (bool disposing)
163                 {
164                         if (disposing)
165                                 _owner.Disposed -= new EventHandler (OnOwnerDisposed);
166                         
167                         base.Dispose (disposing);
168                 }
169
170                 private void OnOwnerDisposed (object sender, EventArgs e)
171                 {
172                         this.Dispose ();
173                 }
174         }
175         
176 }