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:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
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.
20 // Copyright (c) 2004-2006 Novell, Inc.
23 // Jordi Mas i Hernandez, jordi@ximian.com
24 // Alexander Olk, alex.olk@googlemail.com
26 // This is an experimental GTK theme.
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 no a device context. We should inverstigate if we
39 // we can encapsulate a dc in a gtkwindow.
41 // Hint: Currently ThemeGtk doesn't work without a modified Control class, it doesn't like
42 // double buffering. As soon as DoubleBufferingSupported is implemented it should run
43 // out of the box. Alex.
50 using System.Drawing.Drawing2D;
51 using System.Drawing.Imaging;
52 using System.Reflection;
53 using System.Runtime.InteropServices;
55 namespace System.Windows.Forms
57 internal class ThemeGtk : ThemeWin32Classic
60 internal enum StateType
69 internal enum ShadowType
78 internal enum ArrowType
87 [StructLayout(LayoutKind.Sequential)]
88 internal struct GdkColorStruct
96 [StructLayout(LayoutKind.Sequential)]
97 internal struct GtkStyleStruct
99 [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=12)]
100 internal byte[] obj; /* GObject is 12 bytes*/
101 [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
102 internal GdkColorStruct[] fg;
103 [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
104 internal GdkColorStruct[] bg;
105 [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
106 internal GdkColorStruct[] light;
107 [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
108 internal GdkColorStruct[] dark;
109 [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
110 internal GdkColorStruct[] mid;
111 [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
112 internal GdkColorStruct[] text;
113 [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
114 internal GdkColorStruct[] baseclr;
115 [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
116 internal GdkColorStruct[] text_aa; /* Halfway between text/base */
118 internal GdkColorStruct black;
119 internal GdkColorStruct white;
121 /* TODO: There is more stuff that we will add when we need it*/
126 [DllImport("libgdk-x11-2.0.so")]
127 internal static extern IntPtr gdk_display_manager_get ();
129 [DllImport("libgdk-x11-2.0.so")]
130 internal static extern IntPtr gdk_display_manager_get_default_display (IntPtr display_manager);
132 [DllImport("libgdk-x11-2.0.so")]
133 internal static extern void gdk_display_manager_set_default_display (IntPtr display_manager, IntPtr display);
135 [DllImport("libgdk-x11-2.0.so")]
136 internal static extern IntPtr gdk_x11_display_get_xdisplay (IntPtr display);
138 [DllImport("libgdk-x11-2.0.so")]
139 static extern IntPtr gdk_window_foreign_new_for_display (IntPtr display, uint anid);
141 [DllImport("libgdk-x11-2.0.so")]
142 static extern bool gdk_init_check(out int argc, string argv);
145 [DllImport("libgtk-x11-2.0.so")]
146 static extern bool gtk_init_check (out int argc, string argv);
148 [DllImport("libgtk-x11-2.0.so")]
149 static extern IntPtr gtk_adjustment_new (double value, double lower, double upper, double step_increment, double page_increment, double page_size);
151 [DllImport("libgtk-x11-2.0.so")]
152 static extern IntPtr gtk_rc_get_style (IntPtr widget);
154 [DllImport("libgtk-x11-2.0.so")]
155 static extern IntPtr gtk_vscrollbar_new(IntPtr adjustment);
157 [DllImport("libgtk-x11-2.0.so")]
158 static extern IntPtr gtk_style_attach (IntPtr raw, IntPtr window);
160 [DllImport("libgtk-x11-2.0.so")]
161 static extern IntPtr gtk_rc_style_new ();
163 [DllImport("libgtk-x11-2.0.so")]
164 static extern IntPtr gtk_invisible_new ();
166 [DllImport("libgtk-x11-2.0.so")]
167 static extern void gtk_widget_ensure_style (IntPtr raw);
169 [DllImport("libgtk-x11-2.0.so")]
170 static extern IntPtr gtk_widget_get_style (IntPtr raw);
172 [DllImport("libgtk-x11-2.0.so")]
173 static extern void gtk_style_detach (IntPtr raw);
175 [DllImport("libgtk-x11-2.0.so")]
176 static extern IntPtr gtk_button_new ();
179 [DllImport("libgtk-x11-2.0.so")]
180 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);
182 [DllImport("libgtk-x11-2.0.so")]
183 static extern void gtk_paint_arrow (IntPtr style, IntPtr window, int state_type, int shadow_type,
184 IntPtr area, IntPtr widget, string detail, int arrow_type, bool fill, int x, int y, int width, int height);
186 [DllImport("libgtk-x11-2.0.so")]
187 static extern void gtk_paint_slider (IntPtr style, IntPtr window, int state_type, int shadow_type,
188 IntPtr area, IntPtr widget, string detail, int x, int y, int width, int height, int orientation);
190 [DllImport("libgtk-x11-2.0.so")]
191 static extern void gtk_paint_box (IntPtr style, IntPtr window, int state_type, int shadow_type,
192 IntPtr area, IntPtr widget, string detail, int x, int y, int width, int height);
194 [DllImport("libgtk-x11-2.0.so")]
195 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);
197 [DllImport("libgtk-x11-2.0.so")]
198 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);
200 [DllImport("libgtk-x11-2.0.so")]
201 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);
204 static protected IntPtr dispmgr;
205 static protected IntPtr gdkdisplay;
206 static protected IntPtr widget;
207 static protected IntPtr style;
208 static protected SolidBrush br_buttonface;
209 static protected SolidBrush br_buttontext;
211 IntPtr global_gtk_button = gtk_button_new();
213 public static void InitGtk ()
215 Console.WriteLine ("ThemeGtk Init");
219 gdk_init_check (out argc, argv);
221 dispmgr = gdk_display_manager_get ();
222 gdkdisplay = gdk_display_manager_get_default_display (dispmgr);
223 gtk_init_check (out argc, argv);
225 widget = gtk_invisible_new ();
226 gtk_widget_ensure_style (widget);
227 style = gtk_widget_get_style (widget);
229 XplatUIX11.GetInstance().SetDisplay (gdk_x11_display_get_xdisplay (gdkdisplay));
232 public void LoadSysDefaultColors ()
234 GtkStyleStruct style_struct;
236 style_struct = (GtkStyleStruct) Marshal.PtrToStructure (style, typeof (GtkStyleStruct));
237 defaultWindowBackColor = ColorFromGdkColor (style_struct.bg[0]);
238 defaultWindowForeColor = ColorFromGdkColor (style_struct.fg[0]);
241 public ThemeGtk () : base ()
243 Console.WriteLine ("ThemeGtk constructor");
245 default_font = new Font (FontFamily.GenericSansSerif, 8.25f);
247 LoadSysDefaultColors ();
249 br_buttonface = new SolidBrush (defaultWindowBackColor);
250 br_buttontext = new SolidBrush (defaultWindowForeColor);
251 always_draw_hotkeys = true;
254 public override bool DoubleBufferingSupported {
258 // public override Color ColorControl {
259 // get { return Color.Blue;}
262 protected override void ButtonBase_DrawButton(ButtonBase button, Graphics dc)
264 Rectangle buttonRectangle = button.ClientRectangle;
266 IntPtr gdkwindow = gdk_window_foreign_new_for_display (gdkdisplay, (uint) button.Handle);
270 style = gtk_rc_get_style (global_gtk_button);
271 style = gtk_style_attach (style, gdkwindow); // need it
273 StateType state_type = StateType.Normal;
274 ShadowType shadow_type = ShadowType.In;
275 string detail = "buttondefault";
277 if (!button.is_enabled) {
278 state_type = StateType.Insensitive;
280 if (button.is_pressed) {
281 state_type = StateType.Active;
282 shadow_type = ShadowType.Out;
285 if (button.is_entered) {
286 state_type = StateType.Prelight;
289 if (button.flat_style != FlatStyle.Popup || (button.flat_style == FlatStyle.Popup && button.is_entered))
290 gtk_paint_box (style, gdkwindow,
296 buttonRectangle.X, buttonRectangle.Y,
297 buttonRectangle.Width, buttonRectangle.Height);
300 protected override void ButtonBase_DrawFocus( ButtonBase button, Graphics dc ) {
302 if ( !button.is_enabled || button.flat_style == FlatStyle.Popup )
305 Rectangle focus_rect = new Rectangle( button.ClientRectangle.X + 5, button.ClientRectangle.Y + 5, button.ClientRectangle.Width - 10, button.ClientRectangle.Height - 10 );
307 IntPtr gdkwindow = gdk_window_foreign_new_for_display (gdkdisplay, (uint) button.Handle);
311 style = gtk_rc_get_style (global_gtk_button);
312 style = gtk_style_attach (style, gdkwindow); // need it
314 gtk_paint_focus (style,
316 (int) StateType.Active,
327 public void DrawScrollButton (Graphics dc, Rectangle area, ScrollButton type, ButtonState state,
328 IntPtr gdkwindow, IntPtr style)
330 ArrowType arrow_type = 0;
332 gtk_paint_box (style,
334 (int) StateType.Normal,
335 (int) ShadowType.Out,
340 area.Width, area.Height);
342 /* Calc arrows coordinates */
344 case ScrollButton.Up:
345 arrow_type = ArrowType.Up;
347 case ScrollButton.Down:
348 arrow_type = ArrowType.Down;
350 case ScrollButton.Right:
351 arrow_type = ArrowType.Right;
353 case ScrollButton.Left:
354 arrow_type = ArrowType.Left;
361 gtk_paint_arrow (style,
363 (int) StateType.Normal,
368 (int) arrow_type, true,
369 area.X + ((area.Width - (area.Width/2) ) / 2),
370 area.Y + ((area.Height - (area.Height/2) ) / 2),
371 area.Width / 2, area.Height / 2);
375 public override void DrawScrollBar (Graphics dc, Rectangle area, ScrollBar bar,
376 ref Rectangle thumb_pos, ref Rectangle first_arrow_area, ref Rectangle second_arrow_area,
377 ButtonState first_arrow, ButtonState second_arrow, ref int scrollbutton_width,
378 ref int scrollbutton_height, bool vert)
380 IntPtr gdkwindow = gdk_window_foreign_new_for_display (gdkdisplay, (uint) bar.Handle);
381 IntPtr adj = gtk_adjustment_new (0, 0, 0, 0, 0, 0);
382 IntPtr scrollbar = gtk_vscrollbar_new (adj);
385 style = gtk_rc_get_style (scrollbar);
386 style = gtk_style_attach (style, gdkwindow); // need it
389 gtk_paint_box (style,
391 (int) StateType.Active,
397 area.Width, area.Height);
399 /* See gtk_range_expose */
400 first_arrow_area.X = first_arrow_area. Y = 0;
401 first_arrow_area.Width = scrollbutton_width;
402 first_arrow_area.Height = scrollbutton_height;
406 second_arrow_area.X = 0;
407 second_arrow_area.Y = area.Height - scrollbutton_height;
408 second_arrow_area.Width = scrollbutton_width;
409 second_arrow_area.Height = scrollbutton_height;
412 DrawScrollButton (dc, first_arrow_area, ScrollButton.Up, first_arrow,
416 DrawScrollButton (dc, second_arrow_area, ScrollButton.Down, second_arrow,
421 second_arrow_area.Y = 0;
422 second_arrow_area.X = area.Width - scrollbutton_width;
423 second_arrow_area.Width = scrollbutton_width;
424 second_arrow_area.Height = scrollbutton_height;
427 DrawScrollButton (dc, first_arrow_area, ScrollButton.Left, first_arrow,
431 DrawScrollButton (dc, second_arrow_area, ScrollButton.Right, second_arrow,
437 gtk_paint_slider (style,
439 (int) StateType.Normal,
440 (int) ShadowType.Out,
444 thumb_pos.X, thumb_pos.Y,
445 thumb_pos.Width, thumb_pos.Height,
446 (int) Orientation.Vertical);
448 //gtk_style_detach (style);
452 private static Color ColorFromGdkColor (GdkColorStruct gtkcolor)
454 return Color.FromArgb (255,
455 (gtkcolor.red >> 8) & 0xff,
456 (gtkcolor.green >> 8) & 0xff,
457 (gtkcolor.blue >> 8) & 0xff );