also, disable the call do BindColumns in
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ThemeGtk.cs
index 2ec52a0d02e04eb7c4a26745f07db09e5611e644..90aa89eaf343050abf15aa9f9c076b5c7da7f495 100644 (file)
 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
-// Copyright (c) 2004 Novell, Inc.
+// Copyright (c) 2004-2006 Novell, Inc.
 //
 // Authors:
 //     Jordi Mas i Hernandez, jordi@ximian.com
+//     Alexander Olk, alex.olk@googlemail.com
 //
 //     This is an experimental GTK theme. 
 //
 //             - When GDK is initialised it opens its own display. There is not way of changing it,
 //             then we use that display as SWF display
 //             - You can activate this Theme in Linux doing export MONO_THEME=gtk
-//             - GTK paints controls into a window no a device context. We should inverstigate if we 
+//             - GTK paints controls into a window not a device context. We should inverstigate if we 
 //             we can encapsulate a dc in a gtkwindow.
-//
-// $Revision: 1.1 $
-// $Modtime: $
-// $Log: ThemeGtk.cs,v $
-// Revision 1.1  2004/08/19 22:27:40  jordi
-// experimental GTK theme support
-//
-//
+
+
 // NOT COMPLETE
 
+// TODO:       - fix position of button focus rectangle
+//             - fix TrackBar drawing location
+
+
+//#define _EXPERIMENTAL_
+
 using System;
 using System.Drawing;
 using System.Drawing.Drawing2D;
 using System.Drawing.Imaging;
 using System.Reflection;
 using System.Runtime.InteropServices;
+using System.IO;
 
 namespace System.Windows.Forms
 {
@@ -83,7 +85,7 @@ namespace System.Windows.Forms
                        Left,
                        Right,
                }
-
+               
                /* Structs */
                [StructLayout(LayoutKind.Sequential)]   
                internal struct GdkColorStruct
@@ -94,11 +96,18 @@ namespace System.Windows.Forms
                        internal short blue;
                }
 
+               [StructLayout(LayoutKind.Sequential)]   
+               internal struct GObjectStruct {
+                       public IntPtr Instance;
+                       public IntPtr ref_count;
+                       public IntPtr data;
+               }
+
+
                [StructLayout(LayoutKind.Sequential)]   
                internal struct GtkStyleStruct
                {
-                       [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=12)]
-                       internal byte[] obj; /* GObject is 12 bytes*/
+                       internal GObjectStruct obj;
                        [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
                        internal GdkColorStruct[] fg;
                        [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]               
@@ -121,8 +130,7 @@ namespace System.Windows.Forms
 
                        /* TODO: There is more stuff that we will add when we need it*/
                }
-
-                       
+               
                /* GDK imports */
                [DllImport("libgdk-x11-2.0.so")]
                internal static extern IntPtr gdk_display_manager_get ();
@@ -140,11 +148,40 @@ namespace System.Windows.Forms
                static extern IntPtr gdk_window_foreign_new_for_display (IntPtr display, uint anid);
 
                [DllImport("libgdk-x11-2.0.so")]
-               static extern bool gdk_init_check(out int argc, string argv);   
+               static extern bool gdk_init_check(IntPtr argc, IntPtr argv);    
+               
+               //[DllImport("libgdk-x11-2.0.so")]
+               //static extern IntPtr gdk_pixmap_new (IntPtr drawable, int width, int height, int depth);
+               
+               //[DllImport("libgdk-x11-2.0.so")]
+               //static extern IntPtr gdk_pixbuf_get_from_drawable (IntPtr dest, IntPtr drawable_src, IntPtr cmap,
+               //                                                 int src_x, int src_y, int dest_x, int dest_y, int width, int height);
+               
+               //[DllImport("libgdk-x11-2.0.so")]
+               //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);
+               
+               //[DllImport("libgdk-x11-2.0.so")]
+               //static extern IntPtr gdk_drawable_get_colormap (IntPtr drawable);
+               
+               //[DllImport("libgdk-x11-2.0.so")]
+               //static extern IntPtr gdk_colormap_get_system ();
+               
+               //[DllImport("libgdk-x11-2.0.so")]
+               //static extern IntPtr gdk_pixbuf_new (int colorspace, bool has_alpha, int bits_per_sample, int width, int height);
+               
+               //[DllImport("libgdk-x11-2.0.so")]
+               //static extern IntPtr gdk_gc_new (IntPtr drawable);
+               
+               /* glib imports*/
+               //[DllImport("libglib-2.0.so")]
+               //static extern void g_free (IntPtr mem);
+               
+               //[DllImport("libgobject-2.0.so")]
+               //static extern void g_object_unref (IntPtr nativeObject);
 
                /* GTK imports */               
                [DllImport("libgtk-x11-2.0.so")]
-               static extern bool gtk_init_check (out int argc, string argv);
+               static extern bool gtk_init_check (IntPtr argc, IntPtr argv);
 
                [DllImport("libgtk-x11-2.0.so")]
                static extern IntPtr gtk_adjustment_new (double value, double lower, double upper, double step_increment, double page_increment, double page_size);
@@ -154,12 +191,15 @@ namespace System.Windows.Forms
 
                [DllImport("libgtk-x11-2.0.so")]
                static extern IntPtr gtk_vscrollbar_new(IntPtr adjustment);
+               
+               [DllImport("libgtk-x11-2.0.so")]
+               static extern IntPtr gtk_hscrollbar_new(IntPtr adjustment);
 
                [DllImport("libgtk-x11-2.0.so")]
                static extern IntPtr gtk_style_attach (IntPtr raw, IntPtr window);
 
-               [DllImport("libgtk-x11-2.0.so")]
-               static extern IntPtr gtk_rc_style_new ();
+               //[DllImport("libgtk-x11-2.0.so")]
+               //static extern IntPtr gtk_rc_style_new ();
 
                [DllImport("libgtk-x11-2.0.so")]
                static extern IntPtr gtk_invisible_new ();
@@ -170,55 +210,171 @@ namespace System.Windows.Forms
                [DllImport("libgtk-x11-2.0.so")]
                static extern IntPtr gtk_widget_get_style (IntPtr raw);
 
+               //[DllImport("libgtk-x11-2.0.so")]
+               //static extern void gtk_style_detach (IntPtr raw);
+               
+               [DllImport("libgtk-x11-2.0.so")]
+               static extern IntPtr gtk_button_new ();
+               
+               [DllImport("libgtk-x11-2.0.so")]
+               static extern IntPtr gtk_progress_bar_new ();
+               
+               [DllImport("libgtk-x11-2.0.so")]
+               static extern IntPtr gtk_radio_button_new (IntPtr group);
+               
                [DllImport("libgtk-x11-2.0.so")]
-               static extern void gtk_style_detach (IntPtr raw);
+               static extern IntPtr gtk_check_button_new ();
+               
+               [DllImport("libgtk-x11-2.0.so")]
+               static extern IntPtr gtk_hscale_new (IntPtr adjustment);
+               
+               [DllImport("libgtk-x11-2.0.so")]
+               static extern IntPtr gtk_vscale_new (IntPtr adjustment);
+               
+               [DllImport("libgtk-x11-2.0.so")]
+               static extern void gtk_range_set_range (IntPtr range, double min, double max);
+               
+               [DllImport("libgtk-x11-2.0.so")]
+               static extern void gtk_range_set_value (IntPtr range, double value);
 
                /* GTK Drawing */
-               [DllImport("libgtk-x11-2.0.so")]
-               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);
+               //[DllImport("libgtk-x11-2.0.so")]
+               //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);
 
                [DllImport("libgtk-x11-2.0.so")]
                static extern void gtk_paint_arrow (IntPtr style, IntPtr window, int state_type, int shadow_type, 
-                       IntPtr area, IntPtr widget, string detail, int arrow_type, bool fill, int x, int y, int width, int height);
+                                                   IntPtr area, IntPtr widget, string detail, int arrow_type, bool fill, int x, int y, int width, int height);
 
                [DllImport("libgtk-x11-2.0.so")]
-               static extern void gtk_paint_slider(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);
+               static extern void gtk_paint_slider (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);
 
                [DllImport("libgtk-x11-2.0.so")]
-               static extern void gtk_paint_box(IntPtr style, IntPtr window, int state_type, int shadow_type, 
-                       IntPtr area, IntPtr widget, string detail, int x, int y, int width, int height);
-
+               static extern void gtk_paint_box (IntPtr style, IntPtr window, int state_type, int shadow_type, 
+                                                 IntPtr area, IntPtr widget, string detail, int x, int y, int width, int height);
+               
+               [DllImport("libgtk-x11-2.0.so")]
+               static extern void gtk_paint_flat_box (IntPtr style, IntPtr window, int state_type, int shadow_type,
+                                                      IntPtr area, IntPtr widget, string detail, int x, int y, int width, int height);
+               
+               //[DllImport("libgtk-x11-2.0.so")]
+               //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);
+               
+               //[DllImport("libgtk-x11-2.0.so")]
+               //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);
+               
+               [DllImport("libgtk-x11-2.0.so")]
+               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);
+               
+               [DllImport("libgtk-x11-2.0.so")]
+               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);
+               
+               [DllImport("libgtk-x11-2.0.so")]
+               static extern void gtk_widget_size_allocate (IntPtr widget, ref Rectangle allocation);
+               
+               [DllImport("libgtk-x11-2.0.so")]
+               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);
+               
+               [DllImport("libgtk-x11-2.0.so")]
+               static extern void gtk_widget_grab_focus (IntPtr widget);
+               
                /* Data */
                static protected IntPtr dispmgr;
                static protected IntPtr gdkdisplay;
                static protected IntPtr widget;
-               static protected IntPtr style;
+               static protected IntPtr global_style;
+               
+               #if _EXPERIMENTAL_
+               static protected IntPtr global_color_map = IntPtr.Zero;
+               #endif
+               
+               static protected IntPtr global_gtk_button = IntPtr.Zero;
+               static protected IntPtr global_gtk_button_style = IntPtr.Zero;
+               
+               static protected IntPtr global_gtk_vscrollbar = IntPtr.Zero;
+               static protected IntPtr global_gtk_vscrollbar_style = IntPtr.Zero;
+               
+               static protected IntPtr global_gtk_hscrollbar = IntPtr.Zero;
+               static protected IntPtr global_gtk_hscrollbar_style = IntPtr.Zero;
+               
+               static protected IntPtr global_gtk_progress_bar = IntPtr.Zero;
+               static protected IntPtr global_gtk_progress_bar_style = IntPtr.Zero;
+               
+               static protected IntPtr global_gtk_radio_button = IntPtr.Zero;
+               static protected IntPtr global_gtk_radio_button_style = IntPtr.Zero;
+               
+               static protected IntPtr global_gtk_check_button = IntPtr.Zero;
+               static protected IntPtr global_gtk_check_button_style = IntPtr.Zero;
+               
+               static protected IntPtr global_gtk_hscale = IntPtr.Zero;
+               static protected IntPtr global_gtk_hscale_style = IntPtr.Zero;
+               
+               static protected IntPtr global_gtk_vscale = IntPtr.Zero;
+               static protected IntPtr global_gtk_vscale_style = IntPtr.Zero;
+               
+               static protected IntPtr current_gdk_drawable = IntPtr.Zero;
+               static protected IntPtr current_style = IntPtr.Zero;
+               static protected IntPtr current_widget = IntPtr.Zero;
 
                public static void InitGtk ()
                {       
                        Console.WriteLine ("ThemeGtk Init");            
-                       int argc = 0;
-                       string argv = "";
                        
-                       gdk_init_check (out argc, argv);        
+                       gdk_init_check (IntPtr.Zero, IntPtr.Zero);      
 
                        dispmgr =  gdk_display_manager_get ();
                        gdkdisplay =  gdk_display_manager_get_default_display (dispmgr);
-                       gtk_init_check (out argc, argv);
+                       gtk_init_check (IntPtr.Zero, IntPtr.Zero);
 
                        widget = gtk_invisible_new ();
                        gtk_widget_ensure_style (widget);
-                       style = gtk_widget_get_style (widget);                  
+                       global_style = gtk_widget_get_style (widget);                   
 
-                       XplatUIX11.SetDisplay (gdk_x11_display_get_xdisplay (gdkdisplay));
+                       XplatUIX11.GetInstance().SetDisplay (gdk_x11_display_get_xdisplay (gdkdisplay));
+                       
+                       global_gtk_button = gtk_button_new();
+                       gtk_widget_ensure_style (global_gtk_button);
+                       global_gtk_button_style = gtk_rc_get_style (global_gtk_button);
+                       
+                       IntPtr adj = gtk_adjustment_new (0, 0, 0, 0, 0, 0);
+                        global_gtk_vscrollbar = gtk_vscrollbar_new (adj);
+                       gtk_widget_ensure_style (global_gtk_vscrollbar);
+                       global_gtk_vscrollbar_style = gtk_rc_get_style (global_gtk_vscrollbar);
+                       
+                       global_gtk_hscrollbar = gtk_hscrollbar_new (adj);
+                       gtk_widget_ensure_style (global_gtk_hscrollbar);
+                       global_gtk_hscrollbar_style = gtk_rc_get_style (global_gtk_hscrollbar);
+                       
+                       global_gtk_progress_bar = gtk_progress_bar_new ();
+                       gtk_widget_ensure_style (global_gtk_progress_bar);
+                       global_gtk_progress_bar_style = gtk_rc_get_style (global_gtk_progress_bar);
+                       
+                       global_gtk_radio_button = gtk_radio_button_new (IntPtr.Zero);
+                       gtk_widget_ensure_style (global_gtk_radio_button);
+                       global_gtk_radio_button_style = gtk_rc_get_style (global_gtk_radio_button);
+                       
+                       global_gtk_check_button = gtk_check_button_new ();
+                       gtk_widget_ensure_style (global_gtk_check_button);
+                       global_gtk_check_button_style = gtk_rc_get_style (global_gtk_check_button);
+                       
+                       global_gtk_hscale = gtk_hscale_new (adj);
+                       gtk_widget_ensure_style (global_gtk_hscale);
+                       global_gtk_hscale_style = gtk_rc_get_style (global_gtk_hscale);
+                       
+                       global_gtk_vscale = gtk_vscale_new (adj);
+                       gtk_widget_ensure_style (global_gtk_vscale);
+                       global_gtk_vscale_style = gtk_rc_get_style (global_gtk_vscale);
+                       
+                       #if _EXPERIMENTAL_
+                       global_color_map = gdk_colormap_get_system ();
+                       #endif
                }
 
                public void LoadSysDefaultColors ()
                {
                        GtkStyleStruct style_struct;                    
                        
-                       style_struct = (GtkStyleStruct) Marshal.PtrToStructure (style, typeof (GtkStyleStruct));                        
+                       style_struct = (GtkStyleStruct) Marshal.PtrToStructure (global_style, typeof (GtkStyleStruct));                 
                        defaultWindowBackColor = ColorFromGdkColor (style_struct.bg[0]);
                        defaultWindowForeColor = ColorFromGdkColor (style_struct.fg[0]);
                }
@@ -227,36 +383,1105 @@ namespace System.Windows.Forms
                {
                        Console.WriteLine ("ThemeGtk constructor");
                        InitGtk ();
-                       default_font =  new Font (FontFamily.GenericSansSerif, 8.25f);
                        
                        LoadSysDefaultColors ();        
 
-                       br_buttonface = new SolidBrush (defaultWindowBackColor);                
-                       br_buttontext = new SolidBrush (defaultWindowForeColor);                        
+                       always_draw_hotkeys = true;
                }       
 
-               public override bool WriteToWindow {
+               public override bool DoubleBufferingSupported {
+                       #if _EXPERIMENTAL_
                        get {return true; }
-               }       
-
+                       #else
+                       get {return false; }
+                       #endif
+               }
+               
+               private void SetDrawableAndStyle (Control control)
+               {
+                       #if _EXPERIMENTAL_
+                       if (current_gdk_drawable != IntPtr.Zero) {
+                               g_object_unref (current_gdk_drawable);
+                               current_gdk_drawable = IntPtr.Zero;
+                       }
+                       current_gdk_drawable = gdk_pixmap_new (IntPtr.Zero, control.ClientRectangle.Width, control.ClientRectangle.Height, 24);
+                       #else
+                       current_gdk_drawable = gdk_window_foreign_new_for_display (gdkdisplay, (uint) control.Handle);
+                       #endif
+                       
+                       IntPtr tmp_style = IntPtr.Zero;
+                       
+                       if (control is ButtonBase) {
+                               tmp_style = global_gtk_button_style;
+                               current_widget = global_gtk_button;
+                       } else
+                       if (control is ScrollBar) {
+                               ScrollBar bar = control as ScrollBar;
+                               if (bar.vert) {
+                                       tmp_style = global_gtk_vscrollbar_style;
+                                       current_widget = global_gtk_vscrollbar;
+                               } else {
+                                       tmp_style = global_gtk_hscrollbar_style;
+                                       current_widget = global_gtk_hscrollbar;
+                               }
+                       } else
+                       if (control is ProgressBar) {
+                               tmp_style = global_gtk_progress_bar_style;
+                               current_widget = global_gtk_progress_bar;
+                       } else
+                       if (control is RadioButton) {
+                               tmp_style = global_gtk_radio_button_style;
+                               current_widget = global_gtk_radio_button;
+                       } else
+                       if (control is CheckBox) {
+                               tmp_style = global_gtk_check_button_style;
+                               current_widget = global_gtk_check_button;
+                       } else
+                       if (control is TrackBar) {
+                               TrackBar bar = control as TrackBar;
+                               if (bar.Orientation == Orientation.Vertical) {
+                                       tmp_style = global_gtk_vscale_style;
+                                       current_widget = global_gtk_vscale;
+                               } else {
+                                       tmp_style = global_gtk_hscale_style;
+                                       current_widget = global_gtk_hscale;
+                               }
+                       } else
+                               tmp_style = global_style;
+                       
+                       current_style = gtk_style_attach (tmp_style, current_gdk_drawable);  // need it
+               }
+               
+               #if _EXPERIMENTAL_
+               private void SetDrawableAndStyle (Rectangle area, Type type, Orientation orientation)
+               {
+                       if (current_gdk_drawable != IntPtr.Zero) {
+                               g_object_unref (current_gdk_drawable);
+                               current_gdk_drawable = IntPtr.Zero;
+                       }
+                       current_gdk_drawable = gdk_pixmap_new (IntPtr.Zero, area.Width, area.Height, 24);
+                       
+                       IntPtr tmp_style = IntPtr.Zero;
+                       
+                       if (type == typeof(ButtonBase)) {
+                               tmp_style = global_gtk_button_style;
+                               current_widget = global_gtk_button;
+                       } else
+                       if (type == typeof(ScrollBar)) {
+                               if (orientation == Orientation.Vertical) {
+                                       tmp_style = global_gtk_vscrollbar_style;
+                                       current_widget = global_gtk_vscrollbar;
+                               } else {
+                                       tmp_style = global_gtk_hscrollbar_style;
+                                       current_widget = global_gtk_hscrollbar;
+                               }
+                       } else
+                       if (type == typeof(ProgressBar)) {
+                               tmp_style = global_gtk_progress_bar_style;
+                               current_widget = global_gtk_progress_bar;
+                       } else
+                       if (type == typeof(RadioButton)) {
+                               tmp_style = global_gtk_radio_button_style;
+                               current_widget = global_gtk_radio_button;
+                       } else
+                       if (type == typeof(CheckBox)) {
+                               tmp_style = global_gtk_check_button_style;
+                               current_widget = global_gtk_check_button;
+                       } else
+                       if (type == typeof(TrackBar)) {
+                               if (orientation == Orientation.Vertical) {
+                                       tmp_style = global_gtk_vscale_style;
+                                       current_widget = global_gtk_vscale;
+                               } else {
+                                       tmp_style = global_gtk_hscale_style;
+                                       current_widget = global_gtk_hscale;
+                               }
+                       } else
+                               tmp_style = global_style;
+                       
+                       current_style = gtk_style_attach (tmp_style, current_gdk_drawable);  // need it
+               }
+               #endif
+               
+               #if _EXPERIMENTAL_
+               private void DrawDrawableToDC (Graphics dc, Control control)
+               {
+                       IntPtr new_pixbuf = gdk_pixbuf_new (0, true, 8, control.ClientRectangle.Width, control.ClientRectangle.Height);
+                       
+                       gdk_pixbuf_get_from_drawable (new_pixbuf,
+                                                     current_gdk_drawable,
+                                                     global_color_map,
+                                                     0,
+                                                     0,
+                                                     0,
+                                                     0,
+                                                     -1,
+                                                     -1);
+                       
+                       IntPtr error = IntPtr.Zero;
+                       IntPtr buffer;
+                       UIntPtr buffer_size_as_ptr;
+                       string type = "png";
+                       
+                       bool saved = gdk_pixbuf_save_to_buffer (new_pixbuf, out buffer, out buffer_size_as_ptr, type, out error, IntPtr.Zero);
+                       
+                       if (!saved)
+                               return;
+                       
+                       int buffer_size = (int) (uint) buffer_size_as_ptr;
+                       byte[] result = new byte [buffer_size];
+                       Marshal.Copy (buffer, result, 0, (int) buffer_size);
+                       g_free (buffer);
+                       g_object_unref (new_pixbuf);
+                       
+                       Image image = null;
+                       using (MemoryStream s = new MemoryStream (result))
+                               image = Image.FromStream (s);
+                       
+                       dc.DrawImage (image, control.ClientRectangle);
+               }
+               
+               private void DrawDrawableToDC (Graphics dc, Rectangle area)
+               {
+                       IntPtr new_pixbuf = gdk_pixbuf_new (0, true, 8, area.Width, area.Height);
+                       
+                       gdk_pixbuf_get_from_drawable (new_pixbuf,
+                                                     current_gdk_drawable,
+                                                     global_color_map,
+                                                     0,
+                                                     0,
+                                                     0,
+                                                     0,
+                                                     -1,
+                                                     -1);
+                       
+                       IntPtr error = IntPtr.Zero;
+                       IntPtr buffer;
+                       UIntPtr buffer_size_as_ptr;
+                       string type = "png";
+                       
+                       bool saved = gdk_pixbuf_save_to_buffer (new_pixbuf, out buffer, out buffer_size_as_ptr, type, out error, IntPtr.Zero);
+                       
+                       if (!saved)
+                               return;
+                       
+                       int buffer_size = (int) (uint) buffer_size_as_ptr;
+                       byte[] result = new byte [buffer_size];
+                       Marshal.Copy (buffer, result, 0, (int) buffer_size);
+                       g_free (buffer);
+                       g_object_unref (new_pixbuf);
+                       
+                       Image image = null;
+                       using (MemoryStream s = new MemoryStream (result))
+                               image = Image.FromStream (s);
+                       
+                       dc.DrawImage (image, area);
+               }
+               #endif
+               
+               public override void DrawButtonBase (Graphics dc, Rectangle clip_area, ButtonBase button)
+               {
+                       SetDrawableAndStyle (button);
+                       
+                       // Draw the button: fill rectangle, draw border, etc.
+                       ButtonBase_DrawButton (button, dc);
+                       
+                       // First, draw the image
+                       if ((button.image != null) || (button.image_list != null))
+                               ButtonBase_DrawImage (button, dc);
+                       
+                       // Draw the focus rectangle
+                       if (button.has_focus)
+                               ButtonBase_DrawFocus (button, dc);
+                       
+                       #if _EXPERIMENTAL_
+                       DrawDrawableToDC (dc, button);
+                       #endif
 
-               public void DrawScrollButton (Graphics dc, Rectangle area, ScrollButton type, ButtonState state,
-                       IntPtr gdkwindow, IntPtr style)
+                       // Now the text
+                       if (button.Text != null && button.Text != String.Empty)
+                               ButtonBase_DrawText (button, dc);
+               }
+               
+               protected override void ButtonBase_DrawButton(ButtonBase button, Graphics dc)
+               {
+                       Rectangle buttonRectangle = button.ClientRectangle;
+                       
+                       StateType state_type = StateType.Normal;
+                       ShadowType shadow_type = button.FlatStyle == FlatStyle.Flat ? ShadowType.In : ShadowType.Out;
+                       string detail = "buttondefault";
+                       
+                       if (((button is CheckBox) && (((CheckBox)button).check_state == CheckState.Checked)) ||
+                           ((button is RadioButton) && (((RadioButton)button).check_state == CheckState.Checked))) {
+                               state_type = StateType.Active;
+                               shadow_type = ShadowType.In;
+                               detail = "button";
+                       } else
+                       if (!button.is_enabled) {
+                               state_type = StateType.Insensitive;
+                       } else
+                       if (button.is_pressed) {
+                               state_type = StateType.Active;
+                               shadow_type = ShadowType.In;
+                               detail = "button";
+                       } else
+                       if (button.is_entered) {
+                               state_type = StateType.Prelight;
+                       }
+                       
+                       if (button.Focused)
+                               gtk_widget_grab_focus (global_gtk_button);
+                       
+                       if (button.FlatStyle == FlatStyle.Flat)
+                               gtk_paint_flat_box (current_style,
+                                                   current_gdk_drawable,
+                                                   (int) state_type,
+                                                   (int) shadow_type,
+                                                   IntPtr.Zero,
+                                                   global_gtk_button,
+                                                   detail,
+                                                   buttonRectangle.X, buttonRectangle.Y,
+                                                   buttonRectangle.Width, buttonRectangle.Height);
+                       else
+                       if (button.FlatStyle != FlatStyle.Popup || (button.FlatStyle == FlatStyle.Popup && button.is_entered))
+                               gtk_paint_box (current_style,
+                                              current_gdk_drawable,
+                                              (int) state_type,
+                                              (int) shadow_type,
+                                              IntPtr.Zero,
+                                              global_gtk_button,
+                                              detail,
+                                              buttonRectangle.X, buttonRectangle.Y,
+                                              buttonRectangle.Width, buttonRectangle.Height);
+               }
+               
+               protected override void ButtonBase_DrawFocus (ButtonBase button, Graphics dc)
+               {
+                       if (!button.is_enabled)
+                               return;
+                       
+                       Rectangle focus_rect = new Rectangle (button.ClientRectangle.X + 4, button.ClientRectangle.Y + 4, button.ClientRectangle.Width - 9, button.ClientRectangle.Height - 9);
+                       
+                       gtk_widget_grab_focus (global_gtk_button);
+                       
+                       gtk_paint_focus (current_style,
+                                        current_gdk_drawable,
+                                        (int) StateType.Active,
+                                        IntPtr.Zero,
+                                        global_gtk_button,
+                                        "button",
+                                        focus_rect.X,
+                                        focus_rect.Y,
+                                        focus_rect.Width,
+                                        focus_rect.Height);
+               }
+               
+               #region ScrollBar
+               public override void DrawScrollBar( Graphics dc, Rectangle clip, ScrollBar bar ) {
+                       int             scrollbutton_width = bar.scrollbutton_width;
+                       int             scrollbutton_height = bar.scrollbutton_height;
+                       Rectangle       first_arrow_area;
+                       Rectangle       second_arrow_area;                      
+                       Rectangle       thumb_pos;
+                       
+                       SetDrawableAndStyle (bar);
+                       
+                       Rectangle allocation = new Rectangle (bar.ClientRectangle.X, bar.ClientRectangle.Y, bar.ClientRectangle.Width, bar.ClientRectangle.Height);
+                       
+                       // fix for artefacts
+                       Color fix_color = bar.Parent != null ? bar.Parent.BackColor : ColorControl;
+                       
+                       if (bar.vert) {
+                               gtk_widget_size_allocate (global_gtk_vscrollbar, ref allocation);
+                               
+                               // fix for artefacts
+                               dc.FillRectangle (ResPool.GetSolidBrush (fix_color), 
+                                                 bar.ClientRectangle.X, bar.ClientRectangle.Y, bar.ClientRectangle.Width, 3);
+                               dc.FillRectangle (ResPool.GetSolidBrush (fix_color), 
+                                                 bar.ClientRectangle.X, bar.ClientRectangle.Bottom - 4, bar.ClientRectangle.Width, 3);
+                       } else {
+                               gtk_widget_size_allocate (global_gtk_hscrollbar, ref allocation);
+                               
+                               // fix for artefacts
+                               dc.FillRectangle (ResPool.GetSolidBrush (fix_color), 
+                                                 bar.ClientRectangle.X, bar.ClientRectangle.Y, 3, bar.ClientRectangle.Height);
+                               dc.FillRectangle (ResPool.GetSolidBrush (fix_color), 
+                                                 bar.ClientRectangle.Right - 4, bar.ClientRectangle.Y, 3, bar.ClientRectangle.Height);
+                       }
+                       
+                       thumb_pos = bar.ThumbPos;
+                       
+                       if ( bar.vert ) {
+                               first_arrow_area = new Rectangle( 0, 0, bar.Width, scrollbutton_height + 1 );
+                               bar.FirstArrowArea = first_arrow_area;
+                               
+                               second_arrow_area = new Rectangle( 0, bar.ClientRectangle.Height - scrollbutton_height - 1, bar.Width, scrollbutton_height + 1 );
+                               bar.SecondArrowArea = second_arrow_area;
+                               
+                               thumb_pos.Width = bar.Width;
+                               bar.ThumbPos = thumb_pos;
+                               
+                               ScrollBar_Vertical_Draw_ThumbMoving_None (scrollbutton_height, bar, clip, dc);
+                               
+                               /* Buttons */
+                               if ( clip.IntersectsWith( first_arrow_area ) )
+                                       CPDrawScrollButton( dc, first_arrow_area, ScrollButton.Up, bar.firstbutton_state );
+                               if ( clip.IntersectsWith( second_arrow_area ) )
+                                       CPDrawScrollButton( dc, second_arrow_area, ScrollButton.Down, bar.secondbutton_state );
+                       } else {
+                               first_arrow_area = new Rectangle( 0, 0, scrollbutton_width + 1, bar.Height );
+                               bar.FirstArrowArea = first_arrow_area;
+                               
+                               second_arrow_area = new Rectangle( bar.ClientRectangle.Width - scrollbutton_width - 1, 0, scrollbutton_width + 1, bar.Height );
+                               bar.SecondArrowArea = second_arrow_area;
+                               
+                               thumb_pos.Height = bar.Height;
+                               bar.ThumbPos = thumb_pos;
+                               
+                               /* Background */                                        
+                               ScrollBar_Horizontal_Draw_ThumbMoving_None (scrollbutton_width, bar, clip, dc);
+                               
+                               /* Buttons */
+                               if ( clip.IntersectsWith( first_arrow_area ) )
+                                       CPDrawScrollButton( dc, first_arrow_area, ScrollButton.Left, bar.firstbutton_state );
+                               if ( clip.IntersectsWith( second_arrow_area ) )
+                                       CPDrawScrollButton( dc, second_arrow_area, ScrollButton.Right, bar.secondbutton_state );
+                       }
+                       
+                       /* Thumb */
+                       ScrollBar_DrawThumb( bar, thumb_pos, clip, dc );
+                       
+                       #if _EXPERIMENTAL_
+                       DrawDrawableToDC (dc, bar);
+                       #endif
+               }
+               
+               protected override void ScrollBar_DrawThumb( ScrollBar bar, Rectangle thumb_pos, Rectangle clip, Graphics dc ) {
+                       if ( bar.Enabled)
+                               DrawScrollBarThumb( dc, thumb_pos, bar );
+               }
+               
+               protected override void ScrollBar_Vertical_Draw_ThumbMoving_None (int scrollbutton_height, ScrollBar bar, Rectangle clip, Graphics dc)
+               {
+                       Rectangle r = new Rectangle (0,
+                                                    scrollbutton_height, bar.ClientRectangle.Width, bar.ClientRectangle.Height - (scrollbutton_height * 2));
+                       gtk_paint_box (current_style, 
+                                      current_gdk_drawable, 
+                                      (int) StateType.Active,
+                                      (int) ShadowType.In,
+                                      IntPtr.Zero,
+                                      global_gtk_vscrollbar,
+                                      "vscrollbar",
+                                      r.X, r.Y,
+                                      r.Width, r.Height);
+               }
+               
+               protected override void ScrollBar_Horizontal_Draw_ThumbMoving_None (int scrollbutton_width, ScrollBar bar, Rectangle clip, Graphics dc)
+               {
+                       Rectangle r = new Rectangle (scrollbutton_width,
+                                                    0, bar.ClientRectangle.Width - (scrollbutton_width * 2), bar.ClientRectangle.Height);
+                       
+                       gtk_paint_box (current_style, 
+                                      current_gdk_drawable, 
+                                      (int) StateType.Active,
+                                      (int) ShadowType.In,
+                                      IntPtr.Zero,
+                                      global_gtk_hscrollbar,
+                                      "hscrollbar",
+                                      r.X, r.Y,
+                                      r.Width, r.Height);
+               }
+               
+               private void DrawScrollBarThumb( Graphics dc, Rectangle area, ScrollBar bar ) {
+                       IntPtr gtk_scrollbar = bar.vert ? global_gtk_vscrollbar : global_gtk_hscrollbar;
+                       
+                       gtk_paint_box (current_style, 
+                                      current_gdk_drawable, 
+                                      (int) StateType.Active,
+                                      (int) ShadowType.Out,
+                                      IntPtr.Zero,
+                                      gtk_scrollbar,
+                                      "slider",
+                                      area.X, area.Y,
+                                      area.Width, area.Height);
+               }
+               #endregion      // ScrollBar
+               
+               #region ProgressBar
+               public override void DrawProgressBar (Graphics dc, Rectangle clip_rect, ProgressBar ctrl)
+               {
+                       Rectangle       client_area = ctrl.client_area;
+                       int             barpos_pixels;
+                       
+                       SetDrawableAndStyle (ctrl);
+                       
+                       // draw background
+                       gtk_paint_box (current_style,
+                                      current_gdk_drawable,
+                                      (int) StateType.Normal,
+                                      (int) ShadowType.In, 
+                                      IntPtr.Zero,
+                                      global_gtk_progress_bar,
+                                      "trough",
+                                      ctrl.ClientRectangle.X, 
+                                      ctrl.ClientRectangle.Y,
+                                      ctrl.ClientRectangle.Width,
+                                      ctrl.ClientRectangle.Height);
+                       
+                       // don't draw the bar if Value is = 0
+                       if (ctrl.Value <= 0)
+                               return;
+                       
+                       int value = ctrl.Value;
+                       
+                       if (value > ctrl.Maximum)
+                               value = ctrl.Maximum;
+                       
+                       if (value == ctrl.Maximum)
+                               barpos_pixels = client_area.Width + 2;
+                       else
+                               barpos_pixels = (((value - ctrl.Minimum) * client_area.Width) / (ctrl.Maximum - ctrl.Minimum)) + 1;
+                       
+                       gtk_paint_box (current_style, 
+                                      current_gdk_drawable, 
+                                      (int) StateType.Prelight,
+                                      (int) ShadowType.Out,
+                                      IntPtr.Zero,
+                                      global_gtk_progress_bar,
+                                      "bar",
+                                      client_area.X - 1, client_area.Y - 1,
+                                      barpos_pixels, client_area.Height + 2);
+                       
+                       #if _EXPERIMENTAL_
+                       DrawDrawableToDC (dc, ctrl);
+                       #endif
+               }
+               #endregion      // ProgressBar
+               
+               #region RadioButton
+               protected override void RadioButton_DrawButton (RadioButton radio_button, Graphics dc, ButtonState state, Rectangle radiobutton_rectangle)
+               {
+                       // we currently don't care for flat or popup radio buttons
+                       if (radio_button.appearance == Appearance.Button) {
+                               DrawButtonBase (dc, radio_button.ClientRectangle, radio_button);
+                       } else {
+                               DrawRadioButton (dc, radio_button, state, radiobutton_rectangle);
+                       }
+               }
+               
+               private void DrawRadioButton (Graphics dc, RadioButton radio_button, ButtonState state, Rectangle radiobutton_rectangle)
+               {
+                       SetDrawableAndStyle (radio_button);
+                       
+                       ShadowType shadow_type;
+                       
+                       if (!radio_button.Enabled)
+                               shadow_type = ShadowType.Out;
+                       else
+                               shadow_type = radio_button.Checked ? ShadowType.In : ShadowType.EtchedIn;
+                       
+                       StateType state_type = StateType.Normal;
+                       
+                       if (!radio_button.Enabled)
+                               state_type = StateType.Insensitive;
+                       else
+                       if (radio_button.is_pressed)
+                               state_type = StateType.Active;
+                       else
+                       if (radio_button.is_entered)
+                               state_type = StateType.Prelight;
+                       
+                       gtk_paint_option (current_style,
+                                         current_gdk_drawable,
+                                         (int) state_type,
+                                         (int) shadow_type,
+                                         IntPtr.Zero,
+                                         global_gtk_radio_button,
+                                         "radiobutton",
+                                         radiobutton_rectangle.X,
+                                         radiobutton_rectangle.Y,
+                                         radiobutton_rectangle.Width,
+                                         radiobutton_rectangle.Height);
+                       
+                       #if _EXPERIMENTAL_
+                       DrawDrawableToDC (dc, radio_button);
+                       #endif
+               }
+               
+               protected override void RadioButton_DrawText (RadioButton radio_button, Rectangle text_rectangle, Graphics dc, StringFormat text_format)
+               {
+                       if (radio_button.Appearance != Appearance.Button)
+                               base.RadioButton_DrawText (radio_button, text_rectangle, dc, text_format);
+               }
+       
+               protected override void RadioButton_DrawFocus (RadioButton radio_button, Graphics dc, Rectangle text_rectangle)
+               {
+                       if (radio_button.Focused && radio_button.appearance != Appearance.Button) {
+                               gtk_paint_focus (current_style,
+                                                current_gdk_drawable,
+                                                (int) StateType.Active,
+                                                IntPtr.Zero,
+                                                global_gtk_radio_button,
+                                                "radiobutton",
+                                                text_rectangle.X,
+                                                text_rectangle.Y,
+                                                text_rectangle.Width,
+                                                text_rectangle.Height);
+                       }
+                       
+                       #if _EXPERIMENTAL_
+                       DrawDrawableToDC (dc, radio_button);
+                       #endif
+               }
+               #endregion      // RadioButton
+               
+               #region CheckBox
+               protected override void CheckBox_DrawCheckBox (Graphics dc, CheckBox checkbox, ButtonState state, Rectangle checkbox_rectangle)
+               {
+                       // render as per normal button
+                       if (checkbox.appearance == Appearance.Button) {
+                               DrawButtonBase (dc, checkbox.ClientRectangle, checkbox);
+                       } else {
+                               InternalDrawCheckBox (dc, checkbox, state, checkbox_rectangle);
+                       }
+               }
+               
+               private void InternalDrawCheckBox (Graphics dc, CheckBox checkbox, ButtonState state, Rectangle checkbox_rectangle)
                {
+                       SetDrawableAndStyle (checkbox);
+                       
+                       ShadowType shadow_type;
+                       
+                       if (!checkbox.Enabled)
+                               shadow_type = ShadowType.Out;
+                       else
+                               shadow_type = checkbox.Checked ? ShadowType.In : ShadowType.EtchedIn;
+                       
+                       StateType state_type = StateType.Normal;
+                       
+                       if (!checkbox.Enabled)
+                               state_type = StateType.Insensitive;
+                       else
+                       if (checkbox.is_pressed)
+                               state_type = StateType.Active;
+                       else
+                       if (checkbox.is_entered)
+                               state_type = StateType.Prelight;
+                       
+                       gtk_paint_check (current_style,
+                                        current_gdk_drawable,
+                                        (int) state_type,
+                                        (int) shadow_type,
+                                        IntPtr.Zero,
+                                        global_gtk_check_button,
+                                        "checkbutton",
+                                        checkbox_rectangle.X,
+                                        checkbox_rectangle.Y,
+                                        checkbox_rectangle.Width,
+                                        checkbox_rectangle.Height);
+                       
+                       #if _EXPERIMENTAL_
+                       DrawDrawableToDC (dc, checkbox);
+                       #endif
+               }
+               
+               protected override void CheckBox_DrawText (CheckBox checkbox, Rectangle text_rectangle, Graphics dc, StringFormat text_format)
+               {
+                       if (checkbox.Appearance != Appearance.Button)
+                               base.CheckBox_DrawText (checkbox, text_rectangle, dc, text_format);
+               }
+               
+               protected override void CheckBox_DrawFocus( CheckBox checkbox, Graphics dc, Rectangle text_rectangle )
+               {
+                       if (checkbox.Focused && checkbox.appearance != Appearance.Button) {
+                               gtk_paint_focus (current_style,
+                                                current_gdk_drawable,
+                                                (int) StateType.Active,
+                                                IntPtr.Zero,
+                                                global_gtk_check_button,
+                                                "checkbutton",
+                                                text_rectangle.X,
+                                                text_rectangle.Y,
+                                                text_rectangle.Width,
+                                                text_rectangle.Height);
+                       }
+                       
+                       #if _EXPERIMENTAL_
+                       DrawDrawableToDC (dc, checkbox);
+                       #endif
+               }
+               #endregion      // CheckBox
+               
+               #region TrackBar
+               private void DrawTrackBar_Vertical (Graphics dc, Rectangle clip_rectangle, TrackBar tb,
+                                                   ref Rectangle thumb_pos, ref Rectangle thumb_area,
+                                                   float ticks, int value_pos, bool mouse_value)
+               {                       
+                       Point toptick_startpoint = new Point ();
+                       Point bottomtick_startpoint = new Point ();
+                       Point channel_startpoint = new Point ();
+                       float pixel_len;
+                       float pixels_betweenticks;
+                       const int space_from_right = 8;
+                       const int space_from_left = 8;
+                       Rectangle area = tb.ClientRectangle;
+                       
+                       Rectangle allocation = new Rectangle (area.X, area.Y, area.Width, area.Height);
+                       
+                       gtk_widget_size_allocate (current_widget, ref allocation);
+                       
+                       gtk_range_set_range (current_widget, tb.Minimum, tb.Maximum);
+                       gtk_range_set_value (current_widget, tb.Value);
+                       
+                       ShadowType shadow_type = ShadowType.In;
+                       
+                       if (!tb.Enabled)
+                               shadow_type = ShadowType.Out;
+                       
+                       StateType state_type = StateType.Normal;
+                       
+                       if (!tb.Enabled)
+                               state_type = StateType.Insensitive;
+                       else
+                       if (tb.is_entered)
+                               state_type = StateType.Prelight;
+                       
+                       switch (tb.TickStyle)   {
+                       case TickStyle.BottomRight:
+                       case TickStyle.None:
+                               channel_startpoint.Y = 8;
+                               channel_startpoint.X = 9;
+                               bottomtick_startpoint.Y = 13;
+                               bottomtick_startpoint.X = 24;                           
+                               break;
+                       case TickStyle.TopLeft:
+                               channel_startpoint.Y = 8;
+                               channel_startpoint.X = 19;
+                               toptick_startpoint.Y = 13;
+                               toptick_startpoint.X = 8;
+                               break;
+                       case TickStyle.Both:
+                               channel_startpoint.Y = 8;
+                               channel_startpoint.X = 18;      
+                               bottomtick_startpoint.Y = 13;
+                               bottomtick_startpoint.X = 32;                           
+                               toptick_startpoint.Y = 13;
+                               toptick_startpoint.X = 8;                               
+                               break;
+                       default:
+                               break;
+                       }
+                       
+                       thumb_area.X = area.X + channel_startpoint.X;
+                       thumb_area.Y = area.Y + channel_startpoint.Y;
+                       thumb_area.Height = area.Height - space_from_right - space_from_left;
+                       thumb_area.Width = 4;
+                       
+                       pixel_len = thumb_area.Height - 11;
+                       pixels_betweenticks = pixel_len / (tb.Maximum - tb.Minimum);
+                       
+                       /* Convert thumb position from mouse position to value*/
+                       if (mouse_value) {
+                               
+                               if (value_pos >= channel_startpoint.Y)
+                                       value_pos = (int)(((float) (value_pos - channel_startpoint.Y)) / pixels_betweenticks);
+                               else
+                                       value_pos = 0;                  
+                               
+                               if (value_pos + tb.Minimum > tb.Maximum)
+                                       value_pos = tb.Maximum - tb.Minimum;
+                                
+                               tb.Value = value_pos + tb.Minimum;
+                       }               
+                       
+                       thumb_pos.Width = 13;
+                       thumb_pos.Height = 29;
+                       
+                       thumb_pos.Y = channel_startpoint.Y + (int) (pixels_betweenticks * (float) value_pos) - (thumb_pos.Height / 3);
+                       
+                       if (thumb_pos.Y < channel_startpoint.Y)
+                               thumb_pos.Y = channel_startpoint.Y;
+                       
+                       if (thumb_pos.Y > thumb_area.Bottom - 29)
+                               thumb_pos.Y = thumb_area.Bottom - 29;
+                       
+                       /* Draw channel */
+                       gtk_paint_box (current_style,
+                                      current_gdk_drawable,
+                                      (int)state_type,
+                                      (int)shadow_type,
+                                      IntPtr.Zero,
+                                      current_widget,
+                                      "trough",
+                                      thumb_area.X,
+                                      thumb_area.Y,
+                                      4,
+                                      thumb_area.Height);
+                       
+                       /* Draw thumb */
+                       thumb_pos.X = channel_startpoint.X + 2 - thumb_pos.Width / 2;
+                       
+                       shadow_type = ShadowType.Out;
+                       
+                       gtk_paint_slider (current_style,
+                                         current_gdk_drawable,
+                                         (int)state_type,
+                                         (int)shadow_type,
+                                         IntPtr.Zero,
+                                         current_widget,
+                                         "vscale",
+                                         thumb_pos.X,
+                                         thumb_pos.Y,
+                                         thumb_pos.Width,
+                                         thumb_pos.Height,
+                                         0);
+                       
+                       pixel_len = thumb_area.Height - 11;
+                       pixels_betweenticks = pixel_len / ticks;
+                       
+                       /* Draw ticks*/
+                       thumb_area.X = thumb_pos.X;
+                       thumb_area.Y = channel_startpoint.Y;
+                       thumb_area.Width = thumb_pos.Width;
+                       
+                       Region outside = new Region (area);
+                       outside.Exclude (thumb_area);                   
+                       
+                       if (outside.IsVisible (clip_rectangle)) {                               
+                               if (pixels_betweenticks > 0 && ((tb.TickStyle & TickStyle.BottomRight) == TickStyle.BottomRight ||
+                                   ((tb.TickStyle & TickStyle.Both) == TickStyle.Both))) {     
+                                       
+                                       for (float inc = 0; inc < (pixel_len + 1); inc += pixels_betweenticks)  {                                       
+                                               if (inc == 0 || (inc +  pixels_betweenticks) >= pixel_len + 1)
+                                                       dc.DrawLine (ResPool.GetPen (pen_ticks_color), area.X + bottomtick_startpoint.X , area.Y + bottomtick_startpoint.Y  + inc, 
+                                                                    area.X + bottomtick_startpoint.X  + 3, area.Y + bottomtick_startpoint.Y + inc);
+                                               else
+                                                       dc.DrawLine (ResPool.GetPen (pen_ticks_color), area.X + bottomtick_startpoint.X, area.Y + bottomtick_startpoint.Y  + inc, 
+                                                                    area.X + bottomtick_startpoint.X  + 2, area.Y + bottomtick_startpoint.Y + inc);
+                                       }
+                               }
+                               
+                               if (pixels_betweenticks > 0 &&  ((tb.TickStyle & TickStyle.TopLeft) == TickStyle.TopLeft ||
+                                   ((tb.TickStyle & TickStyle.Both) == TickStyle.Both))) {
+                                       
+                                       pixel_len = thumb_area.Height - 11;
+                                       pixels_betweenticks = pixel_len / ticks;
+                                       
+                                       for (float inc = 0; inc < (pixel_len + 1); inc += pixels_betweenticks) {                                        
+                                               if (inc == 0 || (inc +  pixels_betweenticks) >= pixel_len + 1)
+                                                       dc.DrawLine (ResPool.GetPen (pen_ticks_color), area.X + toptick_startpoint.X  - 3 , area.Y + toptick_startpoint.Y + inc, 
+                                                                    area.X + toptick_startpoint.X, area.Y + toptick_startpoint.Y + inc);
+                                               else
+                                                       dc.DrawLine (ResPool.GetPen (pen_ticks_color), area.X + toptick_startpoint.X  - 2, area.Y + toptick_startpoint.Y + inc, 
+                                                                    area.X + toptick_startpoint.X, area.Y + toptick_startpoint.Y  + inc);
+                                       }                       
+                               }
+                       }
+                       
+                       outside.Dispose ();
+               }
+               
+               private void DrawTrackBar_Horizontal (Graphics dc, Rectangle clip_rectangle, TrackBar tb,
+                                                     ref Rectangle thumb_pos, ref Rectangle thumb_area,
+                                                     float ticks, int value_pos, bool mouse_value)
+               {                       
+                       Point toptick_startpoint = new Point ();
+                       Point bottomtick_startpoint = new Point ();
+                       Point channel_startpoint = new Point ();
+                       float pixel_len;
+                       float pixels_betweenticks;
+                       const int space_from_right = 8;
+                       const int space_from_left = 8;
+                       Rectangle area = tb.ClientRectangle;
+                       
+                       Rectangle allocation = new Rectangle (area.X, area.Y, area.Width, area.Height);
+                       
+                       gtk_widget_size_allocate (current_widget, ref allocation);
+                       
+                       gtk_range_set_range (current_widget, tb.Minimum, tb.Maximum);
+                       gtk_range_set_value (current_widget, tb.Value);
+                       
+                       ShadowType shadow_type = ShadowType.In;
+                       
+                       if (!tb.Enabled)
+                               shadow_type = ShadowType.Out;
+                       
+                       StateType state_type = StateType.Normal;
+                       
+                       if (!tb.Enabled)
+                               state_type = StateType.Insensitive;
+                       else
+                       if (tb.is_entered)
+                               state_type = StateType.Prelight;
+                       
+                       switch (tb.TickStyle) {
+                       case TickStyle.BottomRight:
+                       case TickStyle.None:
+                               channel_startpoint.X = 8;
+                               channel_startpoint.Y = 9;
+                               bottomtick_startpoint.X = 13;
+                               bottomtick_startpoint.Y = 24;                           
+                               break;
+                       case TickStyle.TopLeft:
+                               channel_startpoint.X = 8;
+                               channel_startpoint.Y = 19;
+                               toptick_startpoint.X = 13;
+                               toptick_startpoint.Y = 8;
+                               break;
+                       case TickStyle.Both:
+                               channel_startpoint.X = 8;
+                               channel_startpoint.Y = 18;      
+                               bottomtick_startpoint.X = 13;
+                               bottomtick_startpoint.Y = 32;                           
+                               toptick_startpoint.X = 13;
+                               toptick_startpoint.Y = 8;                               
+                               break;
+                       default:
+                               break;
+                       }
+                       
+                       thumb_area.X = area.X + channel_startpoint.X;
+                       thumb_area.Y = area.Y + channel_startpoint.Y;
+                       thumb_area.Width = area.Width - space_from_right - space_from_left;
+                       thumb_area.Height = 4;
+                       
+                       pixel_len = thumb_area.Width - 11;
+                       pixels_betweenticks = pixel_len / (tb.Maximum - tb.Minimum);
+                       
+                       /* Convert thumb position from mouse position to value*/
+                       if (mouse_value) {                      
+                               if (value_pos >= channel_startpoint.X)
+                                       value_pos = (int)(((float) (value_pos - channel_startpoint.X)) / pixels_betweenticks);
+                               else
+                                       value_pos = 0;                          
+                               
+                               if (value_pos + tb.Minimum > tb.Maximum)
+                                       value_pos = tb.Maximum - tb.Minimum;
+                                
+                               tb.Value = value_pos + tb.Minimum;
+                       }                       
+                       
+                       thumb_pos.Width = 29;
+                       thumb_pos.Height = 13;
+                       
+                       thumb_pos.X = channel_startpoint.X + (int) (pixels_betweenticks * (float) value_pos) - (thumb_pos.Width / 3);
+                       
+                       
+                       if (thumb_pos.X < channel_startpoint.X)
+                               thumb_pos.X = channel_startpoint.X;
+                       
+                       if (thumb_pos.X > thumb_area.Right - 29)
+                               thumb_pos.X = thumb_area.Right - 29;
+                       
+                       /* Draw channel */
+                       gtk_paint_box (current_style,
+                                      current_gdk_drawable,
+                                      (int)state_type,
+                                      (int)shadow_type,
+                                      IntPtr.Zero,
+                                      current_widget,
+                                      "trough",
+                                      thumb_area.X,
+                                      thumb_area.Y,
+                                      thumb_area.Width,
+                                      4);
+                       
+                       /* Draw thumb */
+                       
+                       thumb_pos.Y = channel_startpoint.Y + 2 - thumb_pos.Height / 2;
+                       
+                       shadow_type = ShadowType.Out;
+                       
+                       gtk_paint_slider (current_style,
+                                         current_gdk_drawable,
+                                         (int)state_type,
+                                         (int)shadow_type,
+                                         IntPtr.Zero,
+                                         current_widget,
+                                         "hscale",
+                                         thumb_pos.X,
+                                         thumb_pos.Y,
+                                         thumb_pos.Width,
+                                         thumb_pos.Height,
+                                         0);
+                       
+                       pixel_len = thumb_area.Width - 11;
+                       pixels_betweenticks = pixel_len / ticks;
+                       
+                       /* Draw ticks*/
+                       thumb_area.Y = thumb_pos.Y;
+                       thumb_area.X = channel_startpoint.X;
+                       thumb_area.Height = thumb_pos.Height;
+                       Region outside = new Region (area);
+                       outside.Exclude (thumb_area);                   
+                       
+                       if (outside.IsVisible (clip_rectangle)) {                               
+                               if (pixels_betweenticks > 0 && ((tb.TickStyle & TickStyle.BottomRight) == TickStyle.BottomRight ||
+                                   ((tb.TickStyle & TickStyle.Both) == TickStyle.Both))) {                             
+                                       
+                                       for (float inc = 0; inc < (pixel_len + 1); inc += pixels_betweenticks) {                                        
+                                               if (inc == 0 || (inc +  pixels_betweenticks) >= pixel_len + 1)
+                                                       dc.DrawLine (ResPool.GetPen (pen_ticks_color), area.X + bottomtick_startpoint.X + inc , area.Y + bottomtick_startpoint.Y, 
+                                                                    area.X + bottomtick_startpoint.X + inc , area.Y + bottomtick_startpoint.Y + 3);
+                                               else
+                                                       dc.DrawLine (ResPool.GetPen (pen_ticks_color), area.X + bottomtick_startpoint.X + inc, area.Y + bottomtick_startpoint.Y, 
+                                                                    area.X + bottomtick_startpoint.X + inc, area.Y + bottomtick_startpoint.Y + 2);
+                                       }
+                               }
+                               
+                               if (pixels_betweenticks > 0 && ((tb.TickStyle & TickStyle.TopLeft) == TickStyle.TopLeft ||
+                                   ((tb.TickStyle & TickStyle.Both) == TickStyle.Both))) {
+                                       
+                                       for (float inc = 0; inc < (pixel_len + 1); inc += pixels_betweenticks) {                                        
+                                               if (inc == 0 || (inc +  pixels_betweenticks) >= pixel_len + 1)
+                                                       dc.DrawLine (ResPool.GetPen (pen_ticks_color), area.X + toptick_startpoint.X + inc , area.Y + toptick_startpoint.Y - 3, 
+                                                                    area.X + toptick_startpoint.X + inc , area.Y + toptick_startpoint.Y);
+                                               else
+                                                       dc.DrawLine (ResPool.GetPen (pen_ticks_color), area.X + toptick_startpoint.X + inc, area.Y + toptick_startpoint.Y - 2, 
+                                                                    area.X + toptick_startpoint.X + inc, area.Y + toptick_startpoint.Y);
+                                       }                       
+                               }
+                       }
+                       
+                       outside.Dispose ();                     
+               }
+               
+               public override void DrawTrackBar (Graphics dc, Rectangle clip_rectangle, TrackBar tb)
+               {
+                       int             value_pos;
+                       bool            mouse_value;
+                       float           ticks = (tb.Maximum - tb.Minimum) / tb.tickFrequency; /* N of ticks draw*/
+                       Rectangle       area;
+                       Rectangle       thumb_pos = tb.ThumbPos;
+                       Rectangle       thumb_area = tb.ThumbArea;
+                       
+                       if (tb.thumb_pressed) {
+                               value_pos = tb.thumb_mouseclick;
+                               mouse_value = true;
+                       } else {
+                               value_pos = tb.Value - tb.Minimum;
+                               mouse_value = false;
+                       }
+                       
+                       area = tb.ClientRectangle;
+                       
+                       SetDrawableAndStyle (tb);
+                       
+                       /* Control Background */
+                       if (tb.BackColor == DefaultControlBackColor) {
+                               dc.FillRectangle (ResPool.GetSolidBrush (ColorControl), clip_rectangle);
+                       } else {
+                               dc.FillRectangle (ResPool.GetSolidBrush (tb.BackColor), clip_rectangle);
+                       }
+                       
+                       if (tb.Orientation == Orientation.Vertical) {
+                               DrawTrackBar_Vertical (dc, clip_rectangle, tb, ref thumb_pos, ref thumb_area,
+                                                      ticks, value_pos, mouse_value);
+                               
+                       } else {
+                               DrawTrackBar_Horizontal (dc, clip_rectangle, tb, ref thumb_pos, ref thumb_area,
+                                                        ticks, value_pos, mouse_value);
+                       }
+                       
+                       if (tb.Enabled && tb.Focused)
+                               gtk_paint_focus (current_style,
+                                                current_gdk_drawable, 
+                                                (int)StateType.Normal,
+                                                IntPtr.Zero,
+                                                current_widget, 
+                                                "trough",
+                                                area.X,
+                                                area.Y,
+                                                area.Width,
+                                                area.Height);
+                       
+                       tb.ThumbPos = thumb_pos;
+                       tb.ThumbArea = thumb_area;
+                       
+                       #if _EXPERIMENTAL_
+                       DrawDrawableToDC (dc, tb);
+                       #endif
+               }
+               #endregion      // TrackBar
+               
+               public override void CPDrawButton (Graphics dc, Rectangle rectangle, ButtonState state)
+               {
+                       #if _EXPERIMENTAL_
+                       SetDrawableAndStyle (rectangle, typeof(ButtonBase), Orientation.Horizontal);
+                       #endif
+                       
+                       bool is_pushed = false;
+//                     bool is_checked = false;
+//                     bool is_flat = false;
+                       bool is_inactive = false;
+                       
+                       if ((state & ButtonState.Pushed) != 0) {
+                               is_pushed = true;
+                       }
+                       
+//                     if ((state & ButtonState.Checked) != 0) {
+//                             is_checked = true;
+//                     }
+//                     
+//                     if ((state & ButtonState.Flat) != 0) {
+//                             is_flat = true;
+//                     }
+                       
+                       if ((state & ButtonState.Inactive) != 0) {
+                               is_inactive = true;
+                       }
+                       
+                       IntPtr drawbutton_style = gtk_style_attach (global_gtk_button_style, current_gdk_drawable);  // need it
+                       
+                       StateType state_type = StateType.Normal;
+                       ShadowType shadow_type = ShadowType.Out;
+                       string detail = "buttondefault";
+                       
+                       if (is_inactive) {
+                               state_type = StateType.Insensitive;
+                       } else
+                       if (is_pushed) {
+                               state_type = StateType.Active;
+                               shadow_type = ShadowType.In;
+                               detail = "button";
+                       }
+                       
+                       gtk_paint_box (drawbutton_style, current_gdk_drawable,
+                                      (int) state_type,
+                                      (int) shadow_type,
+                                      IntPtr.Zero,
+                                      IntPtr.Zero,
+                                      detail,
+                                      rectangle.X, rectangle.Y,
+                                      rectangle.Width, rectangle.Height);
+                       
+                       #if _EXPERIMENTAL_
+                       DrawDrawableToDC (dc, rectangle);
+                       #endif
+               }
+               
+               /* Scroll button: regular button + direction arrow */
+               public override void CPDrawScrollButton (Graphics dc, Rectangle area, ScrollButton scroll_button_type, ButtonState state)
+               {
+                       #if _EXPERIMENTAL_
+                       Orientation orientation = Orientation.Vertical;
+                       if (scroll_button_type == ScrollButton.Left || scroll_button_type == ScrollButton.Right)
+                               orientation = Orientation.Horizontal;
+                       SetDrawableAndStyle (area, typeof(ScrollBar), orientation);
+                       #endif
+                       
+                       bool enabled = (state == ButtonState.Inactive) ? false: true;
+                       
+                       StateType state_type = enabled ? StateType.Normal : StateType.Insensitive;
+                       
+                       DrawScrollButtonPrimitive (dc, area, state, scroll_button_type);
+                       
+                       if (area.Width < 12 || area.Height < 12) /* Cannot see a thing at smaller sizes */
+                               return;
+                       
                        ArrowType arrow_type = 0;
-
-                       gtk_paint_box (style, 
-                                       gdkwindow, 
-                                       (int) StateType.Normal,
-                                       (int) ShadowType.Out,
-                                       IntPtr.Zero,
-                                       IntPtr.Zero,
-                                       "trough",                                       
-                                       area.X, area.Y,
-                                       area.Width, area.Height);
-                       
-                       /* Calc arrows coordinates */
-                       switch (type) {
+                       
+                       switch (scroll_button_type) {
                        case ScrollButton.Up:
                                arrow_type = ArrowType.Up;
                                break;
@@ -272,98 +1497,86 @@ namespace System.Windows.Forms
                        default:
                                break;
                        }
-                               
-
-                       gtk_paint_arrow (style, 
-                                       gdkwindow, 
-                                       (int) StateType.Normal,
-                                       (int) ShadowType.In,
-                                       IntPtr.Zero,
-                                       IntPtr.Zero,
-                                       "",             
-                                       (int) arrow_type, true, 
-                                       area.X + ((area.Width - (area.Width/2) ) / 2), 
-                                       area.Y + ((area.Height - (area.Height/2) ) / 2),
-                                       area.Width / 2, area.Height / 2);                       
-               
+                       
+                       int centerX = area.Left + area.Width / 2;
+                       int centerY = area.Top + area.Height / 2;
+                       int arrow_x = 0, arrow_y = 0, arrow_height = 0, arrow_width = 0;
+                       
+                       switch (scroll_button_type) {
+                       case ScrollButton.Down:
+                       case ScrollButton.Up:
+                               arrow_x = centerX - 4;
+                               arrow_y = centerY - 2;
+                               arrow_width = 8;
+                               arrow_height = 4;
+                               break;
+                       case ScrollButton.Left:
+                       case ScrollButton.Right:
+                               arrow_x = centerX - 2;
+                               arrow_y = centerY - 4;
+                               arrow_width = 4;
+                               arrow_height = 8;
+                               break;
+                       default:
+                               break;
+                       }
+                       
+                       gtk_paint_arrow (current_style, 
+                                        current_gdk_drawable, 
+                                        (int) state_type,
+                                        (int) ShadowType.Out,
+                                        IntPtr.Zero,
+                                        current_widget,
+                                        "",            
+                                        (int) arrow_type, true, 
+                                        arrow_x, 
+                                        arrow_y,
+                                        arrow_width, arrow_height);
+                       
+                       current_widget = IntPtr.Zero;
+                       
+                       #if _EXPERIMENTAL_
+                       DrawDrawableToDC (dc, area);
+                       #endif
                }
                
-               public override void DrawScrollBar (Graphics dc, Rectangle area, ScrollBar bar,
-                       Rectangle thumb_pos, ref Rectangle first_arrow_area, ref Rectangle second_arrow_area, 
-                       ButtonState first_arrow, ButtonState second_arrow, ref int scrollbutton_width, 
-                       ref int scrollbutton_height, bool vert)
+               public void DrawScrollButtonPrimitive (Graphics dc, Rectangle area, ButtonState state, ScrollButton scroll_button_type)
                {
-                       IntPtr gdkwindow = gdk_window_foreign_new_for_display (gdkdisplay, (uint) bar.Handle);                  
-                       IntPtr adj = gtk_adjustment_new (0, 0, 0, 0, 0, 0);
-                        IntPtr scrollbar = gtk_vscrollbar_new (adj);
-                       IntPtr style;
-                                       
-                        style = gtk_rc_get_style (scrollbar);          
-                       //style = gtk_style_attach (style, gdkwindow);  // need it?                     
-                       
-                       /* Background */
-                       gtk_paint_box (style, 
-                               gdkwindow, 
-                               (int) StateType.Active,
-                               (int) ShadowType.In,
-                               IntPtr.Zero,
-                               IntPtr.Zero,
-                               "trough",
-                               area.X, area.Y,
-                               area.Width, area.Height);
-
-                       /* See gtk_range_expose */
-                       first_arrow_area.X = first_arrow_area. Y = 0;
-                       first_arrow_area.Width = scrollbutton_width;
-                       first_arrow_area.Height = scrollbutton_height;
-
-                       if (vert) {             
-
-                               second_arrow_area.X = 0;
-                               second_arrow_area.Y = area.Height - scrollbutton_height;
-                               second_arrow_area.Width = scrollbutton_width;
-                               second_arrow_area.Height = scrollbutton_height;
-
-                               /* First button*/
-                               DrawScrollButton (dc, first_arrow_area, ScrollButton.Up, first_arrow,
-                                       gdkwindow, style);
-
-                               /* Second button*/
-                               DrawScrollButton (dc, first_arrow_area, ScrollButton.Down, first_arrow,
-                                       gdkwindow, style);
-
-                       } else {
-
-                               second_arrow_area.Y = 0;
-                               second_arrow_area.X = area.Width - scrollbutton_width;
-                               second_arrow_area.Width = scrollbutton_width;
-                               second_arrow_area.Height = scrollbutton_height;
-
-                               /* First button*/
-                               DrawScrollButton (dc, first_arrow_area, ScrollButton.Left, first_arrow,
-                                       gdkwindow, style);
-
-                               /* Second button*/
-                               DrawScrollButton (dc, second_arrow_area, ScrollButton.Right, second_arrow,
-                                       gdkwindow, style);
-
+                       StateType state_type = StateType.Normal;
+                       ShadowType shadow_type = ShadowType.Out;
+                       
+                       if ((state & ButtonState.Pushed) == ButtonState.Pushed) {
+                               state_type = StateType.Active;
+                               shadow_type = ShadowType.In;
+                       }
+                       
+                       switch (scroll_button_type) {
+                       case ScrollButton.Left:
+                       case ScrollButton.Right:
+                               gtk_paint_box (current_style, 
+                                              current_gdk_drawable, 
+                                              (int) state_type,
+                                              (int) shadow_type,
+                                              IntPtr.Zero,
+                                              global_gtk_hscrollbar,
+                                              "stepper",
+                                              area.X, area.Y,
+                                              area.Width, area.Height);
+                               break;
+                       case ScrollButton.Up:
+                       case ScrollButton.Down:
+                               gtk_paint_box (current_style, 
+                                              current_gdk_drawable, 
+                                              (int) state_type,
+                                              (int) shadow_type,
+                                              IntPtr.Zero,
+                                              global_gtk_vscrollbar,
+                                              "stepper",
+                                              area.X, area.Y,
+                                              area.Width, area.Height);
+                               break;
                        }
-
-                       /* Slider */
-                       gtk_paint_slider (style, 
-                               gdkwindow, 
-                               (int) StateType.Normal,
-                               (int) ShadowType.Out,
-                               IntPtr.Zero,
-                               IntPtr.Zero,
-                               "",             
-                               thumb_pos.X, thumb_pos.Y,
-                               thumb_pos.Width, thumb_pos.Height,
-                               (int) Orientation.Vertical);
-
-                       //gtk_style_detach (style);
                }
-
                
                private static Color ColorFromGdkColor (GdkColorStruct gtkcolor)
                {