* TabControl.cs: Show the tooltip depending on the value
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / DataGridTextBoxColumn.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 //
25 //
26
27 using System.ComponentModel;
28 using System.Drawing;
29 using System.Globalization;
30 using System.Runtime.InteropServices;
31 using System.Diagnostics;
32
33 namespace System.Windows.Forms
34 {
35         public class DataGridTextBoxColumn : DataGridColumnStyle
36         {
37                 #region Local Variables
38                 private string format;
39                 private IFormatProvider format_provider = null;
40                 private StringFormat string_format =  new StringFormat ();
41                 private DataGridTextBox textbox;
42                 private static readonly int offset_x = 2;
43                 private static readonly int offset_y = 2;
44                 #endregion      // Local Variables
45
46                 #region Constructors
47                 public DataGridTextBoxColumn () : this (null, String.Empty, false)
48                 {
49                 }
50
51                 public DataGridTextBoxColumn (PropertyDescriptor prop) : this (prop, String.Empty, false)
52                 {
53                 }
54                 
55                 public DataGridTextBoxColumn (PropertyDescriptor prop,  bool isDefault) : this (prop, String.Empty, isDefault)
56                 {
57                 }
58
59                 public DataGridTextBoxColumn (PropertyDescriptor prop,  string format) : this (prop, format, false)
60                 {
61                 }
62                 
63                 public DataGridTextBoxColumn (PropertyDescriptor prop,  string format, bool isDefault) : base (prop)
64                 {
65                         Format = format;
66                         is_default = isDefault;
67
68                         textbox = new DataGridTextBox ();
69                         textbox.Multiline = true;
70                         textbox.WordWrap = false;
71                         textbox.BorderStyle = BorderStyle.None;
72                         textbox.Visible = false;
73                 }
74
75                 #endregion
76
77                 #region Public Instance Properties
78                 [Editor("System.Windows.Forms.Design.DataGridColumnStyleFormatEditor, " + Consts.AssemblySystem_Design, typeof(System.Drawing.Design.UITypeEditor))]
79 #if NET_2_0
80                 [DefaultValue (null)]
81 #endif
82                 public string Format {
83                         get { return format; }
84                         set {
85                                 if (value != format) {
86                                         format = value;
87                                         Invalidate ();
88                                 }
89                         }
90                 }
91
92                 [Browsable(false)]
93                 [EditorBrowsable(EditorBrowsableState.Advanced)]
94                 public IFormatProvider FormatInfo {
95                         get { return format_provider; }
96                         set {
97                                 if (value != format_provider) {
98                                         format_provider = value;
99                                 }
100                         }
101                 }
102
103                 [DefaultValue(null)]
104                 public override PropertyDescriptor PropertyDescriptor {
105                         set { base.PropertyDescriptor = value; }
106                 }
107
108                 public override bool ReadOnly {
109                         get { return base.ReadOnly; }
110                         set { base.ReadOnly = value; }
111                 }
112                 
113                 [Browsable(false)]
114                 public virtual TextBox TextBox {
115                         get { return textbox; }
116                 }
117                 #endregion      // Public Instance Properties
118
119                 #region Public Instance Methods
120
121                 protected internal override void Abort (int rowNum)
122                 {
123                         EndEdit ();
124                 }
125                 
126                 protected internal override bool Commit (CurrencyManager dataSource, int rowNum)
127                 {
128                         textbox.Bounds = Rectangle.Empty;
129
130                         /* Do not write data if not editing. */
131                         if (textbox.IsInEditOrNavigateMode)
132                                 return true;
133
134                         try {
135                                 string existing_text = GetFormattedValue (dataSource, rowNum);
136
137                                 if (existing_text != textbox.Text) {
138                                         if (textbox.Text == NullText) {
139                                                 SetColumnValueAtRow (dataSource, rowNum, DBNull.Value);
140                                         } else {
141                                                 object newValue = textbox.Text;
142
143                                                 TypeConverter converter = TypeDescriptor.GetConverter (
144                                                         PropertyDescriptor.PropertyType);
145                                                 if (converter != null && converter.CanConvertFrom (typeof (string))) {
146                                                         newValue = converter.ConvertFrom (null, CultureInfo.CurrentCulture,
147                                                                 textbox.Text);
148                                                         if (converter.CanConvertTo (typeof (string)))
149                                                                 textbox.Text = (string) converter.ConvertTo (null, 
150                                                                         CultureInfo.CurrentCulture, newValue, typeof (string));
151                                                 }
152
153                                                 SetColumnValueAtRow (dataSource, rowNum, newValue);
154                                         }
155                                 }
156                         } catch {
157                                 return false;
158                         }
159                         
160                         EndEdit ();
161                         return true;
162                 }
163
164                 protected internal override void ConcedeFocus ()
165                 {
166                         HideEditBox ();
167                 }
168
169 #if NET_2_0
170                 protected internal override void Edit (CurrencyManager source, int rowNum, Rectangle bounds, bool readOnly, string displayText, bool cellIsVisible)
171                 {
172                         string instantText = displayText;
173 #else
174                 protected internal override void Edit (CurrencyManager source, int rowNum, Rectangle bounds, bool readOnly, string instantText, bool cellIsVisible)
175                 {
176 #endif
177                         grid.SuspendLayout ();
178
179                         textbox.TextChanged -= new EventHandler (textbox_TextChanged);
180
181                         textbox.TextAlign = alignment;
182                         
183                         bool ro = false;
184
185                         ro = (TableStyleReadOnly || ReadOnly || readOnly);
186
187                         if (!ro && instantText != null) {
188                                 textbox.Text = instantText;
189                                 textbox.IsInEditOrNavigateMode = false;
190                         } else {
191                                 textbox.Text = GetFormattedValue (source, rowNum);
192                         }
193
194                         textbox.TextChanged += new EventHandler (textbox_TextChanged);
195
196                         textbox.ReadOnly = ro;
197                         textbox.Bounds = new Rectangle (new Point (bounds.X + offset_x, bounds.Y + offset_y),
198                                                         new Size (bounds.Width - offset_x - 1, bounds.Height - offset_y - 1));
199
200                         textbox.Visible = cellIsVisible;
201                         textbox.SelectAll ();
202                         textbox.Focus ();
203                         grid.ResumeLayout (false);
204
205                 }
206
207                 void textbox_TextChanged (object o, EventArgs e)
208                 {
209                         textbox.IsInEditOrNavigateMode = false;
210                         grid.EditRowChanged (this);
211                 }
212
213                 protected void EndEdit ()
214                 {
215                         textbox.TextChanged -= new EventHandler (textbox_TextChanged);
216                         HideEditBox ();
217                 }
218
219                 protected internal override void EnterNullValue ()
220                 {
221                         textbox.Text = NullText;
222                 }
223
224                 protected internal override int GetMinimumHeight ()
225                 {
226                         return FontHeight + 3;
227                 }
228
229                 protected internal override int GetPreferredHeight (Graphics g, object value)
230                 {
231                         string text = GetFormattedValue (value);
232                         System.Text.RegularExpressions.Regex r = new System.Text.RegularExpressions.Regex("/\r\n/");
233                         int lines = r.Matches (text).Count;
234                         return this.DataGridTableStyle.DataGrid.Font.Height * (lines+1) + 1;
235                 }
236
237                 protected internal override Size GetPreferredSize (Graphics g, object value)
238                 {
239                         string text = GetFormattedValue (value);
240                         Size s = Size.Ceiling (g.MeasureString (text, this.DataGridTableStyle.DataGrid.Font));
241                         s.Width += 4;
242                         return s;
243                 }
244
245                 protected void HideEditBox ()
246                 {
247                         if (!textbox.Visible)
248                                 return;
249
250                         grid.SuspendLayout ();
251                         textbox.Bounds = Rectangle.Empty;
252                         textbox.Visible = false;
253                         textbox.IsInEditOrNavigateMode = true;
254                         grid.ResumeLayout (false);
255                 }
256
257                 protected internal override void Paint (Graphics g, Rectangle bounds, CurrencyManager source, int rowNum)
258                 {
259                         Paint (g, bounds, source, rowNum, false);
260                 }
261
262                 protected internal override void Paint (Graphics g, Rectangle bounds, CurrencyManager source, int rowNum, bool alignToRight)
263                 {
264                         Paint (g, bounds, source, rowNum, ThemeEngine.Current.ResPool.GetSolidBrush (DataGridTableStyle.BackColor),
265                                 ThemeEngine.Current.ResPool.GetSolidBrush (DataGridTableStyle.ForeColor), alignToRight);
266                 }
267
268                 protected internal override void Paint (Graphics g, Rectangle bounds, CurrencyManager source, int rowNum, Brush backBrush, Brush foreBrush, bool alignToRight)
269                 {
270                         PaintText (g, bounds, GetFormattedValue (source, rowNum),  backBrush, foreBrush, alignToRight);
271                 }
272
273                 protected void PaintText (Graphics g, Rectangle bounds, string text, bool alignToRight)
274                 {
275                         PaintText (g, bounds, text,  ThemeEngine.Current.ResPool.GetSolidBrush (DataGridTableStyle.BackColor),
276                                 ThemeEngine.Current.ResPool.GetSolidBrush (DataGridTableStyle.ForeColor), alignToRight);
277                 }
278
279                 protected void PaintText (Graphics g, Rectangle textBounds, string text, Brush backBrush, Brush foreBrush, bool alignToRight)
280                 {
281                         if (alignToRight == true) {
282                                 string_format.FormatFlags |= StringFormatFlags.DirectionRightToLeft;
283                         } else {
284                                 string_format.FormatFlags &= ~StringFormatFlags.DirectionRightToLeft;
285                         }
286                         
287                         switch (alignment) {
288                         case HorizontalAlignment.Center:
289                                 string_format.Alignment = StringAlignment.Center;
290                                 break;
291                         case HorizontalAlignment.Right:
292                                 string_format.Alignment = StringAlignment.Far;
293                                 break;
294                         default:
295                                 string_format.Alignment = StringAlignment.Near;
296                                 break;
297                         }
298                         
299                         g.FillRectangle (backBrush, textBounds);
300                         PaintGridLine (g, textBounds);
301
302                         textBounds.X += offset_x;
303                         textBounds.Width -= offset_x;
304
305                         textBounds.Y += offset_y;
306                         textBounds.Height -= offset_y;
307
308                         string_format.FormatFlags |= StringFormatFlags.NoWrap;
309                         g.DrawString (text, DataGridTableStyle.DataGrid.Font, foreBrush, textBounds, string_format);
310                         
311                 }
312                 
313                 protected internal override void ReleaseHostedControl ()
314                 {
315                         if (textbox == null)
316                                 return;
317
318                         grid.SuspendLayout ();
319                         grid.Controls.Remove (textbox);
320                         grid.Invalidate (new Rectangle (textbox.Location, textbox.Size));
321                         textbox.Dispose ();
322                         textbox = null;
323                         grid.ResumeLayout (false);
324                 }
325
326                 protected override void SetDataGridInColumn (DataGrid value)
327                 {
328                         base.SetDataGridInColumn (value);
329
330                         if (value == null)
331                                 return;
332
333                         textbox.SetDataGrid (grid);
334                         grid.SuspendLayout ();
335                         grid.Controls.Add (textbox);
336                         grid.ResumeLayout (false);
337                 }
338
339 #if NET_2_0
340                 protected internal override void UpdateUI (CurrencyManager source, int rowNum, string displayText)
341                 {
342                         string instantText = displayText;
343 #else
344                 protected internal override void UpdateUI (CurrencyManager source, int rowNum, string instantText)
345                 {
346 #endif
347                         if (textbox.Visible // I don't really like this, but it gets DataGridTextBoxColumnTest.TestUpdateUI passing
348                             && textbox.IsInEditOrNavigateMode) {
349                                 textbox.Text = GetFormattedValue (source, rowNum);
350                         } else {
351                                 textbox.Text = instantText;
352                         }
353                 }
354
355                 #endregion      // Public Instance Methods
356
357                 #region Private Instance Methods
358
359                 private string GetFormattedValue (CurrencyManager source, int rowNum)
360                 {
361                         object obj = GetColumnValueAtRow (source, rowNum);
362                         return GetFormattedValue (obj);
363                 }
364
365                 private string GetFormattedValue (object obj)
366                 {
367                         if (DBNull.Value.Equals(obj) || obj == null)
368                                 return NullText;
369
370                         if (format != null && format != String.Empty && obj as IFormattable != null)
371                                 return ((IFormattable) obj).ToString (format, format_provider);
372
373                         TypeConverter converter = TypeDescriptor.GetConverter (
374                                 PropertyDescriptor.PropertyType);
375                         if (converter != null && converter.CanConvertTo (typeof (string)))
376                                 return (string) converter.ConvertTo (null, CultureInfo.CurrentCulture,
377                                         obj, typeof (string));
378
379                         return obj.ToString ();
380
381                 }
382                 #endregion Private Instance Methods
383         }
384 }