2006-02-07 Peter Dennis Bartok <pbartok@novell.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ThemeGtk.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) 2004-2006 Novell, Inc.
21 //
22 // Authors:
23 //      Jordi Mas i Hernandez, jordi@ximian.com
24 //      Alexander Olk, alex.olk@googlemail.com
25 //
26 //      This is an experimental GTK theme. 
27 //
28 //      Comments:
29 //              - For now we would keep all the themes in the same assembly to have
30 //              handy the internals methods. 
31 //              - We are using Pinovoke for now to access GTK/GDK to avoid adding 
32 //              gtk-sharp as a SWF dependency
33 //              - The ThemeGtk comes from ThemeWin32Classic, we use it as the default
34 //              implementation for the methods that we are not taking care of.
35 //              - When GDK is initialised it opens its own display. There is not way of changing it,
36 //              then we use that display as SWF display
37 //              - You can activate this Theme in Linux doing export MONO_THEME=gtk
38 //              - GTK paints controls into a window not a device context. We should inverstigate if we 
39 //              we can encapsulate a dc in a gtkwindow.
40
41
42 // NOT COMPLETE
43
44 // TODO:        - fix position of button focus rectangle
45 //              - fix TrackBar drawing location
46
47
48 //#define _EXPERIMENTAL_
49
50 using System;
51 using System.Drawing;
52 using System.Drawing.Drawing2D;
53 using System.Drawing.Imaging;
54 using System.Reflection;
55 using System.Runtime.InteropServices;
56 using System.IO;
57
58 namespace System.Windows.Forms
59 {
60         internal class ThemeGtk : ThemeWin32Classic
61         {               
62                 /* GTK enums */
63                 internal enum StateType 
64                 {
65                         Normal,
66                         Active,
67                         Prelight,
68                         Selected,
69                         Insensitive,
70                 }       
71
72                 internal enum ShadowType 
73                 {
74                         None,
75                         In,
76                         Out,
77                         EtchedIn,
78                         EtchedOut,
79                 }       
80
81                 internal enum ArrowType 
82                 {
83                         Up,
84                         Down,
85                         Left,
86                         Right,
87                 }
88                 
89                 /* Structs */
90                 [StructLayout(LayoutKind.Sequential)]   
91                 internal struct GdkColorStruct
92                 {
93                         internal int pixel;
94                         internal short red;
95                         internal short green;
96                         internal short blue;
97                 }
98
99                 [StructLayout(LayoutKind.Sequential)]   
100                 internal struct GObjectStruct {
101                         IntPtr  Instance;
102                         IntPtr  ref_count;
103                         IntPtr  data;
104                 }
105
106
107                 [StructLayout(LayoutKind.Sequential)]   
108                 internal struct GtkStyleStruct
109                 {
110                         internal GObjectStruct obj;
111                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
112                         internal GdkColorStruct[] fg;
113                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]               
114                         internal GdkColorStruct[] bg;
115                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
116                         internal GdkColorStruct[] light;
117                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
118                         internal GdkColorStruct[] dark;
119                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
120                         internal GdkColorStruct[] mid;
121                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
122                         internal GdkColorStruct[] text;
123                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
124                         internal GdkColorStruct[] baseclr;
125                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
126                         internal GdkColorStruct[] text_aa;              /* Halfway between text/base */
127   
128                         internal GdkColorStruct black;
129                         internal GdkColorStruct white;
130
131                         /* TODO: There is more stuff that we will add when we need it*/
132                 }
133                 
134                 /* GDK imports */
135                 [DllImport("libgdk-x11-2.0.so")]
136                 internal static extern IntPtr gdk_display_manager_get ();
137
138                 [DllImport("libgdk-x11-2.0.so")]
139                 internal static extern IntPtr gdk_display_manager_get_default_display (IntPtr display_manager);
140
141                 [DllImport("libgdk-x11-2.0.so")]
142                 internal static extern void gdk_display_manager_set_default_display (IntPtr display_manager, IntPtr display);
143
144                 [DllImport("libgdk-x11-2.0.so")]
145                 internal static extern IntPtr gdk_x11_display_get_xdisplay (IntPtr display);
146
147                 [DllImport("libgdk-x11-2.0.so")]
148                 static extern IntPtr gdk_window_foreign_new_for_display (IntPtr display, uint anid);
149
150                 [DllImport("libgdk-x11-2.0.so")]
151                 static extern bool gdk_init_check(out int argc, string argv);   
152                 
153                 [DllImport("libgdk-x11-2.0.so")]
154                 static extern IntPtr gdk_pixmap_new (IntPtr drawable, int width, int height, int depth);
155                 
156                 [DllImport("libgdk-x11-2.0.so")]
157                 static extern IntPtr gdk_pixbuf_get_from_drawable (IntPtr dest, IntPtr drawable_src, IntPtr cmap,
158                                                                    int src_x, int src_y, int dest_x, int dest_y, int width, int height);
159                 
160                 [DllImport("libgdk-x11-2.0.so")]
161                 static extern bool gdk_pixbuf_save_to_buffer (IntPtr pixbuf, out IntPtr buffer, out UIntPtr buffer_size, string type, out IntPtr error, IntPtr option_dummy);
162                 
163                 [DllImport("libgdk-x11-2.0.so")]
164                 static extern IntPtr gdk_drawable_get_colormap (IntPtr drawable);
165                 
166                 [DllImport("libgdk-x11-2.0.so")]
167                 static extern IntPtr gdk_colormap_get_system ();
168                 
169                 [DllImport("libgdk-x11-2.0.so")]
170                 static extern IntPtr gdk_pixbuf_new (int colorspace, bool has_alpha, int bits_per_sample, int width, int height);
171                 
172                 [DllImport("libgdk-x11-2.0.so")]
173                 static extern IntPtr gdk_gc_new (IntPtr drawable);
174                 
175                 /* glib imports*/
176                 [DllImport("libglib-2.0.so")]
177                 static extern void g_free (IntPtr mem);
178                 
179                 [DllImport("libgobject-2.0.so")]
180                 static extern void g_object_unref (IntPtr nativeObject);
181
182                 /* GTK imports */               
183                 [DllImport("libgtk-x11-2.0.so")]
184                 static extern bool gtk_init_check (out int argc, string argv);
185
186                 [DllImport("libgtk-x11-2.0.so")]
187                 static extern IntPtr gtk_adjustment_new (double value, double lower, double upper, double step_increment, double page_increment, double page_size);
188
189                 [DllImport("libgtk-x11-2.0.so")]
190                 static extern IntPtr gtk_rc_get_style (IntPtr widget);
191
192                 [DllImport("libgtk-x11-2.0.so")]
193                 static extern IntPtr gtk_vscrollbar_new(IntPtr adjustment);
194                 
195                 [DllImport("libgtk-x11-2.0.so")]
196                 static extern IntPtr gtk_hscrollbar_new(IntPtr adjustment);
197
198                 [DllImport("libgtk-x11-2.0.so")]
199                 static extern IntPtr gtk_style_attach (IntPtr raw, IntPtr window);
200
201                 [DllImport("libgtk-x11-2.0.so")]
202                 static extern IntPtr gtk_rc_style_new ();
203
204                 [DllImport("libgtk-x11-2.0.so")]
205                 static extern IntPtr gtk_invisible_new ();
206
207                 [DllImport("libgtk-x11-2.0.so")]
208                 static extern void gtk_widget_ensure_style (IntPtr raw);
209
210                 [DllImport("libgtk-x11-2.0.so")]
211                 static extern IntPtr gtk_widget_get_style (IntPtr raw);
212
213                 [DllImport("libgtk-x11-2.0.so")]
214                 static extern void gtk_style_detach (IntPtr raw);
215                 
216                 [DllImport("libgtk-x11-2.0.so")]
217                 static extern IntPtr gtk_button_new ();
218                 
219                 [DllImport("libgtk-x11-2.0.so")]
220                 static extern IntPtr gtk_progress_bar_new ();
221                 
222                 [DllImport("libgtk-x11-2.0.so")]
223                 static extern IntPtr gtk_radio_button_new (IntPtr group);
224                 
225                 [DllImport("libgtk-x11-2.0.so")]
226                 static extern IntPtr gtk_check_button_new ();
227                 
228                 [DllImport("libgtk-x11-2.0.so")]
229                 static extern IntPtr gtk_hscale_new (IntPtr adjustment);
230                 
231                 [DllImport("libgtk-x11-2.0.so")]
232                 static extern IntPtr gtk_vscale_new (IntPtr adjustment);
233                 
234                 [DllImport("libgtk-x11-2.0.so")]
235                 static extern void gtk_range_set_range (IntPtr range, double min, double max);
236                 
237                 [DllImport("libgtk-x11-2.0.so")]
238                 static extern void gtk_range_set_value (IntPtr range, double value);
239
240                 /* GTK Drawing */
241                 [DllImport("libgtk-x11-2.0.so")]
242                 static extern void gtk_paint_handle (IntPtr style, IntPtr window, int state_type, int shadow_type, IntPtr area, IntPtr widget, string detail, int x, int y, int width, int height, int orientation);
243
244                 [DllImport("libgtk-x11-2.0.so")]
245                 static extern void gtk_paint_arrow (IntPtr style, IntPtr window, int state_type, int shadow_type, 
246                                                     IntPtr area, IntPtr widget, string detail, int arrow_type, bool fill, int x, int y, int width, int height);
247
248                 [DllImport("libgtk-x11-2.0.so")]
249                 static extern void gtk_paint_slider (IntPtr style, IntPtr window, int state_type, int shadow_type, 
250                                                      IntPtr area, IntPtr widget, string detail, int x, int y, int width, int height, int orientation);
251
252                 [DllImport("libgtk-x11-2.0.so")]
253                 static extern void gtk_paint_box (IntPtr style, IntPtr window, int state_type, int shadow_type, 
254                                                   IntPtr area, IntPtr widget, string detail, int x, int y, int width, int height);
255                 
256                 [DllImport("libgtk-x11-2.0.so")]
257                 static extern void gtk_paint_flat_box (IntPtr style, IntPtr window, int state_type, int shadow_type,
258                                                        IntPtr area, IntPtr widget, string detail, int x, int y, int width, int height);
259                 
260                 [DllImport("libgtk-x11-2.0.so")]
261                 static extern void gtk_paint_hline(IntPtr style, IntPtr window, int state_type, IntPtr area, IntPtr widget, string detail, int x1, int x2, int y);
262                 
263                 [DllImport("libgtk-x11-2.0.so")]
264                 static extern void gtk_paint_vline(IntPtr style, IntPtr window, int state_type, IntPtr area, IntPtr widget, string detail, int y1, int y2, int x);
265                 
266                 [DllImport("libgtk-x11-2.0.so")]
267                 static extern void gtk_paint_check(IntPtr style, IntPtr window, int state_type, int shadow_type, IntPtr area, IntPtr widget, string detail, int x, int y, int width, int height);
268                 
269                 [DllImport("libgtk-x11-2.0.so")]
270                 static extern void gtk_paint_focus(IntPtr style, IntPtr window, int state_type, IntPtr area, IntPtr widget, string detail, int x, int y, int width, int height);
271                 
272                 [DllImport("libgtk-x11-2.0.so")]
273                 static extern void gtk_widget_size_allocate (IntPtr widget, ref Rectangle allocation);
274                 
275                 [DllImport("libgtk-x11-2.0.so")]
276                 static extern void gtk_paint_option (IntPtr style, IntPtr window, int state_type, int shadow_type, IntPtr area, IntPtr widget, string detail, int x, int y, int width, int height);
277                 
278                 [DllImport("libgtk-x11-2.0.so")]
279                 static extern void gtk_widget_grab_focus (IntPtr widget);
280                 
281                 /* Data */
282                 static protected IntPtr dispmgr;
283                 static protected IntPtr gdkdisplay;
284                 static protected IntPtr widget;
285                 static protected IntPtr global_style;
286                 
287                 #if _EXPERIMENTAL_
288                 static protected IntPtr global_color_map = IntPtr.Zero;
289                 #endif
290                 
291                 static protected IntPtr global_gtk_button = IntPtr.Zero;
292                 static protected IntPtr global_gtk_button_style = IntPtr.Zero;
293                 
294                 static protected IntPtr global_gtk_vscrollbar = IntPtr.Zero;
295                 static protected IntPtr global_gtk_vscrollbar_style = IntPtr.Zero;
296                 
297                 static protected IntPtr global_gtk_hscrollbar = IntPtr.Zero;
298                 static protected IntPtr global_gtk_hscrollbar_style = IntPtr.Zero;
299                 
300                 static protected IntPtr global_gtk_progress_bar = IntPtr.Zero;
301                 static protected IntPtr global_gtk_progress_bar_style = IntPtr.Zero;
302                 
303                 static protected IntPtr global_gtk_radio_button = IntPtr.Zero;
304                 static protected IntPtr global_gtk_radio_button_style = IntPtr.Zero;
305                 
306                 static protected IntPtr global_gtk_check_button = IntPtr.Zero;
307                 static protected IntPtr global_gtk_check_button_style = IntPtr.Zero;
308                 
309                 static protected IntPtr global_gtk_hscale = IntPtr.Zero;
310                 static protected IntPtr global_gtk_hscale_style = IntPtr.Zero;
311                 
312                 static protected IntPtr global_gtk_vscale = IntPtr.Zero;
313                 static protected IntPtr global_gtk_vscale_style = IntPtr.Zero;
314                 
315                 static protected IntPtr current_gdk_drawable = IntPtr.Zero;
316                 static protected IntPtr current_style = IntPtr.Zero;
317                 static protected IntPtr current_widget = IntPtr.Zero;
318
319                 public static void InitGtk ()
320                 {       
321                         Console.WriteLine ("ThemeGtk Init");            
322                         int argc = 0;
323                         string argv = "";
324                         
325                         gdk_init_check (out argc, argv);        
326
327                         dispmgr =  gdk_display_manager_get ();
328                         gdkdisplay =  gdk_display_manager_get_default_display (dispmgr);
329                         gtk_init_check (out argc, argv);
330
331                         widget = gtk_invisible_new ();
332                         gtk_widget_ensure_style (widget);
333                         global_style = gtk_widget_get_style (widget);                   
334
335                         XplatUIX11.GetInstance().SetDisplay (gdk_x11_display_get_xdisplay (gdkdisplay));
336                         
337                         global_gtk_button = gtk_button_new();
338                         gtk_widget_ensure_style (global_gtk_button);
339                         global_gtk_button_style = gtk_rc_get_style (global_gtk_button);
340                         
341                         IntPtr adj = gtk_adjustment_new (0, 0, 0, 0, 0, 0);
342                         global_gtk_vscrollbar = gtk_vscrollbar_new (adj);
343                         gtk_widget_ensure_style (global_gtk_vscrollbar);
344                         global_gtk_vscrollbar_style = gtk_rc_get_style (global_gtk_vscrollbar);
345                         
346                         global_gtk_hscrollbar = gtk_hscrollbar_new (adj);
347                         gtk_widget_ensure_style (global_gtk_hscrollbar);
348                         global_gtk_hscrollbar_style = gtk_rc_get_style (global_gtk_hscrollbar);
349                         
350                         global_gtk_progress_bar = gtk_progress_bar_new ();
351                         gtk_widget_ensure_style (global_gtk_progress_bar);
352                         global_gtk_progress_bar_style = gtk_rc_get_style (global_gtk_progress_bar);
353                         
354                         global_gtk_radio_button = gtk_radio_button_new (IntPtr.Zero);
355                         gtk_widget_ensure_style (global_gtk_radio_button);
356                         global_gtk_radio_button_style = gtk_rc_get_style (global_gtk_radio_button);
357                         
358                         global_gtk_check_button = gtk_check_button_new ();
359                         gtk_widget_ensure_style (global_gtk_check_button);
360                         global_gtk_check_button_style = gtk_rc_get_style (global_gtk_check_button);
361                         
362                         global_gtk_hscale = gtk_hscale_new (adj);
363                         gtk_widget_ensure_style (global_gtk_hscale);
364                         global_gtk_hscale_style = gtk_rc_get_style (global_gtk_hscale);
365                         
366                         global_gtk_vscale = gtk_vscale_new (adj);
367                         gtk_widget_ensure_style (global_gtk_vscale);
368                         global_gtk_vscale_style = gtk_rc_get_style (global_gtk_vscale);
369                         
370                         #if _EXPERIMENTAL_
371                         global_color_map = gdk_colormap_get_system ();
372                         #endif
373                 }
374
375                 public void LoadSysDefaultColors ()
376                 {
377                         GtkStyleStruct style_struct;                    
378                         
379                         style_struct = (GtkStyleStruct) Marshal.PtrToStructure (global_style, typeof (GtkStyleStruct));                 
380                         defaultWindowBackColor = ColorFromGdkColor (style_struct.bg[0]);
381                         defaultWindowForeColor = ColorFromGdkColor (style_struct.fg[0]);
382                 }
383
384                 public ThemeGtk () : base ()
385                 {
386                         Console.WriteLine ("ThemeGtk constructor");
387                         InitGtk ();
388                         default_font =  new Font (FontFamily.GenericSansSerif, 8.25f);
389                         
390                         LoadSysDefaultColors ();        
391
392                         always_draw_hotkeys = true;
393                 }       
394
395                 public override bool DoubleBufferingSupported {
396                         #if _EXPERIMENTAL_
397                         get {return true; }
398                         #else
399                         get {return false; }
400                         #endif
401                 }
402                 
403                 private void SetDrawableAndStyle (Control control)
404                 {
405                         #if _EXPERIMENTAL_
406                         if (current_gdk_drawable != IntPtr.Zero) {
407                                 g_object_unref (current_gdk_drawable);
408                                 current_gdk_drawable = IntPtr.Zero;
409                         }
410                         current_gdk_drawable = gdk_pixmap_new (IntPtr.Zero, control.ClientRectangle.Width, control.ClientRectangle.Height, 24);
411                         #else
412                         current_gdk_drawable = gdk_window_foreign_new_for_display (gdkdisplay, (uint) control.Handle);
413                         #endif
414                         
415                         IntPtr tmp_style = IntPtr.Zero;
416                         
417                         if (control is ButtonBase) {
418                                 tmp_style = global_gtk_button_style;
419                                 current_widget = global_gtk_button;
420                         } else
421                         if (control is ScrollBar) {
422                                 ScrollBar bar = control as ScrollBar;
423                                 if (bar.vert) {
424                                         tmp_style = global_gtk_vscrollbar_style;
425                                         current_widget = global_gtk_vscrollbar;
426                                 } else {
427                                         tmp_style = global_gtk_hscrollbar_style;
428                                         current_widget = global_gtk_hscrollbar;
429                                 }
430                         } else
431                         if (control is ProgressBar) {
432                                 tmp_style = global_gtk_progress_bar_style;
433                                 current_widget = global_gtk_progress_bar;
434                         } else
435                         if (control is RadioButton) {
436                                 tmp_style = global_gtk_radio_button_style;
437                                 current_widget = global_gtk_radio_button;
438                         } else
439                         if (control is CheckBox) {
440                                 tmp_style = global_gtk_check_button_style;
441                                 current_widget = global_gtk_check_button;
442                         } else
443                         if (control is TrackBar) {
444                                 TrackBar bar = control as TrackBar;
445                                 if (bar.Orientation == Orientation.Vertical) {
446                                         tmp_style = global_gtk_vscale_style;
447                                         current_widget = global_gtk_vscale;
448                                 } else {
449                                         tmp_style = global_gtk_hscale_style;
450                                         current_widget = global_gtk_hscale;
451                                 }
452                         } else
453                                 tmp_style = global_style;
454                         
455                         current_style = gtk_style_attach (tmp_style, current_gdk_drawable);  // need it
456                 }
457                 
458                 #if _EXPERIMENTAL_
459                 private void SetDrawableAndStyle (Rectangle area, Type type, Orientation orientation)
460                 {
461                         if (current_gdk_drawable != IntPtr.Zero) {
462                                 g_object_unref (current_gdk_drawable);
463                                 current_gdk_drawable = IntPtr.Zero;
464                         }
465                         current_gdk_drawable = gdk_pixmap_new (IntPtr.Zero, area.Width, area.Height, 24);
466                         
467                         IntPtr tmp_style = IntPtr.Zero;
468                         
469                         if (type == typeof(ButtonBase)) {
470                                 tmp_style = global_gtk_button_style;
471                                 current_widget = global_gtk_button;
472                         } else
473                         if (type == typeof(ScrollBar)) {
474                                 if (orientation == Orientation.Vertical) {
475                                         tmp_style = global_gtk_vscrollbar_style;
476                                         current_widget = global_gtk_vscrollbar;
477                                 } else {
478                                         tmp_style = global_gtk_hscrollbar_style;
479                                         current_widget = global_gtk_hscrollbar;
480                                 }
481                         } else
482                         if (type == typeof(ProgressBar)) {
483                                 tmp_style = global_gtk_progress_bar_style;
484                                 current_widget = global_gtk_progress_bar;
485                         } else
486                         if (type == typeof(RadioButton)) {
487                                 tmp_style = global_gtk_radio_button_style;
488                                 current_widget = global_gtk_radio_button;
489                         } else
490                         if (type == typeof(CheckBox)) {
491                                 tmp_style = global_gtk_check_button_style;
492                                 current_widget = global_gtk_check_button;
493                         } else
494                         if (type == typeof(TrackBar)) {
495                                 if (orientation == Orientation.Vertical) {
496                                         tmp_style = global_gtk_vscale_style;
497                                         current_widget = global_gtk_vscale;
498                                 } else {
499                                         tmp_style = global_gtk_hscale_style;
500                                         current_widget = global_gtk_hscale;
501                                 }
502                         } else
503                                 tmp_style = global_style;
504                         
505                         current_style = gtk_style_attach (tmp_style, current_gdk_drawable);  // need it
506                 }
507                 #endif
508                 
509                 #if _EXPERIMENTAL_
510                 private void DrawDrawableToDC (Graphics dc, Control control)
511                 {
512                         IntPtr new_pixbuf = gdk_pixbuf_new (0, true, 8, control.ClientRectangle.Width, control.ClientRectangle.Height);
513                         
514                         gdk_pixbuf_get_from_drawable (new_pixbuf,
515                                                       current_gdk_drawable,
516                                                       global_color_map,
517                                                       0,
518                                                       0,
519                                                       0,
520                                                       0,
521                                                       -1,
522                                                       -1);
523                         
524                         IntPtr error = IntPtr.Zero;
525                         IntPtr buffer;
526                         UIntPtr buffer_size_as_ptr;
527                         string type = "png";
528                         
529                         bool saved = gdk_pixbuf_save_to_buffer (new_pixbuf, out buffer, out buffer_size_as_ptr, type, out error, IntPtr.Zero);
530                         
531                         if (!saved)
532                                 return;
533                         
534                         int buffer_size = (int) (uint) buffer_size_as_ptr;
535                         byte[] result = new byte [buffer_size];
536                         Marshal.Copy (buffer, result, 0, (int) buffer_size);
537                         g_free (buffer);
538                         g_object_unref (new_pixbuf);
539                         
540                         Image image = null;
541                         using (MemoryStream s = new MemoryStream (result))
542                                 image = Image.FromStream (s);
543                         
544                         dc.DrawImage (image, control.ClientRectangle);
545                 }
546                 
547                 private void DrawDrawableToDC (Graphics dc, Rectangle area)
548                 {
549                         IntPtr new_pixbuf = gdk_pixbuf_new (0, true, 8, area.Width, area.Height);
550                         
551                         gdk_pixbuf_get_from_drawable (new_pixbuf,
552                                                       current_gdk_drawable,
553                                                       global_color_map,
554                                                       0,
555                                                       0,
556                                                       0,
557                                                       0,
558                                                       -1,
559                                                       -1);
560                         
561                         IntPtr error = IntPtr.Zero;
562                         IntPtr buffer;
563                         UIntPtr buffer_size_as_ptr;
564                         string type = "png";
565                         
566                         bool saved = gdk_pixbuf_save_to_buffer (new_pixbuf, out buffer, out buffer_size_as_ptr, type, out error, IntPtr.Zero);
567                         
568                         if (!saved)
569                                 return;
570                         
571                         int buffer_size = (int) (uint) buffer_size_as_ptr;
572                         byte[] result = new byte [buffer_size];
573                         Marshal.Copy (buffer, result, 0, (int) buffer_size);
574                         g_free (buffer);
575                         g_object_unref (new_pixbuf);
576                         
577                         Image image = null;
578                         using (MemoryStream s = new MemoryStream (result))
579                                 image = Image.FromStream (s);
580                         
581                         dc.DrawImage (image, area);
582                 }
583                 #endif
584                 
585                 public override void DrawButtonBase (Graphics dc, Rectangle clip_area, ButtonBase button)
586                 {
587                         SetDrawableAndStyle (button);
588                         
589                         // Draw the button: fill rectangle, draw border, etc.
590                         ButtonBase_DrawButton (button, dc);
591                         
592                         // First, draw the image
593                         if ((button.image != null) || (button.image_list != null))
594                                 ButtonBase_DrawImage (button, dc);
595                         
596                         // Draw the focus rectangle
597                         if (button.has_focus)
598                                 ButtonBase_DrawFocus (button, dc);
599                         
600                         #if _EXPERIMENTAL_
601                         DrawDrawableToDC (dc, button);
602                         #endif
603
604                         // Now the text
605                         if (button.text != null && button.text != String.Empty)
606                                 ButtonBase_DrawText (button, dc);
607                 }
608                 
609                 protected override void ButtonBase_DrawButton(ButtonBase button, Graphics dc)
610                 {
611                         Rectangle buttonRectangle = button.ClientRectangle;
612                         
613                         StateType state_type = StateType.Normal;
614                         ShadowType shadow_type = button.flat_style == FlatStyle.Flat ? ShadowType.In : ShadowType.Out;
615                         string detail = "buttondefault";
616                         
617                         if (((button is CheckBox) && (((CheckBox)button).check_state == CheckState.Checked)) ||
618                             ((button is RadioButton) && (((RadioButton)button).check_state == CheckState.Checked))) {
619                                 state_type = StateType.Active;
620                                 shadow_type = ShadowType.In;
621                                 detail = "button";
622                         } else
623                         if (!button.is_enabled) {
624                                 state_type = StateType.Insensitive;
625                         } else
626                         if (button.is_pressed) {
627                                 state_type = StateType.Active;
628                                 shadow_type = ShadowType.In;
629                                 detail = "button";
630                         } else
631                         if (button.is_entered) {
632                                 state_type = StateType.Prelight;
633                         }
634                         
635                         if (button.Focused)
636                                 gtk_widget_grab_focus (global_gtk_button);
637                         
638                         if (button.flat_style == FlatStyle.Flat)
639                                 gtk_paint_flat_box (current_style,
640                                                     current_gdk_drawable,
641                                                     (int) state_type,
642                                                     (int) shadow_type,
643                                                     IntPtr.Zero,
644                                                     global_gtk_button,
645                                                     detail,
646                                                     buttonRectangle.X, buttonRectangle.Y,
647                                                     buttonRectangle.Width, buttonRectangle.Height);
648                         else
649                         if (button.flat_style != FlatStyle.Popup || (button.flat_style == FlatStyle.Popup && button.is_entered))
650                                 gtk_paint_box (current_style,
651                                                current_gdk_drawable,
652                                                (int) state_type,
653                                                (int) shadow_type,
654                                                IntPtr.Zero,
655                                                global_gtk_button,
656                                                detail,
657                                                buttonRectangle.X, buttonRectangle.Y,
658                                                buttonRectangle.Width, buttonRectangle.Height);
659                 }
660                 
661                 protected override void ButtonBase_DrawFocus (ButtonBase button, Graphics dc)
662                 {
663                         if (!button.is_enabled)
664                                 return;
665                         
666                         Rectangle focus_rect = new Rectangle (button.ClientRectangle.X + 4, button.ClientRectangle.Y + 4, button.ClientRectangle.Width - 9, button.ClientRectangle.Height - 9);
667                         
668                         gtk_widget_grab_focus (global_gtk_button);
669                         
670                         gtk_paint_focus (current_style,
671                                          current_gdk_drawable,
672                                          (int) StateType.Active,
673                                          IntPtr.Zero,
674                                          global_gtk_button,
675                                          "button",
676                                          focus_rect.X,
677                                          focus_rect.Y,
678                                          focus_rect.Width,
679                                          focus_rect.Height);
680                 }
681                 
682                 #region ScrollBar
683                 public override void DrawScrollBar( Graphics dc, Rectangle clip, ScrollBar bar ) {
684                         int             scrollbutton_width = bar.scrollbutton_width;
685                         int             scrollbutton_height = bar.scrollbutton_height;
686                         Rectangle       first_arrow_area;
687                         Rectangle       second_arrow_area;                      
688                         Rectangle       thumb_pos;
689                         
690                         SetDrawableAndStyle (bar);
691                         
692                         Rectangle allocation = new Rectangle (bar.ClientRectangle.X, bar.ClientRectangle.Y, bar.ClientRectangle.Width, bar.ClientRectangle.Height);
693                         
694                         // fix for artefacts
695                         Color fix_color = bar.Parent != null ? bar.Parent.BackColor : ColorControl;
696                         
697                         if (bar.vert) {
698                                 gtk_widget_size_allocate (global_gtk_vscrollbar, ref allocation);
699                                 
700                                 // fix for artefacts
701                                 dc.FillRectangle (ResPool.GetSolidBrush (fix_color), 
702                                                   bar.ClientRectangle.X, bar.ClientRectangle.Y, bar.ClientRectangle.Width, 3);
703                                 dc.FillRectangle (ResPool.GetSolidBrush (fix_color), 
704                                                   bar.ClientRectangle.X, bar.ClientRectangle.Bottom - 4, bar.ClientRectangle.Width, 3);
705                         } else {
706                                 gtk_widget_size_allocate (global_gtk_hscrollbar, ref allocation);
707                                 
708                                 // fix for artefacts
709                                 dc.FillRectangle (ResPool.GetSolidBrush (fix_color), 
710                                                   bar.ClientRectangle.X, bar.ClientRectangle.Y, 3, bar.ClientRectangle.Height);
711                                 dc.FillRectangle (ResPool.GetSolidBrush (fix_color), 
712                                                   bar.ClientRectangle.Right - 4, bar.ClientRectangle.Y, 3, bar.ClientRectangle.Height);
713                         }
714                         
715                         thumb_pos = bar.ThumbPos;
716                         
717                         if ( bar.vert ) {
718                                 first_arrow_area = new Rectangle( 0, 0, bar.Width, scrollbutton_height + 1 );
719                                 bar.FirstArrowArea = first_arrow_area;
720                                 
721                                 second_arrow_area = new Rectangle( 0, bar.ClientRectangle.Height - scrollbutton_height - 1, bar.Width, scrollbutton_height + 1 );
722                                 bar.SecondArrowArea = second_arrow_area;
723                                 
724                                 thumb_pos.Width = bar.Width;
725                                 bar.ThumbPos = thumb_pos;
726                                 
727                                 ScrollBar_Vertical_Draw_ThumbMoving_None (scrollbutton_height, bar, clip, dc);
728                                 
729                                 /* Buttons */
730                                 if ( clip.IntersectsWith( first_arrow_area ) )
731                                         CPDrawScrollButton( dc, first_arrow_area, ScrollButton.Up, bar.firstbutton_state );
732                                 if ( clip.IntersectsWith( second_arrow_area ) )
733                                         CPDrawScrollButton( dc, second_arrow_area, ScrollButton.Down, bar.secondbutton_state );
734                         } else {
735                                 first_arrow_area = new Rectangle( 0, 0, scrollbutton_width + 1, bar.Height );
736                                 bar.FirstArrowArea = first_arrow_area;
737                                 
738                                 second_arrow_area = new Rectangle( bar.ClientRectangle.Width - scrollbutton_width - 1, 0, scrollbutton_width + 1, bar.Height );
739                                 bar.SecondArrowArea = second_arrow_area;
740                                 
741                                 thumb_pos.Height = bar.Height;
742                                 bar.ThumbPos = thumb_pos;
743                                 
744                                 /* Background */                                        
745                                 ScrollBar_Horizontal_Draw_ThumbMoving_None (scrollbutton_width, bar, clip, dc);
746                                 
747                                 /* Buttons */
748                                 if ( clip.IntersectsWith( first_arrow_area ) )
749                                         CPDrawScrollButton( dc, first_arrow_area, ScrollButton.Left, bar.firstbutton_state );
750                                 if ( clip.IntersectsWith( second_arrow_area ) )
751                                         CPDrawScrollButton( dc, second_arrow_area, ScrollButton.Right, bar.secondbutton_state );
752                         }
753                         
754                         /* Thumb */
755                         ScrollBar_DrawThumb( bar, thumb_pos, clip, dc );
756                         
757                         #if _EXPERIMENTAL_
758                         DrawDrawableToDC (dc, bar);
759                         #endif
760                 }
761                 
762                 protected override void ScrollBar_DrawThumb( ScrollBar bar, Rectangle thumb_pos, Rectangle clip, Graphics dc ) {
763                         if ( bar.Enabled)
764                                 DrawScrollBarThumb( dc, thumb_pos, bar );
765                 }
766                 
767                 protected override void ScrollBar_Vertical_Draw_ThumbMoving_None (int scrollbutton_height, ScrollBar bar, Rectangle clip, Graphics dc)
768                 {
769                         Rectangle r = new Rectangle (0,
770                                                      scrollbutton_height, bar.ClientRectangle.Width, bar.ClientRectangle.Height - (scrollbutton_height * 2));
771                         gtk_paint_box (current_style, 
772                                        current_gdk_drawable, 
773                                        (int) StateType.Active,
774                                        (int) ShadowType.In,
775                                        IntPtr.Zero,
776                                        global_gtk_vscrollbar,
777                                        "vscrollbar",
778                                        r.X, r.Y,
779                                        r.Width, r.Height);
780                 }
781                 
782                 protected override void ScrollBar_Horizontal_Draw_ThumbMoving_None (int scrollbutton_width, ScrollBar bar, Rectangle clip, Graphics dc)
783                 {
784                         Rectangle r = new Rectangle (scrollbutton_width,
785                                                      0, bar.ClientRectangle.Width - (scrollbutton_width * 2), bar.ClientRectangle.Height);
786                         
787                         gtk_paint_box (current_style, 
788                                        current_gdk_drawable, 
789                                        (int) StateType.Active,
790                                        (int) ShadowType.In,
791                                        IntPtr.Zero,
792                                        global_gtk_hscrollbar,
793                                        "hscrollbar",
794                                        r.X, r.Y,
795                                        r.Width, r.Height);
796                 }
797                 
798                 private void DrawScrollBarThumb( Graphics dc, Rectangle area, ScrollBar bar ) {
799                         IntPtr gtk_scrollbar = bar.vert ? global_gtk_vscrollbar : global_gtk_hscrollbar;
800                         
801                         gtk_paint_box (current_style, 
802                                        current_gdk_drawable, 
803                                        (int) StateType.Active,
804                                        (int) ShadowType.Out,
805                                        IntPtr.Zero,
806                                        gtk_scrollbar,
807                                        "slider",
808                                        area.X, area.Y,
809                                        area.Width, area.Height);
810                 }
811                 #endregion      // ScrollBar
812                 
813                 #region ProgressBar
814                 public override void DrawProgressBar (Graphics dc, Rectangle clip_rect, ProgressBar ctrl)
815                 {
816                         Rectangle       client_area = ctrl.client_area;
817                         int             barpos_pixels;
818                         
819                         SetDrawableAndStyle (ctrl);
820                         
821                         // draw background
822                         gtk_paint_box (current_style,
823                                        current_gdk_drawable,
824                                        (int) StateType.Normal,
825                                        (int) ShadowType.In, 
826                                        IntPtr.Zero,
827                                        global_gtk_progress_bar,
828                                        "trough",
829                                        ctrl.ClientRectangle.X, 
830                                        ctrl.ClientRectangle.Y,
831                                        ctrl.ClientRectangle.Width,
832                                        ctrl.ClientRectangle.Height);
833                         
834                         // don't draw the bar if Value is = 0
835                         if (ctrl.Value <= 0)
836                                 return;
837                         
838                         int value = ctrl.Value;
839                         
840                         if (value > ctrl.Maximum)
841                                 value = ctrl.Maximum;
842                         
843                         if (value == ctrl.Maximum)
844                                 barpos_pixels = client_area.Width + 2;
845                         else
846                                 barpos_pixels = (((value - ctrl.Minimum) * client_area.Width) / (ctrl.Maximum - ctrl.Minimum)) + 1;
847                         
848                         gtk_paint_box (current_style, 
849                                        current_gdk_drawable, 
850                                        (int) StateType.Prelight,
851                                        (int) ShadowType.Out,
852                                        IntPtr.Zero,
853                                        global_gtk_progress_bar,
854                                        "bar",
855                                        client_area.X - 1, client_area.Y - 1,
856                                        barpos_pixels, client_area.Height + 2);
857                         
858                         #if _EXPERIMENTAL_
859                         DrawDrawableToDC (dc, ctrl);
860                         #endif
861                 }
862                 #endregion      // ProgressBar
863                 
864                 #region RadioButton
865                 protected override void RadioButton_DrawButton (RadioButton radio_button, Graphics dc, ButtonState state, Rectangle radiobutton_rectangle)
866                 {
867                         // we currently don't care for flat or popup radio buttons
868                         if (radio_button.appearance == Appearance.Button) {
869                                 DrawButtonBase (dc, radio_button.ClientRectangle, radio_button);
870                         } else {
871                                 DrawRadioButton (dc, radio_button, state, radiobutton_rectangle);
872                         }
873                 }
874                 
875                 private void DrawRadioButton (Graphics dc, RadioButton radio_button, ButtonState state, Rectangle radiobutton_rectangle)
876                 {
877                         SetDrawableAndStyle (radio_button);
878                         
879                         ShadowType shadow_type;
880                         
881                         if (!radio_button.Enabled)
882                                 shadow_type = ShadowType.Out;
883                         else
884                                 shadow_type = radio_button.Checked ? ShadowType.In : ShadowType.EtchedIn;
885                         
886                         StateType state_type = StateType.Normal;
887                         
888                         if (!radio_button.Enabled)
889                                 state_type = StateType.Insensitive;
890                         else
891                         if (radio_button.is_pressed)
892                                 state_type = StateType.Active;
893                         else
894                         if (radio_button.is_entered)
895                                 state_type = StateType.Prelight;
896                         
897                         gtk_paint_option (current_style,
898                                           current_gdk_drawable,
899                                           (int) state_type,
900                                           (int) shadow_type,
901                                           IntPtr.Zero,
902                                           global_gtk_radio_button,
903                                           "radiobutton",
904                                           radiobutton_rectangle.X,
905                                           radiobutton_rectangle.Y,
906                                           radiobutton_rectangle.Width,
907                                           radiobutton_rectangle.Height);
908                         
909                         #if _EXPERIMENTAL_
910                         DrawDrawableToDC (dc, radio_button);
911                         #endif
912                 }
913                 
914                 protected override void RadioButton_DrawText (RadioButton radio_button, Rectangle text_rectangle, Graphics dc, StringFormat text_format)
915                 {
916                         if (radio_button.Appearance != Appearance.Button)
917                                 base.RadioButton_DrawText (radio_button, text_rectangle, dc, text_format);
918                 }
919         
920                 protected override void RadioButton_DrawFocus (RadioButton radio_button, Graphics dc, Rectangle text_rectangle)
921                 {
922                         if (radio_button.Focused && radio_button.appearance != Appearance.Button) {
923                                 gtk_paint_focus (current_style,
924                                                  current_gdk_drawable,
925                                                  (int) StateType.Active,
926                                                  IntPtr.Zero,
927                                                  global_gtk_radio_button,
928                                                  "radiobutton",
929                                                  text_rectangle.X,
930                                                  text_rectangle.Y,
931                                                  text_rectangle.Width,
932                                                  text_rectangle.Height);
933                         }
934                         
935                         #if _EXPERIMENTAL_
936                         DrawDrawableToDC (dc, radio_button);
937                         #endif
938                 }
939                 #endregion      // RadioButton
940                 
941                 #region CheckBox
942                 protected override void CheckBox_DrawCheckBox (Graphics dc, CheckBox checkbox, ButtonState state, Rectangle checkbox_rectangle)
943                 {
944                         // render as per normal button
945                         if (checkbox.appearance == Appearance.Button) {
946                                 DrawButtonBase (dc, checkbox.ClientRectangle, checkbox);
947                         } else {
948                                 InternalDrawCheckBox (dc, checkbox, state, checkbox_rectangle);
949                         }
950                 }
951                 
952                 private void InternalDrawCheckBox (Graphics dc, CheckBox checkbox, ButtonState state, Rectangle checkbox_rectangle)
953                 {
954                         SetDrawableAndStyle (checkbox);
955                         
956                         ShadowType shadow_type;
957                         
958                         if (!checkbox.Enabled)
959                                 shadow_type = ShadowType.Out;
960                         else
961                                 shadow_type = checkbox.Checked ? ShadowType.In : ShadowType.EtchedIn;
962                         
963                         StateType state_type = StateType.Normal;
964                         
965                         if (!checkbox.Enabled)
966                                 state_type = StateType.Insensitive;
967                         else
968                         if (checkbox.is_pressed)
969                                 state_type = StateType.Active;
970                         else
971                         if (checkbox.is_entered)
972                                 state_type = StateType.Prelight;
973                         
974                         gtk_paint_check (current_style,
975                                          current_gdk_drawable,
976                                          (int) state_type,
977                                          (int) shadow_type,
978                                          IntPtr.Zero,
979                                          global_gtk_check_button,
980                                          "checkbutton",
981                                          checkbox_rectangle.X,
982                                          checkbox_rectangle.Y,
983                                          checkbox_rectangle.Width,
984                                          checkbox_rectangle.Height);
985                         
986                         #if _EXPERIMENTAL_
987                         DrawDrawableToDC (dc, checkbox);
988                         #endif
989                 }
990                 
991                 protected override void CheckBox_DrawText (CheckBox checkbox, Rectangle text_rectangle, Graphics dc, StringFormat text_format)
992                 {
993                         if (checkbox.Appearance != Appearance.Button)
994                                 base.CheckBox_DrawText (checkbox, text_rectangle, dc, text_format);
995                 }
996                 
997                 protected override void CheckBox_DrawFocus( CheckBox checkbox, Graphics dc, Rectangle text_rectangle )
998                 {
999                         if (checkbox.Focused && checkbox.appearance != Appearance.Button) {
1000                                 gtk_paint_focus (current_style,
1001                                                  current_gdk_drawable,
1002                                                  (int) StateType.Active,
1003                                                  IntPtr.Zero,
1004                                                  global_gtk_check_button,
1005                                                  "checkbutton",
1006                                                  text_rectangle.X,
1007                                                  text_rectangle.Y,
1008                                                  text_rectangle.Width,
1009                                                  text_rectangle.Height);
1010                         }
1011                         
1012                         #if _EXPERIMENTAL_
1013                         DrawDrawableToDC (dc, checkbox);
1014                         #endif
1015                 }
1016                 #endregion      // CheckBox
1017                 
1018                 #region TrackBar
1019                 private void DrawTrackBar_Vertical (Graphics dc, Rectangle clip_rectangle, TrackBar tb,
1020                                                     ref Rectangle thumb_pos, ref Rectangle thumb_area,
1021                                                     float ticks, int value_pos, bool mouse_value)
1022                 {                       
1023                         Point toptick_startpoint = new Point ();
1024                         Point bottomtick_startpoint = new Point ();
1025                         Point channel_startpoint = new Point ();
1026                         float pixel_len;
1027                         float pixels_betweenticks;
1028                         const int space_from_right = 8;
1029                         const int space_from_left = 8;
1030                         Rectangle area = tb.ClientRectangle;
1031                         
1032                         Rectangle allocation = new Rectangle (area.X, area.Y, area.Width, area.Height);
1033                         
1034                         gtk_widget_size_allocate (current_widget, ref allocation);
1035                         
1036                         gtk_range_set_range (current_widget, tb.Minimum, tb.Maximum);
1037                         gtk_range_set_value (current_widget, tb.Value);
1038                         
1039                         ShadowType shadow_type = ShadowType.In;
1040                         
1041                         if (!tb.Enabled)
1042                                 shadow_type = ShadowType.Out;
1043                         
1044                         StateType state_type = StateType.Normal;
1045                         
1046                         if (!tb.Enabled)
1047                                 state_type = StateType.Insensitive;
1048                         else
1049                         if (tb.is_entered)
1050                                 state_type = StateType.Prelight;
1051                         
1052                         switch (tb.TickStyle)   {
1053                         case TickStyle.BottomRight:
1054                         case TickStyle.None:
1055                                 channel_startpoint.Y = 8;
1056                                 channel_startpoint.X = 9;
1057                                 bottomtick_startpoint.Y = 13;
1058                                 bottomtick_startpoint.X = 24;                           
1059                                 break;
1060                         case TickStyle.TopLeft:
1061                                 channel_startpoint.Y = 8;
1062                                 channel_startpoint.X = 19;
1063                                 toptick_startpoint.Y = 13;
1064                                 toptick_startpoint.X = 8;
1065                                 break;
1066                         case TickStyle.Both:
1067                                 channel_startpoint.Y = 8;
1068                                 channel_startpoint.X = 18;      
1069                                 bottomtick_startpoint.Y = 13;
1070                                 bottomtick_startpoint.X = 32;                           
1071                                 toptick_startpoint.Y = 13;
1072                                 toptick_startpoint.X = 8;                               
1073                                 break;
1074                         default:
1075                                 break;
1076                         }
1077                         
1078                         thumb_area.X = area.X + channel_startpoint.X;
1079                         thumb_area.Y = area.Y + channel_startpoint.Y;
1080                         thumb_area.Height = area.Height - space_from_right - space_from_left;
1081                         thumb_area.Width = 4;
1082                         
1083                         pixel_len = thumb_area.Height - 11;
1084                         pixels_betweenticks = pixel_len / (tb.Maximum - tb.Minimum);
1085                         
1086                         /* Convert thumb position from mouse position to value*/
1087                         if (mouse_value) {
1088                                 
1089                                 if (value_pos >= channel_startpoint.Y)
1090                                         value_pos = (int)(((float) (value_pos - channel_startpoint.Y)) / pixels_betweenticks);
1091                                 else
1092                                         value_pos = 0;                  
1093                                 
1094                                 if (value_pos + tb.Minimum > tb.Maximum)
1095                                         value_pos = tb.Maximum - tb.Minimum;
1096                                 
1097                                 tb.Value = value_pos + tb.Minimum;
1098                         }               
1099                         
1100                         thumb_pos.Width = 13;
1101                         thumb_pos.Height = 29;
1102                         
1103                         thumb_pos.Y = channel_startpoint.Y + (int) (pixels_betweenticks * (float) value_pos) - (thumb_pos.Height / 3);
1104                         
1105                         if (thumb_pos.Y < channel_startpoint.Y)
1106                                 thumb_pos.Y = channel_startpoint.Y;
1107                         
1108                         if (thumb_pos.Y > thumb_area.Bottom - 29)
1109                                 thumb_pos.Y = thumb_area.Bottom - 29;
1110                         
1111                         /* Draw channel */
1112                         gtk_paint_box (current_style,
1113                                        current_gdk_drawable,
1114                                        (int)state_type,
1115                                        (int)shadow_type,
1116                                        IntPtr.Zero,
1117                                        current_widget,
1118                                        "trough",
1119                                        thumb_area.X,
1120                                        thumb_area.Y,
1121                                        4,
1122                                        thumb_area.Height);
1123                         
1124                         /* Draw thumb */
1125                         thumb_pos.X = channel_startpoint.X + 2 - thumb_pos.Width / 2;
1126                         
1127                         shadow_type = ShadowType.Out;
1128                         
1129                         gtk_paint_slider (current_style,
1130                                           current_gdk_drawable,
1131                                           (int)state_type,
1132                                           (int)shadow_type,
1133                                           IntPtr.Zero,
1134                                           current_widget,
1135                                           "vscale",
1136                                           thumb_pos.X,
1137                                           thumb_pos.Y,
1138                                           thumb_pos.Width,
1139                                           thumb_pos.Height,
1140                                           0);
1141                         
1142                         pixel_len = thumb_area.Height - 11;
1143                         pixels_betweenticks = pixel_len / ticks;
1144                         
1145                         /* Draw ticks*/
1146                         thumb_area.X = thumb_pos.X;
1147                         thumb_area.Y = channel_startpoint.Y;
1148                         thumb_area.Width = thumb_pos.Width;
1149                         
1150                         Region outside = new Region (area);
1151                         outside.Exclude (thumb_area);                   
1152                         
1153                         if (outside.IsVisible (clip_rectangle)) {                               
1154                                 if (pixels_betweenticks > 0 && ((tb.TickStyle & TickStyle.BottomRight) == TickStyle.BottomRight ||
1155                                     ((tb.TickStyle & TickStyle.Both) == TickStyle.Both))) {     
1156                                         
1157                                         for (float inc = 0; inc < (pixel_len + 1); inc += pixels_betweenticks)  {                                       
1158                                                 if (inc == 0 || (inc +  pixels_betweenticks) >= pixel_len + 1)
1159                                                         dc.DrawLine (ResPool.GetPen (pen_ticks_color), area.X + bottomtick_startpoint.X , area.Y + bottomtick_startpoint.Y  + inc, 
1160                                                                      area.X + bottomtick_startpoint.X  + 3, area.Y + bottomtick_startpoint.Y + inc);
1161                                                 else
1162                                                         dc.DrawLine (ResPool.GetPen (pen_ticks_color), area.X + bottomtick_startpoint.X, area.Y + bottomtick_startpoint.Y  + inc, 
1163                                                                      area.X + bottomtick_startpoint.X  + 2, area.Y + bottomtick_startpoint.Y + inc);
1164                                         }
1165                                 }
1166                                 
1167                                 if (pixels_betweenticks > 0 &&  ((tb.TickStyle & TickStyle.TopLeft) == TickStyle.TopLeft ||
1168                                     ((tb.TickStyle & TickStyle.Both) == TickStyle.Both))) {
1169                                         
1170                                         pixel_len = thumb_area.Height - 11;
1171                                         pixels_betweenticks = pixel_len / ticks;
1172                                         
1173                                         for (float inc = 0; inc < (pixel_len + 1); inc += pixels_betweenticks) {                                        
1174                                                 if (inc == 0 || (inc +  pixels_betweenticks) >= pixel_len + 1)
1175                                                         dc.DrawLine (ResPool.GetPen (pen_ticks_color), area.X + toptick_startpoint.X  - 3 , area.Y + toptick_startpoint.Y + inc, 
1176                                                                      area.X + toptick_startpoint.X, area.Y + toptick_startpoint.Y + inc);
1177                                                 else
1178                                                         dc.DrawLine (ResPool.GetPen (pen_ticks_color), area.X + toptick_startpoint.X  - 2, area.Y + toptick_startpoint.Y + inc, 
1179                                                                      area.X + toptick_startpoint.X, area.Y + toptick_startpoint.Y  + inc);
1180                                         }                       
1181                                 }
1182                         }
1183                         
1184                         outside.Dispose ();
1185                 }
1186                 
1187                 private void DrawTrackBar_Horizontal (Graphics dc, Rectangle clip_rectangle, TrackBar tb,
1188                                                       ref Rectangle thumb_pos, ref Rectangle thumb_area,
1189                                                       float ticks, int value_pos, bool mouse_value)
1190                 {                       
1191                         Point toptick_startpoint = new Point ();
1192                         Point bottomtick_startpoint = new Point ();
1193                         Point channel_startpoint = new Point ();
1194                         float pixel_len;
1195                         float pixels_betweenticks;
1196                         const int space_from_right = 8;
1197                         const int space_from_left = 8;
1198                         Rectangle area = tb.ClientRectangle;
1199                         
1200                         Rectangle allocation = new Rectangle (area.X, area.Y, area.Width, area.Height);
1201                         
1202                         gtk_widget_size_allocate (current_widget, ref allocation);
1203                         
1204                         gtk_range_set_range (current_widget, tb.Minimum, tb.Maximum);
1205                         gtk_range_set_value (current_widget, tb.Value);
1206                         
1207                         ShadowType shadow_type = ShadowType.In;
1208                         
1209                         if (!tb.Enabled)
1210                                 shadow_type = ShadowType.Out;
1211                         
1212                         StateType state_type = StateType.Normal;
1213                         
1214                         if (!tb.Enabled)
1215                                 state_type = StateType.Insensitive;
1216                         else
1217                         if (tb.is_entered)
1218                                 state_type = StateType.Prelight;
1219                         
1220                         switch (tb.TickStyle) {
1221                         case TickStyle.BottomRight:
1222                         case TickStyle.None:
1223                                 channel_startpoint.X = 8;
1224                                 channel_startpoint.Y = 9;
1225                                 bottomtick_startpoint.X = 13;
1226                                 bottomtick_startpoint.Y = 24;                           
1227                                 break;
1228                         case TickStyle.TopLeft:
1229                                 channel_startpoint.X = 8;
1230                                 channel_startpoint.Y = 19;
1231                                 toptick_startpoint.X = 13;
1232                                 toptick_startpoint.Y = 8;
1233                                 break;
1234                         case TickStyle.Both:
1235                                 channel_startpoint.X = 8;
1236                                 channel_startpoint.Y = 18;      
1237                                 bottomtick_startpoint.X = 13;
1238                                 bottomtick_startpoint.Y = 32;                           
1239                                 toptick_startpoint.X = 13;
1240                                 toptick_startpoint.Y = 8;                               
1241                                 break;
1242                         default:
1243                                 break;
1244                         }
1245                         
1246                         thumb_area.X = area.X + channel_startpoint.X;
1247                         thumb_area.Y = area.Y + channel_startpoint.Y;
1248                         thumb_area.Width = area.Width - space_from_right - space_from_left;
1249                         thumb_area.Height = 4;
1250                         
1251                         pixel_len = thumb_area.Width - 11;
1252                         pixels_betweenticks = pixel_len / (tb.Maximum - tb.Minimum);
1253                         
1254                         /* Convert thumb position from mouse position to value*/
1255                         if (mouse_value) {                      
1256                                 if (value_pos >= channel_startpoint.X)
1257                                         value_pos = (int)(((float) (value_pos - channel_startpoint.X)) / pixels_betweenticks);
1258                                 else
1259                                         value_pos = 0;                          
1260                                 
1261                                 if (value_pos + tb.Minimum > tb.Maximum)
1262                                         value_pos = tb.Maximum - tb.Minimum;
1263                                 
1264                                 tb.Value = value_pos + tb.Minimum;
1265                         }                       
1266                         
1267                         thumb_pos.Width = 29;
1268                         thumb_pos.Height = 13;
1269                         
1270                         thumb_pos.X = channel_startpoint.X + (int) (pixels_betweenticks * (float) value_pos) - (thumb_pos.Width / 3);
1271                         
1272                         
1273                         if (thumb_pos.X < channel_startpoint.X)
1274                                 thumb_pos.X = channel_startpoint.X;
1275                         
1276                         if (thumb_pos.X > thumb_area.Right - 29)
1277                                 thumb_pos.X = thumb_area.Right - 29;
1278                         
1279                         /* Draw channel */
1280                         gtk_paint_box (current_style,
1281                                        current_gdk_drawable,
1282                                        (int)state_type,
1283                                        (int)shadow_type,
1284                                        IntPtr.Zero,
1285                                        current_widget,
1286                                        "trough",
1287                                        thumb_area.X,
1288                                        thumb_area.Y,
1289                                        thumb_area.Width,
1290                                        4);
1291                         
1292                         /* Draw thumb */
1293                         
1294                         thumb_pos.Y = channel_startpoint.Y + 2 - thumb_pos.Height / 2;
1295                         
1296                         shadow_type = ShadowType.Out;
1297                         
1298                         gtk_paint_slider (current_style,
1299                                           current_gdk_drawable,
1300                                           (int)state_type,
1301                                           (int)shadow_type,
1302                                           IntPtr.Zero,
1303                                           current_widget,
1304                                           "hscale",
1305                                           thumb_pos.X,
1306                                           thumb_pos.Y,
1307                                           thumb_pos.Width,
1308                                           thumb_pos.Height,
1309                                           0);
1310                         
1311                         pixel_len = thumb_area.Width - 11;
1312                         pixels_betweenticks = pixel_len / ticks;
1313                         
1314                         /* Draw ticks*/
1315                         thumb_area.Y = thumb_pos.Y;
1316                         thumb_area.X = channel_startpoint.X;
1317                         thumb_area.Height = thumb_pos.Height;
1318                         Region outside = new Region (area);
1319                         outside.Exclude (thumb_area);                   
1320                         
1321                         if (outside.IsVisible (clip_rectangle)) {                               
1322                                 if (pixels_betweenticks > 0 && ((tb.TickStyle & TickStyle.BottomRight) == TickStyle.BottomRight ||
1323                                     ((tb.TickStyle & TickStyle.Both) == TickStyle.Both))) {                             
1324                                         
1325                                         for (float inc = 0; inc < (pixel_len + 1); inc += pixels_betweenticks) {                                        
1326                                                 if (inc == 0 || (inc +  pixels_betweenticks) >= pixel_len + 1)
1327                                                         dc.DrawLine (ResPool.GetPen (pen_ticks_color), area.X + bottomtick_startpoint.X + inc , area.Y + bottomtick_startpoint.Y, 
1328                                                                      area.X + bottomtick_startpoint.X + inc , area.Y + bottomtick_startpoint.Y + 3);
1329                                                 else
1330                                                         dc.DrawLine (ResPool.GetPen (pen_ticks_color), area.X + bottomtick_startpoint.X + inc, area.Y + bottomtick_startpoint.Y, 
1331                                                                      area.X + bottomtick_startpoint.X + inc, area.Y + bottomtick_startpoint.Y + 2);
1332                                         }
1333                                 }
1334                                 
1335                                 if (pixels_betweenticks > 0 && ((tb.TickStyle & TickStyle.TopLeft) == TickStyle.TopLeft ||
1336                                     ((tb.TickStyle & TickStyle.Both) == TickStyle.Both))) {
1337                                         
1338                                         for (float inc = 0; inc < (pixel_len + 1); inc += pixels_betweenticks) {                                        
1339                                                 if (inc == 0 || (inc +  pixels_betweenticks) >= pixel_len + 1)
1340                                                         dc.DrawLine (ResPool.GetPen (pen_ticks_color), area.X + toptick_startpoint.X + inc , area.Y + toptick_startpoint.Y - 3, 
1341                                                                      area.X + toptick_startpoint.X + inc , area.Y + toptick_startpoint.Y);
1342                                                 else
1343                                                         dc.DrawLine (ResPool.GetPen (pen_ticks_color), area.X + toptick_startpoint.X + inc, area.Y + toptick_startpoint.Y - 2, 
1344                                                                      area.X + toptick_startpoint.X + inc, area.Y + toptick_startpoint.Y);
1345                                         }                       
1346                                 }
1347                         }
1348                         
1349                         outside.Dispose ();                     
1350                 }
1351                 
1352                 public override void DrawTrackBar (Graphics dc, Rectangle clip_rectangle, TrackBar tb)
1353                 {
1354                         int             value_pos;
1355                         bool            mouse_value;
1356                         float           ticks = (tb.Maximum - tb.Minimum) / tb.tickFrequency; /* N of ticks draw*/
1357                         Rectangle       area;
1358                         Rectangle       thumb_pos = tb.ThumbPos;
1359                         Rectangle       thumb_area = tb.ThumbArea;
1360                         
1361                         if (tb.thumb_pressed) {
1362                                 value_pos = tb.thumb_mouseclick;
1363                                 mouse_value = true;
1364                         } else {
1365                                 value_pos = tb.Value - tb.Minimum;
1366                                 mouse_value = false;
1367                         }
1368                         
1369                         area = tb.ClientRectangle;
1370                         
1371                         SetDrawableAndStyle (tb);
1372                         
1373                         /* Control Background */
1374                         if (tb.BackColor == DefaultControlBackColor) {
1375                                 dc.FillRectangle (ResPool.GetSolidBrush (ColorControl), clip_rectangle);
1376                         } else {
1377                                 dc.FillRectangle (ResPool.GetSolidBrush (tb.BackColor), clip_rectangle);
1378                         }
1379                         
1380                         if (tb.Orientation == Orientation.Vertical) {
1381                                 DrawTrackBar_Vertical (dc, clip_rectangle, tb, ref thumb_pos, ref thumb_area,
1382                                                        ticks, value_pos, mouse_value);
1383                                 
1384                         } else {
1385                                 DrawTrackBar_Horizontal (dc, clip_rectangle, tb, ref thumb_pos, ref thumb_area,
1386                                                          ticks, value_pos, mouse_value);
1387                         }
1388                         
1389                         if (tb.Enabled && tb.Focused)
1390                                 gtk_paint_focus (current_style,
1391                                                  current_gdk_drawable, 
1392                                                  (int)StateType.Normal,
1393                                                  IntPtr.Zero,
1394                                                  current_widget, 
1395                                                  "trough",
1396                                                  area.X,
1397                                                  area.Y,
1398                                                  area.Width,
1399                                                  area.Height);
1400                         
1401                         tb.ThumbPos = thumb_pos;
1402                         tb.ThumbArea = thumb_area;
1403                         
1404                         #if _EXPERIMENTAL_
1405                         DrawDrawableToDC (dc, tb);
1406                         #endif
1407                 }
1408                 #endregion      // TrackBar
1409                 
1410                 public override void CPDrawButton (Graphics dc, Rectangle rectangle, ButtonState state)
1411                 {
1412                         #if _EXPERIMENTAL_
1413                         SetDrawableAndStyle (rectangle, typeof(ButtonBase), Orientation.Horizontal);
1414                         #endif
1415                         
1416                         bool is_pushed = false;
1417 //                      bool is_checked = false;
1418 //                      bool is_flat = false;
1419                         bool is_inactive = false;
1420                         
1421                         if ((state & ButtonState.Pushed) != 0) {
1422                                 is_pushed = true;
1423                         }
1424                         
1425 //                      if ((state & ButtonState.Checked) != 0) {
1426 //                              is_checked = true;
1427 //                      }
1428 //                      
1429 //                      if ((state & ButtonState.Flat) != 0) {
1430 //                              is_flat = true;
1431 //                      }
1432                         
1433                         if ((state & ButtonState.Inactive) != 0) {
1434                                 is_inactive = true;
1435                         }
1436                         
1437                         IntPtr drawbutton_style = gtk_style_attach (global_gtk_button_style, current_gdk_drawable);  // need it
1438                         
1439                         StateType state_type = StateType.Normal;
1440                         ShadowType shadow_type = ShadowType.Out;
1441                         string detail = "buttondefault";
1442                         
1443                         if (is_inactive) {
1444                                 state_type = StateType.Insensitive;
1445                         } else
1446                         if (is_pushed) {
1447                                 state_type = StateType.Active;
1448                                 shadow_type = ShadowType.In;
1449                                 detail = "button";
1450                         }
1451                         
1452                         gtk_paint_box (drawbutton_style, current_gdk_drawable,
1453                                        (int) state_type,
1454                                        (int) shadow_type,
1455                                        IntPtr.Zero,
1456                                        IntPtr.Zero,
1457                                        detail,
1458                                        rectangle.X, rectangle.Y,
1459                                        rectangle.Width, rectangle.Height);
1460                         
1461                         #if _EXPERIMENTAL_
1462                         DrawDrawableToDC (dc, rectangle);
1463                         #endif
1464                 }
1465                 
1466                 /* Scroll button: regular button + direction arrow */
1467                 public override void CPDrawScrollButton (Graphics dc, Rectangle area, ScrollButton scroll_button_type, ButtonState state)
1468                 {
1469                         #if _EXPERIMENTAL_
1470                         Orientation orientation = Orientation.Vertical;
1471                         if (scroll_button_type == ScrollButton.Left || scroll_button_type == ScrollButton.Right)
1472                                 orientation = Orientation.Horizontal;
1473                         SetDrawableAndStyle (area, typeof(ScrollBar), orientation);
1474                         #endif
1475                         
1476                         bool enabled = (state == ButtonState.Inactive) ? false: true;
1477                         
1478                         StateType state_type = enabled ? StateType.Normal : StateType.Insensitive;
1479                         
1480                         DrawScrollButtonPrimitive (dc, area, state, scroll_button_type);
1481                         
1482                         if (area.Width < 12 || area.Height < 12) /* Cannot see a thing at smaller sizes */
1483                                 return;
1484                         
1485                         ArrowType arrow_type = 0;
1486                         
1487                         switch (scroll_button_type) {
1488                         case ScrollButton.Up:
1489                                 arrow_type = ArrowType.Up;
1490                                 break;
1491                         case ScrollButton.Down:
1492                                 arrow_type = ArrowType.Down;
1493                                 break;
1494                         case ScrollButton.Right:
1495                                 arrow_type = ArrowType.Right;
1496                                 break;
1497                         case ScrollButton.Left:
1498                                 arrow_type = ArrowType.Left;
1499                                 break;
1500                         default:
1501                                 break;
1502                         }
1503                         
1504                         int centerX = area.Left + area.Width / 2;
1505                         int centerY = area.Top + area.Height / 2;
1506                         int arrow_x = 0, arrow_y = 0, arrow_height = 0, arrow_width = 0;
1507                         
1508                         switch (scroll_button_type) {
1509                         case ScrollButton.Down:
1510                         case ScrollButton.Up:
1511                                 arrow_x = centerX - 4;
1512                                 arrow_y = centerY - 2;
1513                                 arrow_width = 8;
1514                                 arrow_height = 4;
1515                                 break;
1516                         case ScrollButton.Left:
1517                         case ScrollButton.Right:
1518                                 arrow_x = centerX - 2;
1519                                 arrow_y = centerY - 4;
1520                                 arrow_width = 4;
1521                                 arrow_height = 8;
1522                                 break;
1523                         default:
1524                                 break;
1525                         }
1526                         
1527                         gtk_paint_arrow (current_style, 
1528                                          current_gdk_drawable, 
1529                                          (int) state_type,
1530                                          (int) ShadowType.Out,
1531                                          IntPtr.Zero,
1532                                          current_widget,
1533                                          "",            
1534                                          (int) arrow_type, true, 
1535                                          arrow_x, 
1536                                          arrow_y,
1537                                          arrow_width, arrow_height);
1538                         
1539                         current_widget = IntPtr.Zero;
1540                         
1541                         #if _EXPERIMENTAL_
1542                         DrawDrawableToDC (dc, area);
1543                         #endif
1544                 }
1545                 
1546                 public void DrawScrollButtonPrimitive (Graphics dc, Rectangle area, ButtonState state, ScrollButton scroll_button_type)
1547                 {
1548                         StateType state_type = StateType.Normal;
1549                         ShadowType shadow_type = ShadowType.Out;
1550                         
1551                         if ((state & ButtonState.Pushed) == ButtonState.Pushed) {
1552                                 state_type = StateType.Active;
1553                                 shadow_type = ShadowType.In;
1554                         }
1555                         
1556                         switch (scroll_button_type) {
1557                         case ScrollButton.Left:
1558                         case ScrollButton.Right:
1559                                 gtk_paint_box (current_style, 
1560                                                current_gdk_drawable, 
1561                                                (int) state_type,
1562                                                (int) shadow_type,
1563                                                IntPtr.Zero,
1564                                                global_gtk_hscrollbar,
1565                                                "stepper",
1566                                                area.X, area.Y,
1567                                                area.Width, area.Height);
1568                                 break;
1569                         case ScrollButton.Up:
1570                         case ScrollButton.Down:
1571                                 gtk_paint_box (current_style, 
1572                                                current_gdk_drawable, 
1573                                                (int) state_type,
1574                                                (int) shadow_type,
1575                                                IntPtr.Zero,
1576                                                global_gtk_vscrollbar,
1577                                                "stepper",
1578                                                area.X, area.Y,
1579                                                area.Width, area.Height);
1580                                 break;
1581                         }
1582                 }
1583                 
1584                 private static Color ColorFromGdkColor (GdkColorStruct gtkcolor)
1585                 {
1586                         return Color.FromArgb (255, 
1587                                 (gtkcolor.red >> 8)  & 0xff, 
1588                                 (gtkcolor.green  >> 8) & 0xff,
1589                                 (gtkcolor.blue >> 8) & 0xff );
1590                 }
1591
1592         } //class
1593 }