merge -r 53370:58178
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / BindingContext.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) 2004-2005 Novell, Inc.
21 //
22 // Authors:
23 //      Peter Bartok    pbartok@novell.com
24 //      Jackson Harper  jackson@ximian.com
25
26
27 using System.Collections;
28 using System.Globalization;
29 using System.ComponentModel;
30
31
32 namespace System.Windows.Forms {
33
34         [DefaultEvent("CollectionChanged")]
35         public class BindingContext : ICollection, IEnumerable {
36
37                 private Hashtable managers;
38
39                 private class ManagerEntry {
40
41                         private object source;
42                         private WeakReference member_ref;
43                         
44                         private int member_hash;
45
46                         public ManagerEntry (object source, string member)
47                         {
48                                 this.source = source;
49                                 if (member == null)
50                                         member = String.Empty;
51                                 
52                                 member_hash = member.ToLower (CultureInfo.InvariantCulture).GetHashCode ();
53                                 if (member_hash == 0)
54                                         member_hash = 1;
55                                 member_ref = new WeakReference (member, false);
56                         }
57
58                         public override bool Equals (object b)
59                         {
60                                 ManagerEntry o = (ManagerEntry) b;
61
62                                 return (o.source == source && o.member_ref.Target == member_ref.Target);
63                         }
64
65                         public override int GetHashCode ()
66                         {
67                                 return member_hash * source.GetHashCode ();
68                         }
69
70                         public override string ToString ()
71                         {
72                                 return source.ToString () + " + " + (member_ref.Target == null ? " -- null --" : member_ref.Target.ToString ());
73                         }
74                 }
75
76                 public BindingContext () 
77                 {
78                         managers = new Hashtable ();
79                 }
80
81                 public bool IsReadOnly {
82                         get {
83                                 return false;
84                         }
85                 }
86
87                 public BindingManagerBase this [object dataSource] {
88                         get {
89                                 return this [dataSource, String.Empty];
90                         }
91                 }
92
93                 public BindingManagerBase this [object data_source, string data_member] {
94                         get {
95                                 ManagerEntry e = CreateEntry (data_source, data_member);
96                                 WeakReference wref = managers [e] as WeakReference;
97
98                                 if (wref != null && wref.Target != null)
99                                         return wref.Target as BindingManagerBase;
100                                 BindingManagerBase res = AddManager (data_source, data_member);
101                                 return res;
102                         }
103                 }
104
105                 private BindingManagerBase AddManager (object data_source, string data_member)
106                 {
107                         BindingManagerBase res = CreateBindingManager (data_source, data_member);
108                         managers [CreateEntry (data_source, data_member)] = new WeakReference (res);
109
110                         return res;
111                 }
112
113                 private BindingManagerBase CreateBindingManager (object data_source, 
114                         string data_member)
115                 {
116                         if (data_source is IList || 
117                                 data_source is IListSource ||
118                                 data_source is IBindingList) {
119                                 CurrencyManager res = new CurrencyManager (data_source);
120                                 return res;
121                         }
122
123                         return new PropertyManager (data_source, data_member);
124                 }
125
126                 #region Public Instance Methods
127                 public bool Contains(object dataSource)
128                 {
129                         return Contains (dataSource, String.Empty);
130                 }
131
132                 public bool Contains (object dataSource, string dataMember)
133                 {
134                         ManagerEntry entry = CreateEntry (dataSource, dataMember);
135
136                         return managers.ContainsKey (entry);
137                 }
138                 #endregion      // Public Instance Methods
139
140                 #region Protected Instance Methods
141
142                 protected internal void Add (object dataSource, BindingManagerBase listManager)
143                 {
144                         AddCore (dataSource, listManager);
145                         OnCollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, dataSource));
146                 }
147
148                 protected virtual void AddCore (object dataSource, BindingManagerBase listManager)
149                 {
150                         if (dataSource == null)
151                                 throw new ArgumentNullException ("dataSource");
152                         if (listManager == null)
153                                 throw new ArgumentNullException ("listManager");
154                         managers.Add (CreateEntry (dataSource, String.Empty), new WeakReference (listManager));
155                 }
156
157                 protected internal void Clear ()
158                 {
159                         ClearCore();
160                         OnCollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Refresh, null));
161                 }
162
163                 protected virtual void ClearCore ()
164                 {
165                         managers.Clear ();
166                 }
167
168                 protected virtual void OnCollectionChanged(System.ComponentModel.CollectionChangeEventArgs ccevent)
169                 {
170                         if (CollectionChanged != null) {
171                                 CollectionChanged (this, ccevent);
172                         }
173                 }
174
175                 protected internal void Remove (object dataSource)
176                 {
177                         RemoveCore (dataSource);
178                         OnCollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, dataSource));
179                 }
180
181                 protected virtual void RemoveCore (object dataSource)
182                 {
183                         managers.Remove (CreateEntry (dataSource, String.Empty));
184                 }
185                 #endregion      // Protected Instance Methods
186
187                 #region Events
188                 public event CollectionChangeEventHandler CollectionChanged;
189                 #endregion      // Events
190
191                 #region ICollection Interfaces
192                 void ICollection.CopyTo (Array array, int index)
193                 {
194                         managers.CopyTo (array, index);
195                 }
196
197                 int ICollection.Count {
198                         get {
199                                 return managers.Count;
200                         }
201                 }
202
203                 bool ICollection.IsSynchronized {
204                         get {
205                                 return false;
206                         }
207                 }
208
209                 object ICollection.SyncRoot {
210                         get {
211                                 return null;
212                         }
213                 }
214
215                 #endregion      // ICollection Interfaces
216
217                 #region IEnumerable Interfaces
218                 [MonoTODO]
219                 IEnumerator IEnumerable.GetEnumerator() {
220                         throw new NotImplementedException();
221                 }
222                 #endregion      // IEnumerable Interfaces
223
224                 private ManagerEntry CreateEntry (object dataSource, string dataMember)
225                 {
226                         return new ManagerEntry (dataSource, dataMember);
227                 }
228         }
229 }