imported everything from my branch (which is slightly harmless).
[mono.git] / mcs / class / System.Web / System.Web.UI / ControlCollection.cs
1 //
2 // System.Web.UI.ControlCollection.cs
3 //
4 // Authors:
5 //      Duncan Mak  (duncan@ximian.com)
6 //      Gonzalo Paniagua Javier (gonzalo@novell.com)
7 //
8 // Copyright (c) 2002-2004 Novell, Inc. (http://www.novell.com)
9 //
10
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System;
33 using System.Collections;
34
35 namespace System.Web.UI {
36
37         public class ControlCollection : ICollection, IEnumerable
38         {
39                 Control owner;
40                 Control [] controls;
41                 int version;
42                 int count;
43                 bool readOnly;
44                 
45                 public ControlCollection (Control owner)
46                 {
47                         if (owner == null)
48                                 throw new ArgumentException ("owner");
49
50                         this.owner = owner;
51                 }
52
53                 public int Count {
54                         get { return count; }
55                 }
56
57                 public bool IsReadOnly {
58                         get { return readOnly; }
59                 }
60
61                 public bool  IsSynchronized {
62                         get { return false; }
63                 }
64
65                 public virtual Control this [int index] {
66                         get {
67                                 if (index < 0 || index >= count)
68                                         throw new ArgumentOutOfRangeException ("index");
69
70                                 return controls [index];
71                         }
72                 }
73
74                 protected Control Owner {
75                         get { return owner; }
76                 }
77
78                 public object SyncRoot {
79                         get { return this; }
80                 }
81
82                 void EnsureControls ()
83                 {
84                         if (controls == null) {
85                                 controls = new Control [5];
86                         } else if (controls.Length < count + 1) {
87                                 int n = controls.Length == 5 ? 3 : 2;
88                                 Control [] newControls = new Control [controls.Length * n];
89                                 Array.Copy (controls, 0, newControls, 0, controls.Length);
90                                 controls = newControls;
91                         }
92                 }
93
94                 public virtual void Add (Control child)
95                 {
96                         if (child == null)
97                                 throw new ArgumentNullException ();
98
99                         if (readOnly)
100                                 throw new HttpException ();
101
102                         EnsureControls ();
103                         version++;
104                         controls [count++] = child;
105                         owner.AddedControl (child, count - 1);
106                 }
107
108                 public virtual void AddAt (int index, Control child)
109                 {
110                         if (child == null) // maybe we should check for ! (child is Control)?
111                                 throw new ArgumentNullException ();
112                         
113                         if (index < -1 || index > count)
114                                 throw new ArgumentOutOfRangeException ();
115
116                         if (readOnly)
117                                 throw new HttpException ();
118
119                         if (index == -1) {
120                                 Add (child);
121                                 return;
122                         }
123
124                         EnsureControls ();
125                         version++;
126                         Array.Copy (controls, index, controls, index + 1, count - index);
127                         count++;
128                         controls [index] = child;
129                         owner.AddedControl (child, index);
130                 }
131
132                 public virtual void Clear ()
133                 {
134                         if (controls == null)
135                                 return;
136
137                         version++;
138                         for (int i = 0; i < count; i++)
139                                 owner.RemovedControl (controls [i]);
140
141                         count = 0;
142                         if (owner != null)
143                                 owner.ResetChildNames ();
144                 }
145
146                 public virtual bool Contains (Control c)
147                 {
148                         return (controls != null && Array.IndexOf (controls, c) != -1);
149                 }
150
151                 public void CopyTo (Array array, int index)
152                 {
153                         if (controls == null)
154                                 return;
155
156                         controls.CopyTo (array, index);
157                 }
158
159                 public IEnumerator GetEnumerator ()
160                 {
161                         return new SimpleEnumerator (this);
162                 }
163
164                 public virtual int IndexOf (Control c)
165                 {
166                         if (controls == null)
167                                 return -1;
168
169                         return Array.IndexOf (controls, c);
170                 }
171
172                 public virtual void Remove (Control value)
173                 {
174                         int idx = IndexOf (value);
175                         if (idx == -1)
176                                 return;
177                         RemoveAt (idx);
178                 }
179
180                 public virtual void RemoveAt (int index)
181                 {
182                         if (readOnly)
183                                 throw new HttpException ();
184
185                         version++;
186                         Control ctrl = controls [index];
187                         count--;
188                         if (count - index > 0)
189                                 Array.Copy (controls, index + 1, controls, index, count - index);
190
191                         controls [count] = null;
192                         owner.RemovedControl (ctrl);
193                 }
194                 
195                 internal void SetReadonly (bool readOnly)
196                 {
197                         this.readOnly = readOnly;
198                 }
199
200                 // Almost the same as in ArrayList
201                 sealed class SimpleEnumerator : IEnumerator
202                 {
203                         ControlCollection coll;
204                         int index;
205                         int version;
206                         object currentElement;
207                                                         
208                         public SimpleEnumerator (ControlCollection coll)
209                         {
210                                 this.coll = coll;
211                                 index = -1;
212                                 version = coll.version;
213                         }
214         
215                         public bool MoveNext ()
216                         {
217                                 if (version != coll.version)
218                                         throw new InvalidOperationException ("List has changed.");
219                                 
220                                 if (index >= -1 && ++index < coll.Count) {
221                                         currentElement = coll [index];
222                                         return true;
223                                 } else {
224                                         index = -2;
225                                         return false;
226                                 }
227                         }
228         
229                         public object Current {
230                                 get {
231                                         if (index < 0)
232                                                 throw new InvalidOperationException (index == -1 ? "Enumerator not started" : "Enumerator ended");
233                                         
234                                         return currentElement;
235                                 }
236                         }
237         
238                         public void Reset ()
239                         {
240                                 if (version != coll.version)
241                                         throw new InvalidOperationException ("List has changed.");
242                                 
243                                 index = -1;
244                         }
245                 }
246         }
247 }
248