2007-01-02 Mike Kestner <mkestner@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                         public IntPtr Instance;
102                         public IntPtr ref_count;
103                         public 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(IntPtr argc, IntPtr 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 (IntPtr argc, IntPtr 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                         
323                         gdk_init_check (IntPtr.Zero, IntPtr.Zero);      
324
325                         dispmgr =  gdk_display_manager_get ();
326                         gdkdisplay =  gdk_display_manager_get_default_display (dispmgr);
327                         gtk_init_check (IntPtr.Zero, IntPtr.Zero);
328
329                         widget = gtk_invisible_new ();
330                         gtk_widget_ensure_style (widget);
331                         global_style = gtk_widget_get_style (widget);                   
332
333                         XplatUIX11.GetInstance().SetDisplay (gdk_x11_display_get_xdisplay (gdkdisplay));
334                         
335                         global_gtk_button = gtk_button_new();
336                         gtk_widget_ensure_style (global_gtk_button);
337                         global_gtk_button_style = gtk_rc_get_style (global_gtk_button);
338                         
339                         IntPtr adj = gtk_adjustment_new (0, 0, 0, 0, 0, 0);
340                         global_gtk_vscrollbar = gtk_vscrollbar_new (adj);
341                         gtk_widget_ensure_style (global_gtk_vscrollbar);
342                         global_gtk_vscrollbar_style = gtk_rc_get_style (global_gtk_vscrollbar);
343                         
344                         global_gtk_hscrollbar = gtk_hscrollbar_new (adj);
345                         gtk_widget_ensure_style (global_gtk_hscrollbar);
346                         global_gtk_hscrollbar_style = gtk_rc_get_style (global_gtk_hscrollbar);
347                         
348                         global_gtk_progress_bar = gtk_progress_bar_new ();
349                         gtk_widget_ensure_style (global_gtk_progress_bar);
350                         global_gtk_progress_bar_style = gtk_rc_get_style (global_gtk_progress_bar);
351                         
352                         global_gtk_radio_button = gtk_radio_button_new (IntPtr.Zero);
353                         gtk_widget_ensure_style (global_gtk_radio_button);
354                         global_gtk_radio_button_style = gtk_rc_get_style (global_gtk_radio_button);
355                         
356                         global_gtk_check_button = gtk_check_button_new ();
357                         gtk_widget_ensure_style (global_gtk_check_button);
358                         global_gtk_check_button_style = gtk_rc_get_style (global_gtk_check_button);
359                         
360                         global_gtk_hscale = gtk_hscale_new (adj);
361                         gtk_widget_ensure_style (global_gtk_hscale);
362                         global_gtk_hscale_style = gtk_rc_get_style (global_gtk_hscale);
363                         
364                         global_gtk_vscale = gtk_vscale_new (adj);
365                         gtk_widget_ensure_style (global_gtk_vscale);
366                         global_gtk_vscale_style = gtk_rc_get_style (global_gtk_vscale);
367                         
368                         #if _EXPERIMENTAL_
369                         global_color_map = gdk_colormap_get_system ();
370                         #endif
371                 }
372
373                 public void LoadSysDefaultColors ()
374                 {
375                         GtkStyleStruct style_struct;                    
376                         
377                         style_struct = (GtkStyleStruct) Marshal.PtrToStructure (global_style, typeof (GtkStyleStruct));                 
378                         defaultWindowBackColor = ColorFromGdkColor (style_struct.bg[0]);
379                         defaultWindowForeColor = ColorFromGdkColor (style_struct.fg[0]);
380                 }
381
382                 public ThemeGtk () : base ()
383                 {
384                         Console.WriteLine ("ThemeGtk constructor");
385                         InitGtk ();
386                         
387                         LoadSysDefaultColors ();        
388
389                         always_draw_hotkeys = true;
390                 }       
391
392                 public override bool DoubleBufferingSupported {
393                         #if _EXPERIMENTAL_
394                         get {return true; }
395                         #else
396                         get {return false; }
397                         #endif
398                 }
399                 
400                 private void SetDrawableAndStyle (Control control)
401                 {
402                         #if _EXPERIMENTAL_
403                         if (current_gdk_drawable != IntPtr.Zero) {
404                                 g_object_unref (current_gdk_drawable);
405                                 current_gdk_drawable = IntPtr.Zero;
406                         }
407                         current_gdk_drawable = gdk_pixmap_new (IntPtr.Zero, control.ClientRectangle.Width, control.ClientRectangle.Height, 24);
408                         #else
409                         current_gdk_drawable = gdk_window_foreign_new_for_display (gdkdisplay, (uint) control.Handle);
410                         #endif
411                         
412                         IntPtr tmp_style = IntPtr.Zero;
413                         
414                         if (control is ButtonBase) {
415                                 tmp_style = global_gtk_button_style;
416                                 current_widget = global_gtk_button;
417                         } else
418                         if (control is ScrollBar) {
419                                 ScrollBar bar = control as ScrollBar;
420                                 if (bar.vert) {
421                                         tmp_style = global_gtk_vscrollbar_style;
422                                         current_widget = global_gtk_vscrollbar;
423                                 } else {
424                                         tmp_style = global_gtk_hscrollbar_style;
425                                         current_widget = global_gtk_hscrollbar;
426                                 }
427                         } else
428                         if (control is ProgressBar) {
429                                 tmp_style = global_gtk_progress_bar_style;
430                                 current_widget = global_gtk_progress_bar;
431                         } else
432                         if (control is RadioButton) {
433                                 tmp_style = global_gtk_radio_button_style;
434                                 current_widget = global_gtk_radio_button;
435                         } else
436                         if (control is CheckBox) {
437                                 tmp_style = global_gtk_check_button_style;
438                                 current_widget = global_gtk_check_button;
439                         } else
440                         if (control is TrackBar) {
441                                 TrackBar bar = control as TrackBar;
442                                 if (bar.Orientation == Orientation.Vertical) {
443                                         tmp_style = global_gtk_vscale_style;
444                                         current_widget = global_gtk_vscale;
445                                 } else {
446                                         tmp_style = global_gtk_hscale_style;
447                                         current_widget = global_gtk_hscale;
448                                 }
449                         } else
450                                 tmp_style = global_style;
451                         
452                         current_style = gtk_style_attach (tmp_style, current_gdk_drawable);  // need it
453                 }
454                 
455                 #if _EXPERIMENTAL_
456                 private void SetDrawableAndStyle (Rectangle area, Type type, Orientation orientation)
457                 {
458                         if (current_gdk_drawable != IntPtr.Zero) {
459                                 g_object_unref (current_gdk_drawable);
460                                 current_gdk_drawable = IntPtr.Zero;
461                         }
462                         current_gdk_drawable = gdk_pixmap_new (IntPtr.Zero, area.Width, area.Height, 24);
463                         
464                         IntPtr tmp_style = IntPtr.Zero;
465                         
466                         if (type == typeof(ButtonBase)) {
467                                 tmp_style = global_gtk_button_style;
468                                 current_widget = global_gtk_button;
469                         } else
470                         if (type == typeof(ScrollBar)) {
471                                 if (orientation == Orientation.Vertical) {
472                                         tmp_style = global_gtk_vscrollbar_style;
473                                         current_widget = global_gtk_vscrollbar;
474                                 } else {
475                                         tmp_style = global_gtk_hscrollbar_style;
476                                         current_widget = global_gtk_hscrollbar;
477                                 }
478                         } else
479                         if (type == typeof(ProgressBar)) {
480                                 tmp_style = global_gtk_progress_bar_style;
481                                 current_widget = global_gtk_progress_bar;
482                         } else
483                         if (type == typeof(RadioButton)) {
484                                 tmp_style = global_gtk_radio_button_style;
485                                 current_widget = global_gtk_radio_button;
486                         } else
487                         if (type == typeof(CheckBox)) {
488                                 tmp_style = global_gtk_check_button_style;
489                                 current_widget = global_gtk_check_button;
490                         } else
491                         if (type == typeof(TrackBar)) {
492                                 if (orientation == Orientation.Vertical) {
493                                         tmp_style = global_gtk_vscale_style;
494                                         current_widget = global_gtk_vscale;
495                                 } else {
496                                         tmp_style = global_gtk_hscale_style;
497                                         current_widget = global_gtk_hscale;
498                                 }
499                         } else
500                                 tmp_style = global_style;
501                         
502                         current_style = gtk_style_attach (tmp_style, current_gdk_drawable);  // need it
503                 }
504                 #endif
505                 
506                 #if _EXPERIMENTAL_
507                 private void DrawDrawableToDC (Graphics dc, Control control)
508                 {
509                         IntPtr new_pixbuf = gdk_pixbuf_new (0, true, 8, control.ClientRectangle.Width, control.ClientRectangle.Height);
510                         
511                         gdk_pixbuf_get_from_drawable (new_pixbuf,
512                                                       current_gdk_drawable,
513                                                       global_color_map,
514                                                       0,
515                                                       0,
516                                                       0,
517                                                       0,
518                                                       -1,
519                                                       -1);
520                         
521                         IntPtr error = IntPtr.Zero;
522                         IntPtr buffer;
523                         UIntPtr buffer_size_as_ptr;
524                         string type = "png";
525                         
526                         bool saved = gdk_pixbuf_save_to_buffer (new_pixbuf, out buffer, out buffer_size_as_ptr, type, out error, IntPtr.Zero);
527                         
528                         if (!saved)
529                                 return;
530                         
531                         int buffer_size = (int) (uint) buffer_size_as_ptr;
532                         byte[] result = new byte [buffer_size];
533                         Marshal.Copy (buffer, result, 0, (int) buffer_size);
534                         g_free (buffer);
535                         g_object_unref (new_pixbuf);
536                         
537                         Image image = null;
538                         using (MemoryStream s = new MemoryStream (result))
539                                 image = Image.FromStream (s);
540                         
541                         dc.DrawImage (image, control.ClientRectangle);
542                 }
543                 
544                 private void DrawDrawableToDC (Graphics dc, Rectangle area)
545                 {
546                         IntPtr new_pixbuf = gdk_pixbuf_new (0, true, 8, area.Width, area.Height);
547                         
548                         gdk_pixbuf_get_from_drawable (new_pixbuf,
549                                                       current_gdk_drawable,
550                                                       global_color_map,
551                                                       0,
552                                                       0,
553                                                       0,
554                                                       0,
555                                                       -1,
556                                                       -1);
557                         
558                         IntPtr error = IntPtr.Zero;
559                         IntPtr buffer;
560                         UIntPtr buffer_size_as_ptr;
561                         string type = "png";
562                         
563                         bool saved = gdk_pixbuf_save_to_buffer (new_pixbuf, out buffer, out buffer_size_as_ptr, type, out error, IntPtr.Zero);
564                         
565                         if (!saved)
566                                 return;
567                         
568                         int buffer_size = (int) (uint) buffer_size_as_ptr;
569                         byte[] result = new byte [buffer_size];
570                         Marshal.Copy (buffer, result, 0, (int) buffer_size);
571                         g_free (buffer);
572                         g_object_unref (new_pixbuf);
573                         
574                         Image image = null;
575                         using (MemoryStream s = new MemoryStream (result))
576                                 image = Image.FromStream (s);
577                         
578                         dc.DrawImage (image, area);
579                 }
580                 #endif
581                 
582                 public override void DrawButtonBase (Graphics dc, Rectangle clip_area, ButtonBase button)
583                 {
584                         SetDrawableAndStyle (button);
585                         
586                         // Draw the button: fill rectangle, draw border, etc.
587                         ButtonBase_DrawButton (button, dc);
588                         
589                         // First, draw the image
590                         if ((button.image != null) || (button.image_list != null))
591                                 ButtonBase_DrawImage (button, dc);
592                         
593                         // Draw the focus rectangle
594                         if (button.has_focus)
595                                 ButtonBase_DrawFocus (button, dc);
596                         
597                         #if _EXPERIMENTAL_
598                         DrawDrawableToDC (dc, button);
599                         #endif
600
601                         // Now the text
602                         if (button.Text != null && button.Text != String.Empty)
603                                 ButtonBase_DrawText (button, dc);
604                 }
605                 
606                 protected override void ButtonBase_DrawButton(ButtonBase button, Graphics dc)
607                 {
608                         Rectangle buttonRectangle = button.ClientRectangle;
609                         
610                         StateType state_type = StateType.Normal;
611                         ShadowType shadow_type = button.FlatStyle == FlatStyle.Flat ? ShadowType.In : ShadowType.Out;
612                         string detail = "buttondefault";
613                         
614                         if (((button is CheckBox) && (((CheckBox)button).check_state == CheckState.Checked)) ||
615                             ((button is RadioButton) && (((RadioButton)button).check_state == CheckState.Checked))) {
616                                 state_type = StateType.Active;
617                                 shadow_type = ShadowType.In;
618                                 detail = "button";
619                         } else
620                         if (!button.is_enabled) {
621                                 state_type = StateType.Insensitive;
622                         } else
623                         if (button.is_pressed) {
624                                 state_type = StateType.Active;
625                                 shadow_type = ShadowType.In;
626                                 detail = "button";
627                         } else
628                         if (button.is_entered) {
629                                 state_type = StateType.Prelight;
630                         }
631                         
632                         if (button.Focused)
633                                 gtk_widget_grab_focus (global_gtk_button);
634                         
635                         if (button.FlatStyle == FlatStyle.Flat)
636                                 gtk_paint_flat_box (current_style,
637                                                     current_gdk_drawable,
638                                                     (int) state_type,
639                                                     (int) shadow_type,
640                                                     IntPtr.Zero,
641                                                     global_gtk_button,
642                                                     detail,
643                                                     buttonRectangle.X, buttonRectangle.Y,
644                                                     buttonRectangle.Width, buttonRectangle.Height);
645                         else
646                         if (button.FlatStyle != FlatStyle.Popup || (button.FlatStyle == FlatStyle.Popup && button.is_entered))
647                                 gtk_paint_box (current_style,
648                                                current_gdk_drawable,
649                                                (int) state_type,
650                                                (int) shadow_type,
651                                                IntPtr.Zero,
652                                                global_gtk_button,
653                                                detail,
654                                                buttonRectangle.X, buttonRectangle.Y,
655                                                buttonRectangle.Width, buttonRectangle.Height);
656                 }
657                 
658                 protected override void ButtonBase_DrawFocus (ButtonBase button, Graphics dc)
659                 {
660                         if (!button.is_enabled)
661                                 return;
662                         
663                         Rectangle focus_rect = new Rectangle (button.ClientRectangle.X + 4, button.ClientRectangle.Y + 4, button.ClientRectangle.Width - 9, button.ClientRectangle.Height - 9);
664                         
665                         gtk_widget_grab_focus (global_gtk_button);
666                         
667                         gtk_paint_focus (current_style,
668                                          current_gdk_drawable,
669                                          (int) StateType.Active,
670                                          IntPtr.Zero,
671                                          global_gtk_button,
672                                          "button",
673                                          focus_rect.X,
674                                          focus_rect.Y,
675                                          focus_rect.Width,
676                                          focus_rect.Height);
677                 }
678                 
679                 #region ScrollBar
680                 public override void DrawScrollBar( Graphics dc, Rectangle clip, ScrollBar bar ) {
681                         int             scrollbutton_width = bar.scrollbutton_width;
682                         int             scrollbutton_height = bar.scrollbutton_height;
683                         Rectangle       first_arrow_area;
684                         Rectangle       second_arrow_area;                      
685                         Rectangle       thumb_pos;
686                         
687                         SetDrawableAndStyle (bar);
688                         
689                         Rectangle allocation = new Rectangle (bar.ClientRectangle.X, bar.ClientRectangle.Y, bar.ClientRectangle.Width, bar.ClientRectangle.Height);
690                         
691                         // fix for artefacts
692                         Color fix_color = bar.Parent != null ? bar.Parent.BackColor : ColorControl;
693                         
694                         if (bar.vert) {
695                                 gtk_widget_size_allocate (global_gtk_vscrollbar, ref allocation);
696                                 
697                                 // fix for artefacts
698                                 dc.FillRectangle (ResPool.GetSolidBrush (fix_color), 
699                                                   bar.ClientRectangle.X, bar.ClientRectangle.Y, bar.ClientRectangle.Width, 3);
700                                 dc.FillRectangle (ResPool.GetSolidBrush (fix_color), 
701                                                   bar.ClientRectangle.X, bar.ClientRectangle.Bottom - 4, bar.ClientRectangle.Width, 3);
702                         } else {
703                                 gtk_widget_size_allocate (global_gtk_hscrollbar, ref allocation);
704                                 
705                                 // fix for artefacts
706                                 dc.FillRectangle (ResPool.GetSolidBrush (fix_color), 
707                                                   bar.ClientRectangle.X, bar.ClientRectangle.Y, 3, bar.ClientRectangle.Height);
708                                 dc.FillRectangle (ResPool.GetSolidBrush (fix_color), 
709                                                   bar.ClientRectangle.Right - 4, bar.ClientRectangle.Y, 3, bar.ClientRectangle.Height);
710                         }
711                         
712                         thumb_pos = bar.ThumbPos;
713                         
714                         if ( bar.vert ) {
715                                 first_arrow_area = new Rectangle( 0, 0, bar.Width, scrollbutton_height + 1 );
716                                 bar.FirstArrowArea = first_arrow_area;
717                                 
718                                 second_arrow_area = new Rectangle( 0, bar.ClientRectangle.Height - scrollbutton_height - 1, bar.Width, scrollbutton_height + 1 );
719                                 bar.SecondArrowArea = second_arrow_area;
720                                 
721                                 thumb_pos.Width = bar.Width;
722                                 bar.ThumbPos = thumb_pos;
723                                 
724                                 ScrollBar_Vertical_Draw_ThumbMoving_None (scrollbutton_height, bar, clip, dc);
725                                 
726                                 /* Buttons */
727                                 if ( clip.IntersectsWith( first_arrow_area ) )
728                                         CPDrawScrollButton( dc, first_arrow_area, ScrollButton.Up, bar.firstbutton_state );
729                                 if ( clip.IntersectsWith( second_arrow_area ) )
730                                         CPDrawScrollButton( dc, second_arrow_area, ScrollButton.Down, bar.secondbutton_state );
731                         } else {
732                                 first_arrow_area = new Rectangle( 0, 0, scrollbutton_width + 1, bar.Height );
733                                 bar.FirstArrowArea = first_arrow_area;
734                                 
735                                 second_arrow_area = new Rectangle( bar.ClientRectangle.Width - scrollbutton_width - 1, 0, scrollbutton_width + 1, bar.Height );
736                                 bar.SecondArrowArea = second_arrow_area;
737                                 
738                                 thumb_pos.Height = bar.Height;
739                                 bar.ThumbPos = thumb_pos;
740                                 
741                                 /* Background */                                        
742                                 ScrollBar_Horizontal_Draw_ThumbMoving_None (scrollbutton_width, bar, clip, dc);
743                                 
744                                 /* Buttons */
745                                 if ( clip.IntersectsWith( first_arrow_area ) )
746                                         CPDrawScrollButton( dc, first_arrow_area, ScrollButton.Left, bar.firstbutton_state );
747                                 if ( clip.IntersectsWith( second_arrow_area ) )
748                                         CPDrawScrollButton( dc, second_arrow_area, ScrollButton.Right, bar.secondbutton_state );
749                         }
750                         
751                         /* Thumb */
752                         ScrollBar_DrawThumb( bar, thumb_pos, clip, dc );
753                         
754                         #if _EXPERIMENTAL_
755                         DrawDrawableToDC (dc, bar);
756                         #endif
757                 }
758                 
759                 protected override void ScrollBar_DrawThumb( ScrollBar bar, Rectangle thumb_pos, Rectangle clip, Graphics dc ) {
760                         if ( bar.Enabled)
761                                 DrawScrollBarThumb( dc, thumb_pos, bar );
762                 }
763                 
764                 protected override void ScrollBar_Vertical_Draw_ThumbMoving_None (int scrollbutton_height, ScrollBar bar, Rectangle clip, Graphics dc)
765                 {
766                         Rectangle r = new Rectangle (0,
767                                                      scrollbutton_height, bar.ClientRectangle.Width, bar.ClientRectangle.Height - (scrollbutton_height * 2));
768                         gtk_paint_box (current_style, 
769                                        current_gdk_drawable, 
770                                        (int) StateType.Active,
771                                        (int) ShadowType.In,
772                                        IntPtr.Zero,
773                                        global_gtk_vscrollbar,
774                                        "vscrollbar",
775                                        r.X, r.Y,
776                                        r.Width, r.Height);
777                 }
778                 
779                 protected override void ScrollBar_Horizontal_Draw_ThumbMoving_None (int scrollbutton_width, ScrollBar bar, Rectangle clip, Graphics dc)
780                 {
781                         Rectangle r = new Rectangle (scrollbutton_width,
782                                                      0, bar.ClientRectangle.Width - (scrollbutton_width * 2), bar.ClientRectangle.Height);
783                         
784                         gtk_paint_box (current_style, 
785                                        current_gdk_drawable, 
786                                        (int) StateType.Active,
787                                        (int) ShadowType.In,
788                                        IntPtr.Zero,
789                                        global_gtk_hscrollbar,
790                                        "hscrollbar",
791                                        r.X, r.Y,
792                                        r.Width, r.Height);
793                 }
794                 
795                 private void DrawScrollBarThumb( Graphics dc, Rectangle area, ScrollBar bar ) {
796                         IntPtr gtk_scrollbar = bar.vert ? global_gtk_vscrollbar : global_gtk_hscrollbar;
797                         
798                         gtk_paint_box (current_style, 
799                                        current_gdk_drawable, 
800                                        (int) StateType.Active,
801                                        (int) ShadowType.Out,
802                                        IntPtr.Zero,
803                                        gtk_scrollbar,
804                                        "slider",
805                                        area.X, area.Y,
806                                        area.Width, area.Height);
807                 }
808                 #endregion      // ScrollBar
809                 
810                 #region ProgressBar
811                 public override void DrawProgressBar (Graphics dc, Rectangle clip_rect, ProgressBar ctrl)
812                 {
813                         Rectangle       client_area = ctrl.client_area;
814                         int             barpos_pixels;
815                         
816                         SetDrawableAndStyle (ctrl);
817                         
818                         // draw background
819                         gtk_paint_box (current_style,
820                                        current_gdk_drawable,
821                                        (int) StateType.Normal,
822                                        (int) ShadowType.In, 
823                                        IntPtr.Zero,
824                                        global_gtk_progress_bar,
825                                        "trough",
826                                        ctrl.ClientRectangle.X, 
827                                        ctrl.ClientRectangle.Y,
828                                        ctrl.ClientRectangle.Width,
829                                        ctrl.ClientRectangle.Height);
830                         
831                         // don't draw the bar if Value is = 0
832                         if (ctrl.Value <= 0)
833                                 return;
834                         
835                         int value = ctrl.Value;
836                         
837                         if (value > ctrl.Maximum)
838                                 value = ctrl.Maximum;
839                         
840                         if (value == ctrl.Maximum)
841                                 barpos_pixels = client_area.Width + 2;
842                         else
843                                 barpos_pixels = (((value - ctrl.Minimum) * client_area.Width) / (ctrl.Maximum - ctrl.Minimum)) + 1;
844                         
845                         gtk_paint_box (current_style, 
846                                        current_gdk_drawable, 
847                                        (int) StateType.Prelight,
848                                        (int) ShadowType.Out,
849                                        IntPtr.Zero,
850                                        global_gtk_progress_bar,
851                                        "bar",
852                                        client_area.X - 1, client_area.Y - 1,
853                                        barpos_pixels, client_area.Height + 2);
854                         
855                         #if _EXPERIMENTAL_
856                         DrawDrawableToDC (dc, ctrl);
857                         #endif
858                 }
859                 #endregion      // ProgressBar
860                 
861                 #region RadioButton
862                 protected override void RadioButton_DrawButton (RadioButton radio_button, Graphics dc, ButtonState state, Rectangle radiobutton_rectangle)
863                 {
864                         // we currently don't care for flat or popup radio buttons
865                         if (radio_button.appearance == Appearance.Button) {
866                                 DrawButtonBase (dc, radio_button.ClientRectangle, radio_button);
867                         } else {
868                                 DrawRadioButton (dc, radio_button, state, radiobutton_rectangle);
869                         }
870                 }
871                 
872                 private void DrawRadioButton (Graphics dc, RadioButton radio_button, ButtonState state, Rectangle radiobutton_rectangle)
873                 {
874                         SetDrawableAndStyle (radio_button);
875                         
876                         ShadowType shadow_type;
877                         
878                         if (!radio_button.Enabled)
879                                 shadow_type = ShadowType.Out;
880                         else
881                                 shadow_type = radio_button.Checked ? ShadowType.In : ShadowType.EtchedIn;
882                         
883                         StateType state_type = StateType.Normal;
884                         
885                         if (!radio_button.Enabled)
886                                 state_type = StateType.Insensitive;
887                         else
888                         if (radio_button.is_pressed)
889                                 state_type = StateType.Active;
890                         else
891                         if (radio_button.is_entered)
892                                 state_type = StateType.Prelight;
893                         
894                         gtk_paint_option (current_style,
895                                           current_gdk_drawable,
896                                           (int) state_type,
897                                           (int) shadow_type,
898                                           IntPtr.Zero,
899                                           global_gtk_radio_button,
900                                           "radiobutton",
901                                           radiobutton_rectangle.X,
902                                           radiobutton_rectangle.Y,
903                                           radiobutton_rectangle.Width,
904                                           radiobutton_rectangle.Height);
905                         
906                         #if _EXPERIMENTAL_
907                         DrawDrawableToDC (dc, radio_button);
908                         #endif
909                 }
910                 
911                 protected override void RadioButton_DrawText (RadioButton radio_button, Rectangle text_rectangle, Graphics dc, StringFormat text_format)
912                 {
913                         if (radio_button.Appearance != Appearance.Button)
914                                 base.RadioButton_DrawText (radio_button, text_rectangle, dc, text_format);
915                 }
916         
917                 protected override void RadioButton_DrawFocus (RadioButton radio_button, Graphics dc, Rectangle text_rectangle)
918                 {
919                         if (radio_button.Focused && radio_button.appearance != Appearance.Button) {
920                                 gtk_paint_focus (current_style,
921                                                  current_gdk_drawable,
922                                                  (int) StateType.Active,
923                                                  IntPtr.Zero,
924                                                  global_gtk_radio_button,
925                                                  "radiobutton",
926                                                  text_rectangle.X,
927                                                  text_rectangle.Y,
928                                                  text_rectangle.Width,
929                                                  text_rectangle.Height);
930                         }
931                         
932                         #if _EXPERIMENTAL_
933                         DrawDrawableToDC (dc, radio_button);
934                         #endif
935                 }
936                 #endregion      // RadioButton
937                 
938                 #region CheckBox
939                 protected override void CheckBox_DrawCheckBox (Graphics dc, CheckBox checkbox, ButtonState state, Rectangle checkbox_rectangle)
940                 {
941                         // render as per normal button
942                         if (checkbox.appearance == Appearance.Button) {
943                                 DrawButtonBase (dc, checkbox.ClientRectangle, checkbox);
944                         } else {
945                                 InternalDrawCheckBox (dc, checkbox, state, checkbox_rectangle);
946                         }
947                 }
948                 
949                 private void InternalDrawCheckBox (Graphics dc, CheckBox checkbox, ButtonState state, Rectangle checkbox_rectangle)
950                 {
951                         SetDrawableAndStyle (checkbox);
952                         
953                         ShadowType shadow_type;
954                         
955                         if (!checkbox.Enabled)
956                                 shadow_type = ShadowType.Out;
957                         else
958                                 shadow_type = checkbox.Checked ? ShadowType.In : ShadowType.EtchedIn;
959                         
960                         StateType state_type = StateType.Normal;
961                         
962                         if (!checkbox.Enabled)
963                                 state_type = StateType.Insensitive;
964                         else
965                         if (checkbox.is_pressed)
966                                 state_type = StateType.Active;
967                         else
968                         if (checkbox.is_entered)
969                                 state_type = StateType.Prelight;
970                         
971                         gtk_paint_check (current_style,
972                                          current_gdk_drawable,
973                                          (int) state_type,
974                                          (int) shadow_type,
975                                          IntPtr.Zero,
976                                          global_gtk_check_button,
977                                          "checkbutton",
978                                          checkbox_rectangle.X,
979                                          checkbox_rectangle.Y,
980                                          checkbox_rectangle.Width,
981                                          checkbox_rectangle.Height);
982                         
983                         #if _EXPERIMENTAL_
984                         DrawDrawableToDC (dc, checkbox);
985                         #endif
986                 }
987                 
988                 protected override void CheckBox_DrawText (CheckBox checkbox, Rectangle text_rectangle, Graphics dc, StringFormat text_format)
989                 {
990                         if (checkbox.Appearance != Appearance.Button)
991                                 base.CheckBox_DrawText (checkbox, text_rectangle, dc, text_format);
992                 }
993                 
994                 protected override void CheckBox_DrawFocus( CheckBox checkbox, Graphics dc, Rectangle text_rectangle )
995                 {
996                         if (checkbox.Focused && checkbox.appearance != Appearance.Button) {
997                                 gtk_paint_focus (current_style,
998                                                  current_gdk_drawable,
999                                                  (int) StateType.Active,
1000                                                  IntPtr.Zero,
1001                                                  global_gtk_check_button,
1002                                                  "checkbutton",
1003                                                  text_rectangle.X,
1004                                                  text_rectangle.Y,
1005                                                  text_rectangle.Width,
1006                                                  text_rectangle.Height);
1007                         }
1008                         
1009                         #if _EXPERIMENTAL_
1010                         DrawDrawableToDC (dc, checkbox);
1011                         #endif
1012                 }
1013                 #endregion      // CheckBox
1014                 
1015                 #region TrackBar
1016                 private void DrawTrackBar_Vertical (Graphics dc, Rectangle clip_rectangle, TrackBar tb,
1017                                                     ref Rectangle thumb_pos, ref Rectangle thumb_area,
1018                                                     float ticks, int value_pos, bool mouse_value)
1019                 {                       
1020                         Point toptick_startpoint = new Point ();
1021                         Point bottomtick_startpoint = new Point ();
1022                         Point channel_startpoint = new Point ();
1023                         float pixel_len;
1024                         float pixels_betweenticks;
1025                         const int space_from_right = 8;
1026                         const int space_from_left = 8;
1027                         Rectangle area = tb.ClientRectangle;
1028                         
1029                         Rectangle allocation = new Rectangle (area.X, area.Y, area.Width, area.Height);
1030                         
1031                         gtk_widget_size_allocate (current_widget, ref allocation);
1032                         
1033                         gtk_range_set_range (current_widget, tb.Minimum, tb.Maximum);
1034                         gtk_range_set_value (current_widget, tb.Value);
1035                         
1036                         ShadowType shadow_type = ShadowType.In;
1037                         
1038                         if (!tb.Enabled)
1039                                 shadow_type = ShadowType.Out;
1040                         
1041                         StateType state_type = StateType.Normal;
1042                         
1043                         if (!tb.Enabled)
1044                                 state_type = StateType.Insensitive;
1045                         else
1046                         if (tb.is_entered)
1047                                 state_type = StateType.Prelight;
1048                         
1049                         switch (tb.TickStyle)   {
1050                         case TickStyle.BottomRight:
1051                         case TickStyle.None:
1052                                 channel_startpoint.Y = 8;
1053                                 channel_startpoint.X = 9;
1054                                 bottomtick_startpoint.Y = 13;
1055                                 bottomtick_startpoint.X = 24;                           
1056                                 break;
1057                         case TickStyle.TopLeft:
1058                                 channel_startpoint.Y = 8;
1059                                 channel_startpoint.X = 19;
1060                                 toptick_startpoint.Y = 13;
1061                                 toptick_startpoint.X = 8;
1062                                 break;
1063                         case TickStyle.Both:
1064                                 channel_startpoint.Y = 8;
1065                                 channel_startpoint.X = 18;      
1066                                 bottomtick_startpoint.Y = 13;
1067                                 bottomtick_startpoint.X = 32;                           
1068                                 toptick_startpoint.Y = 13;
1069                                 toptick_startpoint.X = 8;                               
1070                                 break;
1071                         default:
1072                                 break;
1073                         }
1074                         
1075                         thumb_area.X = area.X + channel_startpoint.X;
1076                         thumb_area.Y = area.Y + channel_startpoint.Y;
1077                         thumb_area.Height = area.Height - space_from_right - space_from_left;
1078                         thumb_area.Width = 4;
1079                         
1080                         pixel_len = thumb_area.Height - 11;
1081                         pixels_betweenticks = pixel_len / (tb.Maximum - tb.Minimum);
1082                         
1083                         /* Convert thumb position from mouse position to value*/
1084                         if (mouse_value) {
1085                                 
1086                                 if (value_pos >= channel_startpoint.Y)
1087                                         value_pos = (int)(((float) (value_pos - channel_startpoint.Y)) / pixels_betweenticks);
1088                                 else
1089                                         value_pos = 0;                  
1090                                 
1091                                 if (value_pos + tb.Minimum > tb.Maximum)
1092                                         value_pos = tb.Maximum - tb.Minimum;
1093                                 
1094                                 tb.Value = value_pos + tb.Minimum;
1095                         }               
1096                         
1097                         thumb_pos.Width = 13;
1098                         thumb_pos.Height = 29;
1099                         
1100                         thumb_pos.Y = channel_startpoint.Y + (int) (pixels_betweenticks * (float) value_pos) - (thumb_pos.Height / 3);
1101                         
1102                         if (thumb_pos.Y < channel_startpoint.Y)
1103                                 thumb_pos.Y = channel_startpoint.Y;
1104                         
1105                         if (thumb_pos.Y > thumb_area.Bottom - 29)
1106                                 thumb_pos.Y = thumb_area.Bottom - 29;
1107                         
1108                         /* Draw channel */
1109                         gtk_paint_box (current_style,
1110                                        current_gdk_drawable,
1111                                        (int)state_type,
1112                                        (int)shadow_type,
1113                                        IntPtr.Zero,
1114                                        current_widget,
1115                                        "trough",
1116                                        thumb_area.X,
1117                                        thumb_area.Y,
1118                                        4,
1119                                        thumb_area.Height);
1120                         
1121                         /* Draw thumb */
1122                         thumb_pos.X = channel_startpoint.X + 2 - thumb_pos.Width / 2;
1123                         
1124                         shadow_type = ShadowType.Out;
1125                         
1126                         gtk_paint_slider (current_style,
1127                                           current_gdk_drawable,
1128                                           (int)state_type,
1129                                           (int)shadow_type,
1130                                           IntPtr.Zero,
1131                                           current_widget,
1132                                           "vscale",
1133                                           thumb_pos.X,
1134                                           thumb_pos.Y,
1135                                           thumb_pos.Width,
1136                                           thumb_pos.Height,
1137                                           0);
1138                         
1139                         pixel_len = thumb_area.Height - 11;
1140                         pixels_betweenticks = pixel_len / ticks;
1141                         
1142                         /* Draw ticks*/
1143                         thumb_area.X = thumb_pos.X;
1144                         thumb_area.Y = channel_startpoint.Y;
1145                         thumb_area.Width = thumb_pos.Width;
1146                         
1147                         Region outside = new Region (area);
1148                         outside.Exclude (thumb_area);                   
1149                         
1150                         if (outside.IsVisible (clip_rectangle)) {                               
1151                                 if (pixels_betweenticks > 0 && ((tb.TickStyle & TickStyle.BottomRight) == TickStyle.BottomRight ||
1152                                     ((tb.TickStyle & TickStyle.Both) == TickStyle.Both))) {     
1153                                         
1154                                         for (float inc = 0; inc < (pixel_len + 1); inc += pixels_betweenticks)  {                                       
1155                                                 if (inc == 0 || (inc +  pixels_betweenticks) >= pixel_len + 1)
1156                                                         dc.DrawLine (ResPool.GetPen (pen_ticks_color), area.X + bottomtick_startpoint.X , area.Y + bottomtick_startpoint.Y  + inc, 
1157                                                                      area.X + bottomtick_startpoint.X  + 3, area.Y + bottomtick_startpoint.Y + inc);
1158                                                 else
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  + 2, area.Y + bottomtick_startpoint.Y + inc);
1161                                         }
1162                                 }
1163                                 
1164                                 if (pixels_betweenticks > 0 &&  ((tb.TickStyle & TickStyle.TopLeft) == TickStyle.TopLeft ||
1165                                     ((tb.TickStyle & TickStyle.Both) == TickStyle.Both))) {
1166                                         
1167                                         pixel_len = thumb_area.Height - 11;
1168                                         pixels_betweenticks = pixel_len / ticks;
1169                                         
1170                                         for (float inc = 0; inc < (pixel_len + 1); inc += pixels_betweenticks) {                                        
1171                                                 if (inc == 0 || (inc +  pixels_betweenticks) >= pixel_len + 1)
1172                                                         dc.DrawLine (ResPool.GetPen (pen_ticks_color), area.X + toptick_startpoint.X  - 3 , area.Y + toptick_startpoint.Y + inc, 
1173                                                                      area.X + toptick_startpoint.X, area.Y + toptick_startpoint.Y + inc);
1174                                                 else
1175                                                         dc.DrawLine (ResPool.GetPen (pen_ticks_color), area.X + toptick_startpoint.X  - 2, area.Y + toptick_startpoint.Y + inc, 
1176                                                                      area.X + toptick_startpoint.X, area.Y + toptick_startpoint.Y  + inc);
1177                                         }                       
1178                                 }
1179                         }
1180                         
1181                         outside.Dispose ();
1182                 }
1183                 
1184                 private void DrawTrackBar_Horizontal (Graphics dc, Rectangle clip_rectangle, TrackBar tb,
1185                                                       ref Rectangle thumb_pos, ref Rectangle thumb_area,
1186                                                       float ticks, int value_pos, bool mouse_value)
1187                 {                       
1188                         Point toptick_startpoint = new Point ();
1189                         Point bottomtick_startpoint = new Point ();
1190                         Point channel_startpoint = new Point ();
1191                         float pixel_len;
1192                         float pixels_betweenticks;
1193                         const int space_from_right = 8;
1194                         const int space_from_left = 8;
1195                         Rectangle area = tb.ClientRectangle;
1196                         
1197                         Rectangle allocation = new Rectangle (area.X, area.Y, area.Width, area.Height);
1198                         
1199                         gtk_widget_size_allocate (current_widget, ref allocation);
1200                         
1201                         gtk_range_set_range (current_widget, tb.Minimum, tb.Maximum);
1202                         gtk_range_set_value (current_widget, tb.Value);
1203                         
1204                         ShadowType shadow_type = ShadowType.In;
1205                         
1206                         if (!tb.Enabled)
1207                                 shadow_type = ShadowType.Out;
1208                         
1209                         StateType state_type = StateType.Normal;
1210                         
1211                         if (!tb.Enabled)
1212                                 state_type = StateType.Insensitive;
1213                         else
1214                         if (tb.is_entered)
1215                                 state_type = StateType.Prelight;
1216                         
1217                         switch (tb.TickStyle) {
1218                         case TickStyle.BottomRight:
1219                         case TickStyle.None:
1220                                 channel_startpoint.X = 8;
1221                                 channel_startpoint.Y = 9;
1222                                 bottomtick_startpoint.X = 13;
1223                                 bottomtick_startpoint.Y = 24;                           
1224                                 break;
1225                         case TickStyle.TopLeft:
1226                                 channel_startpoint.X = 8;
1227                                 channel_startpoint.Y = 19;
1228                                 toptick_startpoint.X = 13;
1229                                 toptick_startpoint.Y = 8;
1230                                 break;
1231                         case TickStyle.Both:
1232                                 channel_startpoint.X = 8;
1233                                 channel_startpoint.Y = 18;      
1234                                 bottomtick_startpoint.X = 13;
1235                                 bottomtick_startpoint.Y = 32;                           
1236                                 toptick_startpoint.X = 13;
1237                                 toptick_startpoint.Y = 8;                               
1238                                 break;
1239                         default:
1240                                 break;
1241                         }
1242                         
1243                         thumb_area.X = area.X + channel_startpoint.X;
1244                         thumb_area.Y = area.Y + channel_startpoint.Y;
1245                         thumb_area.Width = area.Width - space_from_right - space_from_left;
1246                         thumb_area.Height = 4;
1247                         
1248                         pixel_len = thumb_area.Width - 11;
1249                         pixels_betweenticks = pixel_len / (tb.Maximum - tb.Minimum);
1250                         
1251                         /* Convert thumb position from mouse position to value*/
1252                         if (mouse_value) {                      
1253                                 if (value_pos >= channel_startpoint.X)
1254                                         value_pos = (int)(((float) (value_pos - channel_startpoint.X)) / pixels_betweenticks);
1255                                 else
1256                                         value_pos = 0;                          
1257                                 
1258                                 if (value_pos + tb.Minimum > tb.Maximum)
1259                                         value_pos = tb.Maximum - tb.Minimum;
1260                                 
1261                                 tb.Value = value_pos + tb.Minimum;
1262                         }                       
1263                         
1264                         thumb_pos.Width = 29;
1265                         thumb_pos.Height = 13;
1266                         
1267                         thumb_pos.X = channel_startpoint.X + (int) (pixels_betweenticks * (float) value_pos) - (thumb_pos.Width / 3);
1268                         
1269                         
1270                         if (thumb_pos.X < channel_startpoint.X)
1271                                 thumb_pos.X = channel_startpoint.X;
1272                         
1273                         if (thumb_pos.X > thumb_area.Right - 29)
1274                                 thumb_pos.X = thumb_area.Right - 29;
1275                         
1276                         /* Draw channel */
1277                         gtk_paint_box (current_style,
1278                                        current_gdk_drawable,
1279                                        (int)state_type,
1280                                        (int)shadow_type,
1281                                        IntPtr.Zero,
1282                                        current_widget,
1283                                        "trough",
1284                                        thumb_area.X,
1285                                        thumb_area.Y,
1286                                        thumb_area.Width,
1287                                        4);
1288                         
1289                         /* Draw thumb */
1290                         
1291                         thumb_pos.Y = channel_startpoint.Y + 2 - thumb_pos.Height / 2;
1292                         
1293                         shadow_type = ShadowType.Out;
1294                         
1295                         gtk_paint_slider (current_style,
1296                                           current_gdk_drawable,
1297                                           (int)state_type,
1298                                           (int)shadow_type,
1299                                           IntPtr.Zero,
1300                                           current_widget,
1301                                           "hscale",
1302                                           thumb_pos.X,
1303                                           thumb_pos.Y,
1304                                           thumb_pos.Width,
1305                                           thumb_pos.Height,
1306                                           0);
1307                         
1308                         pixel_len = thumb_area.Width - 11;
1309                         pixels_betweenticks = pixel_len / ticks;
1310                         
1311                         /* Draw ticks*/
1312                         thumb_area.Y = thumb_pos.Y;
1313                         thumb_area.X = channel_startpoint.X;
1314                         thumb_area.Height = thumb_pos.Height;
1315                         Region outside = new Region (area);
1316                         outside.Exclude (thumb_area);                   
1317                         
1318                         if (outside.IsVisible (clip_rectangle)) {                               
1319                                 if (pixels_betweenticks > 0 && ((tb.TickStyle & TickStyle.BottomRight) == TickStyle.BottomRight ||
1320                                     ((tb.TickStyle & TickStyle.Both) == TickStyle.Both))) {                             
1321                                         
1322                                         for (float inc = 0; inc < (pixel_len + 1); inc += pixels_betweenticks) {                                        
1323                                                 if (inc == 0 || (inc +  pixels_betweenticks) >= pixel_len + 1)
1324                                                         dc.DrawLine (ResPool.GetPen (pen_ticks_color), area.X + bottomtick_startpoint.X + inc , area.Y + bottomtick_startpoint.Y, 
1325                                                                      area.X + bottomtick_startpoint.X + inc , area.Y + bottomtick_startpoint.Y + 3);
1326                                                 else
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 + 2);
1329                                         }
1330                                 }
1331                                 
1332                                 if (pixels_betweenticks > 0 && ((tb.TickStyle & TickStyle.TopLeft) == TickStyle.TopLeft ||
1333                                     ((tb.TickStyle & TickStyle.Both) == TickStyle.Both))) {
1334                                         
1335                                         for (float inc = 0; inc < (pixel_len + 1); inc += pixels_betweenticks) {                                        
1336                                                 if (inc == 0 || (inc +  pixels_betweenticks) >= pixel_len + 1)
1337                                                         dc.DrawLine (ResPool.GetPen (pen_ticks_color), area.X + toptick_startpoint.X + inc , area.Y + toptick_startpoint.Y - 3, 
1338                                                                      area.X + toptick_startpoint.X + inc , area.Y + toptick_startpoint.Y);
1339                                                 else
1340                                                         dc.DrawLine (ResPool.GetPen (pen_ticks_color), area.X + toptick_startpoint.X + inc, area.Y + toptick_startpoint.Y - 2, 
1341                                                                      area.X + toptick_startpoint.X + inc, area.Y + toptick_startpoint.Y);
1342                                         }                       
1343                                 }
1344                         }
1345                         
1346                         outside.Dispose ();                     
1347                 }
1348                 
1349                 public override void DrawTrackBar (Graphics dc, Rectangle clip_rectangle, TrackBar tb)
1350                 {
1351                         int             value_pos;
1352                         bool            mouse_value;
1353                         float           ticks = (tb.Maximum - tb.Minimum) / tb.tickFrequency; /* N of ticks draw*/
1354                         Rectangle       area;
1355                         Rectangle       thumb_pos = tb.ThumbPos;
1356                         Rectangle       thumb_area = tb.ThumbArea;
1357                         
1358                         if (tb.thumb_pressed) {
1359                                 value_pos = tb.thumb_mouseclick;
1360                                 mouse_value = true;
1361                         } else {
1362                                 value_pos = tb.Value - tb.Minimum;
1363                                 mouse_value = false;
1364                         }
1365                         
1366                         area = tb.ClientRectangle;
1367                         
1368                         SetDrawableAndStyle (tb);
1369                         
1370                         /* Control Background */
1371                         if (tb.BackColor == DefaultControlBackColor) {
1372                                 dc.FillRectangle (ResPool.GetSolidBrush (ColorControl), clip_rectangle);
1373                         } else {
1374                                 dc.FillRectangle (ResPool.GetSolidBrush (tb.BackColor), clip_rectangle);
1375                         }
1376                         
1377                         if (tb.Orientation == Orientation.Vertical) {
1378                                 DrawTrackBar_Vertical (dc, clip_rectangle, tb, ref thumb_pos, ref thumb_area,
1379                                                        ticks, value_pos, mouse_value);
1380                                 
1381                         } else {
1382                                 DrawTrackBar_Horizontal (dc, clip_rectangle, tb, ref thumb_pos, ref thumb_area,
1383                                                          ticks, value_pos, mouse_value);
1384                         }
1385                         
1386                         if (tb.Enabled && tb.Focused)
1387                                 gtk_paint_focus (current_style,
1388                                                  current_gdk_drawable, 
1389                                                  (int)StateType.Normal,
1390                                                  IntPtr.Zero,
1391                                                  current_widget, 
1392                                                  "trough",
1393                                                  area.X,
1394                                                  area.Y,
1395                                                  area.Width,
1396                                                  area.Height);
1397                         
1398                         tb.ThumbPos = thumb_pos;
1399                         tb.ThumbArea = thumb_area;
1400                         
1401                         #if _EXPERIMENTAL_
1402                         DrawDrawableToDC (dc, tb);
1403                         #endif
1404                 }
1405                 #endregion      // TrackBar
1406                 
1407                 public override void CPDrawButton (Graphics dc, Rectangle rectangle, ButtonState state)
1408                 {
1409                         #if _EXPERIMENTAL_
1410                         SetDrawableAndStyle (rectangle, typeof(ButtonBase), Orientation.Horizontal);
1411                         #endif
1412                         
1413                         bool is_pushed = false;
1414 //                      bool is_checked = false;
1415 //                      bool is_flat = false;
1416                         bool is_inactive = false;
1417                         
1418                         if ((state & ButtonState.Pushed) != 0) {
1419                                 is_pushed = true;
1420                         }
1421                         
1422 //                      if ((state & ButtonState.Checked) != 0) {
1423 //                              is_checked = true;
1424 //                      }
1425 //                      
1426 //                      if ((state & ButtonState.Flat) != 0) {
1427 //                              is_flat = true;
1428 //                      }
1429                         
1430                         if ((state & ButtonState.Inactive) != 0) {
1431                                 is_inactive = true;
1432                         }
1433                         
1434                         IntPtr drawbutton_style = gtk_style_attach (global_gtk_button_style, current_gdk_drawable);  // need it
1435                         
1436                         StateType state_type = StateType.Normal;
1437                         ShadowType shadow_type = ShadowType.Out;
1438                         string detail = "buttondefault";
1439                         
1440                         if (is_inactive) {
1441                                 state_type = StateType.Insensitive;
1442                         } else
1443                         if (is_pushed) {
1444                                 state_type = StateType.Active;
1445                                 shadow_type = ShadowType.In;
1446                                 detail = "button";
1447                         }
1448                         
1449                         gtk_paint_box (drawbutton_style, current_gdk_drawable,
1450                                        (int) state_type,
1451                                        (int) shadow_type,
1452                                        IntPtr.Zero,
1453                                        IntPtr.Zero,
1454                                        detail,
1455                                        rectangle.X, rectangle.Y,
1456                                        rectangle.Width, rectangle.Height);
1457                         
1458                         #if _EXPERIMENTAL_
1459                         DrawDrawableToDC (dc, rectangle);
1460                         #endif
1461                 }
1462                 
1463                 /* Scroll button: regular button + direction arrow */
1464                 public override void CPDrawScrollButton (Graphics dc, Rectangle area, ScrollButton scroll_button_type, ButtonState state)
1465                 {
1466                         #if _EXPERIMENTAL_
1467                         Orientation orientation = Orientation.Vertical;
1468                         if (scroll_button_type == ScrollButton.Left || scroll_button_type == ScrollButton.Right)
1469                                 orientation = Orientation.Horizontal;
1470                         SetDrawableAndStyle (area, typeof(ScrollBar), orientation);
1471                         #endif
1472                         
1473                         bool enabled = (state == ButtonState.Inactive) ? false: true;
1474                         
1475                         StateType state_type = enabled ? StateType.Normal : StateType.Insensitive;
1476                         
1477                         DrawScrollButtonPrimitive (dc, area, state, scroll_button_type);
1478                         
1479                         if (area.Width < 12 || area.Height < 12) /* Cannot see a thing at smaller sizes */
1480                                 return;
1481                         
1482                         ArrowType arrow_type = 0;
1483                         
1484                         switch (scroll_button_type) {
1485                         case ScrollButton.Up:
1486                                 arrow_type = ArrowType.Up;
1487                                 break;
1488                         case ScrollButton.Down:
1489                                 arrow_type = ArrowType.Down;
1490                                 break;
1491                         case ScrollButton.Right:
1492                                 arrow_type = ArrowType.Right;
1493                                 break;
1494                         case ScrollButton.Left:
1495                                 arrow_type = ArrowType.Left;
1496                                 break;
1497                         default:
1498                                 break;
1499                         }
1500                         
1501                         int centerX = area.Left + area.Width / 2;
1502                         int centerY = area.Top + area.Height / 2;
1503                         int arrow_x = 0, arrow_y = 0, arrow_height = 0, arrow_width = 0;
1504                         
1505                         switch (scroll_button_type) {
1506                         case ScrollButton.Down:
1507                         case ScrollButton.Up:
1508                                 arrow_x = centerX - 4;
1509                                 arrow_y = centerY - 2;
1510                                 arrow_width = 8;
1511                                 arrow_height = 4;
1512                                 break;
1513                         case ScrollButton.Left:
1514                         case ScrollButton.Right:
1515                                 arrow_x = centerX - 2;
1516                                 arrow_y = centerY - 4;
1517                                 arrow_width = 4;
1518                                 arrow_height = 8;
1519                                 break;
1520                         default:
1521                                 break;
1522                         }
1523                         
1524                         gtk_paint_arrow (current_style, 
1525                                          current_gdk_drawable, 
1526                                          (int) state_type,
1527                                          (int) ShadowType.Out,
1528                                          IntPtr.Zero,
1529                                          current_widget,
1530                                          "",            
1531                                          (int) arrow_type, true, 
1532                                          arrow_x, 
1533                                          arrow_y,
1534                                          arrow_width, arrow_height);
1535                         
1536                         current_widget = IntPtr.Zero;
1537                         
1538                         #if _EXPERIMENTAL_
1539                         DrawDrawableToDC (dc, area);
1540                         #endif
1541                 }
1542                 
1543                 public void DrawScrollButtonPrimitive (Graphics dc, Rectangle area, ButtonState state, ScrollButton scroll_button_type)
1544                 {
1545                         StateType state_type = StateType.Normal;
1546                         ShadowType shadow_type = ShadowType.Out;
1547                         
1548                         if ((state & ButtonState.Pushed) == ButtonState.Pushed) {
1549                                 state_type = StateType.Active;
1550                                 shadow_type = ShadowType.In;
1551                         }
1552                         
1553                         switch (scroll_button_type) {
1554                         case ScrollButton.Left:
1555                         case ScrollButton.Right:
1556                                 gtk_paint_box (current_style, 
1557                                                current_gdk_drawable, 
1558                                                (int) state_type,
1559                                                (int) shadow_type,
1560                                                IntPtr.Zero,
1561                                                global_gtk_hscrollbar,
1562                                                "stepper",
1563                                                area.X, area.Y,
1564                                                area.Width, area.Height);
1565                                 break;
1566                         case ScrollButton.Up:
1567                         case ScrollButton.Down:
1568                                 gtk_paint_box (current_style, 
1569                                                current_gdk_drawable, 
1570                                                (int) state_type,
1571                                                (int) shadow_type,
1572                                                IntPtr.Zero,
1573                                                global_gtk_vscrollbar,
1574                                                "stepper",
1575                                                area.X, area.Y,
1576                                                area.Width, area.Height);
1577                                 break;
1578                         }
1579                 }
1580                 
1581                 private static Color ColorFromGdkColor (GdkColorStruct gtkcolor)
1582                 {
1583                         return Color.FromArgb (255, 
1584                                 (gtkcolor.red >> 8)  & 0xff, 
1585                                 (gtkcolor.green  >> 8) & 0xff,
1586                                 (gtkcolor.blue >> 8) & 0xff );
1587                 }
1588
1589         } //class
1590 }