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