merge -r 53370:58178
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / CurrencyManager.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.
21 //
22 // Authors:
23 //      Jackson Harper (jackson@ximian.com)
24 //
25
26 using System;
27 using System.Data;
28 using System.Reflection;
29 using System.Collections;
30 using System.ComponentModel;
31
32 namespace System.Windows.Forms {
33         [DefaultMember("Item")]
34         public class CurrencyManager : BindingManagerBase {
35
36                 protected Type finalType;
37                 protected int listposition;
38
39                 private IList list;
40                 private bool binding_suspended;
41
42                 internal CurrencyManager (object data_source)
43                 {                       
44                         if (data_source is IListSource) {
45                                 list = ((IListSource) data_source).GetList ();
46                         } else if (data_source is IList) {
47                                 list = (IList) data_source;
48                         } else {
49                                 throw new Exception ("Attempted to create currency manager " +
50                                         "from invalid type: " + data_source.GetType ());
51                         }
52
53                         if (data_source as ArrayList != null) {
54                                 finalType = ((ArrayList)data_source).GetType ();
55                         } else {
56                                 if (data_source as Array != null) {
57                                         finalType = ((Array) data_source).GetType ();
58                                 } else {
59                                         finalType = null;
60                                 }
61                         }
62
63                         DataTable table = data_source as DataTable;
64                         if (table == null && data_source is DataView)
65                                 table = ((DataView) data_source).Table;
66
67                         if (table != null) {
68                                 table.Columns.CollectionChanged  += new CollectionChangeEventHandler (MetaDataChangedHandler);
69                                 table.ChildRelations.CollectionChanged  += new CollectionChangeEventHandler (MetaDataChangedHandler);
70                                 table.ParentRelations.CollectionChanged  += new CollectionChangeEventHandler (MetaDataChangedHandler);
71                                 table.Constraints.CollectionChanged += new CollectionChangeEventHandler (MetaDataChangedHandler);
72                         }
73                 }
74
75                 public IList List {
76                         get { return list; }
77                 }
78
79                 public override object Current {
80                         get {
81                                 return list [listposition];
82                         }
83                 }
84
85                 public override int Count {
86                         get { return list.Count; }
87                 }
88
89                 public override int Position {
90                         get {
91                                 return listposition;
92                         } 
93                         set {
94                                 if (value < 0)
95                                         value = 0;
96                                 if (value == list.Count)
97                                         value = list.Count - 1;
98                                 if (listposition == value)
99                                         return;
100                                 listposition = value;
101                                 OnCurrentChanged (EventArgs.Empty);
102                                 OnPositionChanged (EventArgs.Empty);
103                         }
104                 }
105                 
106                 internal string ListName {
107                         get {
108                                 ITypedList typed = list as ITypedList;
109                                 
110                                 if (typed == null) {
111                                         return finalType.Name;
112                                 } else {
113                                         return typed.GetListName (null);
114                                 }
115                         }               
116                 }
117
118                 public override PropertyDescriptorCollection GetItemProperties ()
119                 {
120                         ITypedList typed = list as ITypedList;
121
122                         if (list is Array) {
123                                 Type element = list.GetType ().GetElementType ();
124                                 return TypeDescriptor.GetProperties (element);
125                         }
126
127                         if (typed != null) {
128                                 return typed.GetItemProperties (null);
129                         }
130
131                         PropertyInfo [] props = finalType.GetProperties ();
132                         for (int i = 0; i < props.Length; i++) {
133                                 if (props [i].Name == "Item") {
134                                         Type t = props [i].PropertyType;
135                                         if (t == typeof (object))
136                                                 continue;
137                                         return GetBrowsableProperties (t);
138                                 }
139                         }
140
141                         if (list.Count > 0) {
142                                 return GetBrowsableProperties (list [0].GetType ());
143                         }
144                         
145                         return new PropertyDescriptorCollection (null);
146                 }
147
148                 public override void RemoveAt (int index)
149                 {
150                         list.RemoveAt (index);
151                 }
152
153                 public override void SuspendBinding ()
154                 {
155                         binding_suspended = true;
156                 }
157                 
158                 public override void ResumeBinding ()
159                 {
160                         binding_suspended = false;
161                 }
162
163                 internal override bool IsSuspended {
164                         get { return binding_suspended; }
165                 }
166                 
167                 internal bool CanAddRows {
168                         get {
169                                 if (list as IBindingList == null) {
170                                         return false;
171                                 }
172                                 
173                                 return true;
174                         }
175                 }
176
177                 public override void AddNew ()
178                 {
179                         if (list as IBindingList == null)
180                                 throw new NotSupportedException ();
181                                 
182                         (list as IBindingList).AddNew ();
183                 }
184
185                 public override void CancelCurrentEdit ()
186                 {
187                         IEditableObject editable = Current as IEditableObject;
188
189                         if (editable == null)
190                                 return;
191                         editable.CancelEdit ();
192                         OnItemChanged (new ItemChangedEventArgs (Position));
193                 }
194                 
195                 public override void EndCurrentEdit ()
196                 {
197                         IEditableObject editable = Current as IEditableObject;
198
199                         if (editable == null)
200                                 return;
201                         editable.EndEdit ();
202                 }
203
204                 public void Refresh ()
205                 {
206                         PullData ();
207                 }
208
209                 [MonoTODO ("This is just a guess, as I can't figure out how to test this method")]
210                 protected void CheckEmpty ()
211                 {
212                         if (list == null || list.Count < 1)
213                                 throw new Exception ("List is empty.");
214                                 
215                 }
216
217                 protected internal override void OnCurrentChanged (EventArgs e)
218                 {
219                         PullData ();
220
221                         if (onCurrentChangedHandler != null) {
222                                 onCurrentChangedHandler (this, e);
223                         }
224                 }
225
226                 protected virtual void OnItemChanged (ItemChangedEventArgs e)
227                 {
228                         PushData ();
229
230                         if (ItemChanged != null)
231                                 ItemChanged (this, e);
232                 }
233
234                 protected virtual void OnPositionChanged (EventArgs e)
235                 {
236                         if (onPositionChangedHandler == null)
237                                 return;
238                         onPositionChangedHandler (this, e);
239                 }
240
241                 protected internal override string GetListName (ArrayList accessors)
242                 {
243                         if (list is ITypedList) {
244                                 PropertyDescriptor [] pds;
245                                 pds = new PropertyDescriptor [accessors.Count];
246                                 accessors.CopyTo (pds, 0);
247                                 return ((ITypedList) list).GetListName (pds);
248                         }
249                         return String.Empty;
250                 }
251
252                 [MonoTODO ("Not totally sure how this works, its doesn't seemt to do a pull/push like i originally assumed")]
253                 protected override void UpdateIsBinding ()
254                 {
255                         UpdateItem ();
256
257                         foreach (Binding binding in Bindings)
258                                 binding.UpdateIsBinding ();
259                 }
260
261                 private void UpdateItem ()
262                 {
263                         // Probably should be validating or something here
264                         EndCurrentEdit ();
265                 }
266                 
267                 internal object GetItem (int index)
268                 {
269                         return list [index];
270                 }               
271                 
272                 private PropertyDescriptorCollection GetBrowsableProperties (Type t)
273                 {
274                         Attribute [] att = new System.Attribute [1];
275                         att [0] = new BrowsableAttribute (true);
276                         return TypeDescriptor.GetProperties (t, att);
277                 }
278
279                 private void MetaDataChangedHandler (object sender, CollectionChangeEventArgs e)
280                 {
281                         if (MetaDataChanged != null)
282                                 MetaDataChanged (this, EventArgs.Empty);
283                 }
284
285                 public event ItemChangedEventHandler ItemChanged;
286                 public event EventHandler MetaDataChanged;
287         }
288 }
289