6c36f2826d093611b824e71a26402105b1d235c4
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / PropertyGridView.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 // Authors:
23 //      Jonathan Chambers       (jonathan.chambers@ansys.com)
24 //
25 //
26
27 // NOT COMPLETE
28
29 using System;
30 using System.Collections;
31 using System.ComponentModel.Design;
32 using System.Drawing;
33 using System.Drawing.Design;
34 using System.ComponentModel;
35 using System.Threading;
36 using System.Windows.Forms.Design;
37
38 namespace System.Windows.Forms.PropertyGridInternal {
39         internal class PropertyGridView : System.Windows.Forms.ScrollableControl, IWindowsFormsEditorService {
40
41                 #region Private Members
42                 private double splitter_percent = .5;
43                 private const int V_INDENT = 16;
44                 private int row_height;
45                 private int font_height_padding = 3;
46                 private const int RESIZE_WIDTH = 3;
47                 private const int BUTTON_WIDTH = 25;
48                 private PropertyGridTextBox grid_textbox;
49                 private PropertyGrid property_grid;
50                 private bool resizing_grid;
51                 private int open_grid_item_count = -1;
52                 private int skipped_grid_items;
53                 private PropertyGridDropDown dropdown_form;
54                 private Form dialog_form;
55                 private ImplicitVScrollBar vbar;
56                 private StringFormat string_format;
57                 private Font bold_font;
58                 #endregion
59
60                 #region Contructors
61                 public PropertyGridView (PropertyGrid propertyGrid) {
62                         property_grid = propertyGrid;
63
64                         property_grid.SelectedGridItemChanged+=new SelectedGridItemChangedEventHandler(HandleSelectedGridItemChanged);
65                         property_grid.PropertyValueChanged+=new PropertyValueChangedEventHandler(HandlePropertyValueChanged);
66
67                         string_format = new StringFormat();
68                         string_format.FormatFlags = StringFormatFlags.NoWrap;
69                         string_format.Trimming = StringTrimming.None;
70
71                         grid_textbox = new PropertyGridTextBox();
72                         grid_textbox.DropDownButtonClicked +=new EventHandler(DropDownButtonClicked);
73                         grid_textbox.DialogButtonClicked +=new EventHandler(DialogButtonClicked);
74
75                         
76                         dropdown_form = new PropertyGridDropDown();
77                         dropdown_form.FormBorderStyle = FormBorderStyle.None;
78                         dropdown_form.StartPosition = FormStartPosition.Manual;
79                         dropdown_form.ShowInTaskbar = false;
80
81                         dialog_form = new Form ();
82                         dialog_form.StartPosition = FormStartPosition.Manual;
83                         dialog_form.FormBorderStyle = FormBorderStyle.None;
84                         dialog_form.ShowInTaskbar = false;
85
86                         skipped_grid_items = 0;
87                         row_height = Font.Height + font_height_padding;
88
89                         grid_textbox.Visible = false;
90                         grid_textbox.Font = this.Font;
91                         grid_textbox.BackColor = this.BackColor;
92                         // Not working at all, used to??
93                         grid_textbox.Validating += new CancelEventHandler(TextBoxValidating);
94                         grid_textbox.ToggleValue+=new EventHandler(grid_textbox_ToggleValue);
95                         this.Controls.Add(grid_textbox);
96
97                         vbar = new ImplicitVScrollBar();
98                         vbar.Visible = false;
99                         vbar.ValueChanged+=new EventHandler(HandleValueChanged);
100                         vbar.Dock = DockStyle.Right;
101                         this.Controls.AddImplicit(vbar);
102
103                         resizing_grid = false;
104
105                         bold_font = new Font(this.Font, FontStyle.Bold);
106
107                         ForeColorChanged+=new EventHandler(RedrawEvent);
108                         BackColorChanged+=new System.EventHandler(RedrawEvent);
109                         FontChanged+=new EventHandler(RedrawEvent);
110                         SizeChanged+=new EventHandler(RedrawEvent);
111                         
112                         SetStyle(ControlStyles.DoubleBuffer, true);
113                         SetStyle(ControlStyles.UserPaint, true);
114                         SetStyle(ControlStyles.AllPaintingInWmPaint, true);
115                         SetStyle(ControlStyles.ResizeRedraw, false);
116                 }
117
118                 #endregion
119
120                 #region Protected Instance Methods
121
122                 protected override void OnFontChanged(EventArgs e) {
123                         bold_font = new Font(this.Font, FontStyle.Bold);
124
125                         
126                         row_height = Font.Height + font_height_padding;
127                         base.OnFontChanged (e);
128                 }
129
130                 protected override void OnDoubleClick(EventArgs e) {
131                         if (property_grid.SelectedGridItem.Expandable)
132                                 property_grid.SelectedGridItem.Expanded = !property_grid.SelectedGridItem.Expanded;
133                         else 
134                                 ToggleValue();
135                         Invalidate();
136                         base.OnDoubleClick (e);
137                 }
138
139                 protected override void OnPaint(PaintEventArgs e) {
140                         // Decide if we need a scrollbar
141                         open_grid_item_count = 0;
142
143                         // Background
144                         e.Graphics.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (BackColor), ClientRectangle);
145                         
146                         // Left column
147                         e.Graphics.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (property_grid.LineColor), 0,0,V_INDENT, ClientRectangle.Height);
148                         
149
150                         int yLoc = -vbar.Value*row_height;
151                         DrawGridItems(property_grid.grid_items, e, 1, ref yLoc);
152
153                         // Grid
154                         DrawGrid(e);
155
156                         UpdateScrollBar();
157                         
158                         base.OnPaint(e);
159                 }
160
161                 protected override void OnMouseWheel(MouseEventArgs e) {
162                         if (vbar == null || !vbar.Visible) {
163                                 return;
164                         }
165
166                         if (e.Delta < 0) {
167                                 vbar.Value = Math.Min(vbar.Value + SystemInformation.MouseWheelScrollLines, vbar.Maximum);
168                         } else {
169                                 vbar.Value = Math.Max(0, vbar.Value - SystemInformation.MouseWheelScrollLines);
170                         }
171                         base.OnMouseWheel (e);
172                 }
173
174
175                 protected override void OnMouseMove (MouseEventArgs e) {
176
177                         if (resizing_grid) {
178                                 int loc = Math.Max(e.X,2*V_INDENT);
179                                 SplitterPercent = 1.0*loc/Width;
180                                 Refresh();
181                         }
182                         if (e.X > SplitterLocation - RESIZE_WIDTH && e.X < SplitterLocation + RESIZE_WIDTH) 
183                                 this.Cursor = Cursors.SizeWE;
184                         else
185                                 this.Cursor = Cursors.Default;
186                         base.OnMouseMove (e);
187                 }
188
189                 protected override void OnMouseDown (MouseEventArgs e) {
190                         if (e.X > SplitterLocation - RESIZE_WIDTH && e.X < SplitterLocation + RESIZE_WIDTH) {
191                                 resizing_grid = true;
192                         }
193                         else {
194                                 int offset = -vbar.Value*row_height;
195                                 GridItem foundItem = GetSelectedGridItem(property_grid.grid_items, e.Y, ref offset);
196                                 
197                                 if (foundItem != null) {
198                                         if (foundItem.Expandable) {
199                                                 if (e.X >=3 && e.X <= 11 && (e.Y % row_height >= row_height/2-2 && e.Y % row_height <= row_height/2+4)) {
200                                                         foundItem.Expanded = !foundItem.Expanded;
201                                                         Invalidate();
202                                                 }
203                                         }
204                                         this.property_grid.SelectedGridItem = foundItem;
205                                 }
206                                 
207                                 base.OnMouseDown (e);
208                         }
209                 }
210
211                 protected override void OnMouseUp (MouseEventArgs e) {
212                         resizing_grid = false;
213                         base.OnMouseUp (e);
214                 }
215
216                 protected override void OnKeyPress(KeyPressEventArgs e) {
217                         if (property_grid.SelectedGridItem.Expandable)
218                                 property_grid.SelectedGridItem.Expanded = !property_grid.SelectedGridItem.Expanded;
219                         base.OnKeyPress (e);
220                 }
221
222                 #endregion
223
224                 #region Private Helper Methods
225
226                 private int SplitterLocation{
227                         get {
228                                 return (int)(splitter_percent*Width);
229                         }
230                 }
231
232                 private double SplitterPercent{
233                         set {
234                                 splitter_percent = Math.Max(Math.Min(value, .9),.1);
235                         }
236                 }
237
238                 private GridItem GetSelectedGridItem (GridItemCollection grid_items, int y, ref int current) {
239                         foreach (GridItem child_grid_item in grid_items) {
240                                 if (y > current && y < current + row_height) {
241                                         return child_grid_item;
242                                 }
243                                 current += row_height;
244                                 if (child_grid_item.Expanded) {
245                                         GridItem foundItem = GetSelectedGridItem(child_grid_item.GridItems, y, ref current);
246                                         if (foundItem != null)
247                                                 return foundItem;
248                                 }
249                         }
250                         return null;
251                 }
252
253                 private void UpdateScrollBar() {
254                         int visible_rows = this.ClientRectangle.Height/row_height;
255                         if (open_grid_item_count > visible_rows) {
256                                 vbar.Visible = true;
257                                 vbar.SmallChange = 1;
258                                 vbar.Minimum = 0;
259                                 vbar.Maximum = open_grid_item_count-1;
260                                 vbar.LargeChange = visible_rows;
261                         }
262                         else {
263                                 vbar.Visible = false;
264                         }
265
266                 }
267
268                 #region Drawing Code
269
270                 private void DrawGrid(PaintEventArgs pevent) {
271                         Pen pen = ThemeEngine.Current.ResPool.GetPen(property_grid.LineColor);
272                         // vertical divider line
273                         pevent.Graphics.DrawLine(pen, SplitterLocation, 0, SplitterLocation, (open_grid_item_count-skipped_grid_items)*row_height);
274                         
275                         int y = 0;
276                         while (y < ClientRectangle.Height && y/row_height + skipped_grid_items < open_grid_item_count) {
277                                 // horizontal lines
278                                 pevent.Graphics.DrawLine(pen, 0, y, ClientRectangle.Width, y);
279                                 y += row_height;
280                         }
281                 }
282
283                 private void DrawGridItems(GridItemCollection grid_items, PaintEventArgs pevent, int depth, ref int yLoc) {
284                         foreach (GridItem grid_item in grid_items) {
285                                 DrawGridItem (grid_item, pevent, depth, ref yLoc);
286                                 if (grid_item.Expanded)
287                                         DrawGridItems(grid_item.GridItems, pevent, (grid_item.GridItemType == GridItemType.Category) ? depth : depth+1, ref yLoc);
288                         }
289                 }
290
291                 private void DrawGridItemLabel(GridItem grid_item, PaintEventArgs pevent, Rectangle rect) {
292                         int x = rect.X+1;
293                         if (grid_item.Parent != null && grid_item.Parent.GridItemType != GridItemType.Category)
294                                 x += V_INDENT;
295
296                         Font font = this.Font;
297                         Brush brush = SystemBrushes.WindowText;
298                         if (grid_item.GridItemType == GridItemType.Category) {
299                                 font = bold_font;
300                                 brush = SystemBrushes.ControlDark;
301                         }
302
303                         if (grid_item == property_grid.SelectedGridItem && grid_item.GridItemType != GridItemType.Category) {
304                                 pevent.Graphics.FillRectangle (SystemBrushes.Highlight, rect);
305                                 // Label
306                                 brush = SystemBrushes.HighlightText;
307                         }
308
309                         
310                         if (grid_item.GridItemType == GridItemType.Category) {
311                                 pevent.Graphics.DrawString(grid_item.Label,font,brush,x, rect.Y + 2);
312                                 if (grid_item == property_grid.SelectedGridItem) {
313                                         SizeF size = pevent.Graphics.MeasureString(grid_item.Label, bold_font);
314                                         ControlPaint.DrawFocusRectangle(pevent.Graphics, new Rectangle(x,rect.Y+2, (int)size.Width, (int)size.Height));
315                                 }
316                         }
317                         else
318                                 pevent.Graphics.DrawString(grid_item.Label,font,brush,new Rectangle(x, rect.Y + 2,x-rect.X+rect.Width-2,rect.Height-2),string_format);
319                 }
320
321                 private void DrawGridItemValue(GridItem grid_item, PaintEventArgs pevent, Rectangle rect) {
322                         // Value
323                         if (grid_item.PropertyDescriptor != null) {
324
325                                 bool paintsValue = false;
326                                 UITypeEditor editor = null;
327                                 object temp = grid_item.PropertyDescriptor.GetEditor(typeof(UITypeEditor));
328                                 editor = (UITypeEditor)temp;//grid_item.PropertyDescriptor.GetEditor(typeof(UITypeEditor));
329                                 if (editor != null) {
330                                         paintsValue = editor.GetPaintValueSupported();
331                                 }
332
333                                 if (grid_item == property_grid.SelectedGridItem) {
334                                         grid_textbox.ReadOnly = false;
335                                         grid_textbox.DropDownButtonVisible = false;
336                                         grid_textbox.DialogButtonVisible = false;
337                                         if (editor != null) {
338                                                 UITypeEditorEditStyle style = editor.GetEditStyle();
339                                         
340                                                 switch (style) {
341                                                         case UITypeEditorEditStyle.DropDown:
342                                                                 grid_textbox.DropDownButtonVisible = true;
343                                                                 break;
344                                                         case UITypeEditorEditStyle.Modal:
345                                                                 grid_textbox.DialogButtonVisible = true;
346                                                                 break;
347                                                 }
348                                         }
349                                         else {
350                                                 try {
351                                                         if (grid_item.PropertyDescriptor.Converter != null) {
352                                                                 if (grid_item.PropertyDescriptor.Converter.GetStandardValuesSupported()) {
353                                                         
354                                                                         grid_textbox.DropDownButtonVisible = true;
355                                                                         grid_textbox.ReadOnly = true;
356                                                                 }
357                                                         }
358                                                         else {
359                                                                 System.Console.WriteLine("Converter not available for type {0}",grid_item.PropertyDescriptor.PropertyType);
360                                                         }
361                                                 
362                                                 }
363                                                 catch (Exception) {
364                                                 }
365                                         }
366                                 }
367
368                                 
369
370                                 int xLoc = SplitterLocation+1;
371                                 if (paintsValue) {
372                                         pevent.Graphics.DrawRectangle(Pens.Black, SplitterLocation+2,rect.Y+2, 20, row_height-4);
373                                         try {
374                                                 editor.PaintValue(grid_item.Value, pevent.Graphics, new Rectangle(SplitterLocation+3,rect.Y+3, 19, row_height-5));
375                                         }
376                                         catch (Exception ex) {
377                                                 System.Console.WriteLine(ex.Message);
378                                                 System.Console.WriteLine("Paint Value failed for type {0}",grid_item.PropertyDescriptor.PropertyType);
379                                                 // design time stuff is not playing nice
380                                         }
381                                         xLoc += 27;
382                                 }
383
384                                 Font font = this.Font;
385                                 try {
386                                         if (grid_item.PropertyDescriptor.Converter != null) {
387                                                 string value = grid_item.PropertyDescriptor.Converter.ConvertToString(grid_item.Value);
388                                                 if (grid_item.PropertyDescriptor.CanResetValue(property_grid.SelectedObject))
389                                                         font = bold_font;
390                                 
391                                                 pevent.Graphics.DrawString(value,font,SystemBrushes.WindowText,new RectangleF(xLoc,rect.Y+2, ClientRectangle.Width-(xLoc), row_height),string_format);
392                                         }
393                                         else {
394                                                 System.Console.WriteLine("No converter for type {0}",grid_item.PropertyDescriptor.PropertyType);
395                                         }
396
397                                 }
398                                 catch (Exception) {
399                                 }
400                                 if (grid_item == property_grid.SelectedGridItem && grid_item.GridItemType != GridItemType.Category) {
401                                         grid_textbox.SetBounds(xLoc, rect.Top, ClientRectangle.Width-xLoc - (vbar.Visible ? vbar.Width: 0),row_height);
402                                 }
403                         }
404                 }
405
406                 private void DrawGridItem (GridItem grid_item, PaintEventArgs pevent, int depth, ref int yLoc) {
407                         if (yLoc > -row_height && yLoc < ClientRectangle.Height) {
408                                 if (grid_item.Expandable) {
409                                         grid_item.PlusMinusBounds = DrawPlusMinus(pevent.Graphics, 3, yLoc+row_height/2-3, grid_item.Expanded, grid_item.GridItemType == GridItemType.Category);
410                                 }
411                         
412                                 if (grid_item.GridItemType == GridItemType.Category) {
413                                         pevent.Graphics.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (property_grid.LineColor), depth*V_INDENT,yLoc,ClientRectangle.Width-(depth*V_INDENT), row_height);
414                                 }
415
416                                 DrawGridItemLabel(grid_item, pevent, new Rectangle(depth*V_INDENT,yLoc, SplitterLocation-depth*V_INDENT, row_height));
417                                 DrawGridItemValue(grid_item, pevent, new Rectangle(SplitterLocation+2,yLoc, ClientRectangle.Width-SplitterLocation-2, row_height));
418                         }
419                         grid_item.Top = yLoc;
420                         yLoc += row_height;
421                         open_grid_item_count++;
422                 }
423
424                 private Rectangle DrawPlusMinus (Graphics g, int x, int y, bool expanded, bool category) {
425                         Rectangle bounds = new Rectangle(x, y, 8, 8);
426                         if (!category) g.FillRectangle (Brushes.White, bounds);
427                         Pen pen = ThemeEngine.Current.ResPool.GetPen (property_grid.ViewForeColor);
428                         g.DrawRectangle (pen, bounds);
429                         g.DrawLine (pen, x+2, y+4, x + 6, y+4);
430                         if (!expanded)
431                                 g.DrawLine (pen, x+4, y+2, x+4, y+6);
432
433                         return bounds;
434                 }
435
436                 #endregion
437
438                 #region Event Handling
439                 private void RedrawEvent (object sender, System.EventArgs e) {
440                         Refresh();
441                 }
442
443                 private void TextBoxValidating (object sender, CancelEventArgs e) {
444                         if (this.property_grid.SelectedGridItem != null) {
445                                 PropertyDescriptor desc = property_grid.SelectedGridItem.PropertyDescriptor;
446                                 if (desc != null) {
447                                         try {
448                                                 if (desc.Converter != null) {
449                                                         SetPropertyValue(desc.Converter.ConvertFromString(grid_textbox.Text));
450                                                 }
451                                                 else {
452                                                         System.Console.WriteLine("No converter for type {0}",desc.PropertyType);
453                                                 }
454                                         }
455                                         catch (Exception) {
456                                                 Console.WriteLine("Error converting string");
457                                         }
458                                 }
459                         }
460                 }
461
462                 #endregion
463
464                 private void ToggleValue() {
465                         if (property_grid.SelectedGridItem.GridItemType == GridItemType.Property) {
466                                 if (property_grid.SelectedGridItem.PropertyDescriptor != null) {
467                                         if (property_grid.SelectedGridItem.PropertyDescriptor.PropertyType == typeof(bool))
468                                                 SetPropertyValue(!(bool)property_grid.SelectedGridItem.Value);
469                                         else if (property_grid.SelectedGridItem.PropertyDescriptor.Converter.GetStandardValuesSupported()){
470                                                 System.ComponentModel.TypeConverter.StandardValuesCollection coll = 
471                                                         (System.ComponentModel.TypeConverter.StandardValuesCollection)property_grid.SelectedGridItem.PropertyDescriptor.Converter.GetStandardValues();
472                                                 for (int i = 0; i < coll.Count; i++) {
473                                                         if (property_grid.SelectedGridItem.Value.Equals(coll[i])){
474                                                                 if (i < coll.Count-1)
475                                                                         SetPropertyValue(coll[i+1]);
476                                                                 else
477                                                                         SetPropertyValue(coll[0]);
478                                                                 break;
479                                                         }
480
481                                                 }
482                                         }
483                                 }
484                         }
485                 }
486
487                 private void dropdown_form_Deactivate (object sender, EventArgs e) {
488                         dropdown_form.Hide();
489                 }
490
491                 private void listBox_MouseUp(object sender, MouseEventArgs e) {
492                         AcceptListBoxSelection (sender);
493                 }
494
495                 private void listBox_KeyDown(object sender, KeyEventArgs e)
496                 {
497                         switch (e.KeyData & Keys.KeyCode) {
498                         case Keys.Enter:
499                                 AcceptListBoxSelection (sender);
500                                 return;
501                         case Keys.Escape:
502                                 dropdown_form.Hide();
503                                 return;
504                         }
505                 }
506
507                 void AcceptListBoxSelection (object sender) {
508                         if (this.property_grid.SelectedGridItem != null) {
509                                 PropertyDescriptor desc = property_grid.SelectedGridItem.PropertyDescriptor;
510                                 if (desc != null) {
511                                         SetPropertyValue(((ListBox)sender).SelectedItem);
512                                 }
513                         }
514                         dropdown_form.Hide();
515                         Refresh();
516                 }
517
518                 private void SetPropertyValue(object newVal) {
519                         if (this.property_grid.SelectedGridItem != null) {
520                                 PropertyDescriptor desc = property_grid.SelectedGridItem.PropertyDescriptor;
521                                 if (desc != null) {
522                                         object target = property_grid.SelectedObject;
523                                         if (property_grid.SelectedGridItem.Parent != null)
524                                                 target = property_grid.SelectedGridItem.Parent.Value;
525                                         desc.SetValue(target, newVal);
526                                 }
527                         }
528                 }
529
530                 private void DropDownButtonClicked (object sender, EventArgs e) {
531                         UITypeEditor editor = property_grid.SelectedGridItem.PropertyDescriptor.GetEditor (typeof (UITypeEditor)) as UITypeEditor;
532                         if (editor == null) {
533                                 if (dropdown_form.Visible) {
534                                         dropdown_form.Hide ();
535                                 }
536                                 else {
537                                         dropdown_form.Deactivate +=new EventHandler(dropdown_form_Deactivate);
538                                         ListBox listBox = new ListBox();
539                                         listBox.BorderStyle = BorderStyle.FixedSingle;
540                                         listBox.Dock = DockStyle.Fill;
541                                         int selected_index = 0;
542                                         int i = 0;
543                                         foreach (object obj in property_grid.SelectedGridItem.PropertyDescriptor.Converter.GetStandardValues()) {
544                                                 listBox.Items.Add(obj);
545                                                 if (property_grid.SelectedGridItem.Value.Equals(obj))
546                                                         selected_index = i;
547                                                 i++;
548                                         }
549                                         listBox.SelectedIndex = selected_index;
550                                         listBox.KeyDown += new KeyEventHandler(listBox_KeyDown);
551                                         listBox.MouseUp+=new MouseEventHandler(listBox_MouseUp);
552                                         dropdown_form.Controls.Clear();
553                                         dropdown_form.Controls.Add(listBox);
554                                         dropdown_form.Location = PointToScreen(new Point(SplitterLocation,grid_textbox.Location.Y+row_height));
555                                         dropdown_form.Width = this.Width - this.SplitterLocation;
556                                         dropdown_form.ActiveControl = listBox;
557                                         dropdown_form.Show();
558                                 }
559                         } else { // use editor
560                                 SetPropertyValueFromUITypeEditor (editor);
561                         }
562                 }
563
564                 void SetPropertyValueFromUITypeEditor (UITypeEditor editor)
565                 {
566                         ServiceContainer service_container = new ServiceContainer ();
567                         service_container.AddService (typeof (IWindowsFormsEditorService), this);
568                         object value = editor.EditValue (
569                                 new ITypeDescriptorContextImpl (this.property_grid),
570                                 service_container,
571                                 property_grid.SelectedGridItem.Value);
572                         SetPropertyValue (value);
573                 }
574                 
575                 private void DialogButtonClicked(object sender, EventArgs e) {
576                         UITypeEditor editor = property_grid.SelectedGridItem.PropertyDescriptor.GetEditor (typeof (UITypeEditor)) as UITypeEditor;
577                         if (editor != null)
578                                 SetPropertyValueFromUITypeEditor (editor);
579                 }
580
581                 private void HandleValueChanged(object sender, EventArgs e) {
582                         if (vbar.Value <= 0) {
583                                 vbar.Value = 0;
584                         }
585                         if (vbar.Value > vbar.Maximum-ClientRectangle.Height/row_height) {
586                                 vbar.Value = vbar.Maximum-ClientRectangle.Height/row_height+1;
587                         }
588                         
589                         int scroll_amount = (skipped_grid_items-vbar.Value)*row_height;
590                         XplatUI.ScrollWindow(Handle, 0, scroll_amount, false);
591                         skipped_grid_items = vbar.Value;
592                         if (scroll_amount > 0)
593                                 Invalidate(new Rectangle(0,0,Width,scroll_amount+1));
594                         else
595                                 Invalidate(new Rectangle(0,Height+scroll_amount-1,Width,1-scroll_amount));
596                 }
597
598                 private void grid_textbox_ToggleValue(object sender, EventArgs e) {
599                         ToggleValue();
600                         Invalidate();
601                 }
602
603                 private void HandleSelectedGridItemChanged(object sender, SelectedGridItemChangedEventArgs e) {                 
604                         // Region not working correctly
605                         //Region clip = new Region();
606                         //if (property_grid.SelectedGridItem != null)
607                         //      clip.Union(new Rectangle(0,property_grid.SelectedGridItem.Top, ClientRectangle.Width, row_height));
608                         //      clip.Union(new Rectangle(0,property_grid.SelectedGridItem.Top, ClientRectangle.Width, row_height));
609
610                         if (e.NewSelection.GridItemType == GridItemType.Property)
611                                 grid_textbox.Visible = true;
612                         else
613                                 grid_textbox.Visible = false;
614
615                         if (e.NewSelection.PropertyDescriptor != null) {
616                                 grid_textbox.Text = e.NewSelection.PropertyDescriptor.Converter.ConvertToString(e.NewSelection.Value);
617                                 if (e.NewSelection.PropertyDescriptor.CanResetValue(property_grid.SelectedObject))
618                                         grid_textbox.Font = bold_font;
619                                 else
620                                         grid_textbox.Font = this.Font;
621                         }
622
623                         Invalidate(/*clip*/this.ClientRectangle);
624                         Update();
625                 }
626
627                 private void HandlePropertyValueChanged(object s, PropertyValueChangedEventArgs e) {
628                         if (e.ChangedItem.PropertyDescriptor != null) {
629                                 grid_textbox.Text = e.ChangedItem.PropertyDescriptor.Converter.ConvertToString(e.ChangedItem.Value);
630                                 if (e.ChangedItem.PropertyDescriptor.CanResetValue(property_grid.SelectedObject))
631                                         grid_textbox.Font = bold_font;
632                                 else
633                                         grid_textbox.Font = this.Font;
634                         }
635                 }
636                 
637
638                 
639                 #endregion
640
641                 #region IWindowsFormsEditorService Members
642
643                 public void CloseDropDown() {
644                         dropdown_form.Hide();
645                 }
646
647                 public void DropDownControl(Control control) {
648                         Object  queue_id;
649
650                         dropdown_form.Deactivate +=new EventHandler(dropdown_form_Deactivate);
651                         dropdown_form.Size = control.Size;
652                         control.Dock = DockStyle.Fill;
653                         dropdown_form.Controls.Clear();
654                         dropdown_form.Controls.Add(control);
655                         dropdown_form.Location = PointToScreen(new Point(SplitterLocation,grid_textbox.Location.Y+row_height));
656                         dropdown_form.Width = Width - SplitterLocation;
657
658                         dropdown_form.Show();
659                         System.Windows.Forms.MSG msg = new MSG();
660                         queue_id = XplatUI.StartLoop(Thread.CurrentThread);
661                         while (XplatUI.GetMessage(queue_id, ref msg, IntPtr.Zero, 0, 0) && dropdown_form.Visible) {
662                                 XplatUI.TranslateMessage(ref msg);
663                                 XplatUI.DispatchMessage(ref msg);
664                         }
665                 }
666
667                 public System.Windows.Forms.DialogResult ShowDialog(Form dialog) {
668                         return dialog.ShowDialog(this);
669                 }
670
671                 #endregion
672
673                 #region Internal Classes
674                 internal class ITypeDescriptorContextImpl : System.ComponentModel.ITypeDescriptorContext {
675                         private PropertyGrid property_grid;
676                         public ITypeDescriptorContextImpl(PropertyGrid propertyGrid) {
677                                 property_grid = propertyGrid;
678                         }
679                         #region ITypeDescriptorContext Members
680
681                         public void OnComponentChanged() {
682                                 // TODO:  Add SystemComp.OnComponentChanged implementation
683                         }
684
685                         public IContainer Container {
686                                 get {
687                                         return property_grid as IContainer;
688                                 }
689                         }
690
691                         public bool OnComponentChanging() {
692                                 // TODO:  Add SystemComp.OnComponentChanging implementation
693                                 return false;
694                         }
695
696                         public object Instance {
697                                 get {
698                                         return property_grid.SelectedGridItem.Value;
699                                 }
700                         }
701
702                         public PropertyDescriptor PropertyDescriptor {
703                                 get {
704                                         return property_grid.SelectedGridItem.PropertyDescriptor;
705                                 }
706                         }
707
708                         #endregion
709
710                         #region IServiceProvider Members
711
712                         public object GetService(Type serviceType) {
713                                 // TODO:  Add SystemComp.GetService implementation
714                                 return null;
715                         }
716
717                         #endregion
718
719                 }
720
721
722                 
723                 /*
724                         class ComboListBox
725                 */
726                 internal class PropertyGridDropDown : Form {
727                         protected override CreateParams CreateParams {
728                                 get {
729                                         CreateParams cp = base.CreateParams;                            
730                                         cp.Style = unchecked ((int)(WindowStyles.WS_POPUP | WindowStyles.WS_CLIPSIBLINGS | WindowStyles.WS_CLIPCHILDREN));
731                                         cp.ExStyle |= (int)(WindowExStyles.WS_EX_TOOLWINDOW | WindowExStyles.WS_EX_TOPMOST);                            
732                                         return cp;
733                                 }
734                         }
735
736                 }
737
738                 #endregion
739         }
740 }