2008-04-21 Jonathan Pobst <monkey@jpobst.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / DataGridViewComboBoxCell.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.Collections;
30 using System.ComponentModel;
31 using System.Drawing;
32
33 namespace System.Windows.Forms {
34
35         public class DataGridViewComboBoxCell : DataGridViewCell {
36
37                 private bool autoComplete;
38                 private object dataSource;
39                 private string displayMember;
40                 private DataGridViewComboBoxDisplayStyle displayStyle;
41                 private bool displayStyleForCurrentCellOnly;
42                 private int dropDownWidth;
43                 private FlatStyle flatStyle;
44                 private ObjectCollection items;
45                 private int maxDropDownItems;
46                 private bool sorted;
47                 private string valueMember;
48
49                 private DataGridViewComboBoxEditingControl editingControl;
50
51                 public DataGridViewComboBoxCell () : base() {
52                         autoComplete = true;
53                         dataSource = null;
54                         displayStyle = DataGridViewComboBoxDisplayStyle.DropDownButton;
55                         displayStyleForCurrentCellOnly = false;
56                         dropDownWidth = 1;
57                         flatStyle = FlatStyle.Standard;
58                         items = new ObjectCollection(this);
59                         maxDropDownItems = 8;
60                         sorted = false;
61                 }
62
63                 [DefaultValue (true)]
64                 public virtual bool AutoComplete {
65                         get { return autoComplete; }
66                         set { autoComplete = value; }
67                 }
68
69                 public virtual object DataSource {
70                         get { return dataSource; }
71                         set {
72                                 if (value is IList || value is IListSource || value == null) {
73                                         dataSource = value;
74                                         return;
75                                 }
76                                 throw new Exception("Value is no IList, IListSource or null.");
77                         }
78                 }
79
80                 [DefaultValue ("")]
81                 public virtual string DisplayMember {
82                         get { return displayMember; }
83                         set { displayMember = value; }
84                 }
85
86                 [DefaultValue (DataGridViewComboBoxDisplayStyle.DropDownButton)]
87                 public DataGridViewComboBoxDisplayStyle DisplayStyle {
88                         get { return displayStyle; }
89                         set { displayStyle = value; }
90                 }
91
92                 [DefaultValue (false)]
93                 public bool DisplayStyleForCurrentCellOnly {
94                         get { return displayStyleForCurrentCellOnly; }
95                         set { displayStyleForCurrentCellOnly = value; }
96                 }
97
98                 [DefaultValue (1)]
99                 public virtual int DropDownWidth {
100                         get { return dropDownWidth; }
101                         set {
102                                 if (value < 1) {
103                                         throw new ArgumentOutOfRangeException("Value is less than 1.");
104                                 }
105                                 dropDownWidth = value;
106                         }
107                 }
108
109                 public override Type EditType {
110                         get { return typeof(DataGridViewComboBoxEditingControl); }
111                 }
112
113                 [DefaultValue (FlatStyle.Standard)]
114                 public FlatStyle FlatStyle {
115                         get { return flatStyle; }
116                         set {
117                                 if (!Enum.IsDefined(typeof(FlatStyle), value)) {
118                                         throw new InvalidEnumArgumentException("Value is not valid FlatStyle.");
119                                 }
120                                 flatStyle = value;
121                         }
122                 }
123
124                 public override Type FormattedValueType {
125                         get { return typeof(string); }
126                 }
127
128                 [Browsable (false)]
129                 public virtual ObjectCollection Items {
130                         get { return items; }
131                 }
132
133                 [DefaultValue (8)]
134                 public virtual int MaxDropDownItems {
135                         get { return maxDropDownItems; }
136                         set {
137                                 if (value < 1 || value > 100) {
138                                         throw new ArgumentOutOfRangeException("Value is less than 1 or greater than 100.");
139                                 }
140                                 maxDropDownItems = value;
141                         }
142                 }
143
144                 [DefaultValue (false)]
145                 public virtual bool Sorted {
146                         get { return sorted; }
147                         set {
148                                 /*
149                                 if () {
150                                         throw new ArgumentException("Cannot sort a cell attached to a data source.");
151                                 }
152                                 */
153                                 sorted = value;
154                         }
155                 }
156
157                 [DefaultValue ("")]
158                 public virtual string ValueMember {
159                         get { return valueMember; }
160                         set { valueMember = value; }
161                 }
162
163                 public override Type ValueType {
164                         get { return typeof(string); }
165                 }
166
167                 public override object Clone () {
168                         DataGridViewComboBoxCell cell = (DataGridViewComboBoxCell) base.Clone();
169                         cell.autoComplete = this.autoComplete;
170                         cell.dataSource = this.dataSource;
171                         cell.displayStyle = this.displayStyle;
172                         cell.displayStyleForCurrentCellOnly = this.displayStyleForCurrentCellOnly;
173                         cell.dropDownWidth = this.dropDownWidth;
174                         cell.flatStyle = this.flatStyle;
175                         cell.items.AddRange(this.items);
176                         cell.maxDropDownItems = this.maxDropDownItems;
177                         cell.sorted = this.sorted;
178                         return cell;
179                 }
180
181                 public override void DetachEditingControl () {
182                         this.DataGridView.EditingControlInternal = null;
183                 }
184
185                 public override void InitializeEditingControl (int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle) {
186                         base.InitializeEditingControl (rowIndex, initialFormattedValue, dataGridViewCellStyle);
187                         
188                         editingControl = DataGridView.EditingControl as DataGridViewComboBoxEditingControl;
189                         
190                         if (editingControl == null)
191                                 return;
192                         
193                         // A simple way to check if the control has
194                         // been initialized already.
195                         if (editingControl.Items.Count > 0)
196                                 return;
197                         
198                         editingControl.DropDownStyle = ComboBoxStyle.DropDownList;
199                         editingControl.Text = initialFormattedValue == null ? string.Empty : initialFormattedValue.ToString ();
200                         editingControl.SelectedIndexChanged += new EventHandler (editingControl_SelectedIndexChanged);
201                         editingControl.Items.Clear ();
202                         editingControl.Items.AddRange (this.Items);             
203                 }
204
205                 void editingControl_SelectedIndexChanged (object sender, EventArgs e)
206                 {
207                         Value = editingControl.SelectedItem;
208                 }
209
210                 public override bool KeyEntersEditMode (KeyEventArgs e) {
211                         throw new NotImplementedException();
212                 }
213
214                 public override object ParseFormattedValue (object formattedValue, DataGridViewCellStyle cellStyle, TypeConverter formattedValueTypeConverter, TypeConverter valueTypeConverter) {
215                         throw new NotImplementedException();
216                 }
217
218                 public override string ToString () {
219                         return string.Format ("DataGridViewComboBoxCell {{ ColumnIndex={0}, RowIndex={1} }}", ColumnIndex, RowIndex);
220                 }
221
222                 protected override Rectangle GetContentBounds (Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex) {
223                         throw new NotImplementedException();
224                 }
225
226                 protected override Rectangle GetErrorIconBounds (Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex)
227                 {
228                         if (DataGridView == null || string.IsNullOrEmpty (ErrorText))
229                                 return Rectangle.Empty;
230
231                         Size error_icon = new Size (12, 11);
232                         return new Rectangle (new Point (Size.Width - error_icon.Width - 23, (Size.Height - error_icon.Height) / 2), error_icon);
233                 }
234
235                 protected override object GetFormattedValue (object value, int rowIndex, ref DataGridViewCellStyle cellStyle, TypeConverter valueTypeConverter, TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context) {
236                         throw new NotImplementedException();
237                 }
238
239                 protected override Size GetPreferredSize (Graphics graphics, DataGridViewCellStyle cellStyle, int rowIndex, Size constraintSize) {
240                         throw new NotImplementedException();
241                 }
242
243                 protected override void OnDataGridViewChanged () {
244                         // Here we're supposed to do something with DataSource, etc, according to MSDN.
245                         base.OnDataGridViewChanged ();
246                 }
247
248                 protected override void OnEnter (int rowIndex, bool throughMouseClick) {
249                         base.OnEnter (rowIndex, throughMouseClick);
250                 }
251
252                 protected override void OnLeave (int rowIndex, bool throughMouseClick) {
253                         base.OnLeave (rowIndex, throughMouseClick);
254                 }
255
256                 protected override void OnMouseClick (DataGridViewCellMouseEventArgs e) {
257                         base.OnMouseClick (e);
258                 }
259
260                 protected override void OnMouseEnter (int rowIndex) {
261                         base.OnMouseEnter (rowIndex);
262                 }
263
264                 protected override void OnMouseLeave (int rowIndex) {
265                         base.OnMouseLeave (rowIndex);
266                 }
267
268                 protected override void OnMouseMove (DataGridViewCellMouseEventArgs e) {
269                         //Console.WriteLine ("MouseMove (Location: {0}", e.Location);
270                         base.OnMouseMove (e);
271                 }
272
273                 protected override void Paint (Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, 
274                                 int rowIndex, DataGridViewElementStates elementState, object value, 
275                                 object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, 
276                                 DataGridViewPaintParts paintParts) {
277                         
278                         
279                         Rectangle button_area, text_area;
280                         text_area = cellBounds;
281                         button_area = CalculateButtonArea (cellBounds);
282                         
283                         graphics.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (cellStyle.BackColor), cellBounds);
284                         ThemeEngine.Current.CPDrawComboButton (graphics, button_area, ButtonState.Normal);
285                         
286                         string text;
287                         if (formattedValue == null)
288                                 text = string.Empty;
289                         else {
290                                 text = formattedValue.ToString ();
291                         }
292                         
293                         graphics.DrawString (text, cellStyle.Font, ThemeEngine.Current.ResPool.GetSolidBrush (cellStyle.ForeColor), text_area, StringFormat.GenericTypographic);
294                 }
295
296                 private Rectangle CalculateButtonArea (Rectangle cellBounds)
297                 {
298                         Rectangle button_area, text_area;
299                         int border = ThemeEngine.Current.Border3DSize.Width;
300                         const int button_width = 16;
301
302                         text_area = cellBounds;
303
304                         button_area = cellBounds;
305                         button_area.X = text_area.Right - button_width - border;
306                         button_area.Y = text_area.Y + border;
307                         button_area.Width = button_width;
308                         button_area.Height = text_area.Height - 2 * border;
309                         
310                         return button_area;
311                 }
312
313                 [ListBindable (false)]
314                 public class ObjectCollection : IList, ICollection, IEnumerable {
315
316                         private ArrayList list;
317
318                         //private DataGridViewComboBoxCell owner;
319
320                         public ObjectCollection (DataGridViewComboBoxCell owner) {
321                                 //this.owner = owner;
322                                 list = new ArrayList();
323                         }
324
325                         public int Count {
326                                 get { return list.Count; }
327                         }
328
329                         bool IList.IsFixedSize {
330                                 get { return list.IsFixedSize; }
331                         }
332
333                         public bool IsReadOnly {
334                                 get { return list.IsReadOnly; }
335                         }
336
337                         bool ICollection.IsSynchronized {
338                                 get { return list.IsSynchronized; }
339                         }
340
341                         object ICollection.SyncRoot {
342                                 get { return list.SyncRoot; }
343                         }
344
345                         public virtual object this [int index] {
346                                 get { return list[index]; }
347                                 set { list[index] = value; }
348                         }
349
350                         public int Add (object item) {
351                                 return list.Add(item);
352                         }
353
354                         public void AddRange (ObjectCollection value) {
355                                 list.AddRange(value.list);
356                         }
357
358                         public void AddRange (params object[] items) {
359                                 list.AddRange(items);
360                         }
361
362                         public void Clear () {
363                                 list.Clear();
364                         }
365
366                         public bool Contains (object value) {
367                                 return list.Contains(value);
368                         }
369
370                         void ICollection.CopyTo (Array destination, int index)
371                         {
372                                 CopyTo ((object[]) destination, index);
373                         }
374
375                         public void CopyTo (object[] destination, int arrayIndex)
376                         {
377                                 list.CopyTo (destination, arrayIndex);
378                         }
379
380                         public IEnumerator GetEnumerator () {
381                                 return list.GetEnumerator();
382                         }
383
384                         public int IndexOf (object value) {
385                                 return list.IndexOf(value);
386                         }
387
388                         public void Insert (int index, object item) {
389                                 list.Insert(index, item);
390                         }
391
392                         public void Remove (object value) {
393                                 list.Remove(value);
394                         }
395
396                         public void RemoveAt (int index) {
397                                 list.RemoveAt(index);
398                         }
399
400
401                         int IList.Add (object item)
402                         {
403                                 return Add (item);
404                         }
405
406                 }
407
408         }
409
410 }
411
412 #endif