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