importing messaging-2008 branch to trunk [continued]
[mono.git] / mcs / class / Mono.WebBrowser / Mono.Mozilla / DOM / NodeList.cs
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 // 
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 // 
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2008 Novell, Inc.
21 //
22 // Authors:
23 //      Andreia Gaita (avidigal@novell.com)
24 //
25
26 using System;
27 using System.Collections;
28 using Mono.WebBrowser;
29 using Mono.WebBrowser.DOM;
30
31 namespace Mono.Mozilla.DOM
32 {
33         internal class NodeList : DOMObject, INodeList
34         {
35                 protected nsIDOMNodeList unmanagedNodes;
36                 protected INode [] nodes;
37                 protected int nodeCount;
38                 
39                 public NodeList(WebBrowser control, nsIDOMNodeList nodeList) : base (control)
40                 {
41                         if (control.platform != control.enginePlatform)
42                                 unmanagedNodes = nsDOMNodeList.GetProxy (control, nodeList);
43                         else
44                                 unmanagedNodes = nodeList;
45                 }
46
47                 public NodeList (WebBrowser control) : base (control)
48                 {
49                         nodes = new Node[0];
50                 }
51                 
52                 public NodeList (WebBrowser control, bool loaded) : base (control)
53                 {
54                 }
55                 
56                 #region IDisposable Members
57                 protected override  void Dispose (bool disposing)
58                 {
59                         if (!disposed) {
60                                 if (disposing) {
61                                         Clear ();
62                                 }
63                         }
64                         base.Dispose(disposing);
65                 }               
66                 #endregion
67
68                 #region Helpers
69                 protected void Clear () 
70                 {
71                         if (nodes != null) {
72                                 for (int i = 0; i < nodeCount; i++) {
73                                         nodes[i] = null;
74                                 }
75                                 nodeCount = 0;
76                                 unmanagedNodes = null;
77                                 nodes = null;
78                         }
79                 }
80                 
81                 internal virtual void Load ()
82                 {
83                         if (unmanagedNodes == null) return;
84                         Clear ();
85                         uint count;
86                         unmanagedNodes.getLength (out count);
87                         nodeCount = (int) count; // hmm.... not good
88                         nodes = new Node[nodeCount];
89                         for (int i = 0; i < nodeCount; i++) {
90                                 nsIDOMNode node;
91                                 unmanagedNodes.item ((uint)i, out node);
92                                 ushort type;
93                                 node.getNodeType (out type);
94                                 nodes[i] = GetTypedNode (node);
95 //                              switch (type) {
96 //                                      case (ushort)NodeType.Element:
97 //                                              nodes[i] = new HTMLElement (control, node as nsIDOMHTMLElement);
98 //                                              break;
99 //                                      default:
100 //                                              nodes[i] = new Node (control, node);
101 //                                              break;
102 //                              }                               
103                         }
104                 }
105                 #endregion
106                 
107                 #region IEnumerable members
108                 public IEnumerator GetEnumerator () 
109                 {
110                         return new NodeListEnumerator (this);
111                 }
112                 #endregion
113                 
114                 #region ICollection members
115                 public void CopyTo (Array dest, int index) 
116                 {
117                         if (nodes != null) {
118                                 Array.Copy (nodes, 0, dest, index, Count);
119                         }
120                 }
121         
122                 public virtual int Count {
123                         get {
124                                 if (unmanagedNodes != null && nodes == null)
125                                         Load ();
126                                 return nodeCount; 
127                         }
128                 }
129                 
130                 object ICollection.SyncRoot {
131                         get { return this; }
132                 }
133                 
134                 bool ICollection.IsSynchronized {
135                         get { return false; }
136                 }
137
138                 #endregion
139                 
140                 #region IList members
141                 public bool IsReadOnly 
142                 {
143                         get { return false;}
144                 }
145
146                 bool IList.IsFixedSize 
147                 {
148                         get { return false;}
149                 }
150
151                 void IList.RemoveAt  (int index) 
152                 {
153                         RemoveAt (index);                       
154                 }
155                 
156                 public void RemoveAt (int index)
157                 {
158                         if (index > Count || index < 0)
159                                 return;                 
160                         Array.Copy (nodes, index + 1, nodes, index, (nodeCount - index) - 1);
161                         nodeCount--;
162                         nodes[nodeCount] = null;
163                 }
164                 
165                 public void Remove (INode node) 
166                 {
167                         this.RemoveAt (IndexOf (node));
168                 }
169
170                 void IList.Remove (object node) 
171                 {
172                         Remove (node as INode);
173                 }
174                 
175                 public void Insert (int index, INode value) 
176                 {
177                         if (index > Count)
178                                 index = nodeCount;
179                         INode[] tmp = new Node[nodeCount+1];
180                         if (index > 0)
181                                 Array.Copy (nodes, 0, tmp, 0, index);
182                         tmp[index] = value;
183                         if (index < nodeCount)
184                                 Array.Copy (nodes, index, tmp, index + 1, (nodeCount - index));
185                         nodes = tmp;
186                         nodeCount++;
187                 }
188
189                 void IList.Insert (int index, object value) 
190                 {
191                         this.Insert (index, value as INode);
192                 }
193                 
194                 public int IndexOf (INode node) 
195                 {
196                         return Array.IndexOf (nodes, node);
197                 }
198
199                 int IList.IndexOf (object node) 
200                 {
201                         return IndexOf (node as INode);
202                 }
203                 
204                 
205                 public bool Contains (INode node)
206                 {
207                         return this.IndexOf (node) != -1;
208                 }
209                 
210                 bool IList.Contains (object node)
211                 {
212                         return Contains (node as INode);                        
213                 }
214                 
215                 void IList.Clear () 
216                 {
217                         this.Clear ();
218                 }
219                 
220                 public int Add (INode node) 
221                 {
222                         this.Insert (Count + 1, node as INode);
223                         return nodeCount - 1;
224                 }
225                 
226                 int IList.Add (object node) 
227                 {
228                         return Add (node as INode);
229                 }
230                 
231                 object IList.this [int index] {
232                         get { 
233                                 return this [index]; 
234                         }
235                         set { 
236                                 this [index] = value as INode; 
237                         }
238                 }
239                 
240                 public INode this [int index] {
241                         get {
242                                 if (index < 0 || index >= Count)
243                                         throw new ArgumentOutOfRangeException ("index");
244                                 return nodes [index];                                                           
245                         }
246                         set {
247                                 if (index < 0 || index >= Count)
248                                         throw new ArgumentOutOfRangeException ("index");
249                                 nodes [index] = value as INode;
250                         }
251                 }
252                 
253                 #endregion
254                 
255                 public override int GetHashCode () {
256                         if (this.unmanagedNodes != null)
257                                 return this.unmanagedNodes.GetHashCode ();
258                         return base.GetHashCode ();
259                 }               
260
261                 internal class NodeListEnumerator : IEnumerator {
262
263                         private NodeList collection;
264                         private int index = -1;
265
266                         public NodeListEnumerator (NodeList collection)
267                         {
268                                 this.collection = collection;
269                         }
270
271                         public object Current {
272                                 get {
273                                         if (index == -1)
274                                                 return null;
275                                         return collection [index];
276                                 }
277                         }
278
279                         public bool MoveNext ()
280                         {
281                                 if (index + 1 >= collection.Count)
282                                         return false;
283                                 index++;
284                                 return true;
285                         }
286
287                         public void Reset ()
288                         {
289                                 index = -1;
290                         }
291                 }
292                 
293         }       
294 }