2005-06-06 Peter Bartok <pbartok@novell.com>
[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.Reflection;
28 using System.Collections;
29 using System.ComponentModel;
30
31 namespace System.Windows.Forms {
32         [DefaultMember("Item")]
33         public class CurrencyManager : BindingManagerBase {
34
35                 protected Type finalType;
36                 protected int listposition;
37
38                 private IList list;
39                 private IBindingList binding_list;
40
41                 private bool binding_suspended;
42
43                 internal CurrencyManager (object data_source)
44                 {
45                         binding_list = data_source as IBindingList;
46                         if (data_source is IListSource) {
47                                 list = ((IListSource) data_source).GetList ();
48                         } else if (data_source is IList) {
49                                 list = (IList) data_source;
50                         } else {
51                                 throw new Exception ("Attempted to create currency manager " +
52                                         "from invalid type: " + data_source.GetType ());
53                         }
54
55                         if (data_source as ArrayList != null) {
56                                 finalType = ((ArrayList)data_source).GetType ();
57                         } else {
58                                 if (data_source as Array != null) {
59                                         finalType = ((Array) data_source).GetType ();
60                                 } else {
61                                         finalType = null;
62                                 }
63                         }
64                 }               
65
66                 public IList List {
67                         get { return list; }
68                 }
69
70                 public override object Current {
71                         get {
72                                 return list [listposition];
73                         }
74                 }
75
76                 public override int Count {
77                         get { return list.Count; }
78                 }
79
80                 public override int Position {
81                         get {
82                                 return listposition;
83                         } 
84                         set {
85                                 if (value < 0)
86                                         value = 0;
87                                 if (value == list.Count)
88                                         value = list.Count - 1;
89                                 if (listposition == value)
90                                         return;
91                                 listposition = value;
92                                 OnCurrentChanged (EventArgs.Empty);
93                                 OnPositionChanged (EventArgs.Empty);
94                         }
95                 }
96
97                 public override PropertyDescriptorCollection GetItemProperties ()
98                 {
99                         ITypedList typed = list as ITypedList;
100
101                         if (list is Array) {
102                                 Type element = list.GetType ().GetElementType ();
103                                 return TypeDescriptor.GetProperties (element);
104                         }
105
106                         if (typed != null) {
107                                 return typed.GetItemProperties (null);
108                         }
109
110                         PropertyInfo [] props = finalType.GetProperties ();
111                         for (int i = 0; i < props.Length; i++) {
112                                 if (props [i].Name == "Item") {
113                                         Type t = props [i].PropertyType;
114                                         if (t == typeof (object))
115                                                 continue;
116                                         return GetBrowsableProperties (t);
117                                 }
118                         }
119
120                         if (list.Count > 0) {
121                                 return GetBrowsableProperties (list [0].GetType ());
122                         }
123                         
124                         return new PropertyDescriptorCollection (null);
125                 }
126
127                 public override void RemoveAt (int index)
128                 {
129                         list.RemoveAt (index);
130                 }
131
132                 public override void SuspendBinding ()
133                 {
134                         binding_suspended = true;
135                 }
136                 
137                 public override void ResumeBinding ()
138                 {
139                         binding_suspended = false;
140                 }
141
142                 internal override bool IsSuspended {
143                         get { return binding_suspended; }
144                 }
145
146                 public override void AddNew ()
147                 {
148                         if (binding_list == null)
149                                 throw new NotSupportedException ();
150                         binding_list.AddNew ();
151                 }
152
153                 public override void CancelCurrentEdit ()
154                 {
155                         IEditableObject editable = Current as IEditableObject;
156
157                         if (editable == null)
158                                 return;
159                         editable.CancelEdit ();
160                         OnItemChanged (new ItemChangedEventArgs (Position));
161                 }
162                 
163                 public override void EndCurrentEdit ()
164                 {
165                         IEditableObject editable = Current as IEditableObject;
166
167                         if (editable == null)
168                                 return;
169                         editable.EndEdit ();
170                 }
171
172                 protected internal override void OnCurrentChanged (EventArgs e)
173                 {
174                         PullData ();
175
176                         if (onCurrentChangedHandler != null) {
177                                 onCurrentChangedHandler (this, e);
178                         }
179                 }
180
181                 protected virtual void OnItemChanged (ItemChangedEventArgs e)
182                 {
183                         PushData ();
184
185                         if (ItemChanged != null)
186                                 ItemChanged (this, e);
187                 }
188
189                 protected virtual void OnPositionChanged (EventArgs e)
190                 {
191                         if (onPositionChangedHandler == null)
192                                 return;
193                         onPositionChangedHandler (this, e);
194                 }
195
196                 protected internal override string GetListName (ArrayList accessors)
197                 {
198                         if (list is ITypedList) {
199                                 PropertyDescriptor [] pds;
200                                 pds = new PropertyDescriptor [accessors.Count];
201                                 accessors.CopyTo (pds, 0);
202                                 return ((ITypedList) list).GetListName (pds);
203                         }
204                         return String.Empty;
205                 }
206
207                 [MonoTODO ("Not totally sure how this works, its doesn't seemt to do a pull/push like i originally assumed")]
208                 protected override void UpdateIsBinding ()
209                 {
210                         UpdateItem ();
211
212                         foreach (Binding binding in Bindings)
213                                 binding.UpdateIsBinding ();
214                 }
215
216                 private void UpdateItem ()
217                 {
218                         // Probably should be validating or something here
219                         EndCurrentEdit ();
220                 }
221                 
222                 internal object GetItem (int index)
223                 {
224                         return list [index];
225                 }
226
227                 private PropertyDescriptorCollection GetBrowsableProperties (Type t)
228                 {
229                         Attribute [] att = new System.Attribute [1];
230                         att [0] = new BrowsableAttribute (true);
231                         return TypeDescriptor.GetProperties (t, att);
232                 }
233
234                 public event ItemChangedEventHandler ItemChanged;
235         }
236 }
237