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