* TreeView.cs: Don't draw the selected node when we lose
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ListControl.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 //      Jordi Mas i Hernandez, jordi@ximian.com
24 //
25 //
26
27 // COMPLETE
28
29 using System;
30 using System.Drawing;
31 using System.Collections;
32 using System.ComponentModel;
33 using System.Reflection;
34
35 namespace System.Windows.Forms
36 {
37         public abstract class ListControl : Control
38         {
39                 private object data_source;
40                 private BindingMemberInfo value_member;
41                 private string display_member;
42                 private CurrencyManager data_manager;
43
44                 protected ListControl ()
45                 {                       
46                         data_source = null;
47                         value_member = new BindingMemberInfo (string.Empty);
48                         display_member = string.Empty;
49                         data_manager = null;
50                         SetStyle (ControlStyles.StandardClick | ControlStyles.UserPaint, false);
51                 }
52
53                 #region Events
54                 public event EventHandler DataSourceChanged;
55                 public event EventHandler DisplayMemberChanged;
56                 public event EventHandler SelectedValueChanged;
57                 public event EventHandler ValueMemberChanged;
58                 #endregion // Events
59
60                 #region Public Properties
61
62                 [DefaultValue(null)]
63                 [RefreshProperties(RefreshProperties.Repaint)]
64                 [TypeConverter("System.Windows.Forms.Design.DataSourceConverter, " + Consts.AssemblySystem_Design)]
65                 public object DataSource {
66                         get { return data_source; }
67                         set {
68                                 if (!(value is IList || value is IListSource)) {
69                                         throw new Exception ("Complex DataBinding accepts as a data source " +
70                                                         "either an IList or an IListSource");
71                                 }
72
73                                 if (data_source == value)
74                                         return;
75
76                                 data_source = value;
77                                 ConnectToDataSource ();
78                                 OnDataSourceChanged (EventArgs.Empty);
79                         }
80                 }
81
82                 [DefaultValue("")]
83                 [Editor("System.Windows.Forms.Design.DataMemberFieldEditor, " + Consts.AssemblySystem_Design, typeof(System.Drawing.Design.UITypeEditor))]
84                 [TypeConverter("System.Windows.Forms.Design.DataMemberFieldConverter, " + Consts.AssemblySystem_Design)]
85                 public string DisplayMember {
86                         get { 
87                                 return display_member;                          
88                         }
89                         set {
90                                 if (display_member == value) {
91                                         return;
92                                 }
93
94                                 display_member = value;
95                                 ConnectToDataSource ();                         
96                                 OnDisplayMemberChanged (EventArgs.Empty);
97                         }
98                 }
99
100                 public abstract int SelectedIndex {
101                         get;
102                         set;
103                 }
104
105                 [Bindable(BindableSupport.Yes)]
106                 [Browsable(false)]
107                 [DefaultValue(null)]
108                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
109                 public object SelectedValue {
110                         get {
111                                 if (data_manager == null) {
112                                         return null;
113                                 }                               
114                                 
115                                 object item = data_manager.GetItem (SelectedIndex);
116                                 object fil = FilterItemOnProperty (item, ValueMember);
117                                 return fil;
118                         }
119                         set {
120                                 if (data_manager != null) {
121                                         
122                                         PropertyDescriptorCollection col = data_manager.GetItemProperties ();
123                                         PropertyDescriptor prop = col.Find (ValueMember, true);
124                                                                                 
125                                         for (int i = 0; i < data_manager.Count; i++) {
126                                                  if (prop.GetValue (data_manager.GetItem (i)) == value) {
127                                                         SelectedIndex = i;
128                                                         return;
129                                                 }
130                                         }
131                                         
132                                 }
133                         }
134                 }
135
136                 [DefaultValue("")]
137                 [Editor("System.Windows.Forms.Design.DataMemberFieldEditor, " + Consts.AssemblySystem_Design, typeof(System.Drawing.Design.UITypeEditor))]
138                 public string ValueMember  {
139                         get { return value_member.BindingMember; }
140                         set {
141                                 BindingMemberInfo new_value = new BindingMemberInfo (value);
142                                 
143                                 if (value_member.Equals (new_value)) {
144                                         return;
145                                 }
146                                 
147                                 value_member = new_value;
148                                 
149                                 if (display_member == string.Empty) {
150                                         DisplayMember = value_member.BindingMember;                                     
151                                 }
152                                 
153                                 ConnectToDataSource ();
154                                 OnValueMemberChanged (EventArgs.Empty);
155                         }
156                 }
157
158                 #endregion Public Properties
159
160                 #region Public Methods
161
162                 protected object FilterItemOnProperty (object item)
163                 {
164                         return FilterItemOnProperty (item, string.Empty);
165                 }
166
167                 protected object FilterItemOnProperty (object item, string field)
168                 {
169                         if (item == null)
170                                 return null;
171
172                         if (field == null || field == string.Empty)
173                                 return item;
174
175                         PropertyDescriptor prop = null;
176
177                         if (data_manager != null) {
178                                 PropertyDescriptorCollection col = data_manager.GetItemProperties ();
179                                 prop = col.Find (field, true);                          
180                         }
181                         
182                         if (prop == null)
183                                 return item;
184                         
185                         return prop.GetValue (item);
186                 }
187
188                 public string GetItemText (object item)
189                 {
190                         if (data_manager != null) {
191                                 object fil = FilterItemOnProperty (item, DisplayMember);
192                                 if (fil != null) {
193                                         return fil.ToString ();
194                                 }
195                         }
196                                                                 
197                         return item.ToString ();                        
198                 }
199
200                 protected CurrencyManager DataManager {
201                         get { return data_manager; }
202                 }
203
204                 // Used only by ListBox to avoid to break Listbox's member signature
205                 protected override bool IsInputKey (Keys keyData)
206                 {
207                         switch (keyData) {
208                         case Keys.Up:
209                         case Keys.Down:
210                         case Keys.PageUp:
211                         case Keys.PageDown:
212                         case Keys.Right:
213                         case Keys.Left:
214                         case Keys.End:
215                         case Keys.Home:
216                         case Keys.ControlKey:
217                         case Keys.Space:
218                         case Keys.ShiftKey:
219                                 return true;
220
221                         default:
222                                 return false;
223                         }
224                 }
225
226                 protected override void OnBindingContextChanged (EventArgs e)
227                 {
228                         base.OnBindingContextChanged (e);
229                         ConnectToDataSource ();
230
231                         if (DataManager != null) {
232                                 SetItemsCore (DataManager.List);
233                                 SelectedIndex = DataManager.Position;
234                         }
235                 }
236
237                 protected virtual void OnDataSourceChanged (EventArgs e)
238                 {
239                         if (DataSourceChanged != null)
240                                 DataSourceChanged (this,e);
241                 }
242
243                 protected virtual void OnDisplayMemberChanged (EventArgs e)
244                 {
245                         if (DisplayMemberChanged != null)
246                                 DisplayMemberChanged (this, e);
247                 }
248
249                 protected virtual void OnSelectedIndexChanged (EventArgs e)
250                 {
251                         if (data_manager == null)
252                                 return;
253                         if (data_manager.Position == SelectedIndex)
254                                 return;
255                         data_manager.Position = SelectedIndex;
256                 }
257
258                 protected virtual void OnSelectedValueChanged (EventArgs e)
259                 {
260                         if (SelectedValueChanged != null)
261                                 SelectedValueChanged (this, e);
262                 }
263
264                 protected virtual void OnValueMemberChanged (EventArgs e)
265                 {
266                         if (ValueMemberChanged != null)
267                                 ValueMemberChanged (this, e);
268                 }
269
270                 protected abstract void RefreshItem (int index);
271
272                 protected virtual void SetItemCore (int index,  object value)
273                 {
274
275                 }
276
277                 protected abstract void SetItemsCore (IList items);
278                 
279                 #endregion Public Methods
280                 
281                 #region Private Methods
282
283                 internal void BindDataItems (IList items)
284                 {
285                         items.Clear ();
286
287                         if (data_manager != null) {
288                                 SetItemsCore (data_manager.List);
289                         }
290                 }
291
292                 private void ConnectToDataSource ()
293                 {
294                         if (data_source == null) {
295                                 data_manager = null;
296                                 return;
297                         }
298
299                         if (BindingContext == null) {
300                                 return;
301                         }
302                         
303                         data_manager = (CurrencyManager) BindingContext [data_source];
304                         data_manager.PositionChanged += new EventHandler (OnPositionChanged);
305                 }               
306                 
307                 private void OnPositionChanged (object sender, EventArgs e)
308                 {                       
309                         SelectedIndex = data_manager.Position;
310                 }
311
312                 #endregion Private Methods      
313         }
314
315 }
316