Fix bug #395
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / DataGridColumnStyle.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 //      Jordi Mas i Hernandez <jordi@ximian.com>
24 //      Chris Toshok <toshok@ximian.com>
25 //
26
27 using System.Drawing;
28 using System.ComponentModel;
29 using System.Runtime.InteropServices;
30 using System.Diagnostics;
31
32 namespace System.Windows.Forms
33 {
34         [DesignTimeVisible(false)]
35         [DefaultProperty("Header")]
36         [ToolboxItem(false)]
37         public abstract class DataGridColumnStyle : Component, IDataGridColumnStyleEditingNotificationService
38         {
39                 [ComVisible(true)]
40                 protected class DataGridColumnHeaderAccessibleObject : AccessibleObject
41                 {
42                         #region Local Variables
43                         private new DataGridColumnStyle owner;
44                         #endregion
45
46                         #region Constructors
47                         public DataGridColumnHeaderAccessibleObject ()
48                         {
49                         }
50                         public DataGridColumnHeaderAccessibleObject (DataGridColumnStyle owner)
51                         {
52                                 this.owner = owner;
53                         }
54                         #endregion //Constructors
55
56                         #region Public Instance Properties
57                         [MonoTODO ("Not implemented, will throw NotImplementedException")]
58                         public override Rectangle Bounds {
59                                 get {
60                                         throw new NotImplementedException ();
61                                 }
62                         }
63
64                         public override string Name {
65                                 get {
66                                         throw new NotImplementedException ();
67                                 }
68                         }
69
70                         protected DataGridColumnStyle Owner {
71                                 get { return owner; }
72                         }
73
74                         public override AccessibleObject Parent {
75                                 get {
76                                         throw new NotImplementedException ();
77                                 }
78                         }
79
80                         public override AccessibleRole Role {
81                                 get {
82                                         throw new NotImplementedException ();
83                                 }
84                         }
85                         #endregion
86
87                         #region Public Instance Methods
88                         [MonoTODO ("Not implemented, will throw NotImplementedException")]
89                         public override AccessibleObject Navigate (AccessibleNavigation navdir)
90                         {
91                                 throw new NotImplementedException ();
92                         }
93                         #endregion Public Instance Methods
94                 }
95
96                 protected class CompModSwitches
97                 {
98                         public CompModSwitches ()
99                         {
100                         }
101
102                         #region Public Instance Methods
103                         [MonoTODO ("Not implemented, will throw NotImplementedException")]
104                         public static TraceSwitch DGEditColumnEditing {
105                                 get {
106                                         throw new NotImplementedException ();
107                                 }
108                         }
109                         #endregion Public Instance Methods
110                 }
111                 
112                 internal enum ArrowDrawing
113                 {
114                         No = 0,
115                         Ascending = 1,
116                         Descending = 2
117                 }
118                 
119                 #region Local Variables
120                 internal HorizontalAlignment alignment;
121                 private int fontheight;
122                 internal DataGridTableStyle table_style;
123                 private string header_text;
124                 private string mapping_name;
125                 private string null_text;
126                 private PropertyDescriptor property_descriptor;
127                 private bool _readonly;
128                 private int width;
129                 internal bool is_default;
130                 internal DataGrid grid;
131                 private DataGridColumnHeaderAccessibleObject accesible_object;
132                 static string def_null_text = "(null)";
133                 private ArrowDrawing arrow_drawing = ArrowDrawing.No;
134                 internal bool bound;
135                 #endregion      // Local Variables
136
137                 #region Constructors
138                 public DataGridColumnStyle () : this (null)
139                 {
140                 }
141
142                 public DataGridColumnStyle (PropertyDescriptor prop)
143                 {
144                         property_descriptor = prop;
145
146                         fontheight = -1;
147                         table_style = null;
148                         header_text = string.Empty;
149                         mapping_name  = string.Empty;
150                         null_text = def_null_text;
151                         accesible_object = new DataGridColumnHeaderAccessibleObject (this);
152                         _readonly = prop == null ? false : prop.IsReadOnly;
153                         width = -1;
154                         grid = null;
155                         is_default = false;
156                         alignment = HorizontalAlignment.Left;
157                 }
158
159                 #endregion
160
161                 #region Public Instance Properties
162                 [Localizable(true)]
163                 [DefaultValue(HorizontalAlignment.Left)]
164                 public virtual HorizontalAlignment Alignment {
165                         get {
166                                 return alignment;
167                         }
168                         set {
169                                 if (value != alignment) {
170                                         alignment = value;
171                                         
172                                         if (table_style != null && table_style.DataGrid != null) {
173                                                 table_style.DataGrid.Invalidate ();
174                                         }
175                                         
176                                         EventHandler eh = (EventHandler)(Events [AlignmentChangedEvent]);
177                                         if (eh != null)
178                                                 eh (this, EventArgs.Empty);
179                                 }
180                         }
181                 }
182
183                 [Browsable(false)]
184                 public virtual DataGridTableStyle DataGridTableStyle {
185                         get { return table_style; }
186                 }
187                 
188                 protected int FontHeight {
189                         get {
190                                 if (fontheight != -1) {
191                                         return fontheight;
192                                 }
193
194                                 if (table_style != null) {
195                                         //return table_style.DataGrid.FontHeight
196                                         return -1;
197                                 }
198
199                                 // TODO: Default Datagrid font height
200                                 return -1;
201                         }
202                 }
203
204                 [Browsable(false)]
205                 public AccessibleObject HeaderAccessibleObject {
206                         get {
207                                 return accesible_object;
208                         }
209                 }
210
211                 [Localizable(true)]
212                 public virtual string HeaderText {
213                         get {
214                                 return header_text;
215                         }
216                         set {
217                                 if (value != header_text) {
218                                         header_text = value;
219                                         
220                                         Invalidate ();
221
222                                         EventHandler eh = (EventHandler)(Events [HeaderTextChangedEvent]);
223                                         if (eh != null)
224                                                 eh (this, EventArgs.Empty);
225                                 }
226                         }
227                 }
228
229
230                 [Editor("System.Windows.Forms.Design.DataGridColumnStyleMappingNameEditor, " + Consts.AssemblySystem_Design, typeof(System.Drawing.Design.UITypeEditor))]
231                 [Localizable(true)]
232                 [DefaultValue ("")]
233                 public string MappingName {
234                         get {
235                                 return mapping_name;
236                         }
237                         set {
238                                 if (value != mapping_name) {
239                                         mapping_name = value;
240
241                                         EventHandler eh = (EventHandler)(Events [MappingNameChangedEvent]);
242                                         if (eh != null)
243                                                 eh (this, EventArgs.Empty);
244                                 }
245                         }
246                 }
247
248                 [Localizable(true)]
249                 public virtual string NullText {
250                         get {
251                                 return null_text;
252                         }
253                         set {
254                                 if (value != null_text) {
255                                         null_text = value;
256                                         
257                                         if (table_style != null && table_style.DataGrid != null) {
258                                                 table_style.DataGrid.Invalidate ();
259                                         }
260
261                                         EventHandler eh = (EventHandler)(Events [NullTextChangedEvent]);
262                                         if (eh != null)
263                                                 eh (this, EventArgs.Empty);
264                                 }
265                         }
266                 }
267
268                 [Browsable(false)]
269                 [DefaultValue(null)]
270                 [EditorBrowsable(EditorBrowsableState.Advanced)]
271                 public virtual PropertyDescriptor PropertyDescriptor {
272                         get {
273                                 return property_descriptor;
274                         }
275                         set {
276                                 if (value != property_descriptor) {
277                                         property_descriptor = value;
278
279                                         EventHandler eh = (EventHandler)(Events [PropertyDescriptorChangedEvent]);
280                                         if (eh != null)
281                                                 eh (this, EventArgs.Empty);
282                                 }
283                         }
284                 }
285
286                 [DefaultValue(false)]
287                 public virtual bool ReadOnly {
288                         get {
289                                 return _readonly;
290                         }
291                         set {
292                                 if (value != _readonly) {
293                                         _readonly = value;
294                                         
295                                         if (table_style != null && table_style.DataGrid != null) {
296                                                 table_style.DataGrid.CalcAreasAndInvalidate ();
297                                         }
298                                         
299                                         EventHandler eh = (EventHandler)(Events [ReadOnlyChangedEvent]);
300                                         if (eh != null)
301                                                 eh (this, EventArgs.Empty);
302                                 }
303                         }
304                 }
305
306                 [DefaultValue(100)]
307                 [Localizable(true)]
308                 public virtual int Width {
309                         get {
310                                 return width;
311                         }
312                         set {
313                                 if (value != width) {
314                                         width = value;
315                                         
316                                         if (table_style != null && table_style.DataGrid != null) {
317                                                 table_style.DataGrid.CalcAreasAndInvalidate ();
318                                         }
319
320                                         EventHandler eh = (EventHandler)(Events [WidthChangedEvent]);
321                                         if (eh != null)
322                                                 eh (this, EventArgs.Empty);
323                                 }
324                         }
325                 }
326
327                 #endregion      // Public Instance Properties
328                 
329                 #region Private Instance Properties
330
331                 internal ArrowDrawing ArrowDrawingMode {
332                         get { return arrow_drawing; }
333                         set { arrow_drawing = value; }
334                 }
335                 
336                 internal bool TableStyleReadOnly {
337                         get {
338                                 return table_style != null && table_style.ReadOnly; 
339                         }
340                 }
341                 
342                 internal DataGridTableStyle TableStyle {
343                         set { table_style = value; }
344                 }
345                 
346                 internal bool IsDefault {
347                         get { return is_default; }
348                 }
349                 #endregion Private Instance Properties
350
351                 #region Public Instance Methods
352                 protected internal abstract void Abort (int rowNum);
353
354                 [MonoTODO ("Will not suspend updates")]
355                 protected void BeginUpdate ()
356                 {
357                 }
358                 
359                 protected void CheckValidDataSource (CurrencyManager value)
360                 {
361                         if (value == null) {
362                                 throw new ArgumentNullException ("CurrencyManager cannot be null");
363                         }
364                         
365                         if (property_descriptor == null) {
366                                 property_descriptor = value.GetItemProperties ()[mapping_name];
367
368 //                              Console.WriteLine ("mapping name = {0}", mapping_name);
369 //                              foreach (PropertyDescriptor prop in value.GetItemProperties ()) {
370 //                                      Console.WriteLine (" + prop = {0}", prop.Name);
371 //                              }
372
373                                 if (property_descriptor == null)
374                                         throw new InvalidOperationException ("The PropertyDescriptor for this column is a null reference");
375
376                                  /*MonoTests.System.Windows.Forms.DataGridColumnStyleTest.GetColumnValueAtRow : System.InvalidOperationException : The 'foo' DataGridColumnStyle cannot be used because it is not associated with a Property or Column in the DataSource.*/
377
378                                 
379                         }
380                 }
381
382                 protected internal virtual void ColumnStartedEditing (Control editingControl)
383                 {
384                 }
385
386                 protected internal abstract bool Commit (CurrencyManager dataSource, int rowNum);
387
388
389                 protected internal virtual void ConcedeFocus ()
390                 {
391                 }
392                 
393                 protected virtual AccessibleObject CreateHeaderAccessibleObject ()
394                 {
395                         return new DataGridColumnHeaderAccessibleObject (this);
396                 }
397
398                 protected internal virtual void Edit (CurrencyManager source, int rowNum,  Rectangle bounds,  bool readOnly)
399                 {
400                         Edit (source, rowNum, bounds, readOnly, string.Empty);
401                 }
402
403                 protected internal virtual void Edit (CurrencyManager source, int rowNum, Rectangle bounds, bool readOnly, string displayText)
404                 {
405                         string instantText = displayText;
406                         Edit (source, rowNum, bounds, readOnly, instantText, true);
407                 }
408
409                 protected internal abstract void Edit (CurrencyManager source,
410                         int rowNum, Rectangle bounds, bool readOnly,
411                         string displayText,
412                         bool cellIsVisible);
413
414
415                 protected void EndUpdate ()
416                 {
417                 }
418
419                 protected internal virtual void EnterNullValue () {}
420                 
421                 protected internal virtual object GetColumnValueAtRow (CurrencyManager source, int rowNum)
422                 {
423                         CheckValidDataSource (source);
424                         if (rowNum >= source.Count)
425                                 return DBNull.Value;
426                         return property_descriptor.GetValue (source [rowNum]);
427                 }
428
429                 protected internal abstract int GetMinimumHeight ();
430
431                 protected internal abstract int GetPreferredHeight (Graphics g, object value);
432
433                 protected internal abstract Size GetPreferredSize (Graphics g,  object value);
434
435                 void IDataGridColumnStyleEditingNotificationService.ColumnStartedEditing (Control editingControl)
436                 {
437                         ColumnStartedEditing (editingControl);
438                 }
439
440                 protected virtual void Invalidate ()
441                 {
442                         if (grid != null)
443                                 grid.InvalidateColumn (this);
444                 }
445
446                 protected internal abstract void Paint (Graphics g, Rectangle bounds, CurrencyManager source, int rowNum);
447                 protected internal abstract void Paint (Graphics g, Rectangle bounds, CurrencyManager source, int rowNum, bool alignToRight);
448                 
449                 protected internal virtual void Paint (Graphics g, Rectangle bounds, CurrencyManager source, int rowNum,
450                         Brush backBrush,  Brush foreBrush, bool alignToRight) {}
451
452                 protected internal virtual void ReleaseHostedControl () {}
453
454                 public void ResetHeaderText ()
455                 {
456                         HeaderText = string.Empty;
457                 }
458
459                 protected internal virtual void SetColumnValueAtRow (CurrencyManager source, int rowNum,  object value)
460                 {
461                         CheckValidDataSource (source);
462
463                         IEditableObject editable = source [rowNum] as IEditableObject;
464
465                         if (editable != null)
466                                 editable.BeginEdit ();
467
468                         property_descriptor.SetValue (source [rowNum], value);
469                 }
470
471                 protected virtual void SetDataGrid (DataGrid value)
472                 {
473                         grid = value;
474
475                         property_descriptor = null;
476
477                         // we don't check whether the DataGrid.ListManager is valid or not.
478                         // This is done by .net later as requiered, but not at this point.
479                 }
480
481                 protected virtual void SetDataGridInColumn (DataGrid value)
482                 {
483                         SetDataGrid (value);
484                 }
485                 
486                 internal void SetDataGridInternal (DataGrid value)
487                 {
488                         SetDataGridInColumn (value);
489                 }
490
491                 protected internal virtual void UpdateUI (CurrencyManager source, int rowNum, string displayText)
492                 {
493                 }
494
495                 #endregion      // Public Instance Methods
496                 
497                 #region Private Instance Methods
498                 virtual internal void OnMouseDown (MouseEventArgs e, int row, int column) {}
499                 virtual internal void OnKeyDown (KeyEventArgs ke, int row, int column) {}
500                 
501                 internal void PaintHeader (Graphics g, Rectangle bounds, int colNum)
502                 {
503                         ThemeEngine.Current.DataGridPaintColumnHeader (g, bounds, grid, colNum);
504                 }
505                 
506                 internal void PaintNewRow (Graphics g, Rectangle bounds, Brush backBrush, Brush foreBrush)
507                 {
508                         g.FillRectangle (backBrush, bounds);
509                         PaintGridLine (g, bounds);
510                 }
511                 
512                 internal void PaintGridLine (Graphics g, Rectangle bounds)
513                 {
514                         if (table_style.CurrentGridLineStyle != DataGridLineStyle.Solid) {
515                                 return;
516                         }
517                         
518                         g.DrawLine (ThemeEngine.Current.ResPool.GetPen (table_style.CurrentGridLineColor),
519                                 bounds.X, bounds.Y + bounds.Height - 1, bounds.X + bounds.Width - 1, bounds.Y + bounds.Height - 1);
520                         
521                         g.DrawLine (ThemeEngine.Current.ResPool.GetPen (table_style.CurrentGridLineColor),
522                                 bounds.X + bounds.Width - 1, bounds.Y , bounds.X + bounds.Width - 1, bounds.Y + bounds.Height);
523                 }
524                 
525                 #endregion Private Instance Methods
526
527                 #region Events
528                 static object AlignmentChangedEvent = new object ();
529                 static object FontChangedEvent = new object ();
530                 static object HeaderTextChangedEvent = new object ();
531                 static object MappingNameChangedEvent = new object ();
532                 static object NullTextChangedEvent = new object ();
533                 static object PropertyDescriptorChangedEvent = new object ();
534                 static object ReadOnlyChangedEvent = new object ();
535                 static object WidthChangedEvent = new object ();
536
537                 public event EventHandler AlignmentChanged {
538                         add { Events.AddHandler (AlignmentChangedEvent, value); }
539                         remove { Events.RemoveHandler (AlignmentChangedEvent, value); }
540                 }
541
542                 public event EventHandler FontChanged {
543                         add { Events.AddHandler (FontChangedEvent, value); }
544                         remove { Events.RemoveHandler (FontChangedEvent, value); }
545                 }
546
547                 public event EventHandler HeaderTextChanged {
548                         add { Events.AddHandler (HeaderTextChangedEvent, value); }
549                         remove { Events.RemoveHandler (HeaderTextChangedEvent, value); }
550                 }
551
552                 public event EventHandler MappingNameChanged {
553                         add { Events.AddHandler (MappingNameChangedEvent, value); }
554                         remove { Events.RemoveHandler (MappingNameChangedEvent, value); }
555                 }
556
557                 public event EventHandler NullTextChanged {
558                         add { Events.AddHandler (NullTextChangedEvent, value); }
559                         remove { Events.RemoveHandler (NullTextChangedEvent, value); }
560                 }
561
562                 [Browsable(false)]
563                 [EditorBrowsable(EditorBrowsableState.Advanced)]
564                 public event EventHandler PropertyDescriptorChanged {
565                         add { Events.AddHandler (PropertyDescriptorChangedEvent, value); }
566                         remove { Events.RemoveHandler (PropertyDescriptorChangedEvent, value); }
567                 }
568
569                 public event EventHandler ReadOnlyChanged {
570                         add { Events.AddHandler (ReadOnlyChangedEvent, value); }
571                         remove { Events.RemoveHandler (ReadOnlyChangedEvent, value); }
572                 }
573
574                 public event EventHandler WidthChanged {
575                         add { Events.AddHandler (WidthChangedEvent, value); }
576                         remove { Events.RemoveHandler (WidthChangedEvent, value); }
577                 }
578                 #endregion      // Events
579         }
580 }