* System.Windows.Forms/DataGridView.cs: SelectedRows: we need to check
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / DataGridViewRowCollection.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) 2005 Novell, Inc. (http://www.novell.com)
21 //
22 // Author:
23 //      Pedro Martínez Juliá <pedromj@gmail.com>
24 //
25
26
27 #if NET_2_0
28
29 using System.ComponentModel;
30 using System.Collections;
31 using System.ComponentModel.Design.Serialization;
32
33 namespace System.Windows.Forms {
34
35         [DesignerSerializerAttribute ("System.Windows.Forms.Design.DataGridViewRowCollectionCodeDomSerializer, " + Consts.AssemblySystem_Design,
36                                       "System.ComponentModel.Design.Serialization.CodeDomSerializer, " + Consts.AssemblySystem_Design)]
37         [ListBindable (false)]
38         public class DataGridViewRowCollection : IList, ICollection, IEnumerable {
39
40                 private ArrayList list;
41                 private DataGridView dataGridView;
42
43                 private bool raiseEvent = true;
44
45                 public DataGridViewRowCollection (DataGridView dataGridView)
46                 {
47                         this.dataGridView = dataGridView;
48                         list = new ArrayList ();
49                 }
50
51                 public int Count {
52                         get { return list.Count; }
53                 }
54
55                 int ICollection.Count
56                 {
57                         get { return Count; }
58                 }
59
60                 bool IList.IsFixedSize {
61                         get { return list.IsFixedSize; }
62                 }
63
64                 bool IList.IsReadOnly {
65                         get { return list.IsReadOnly; }
66                 }
67
68                 bool ICollection.IsSynchronized {
69                         get { return list.IsSynchronized; }
70                 }
71
72                 object IList.this [int index] {
73                         get {
74                                 return this[index];
75                         }
76                         set { list[index] = value as DataGridViewRow; }
77                 }
78
79                 public DataGridViewRow this [int index] {
80                         get {
81                                 // Accessing a System.Windows.Forms.DataGridViewRow with this indexer causes the row to become unshared. 
82                                 // To keep the row shared, use the System.Windows.Forms.DataGridViewRowCollection.SharedRow method. 
83                                 // For more information, see Best Practices for Scaling the Windows Forms DataGridView Control.
84                                 DataGridViewRow row = (DataGridViewRow) list [index];
85                                 if (row.Index == -1) {
86                                         row = (DataGridViewRow) row.Clone ();
87                                         row.SetIndex (index);
88                                         list [index] = row;
89                                 }
90                                 return row;
91                         }
92                 }
93
94                 object ICollection.SyncRoot {
95                         get { return list.SyncRoot; }
96                 }
97
98                 public event CollectionChangeEventHandler CollectionChanged;
99
100                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
101                 public virtual int Add ()
102                 {
103                         return Add(dataGridView.RowTemplate.Clone() as DataGridViewRow);
104                 }
105
106                 int IList.Add(object o)
107                 {
108                         return Add(o as DataGridViewRow);
109                 }
110
111                 internal int AddInternal (DataGridViewRow dataGridViewRow, bool sharable)
112                 {
113                         if (dataGridView.DataSource != null) {
114                                 throw new InvalidOperationException ("DataSource of DataGridView is not null.");
115                         }
116                         if (dataGridView.Columns.Count == 0) {
117                                 throw new InvalidOperationException ("DataGridView has no columns.");
118                         }
119                         int result = list.Add (dataGridViewRow);
120                         if (sharable && CanBeShared (dataGridViewRow)) {
121                                 dataGridViewRow.SetIndex (-1);
122                         } else {
123                                 dataGridViewRow.SetIndex (list.Count - 1);
124                         }
125                         dataGridViewRow.SetDataGridView (dataGridView);
126
127                         for (int i = 0; i < dataGridViewRow.Cells.Count; i++) {
128                                 dataGridViewRow.Cells [i].SetOwningColumn (dataGridView.Columns [i]);
129                         }
130
131                         OnCollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, dataGridViewRow));
132                         if (raiseEvent) {
133                                 DataGridView.OnRowsAddedInternal (new DataGridViewRowsAddedEventArgs (result, 1));
134                         }
135                         return result;
136                 }
137
138                 public virtual int Add (DataGridViewRow dataGridViewRow)
139                 {
140                         return AddInternal (dataGridViewRow, true);
141                 }
142                 
143                 private bool CanBeShared (DataGridViewRow row)
144                 {
145                         foreach (DataGridViewCell cell in row.Cells) {
146                                 if (cell.Value != null)
147                                         return false;
148                                 
149                                 if (cell.ToolTipText != string.Empty)
150                                         return false;
151                                         
152                                 if (cell.ContextMenuStrip != null)
153                                         return false;
154                         }       
155                         
156                         return true;
157                 }
158                 
159
160                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
161                 public virtual int Add (int count)
162                 {
163                         if (count <= 0) {
164                                 throw new ArgumentOutOfRangeException("Count is less than or equeal to 0.");
165                         }
166                         if (dataGridView.DataSource != null) {
167                                 throw new InvalidOperationException("DataSource of DataGridView is not null.");
168                         }
169                         if (dataGridView.Columns.Count == 0) {
170                                 throw new InvalidOperationException("DataGridView has no columns.");
171                         }
172                         raiseEvent = false;
173                         int result = 0;
174                         for (int i = 0; i < count; i++) {
175                                 result = Add(dataGridView.RowTemplate.Clone() as DataGridViewRow);
176                         }
177                         DataGridView.OnRowsAdded(new DataGridViewRowsAddedEventArgs(result - count + 1, count));
178                         raiseEvent = true;
179                         return result;
180                 }
181
182                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
183                 public virtual int Add (params object[] values)
184                 {
185                         if (values == null) {
186                                 throw new ArgumentNullException("values is null.");
187                         }
188                         if (dataGridView.VirtualMode) {
189                                 throw new InvalidOperationException("DataGridView is in virtual mode.");
190                         }
191                         DataGridViewRow row = (DataGridViewRow)dataGridView.RowTemplateFull;
192                         
193                         int result = AddInternal (row, false);
194                         row.SetValues(values);
195                         return result;
196                 }
197
198                 public virtual int AddCopies (int indexSource, int count)
199                 {
200                         raiseEvent = false;
201                         int lastIndex = 0;
202                         for (int i = 0; i < count; i++) {
203                                 lastIndex = AddCopy(indexSource);
204                         }
205                         DataGridView.OnRowsAdded(new DataGridViewRowsAddedEventArgs(lastIndex - count + 1, count));
206                         raiseEvent = true;
207                         return lastIndex;
208                 }
209
210                 public virtual int AddCopy (int indexSource)
211                 {
212                         return Add((list[indexSource] as DataGridViewRow).Clone() as DataGridViewRow);
213                 }
214
215                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
216                 public virtual void AddRange (params DataGridViewRow[] dataGridViewRows)
217                 {
218                         raiseEvent = false;
219                         int count = 0;
220                         int lastIndex = -1;
221                         foreach (DataGridViewRow row in dataGridViewRows) {
222                                 lastIndex = Add(row);
223                                 count++;
224                         }
225                         DataGridView.OnRowsAdded(new DataGridViewRowsAddedEventArgs(lastIndex - count + 1, count));
226                         raiseEvent = true;
227                 }
228
229                 public virtual void Clear ()
230                 {
231                         list.Clear();
232                 }
233
234                 bool IList.Contains (object o)
235                 {
236                         return Contains(o as DataGridViewRow);
237                 }
238
239                 public virtual bool Contains (DataGridViewRow dataGridViewRow)
240                 {
241                         return list.Contains(dataGridViewRow);
242                 }
243
244                 void ICollection.CopyTo (Array array, int index)
245                 {
246                         list.CopyTo(array, index);
247                 }
248
249                 public void CopyTo (DataGridViewRow[] array, int index)
250                 {
251                         list.CopyTo(array, index);
252                 }
253
254                 IEnumerator IEnumerable.GetEnumerator ()
255                 {
256                         return list.GetEnumerator();
257                 }
258
259                 public int GetFirstRow (DataGridViewElementStates includeFilter)
260                 {
261                         for (int i = 0; i < list.Count; i++) {
262                                 DataGridViewRow row = (DataGridViewRow) list[i];
263                                 if ((row.State & includeFilter) != 0) {
264                                         return i;
265                                 }
266                         }
267                         return -1;
268                 }
269
270                 public int GetFirstRow (DataGridViewElementStates includeFilter, DataGridViewElementStates excludeFilter)
271                 {
272                         for (int i = 0; i < list.Count; i++) {
273                                 DataGridViewRow row = (DataGridViewRow) list[i];
274                                 if (((row.State & includeFilter) != 0) && ((row.State & excludeFilter) == 0)) {
275                                         return i;
276                                 }
277                         }
278                         return -1;
279                 }
280
281                 public int GetLastRow (DataGridViewElementStates includeFilter)
282                 {
283                         for (int i = list.Count - 1; i >= 0; i--) {
284                                 DataGridViewRow row = (DataGridViewRow) list[i];
285                                 if ((row.State & includeFilter) != 0) {
286                                         return i;
287                                 }
288                         }
289                         return -1;
290                 }
291
292                 public int GetNextRow (int indexStart, DataGridViewElementStates includeFilter)
293                 {
294                         for (int i = indexStart + 1; i < list.Count; i++) {
295                                 DataGridViewRow row = (DataGridViewRow) list[i];
296                                 if ((row.State & includeFilter) != 0) {
297                                         return i;
298                                 }
299                         }
300                         return -1;
301                 }
302
303                 public int GetNextRow (int indexStart, DataGridViewElementStates includeFilter, DataGridViewElementStates excludeFilter)
304                 {
305                         for (int i = indexStart + 1; i < list.Count; i++) {
306                                 DataGridViewRow row = (DataGridViewRow) list[i];
307                                 if (((row.State & includeFilter) != 0) && ((row.State & excludeFilter) == 0)) {
308                                         return i;
309                                 }
310                         }
311                         return -1;
312                 }
313
314                 public int GetPreviousRow (int indexStart, DataGridViewElementStates includeFilter)
315                 {
316                         for (int i = indexStart - 1; i >= 0; i--) {
317                                 DataGridViewRow row = (DataGridViewRow) list[i];
318                                 if ((row.State & includeFilter) != 0) {
319                                         return i;
320                                 }
321                         }
322                         return -1;
323                 }
324
325                 public int GetPreviousRow (int indexStart, DataGridViewElementStates includeFilter, DataGridViewElementStates excludeFilter)
326                 {
327                         for (int i = indexStart - 1; i >= 0; i--) {
328                                 DataGridViewRow row = (DataGridViewRow) list[i];
329                                 if (((row.State & includeFilter) != 0) && ((row.State & excludeFilter) == 0)) {
330                                         return i;
331                                 }
332                         }
333                         return -1;
334                 }
335
336                 public int GetRowCount (DataGridViewElementStates includeFilter)
337                 {
338                         int result = 0;
339                         foreach (DataGridViewRow row in list) {
340                                 if ((row.State & includeFilter) != 0) {
341                                         result ++;
342                                 }
343                         }
344                         return result;
345                 }
346
347                 public int GetRowsHeight (DataGridViewElementStates includeFilter)
348                 {
349                         int result = 0;
350                         foreach (DataGridViewRow row in list) {
351                                 if ((row.State & includeFilter) != 0) {
352                                         result += row.Height;
353                                 }
354                         }
355                         return result;
356                 }
357
358                 public virtual DataGridViewElementStates GetRowState (int rowIndex)
359                 {
360                         return (list[rowIndex] as DataGridViewRow).State;
361                 }
362
363                 int IList.IndexOf (object o)
364                 {
365                         return IndexOf(o as DataGridViewRow);
366                 }
367
368                 public int IndexOf (DataGridViewRow dataGridViewRow)
369                 {
370                         return list.IndexOf(dataGridViewRow);
371                 }
372
373                 void IList.Insert (int rowIndex, object o)
374                 {
375                         Insert(rowIndex, o as DataGridViewRow);
376                 }
377
378                 public virtual void Insert (int rowIndex, DataGridViewRow dataGridViewRow)
379                 {
380                         dataGridViewRow.SetIndex(rowIndex);
381                         dataGridViewRow.SetDataGridView(dataGridView);
382                         list[rowIndex] = dataGridViewRow;
383                         OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Add, dataGridViewRow));
384                         if (raiseEvent) {
385                                 DataGridView.OnRowsAdded(new DataGridViewRowsAddedEventArgs(rowIndex, 1));
386                         }
387                 }
388
389                 public virtual void Insert (int rowIndex, int count)
390                 {
391                         int index = rowIndex;
392                         raiseEvent = false;
393                         for (int i = 0; i < count; i++) {
394                                 Insert(index++, dataGridView.RowTemplate.Clone());
395                         }
396                         DataGridView.OnRowsAdded(new DataGridViewRowsAddedEventArgs(rowIndex, count));
397                         raiseEvent = true;
398                 }
399
400                 public virtual void Insert (int rowIndex, params object[] values)
401                 {
402                         if (values == null) {
403                                 throw new ArgumentNullException("Values is null.");
404                         }
405                         if (dataGridView.VirtualMode || dataGridView.DataSource != null) {
406                                 throw new InvalidOperationException();
407                         }
408                         DataGridViewRow row = new DataGridViewRow();
409                         row.SetValues(values);
410                         Insert(rowIndex, row);
411                 }
412
413                 public virtual void InsertCopies (int indexSource, int indexDestination, int count)
414                 {
415                         raiseEvent = false;
416                         int index = indexDestination;
417                         for (int i = 0; i < count; i++) {
418                                 InsertCopy(indexSource, index++);
419                         }
420                         DataGridView.OnRowsAdded(new DataGridViewRowsAddedEventArgs(indexDestination, count));
421                         raiseEvent = true;
422                 }
423
424                 public virtual void InsertCopy (int indexSource, int indexDestination)
425                 {
426                         Insert(indexDestination, (list[indexSource] as DataGridViewRow).Clone());
427                 }
428
429                 public virtual void InsertRange (int rowIndex, params DataGridViewRow[] dataGridViewRows)
430                 {
431                         raiseEvent = false;
432                         int index = rowIndex;
433                         int count = 0;
434                         foreach (DataGridViewRow row in dataGridViewRows) {
435                                 Insert(index++, row);
436                                 count++;
437                         }
438                         DataGridView.OnRowsAdded(new DataGridViewRowsAddedEventArgs(rowIndex, count));
439                         raiseEvent = true;
440                 }
441
442                 void IList.Remove (object o)
443                 {
444                         Remove(o as DataGridViewRow);
445                 }
446
447                 public virtual void Remove (DataGridViewRow dataGridViewRow)
448                 {
449                         list.Remove(dataGridViewRow);
450                         OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Remove, dataGridViewRow));
451                         DataGridView.OnRowsRemoved(new DataGridViewRowsRemovedEventArgs(dataGridViewRow.Index, 1));
452                 }
453
454                 public virtual void RemoveAt (int index)
455                 {
456                         DataGridViewRow row = this[index];
457                         list.RemoveAt(index);
458                         OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Remove, row));
459                         DataGridView.OnRowsRemoved(new DataGridViewRowsRemovedEventArgs(index, 1));
460                 }
461
462                 public DataGridViewRow SharedRow (int rowIndex)
463                 {
464                         return (DataGridViewRow) list[rowIndex];
465                 }
466
467                 internal int SharedRowIndexOf (DataGridViewRow row)
468                 {
469                         return list.IndexOf (row);
470                 }
471
472                 protected DataGridView DataGridView {
473                         get { return dataGridView; }
474                 }
475
476                 protected ArrayList List {
477                         get { return list; }
478                 }
479
480                 protected virtual void OnCollectionChanged (CollectionChangeEventArgs e)
481                 {
482                         if (CollectionChanged != null) {
483                                 CollectionChanged (this, e);
484                         }
485                 }
486
487                 /************************/
488
489                 internal void InternalAdd (DataGridViewRow dataGridViewRow)
490                 {
491                         dataGridViewRow.SetIndex(list.Count);
492                         dataGridViewRow.SetDataGridView(dataGridView);
493                         list.Add(dataGridViewRow);
494                 }
495
496                 internal ArrayList RowIndexSortedArrayList {
497                         get {
498                                 ArrayList result = (ArrayList) list.Clone();
499                                 result.Sort(new RowIndexComparator());
500                                 return result;
501                         }
502                 }
503
504                 private class RowIndexComparator : IComparer {
505
506                         public int Compare (object o1, object o2) {
507                                 DataGridViewRow row1 = (DataGridViewRow) o1;
508                                 DataGridViewRow row2 = (DataGridViewRow) o2;
509                                 if (row1.Index < row2.Index) {
510                                         return -1;
511                                 }
512                                 else if (row1.Index > row2.Index) {
513                                         return 1;
514                                 }
515                                 else {
516                                         return 0;
517                                 }
518                         }
519
520                 }
521
522                 /************************/
523
524         }
525
526 }
527
528 #endif