* X11Keyboard.cs: Detect and use the num lock mask.
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ThemeGtk.cs
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2004 Novell, Inc.
21 //
22 // Authors:
23 //      Jordi Mas i Hernandez, jordi@ximian.com
24 //
25 //      This is an experimental GTK theme. 
26 //
27 //      Comments:
28 //              - For now we would keep all the themes in the same assembly to have
29 //              handy the internals methods. 
30 //              - We are using Pinovoke for now to access GTK/GDK to avoid adding 
31 //              gtk-sharp as a SWF dependency
32 //              - The ThemeGtk comes from ThemeWin32Classic, we use it as the default
33 //              implementation for the methods that we are not taking care of.
34 //              - When GDK is initialised it opens its own display. There is not way of changing it,
35 //              then we use that display as SWF display
36 //              - You can activate this Theme in Linux doing export MONO_THEME=gtk
37 //              - GTK paints controls into a window no a device context. We should inverstigate if we 
38 //              we can encapsulate a dc in a gtkwindow.
39 //
40 // $Revision: 1.6 $
41 // $Modtime: $
42 // $Log: ThemeGtk.cs,v $
43 // Revision 1.6  2004/09/28 18:44:25  pbartok
44 // - Streamlined Theme interfaces:
45 //   * Each DrawXXX method for a control now is passed the object for the
46 //     control to be drawn in order to allow accessing any state the theme
47 //     might require
48 //
49 //   * ControlPaint methods for the theme now have a CP prefix to avoid
50 //     name clashes with the Draw methods for controls
51 //
52 //   * Every control now retrieves it's DefaultSize from the current theme
53 //
54 // Revision 1.5  2004/09/02 16:32:54  jordi
55 // implements resource pool for pens, brushes, and hatchbruses
56 //
57 // Revision 1.4  2004/08/24 18:37:02  jordi
58 // fixes formmating, methods signature, and adds missing events
59 //
60 // Revision 1.3  2004/08/20 20:39:51  jordi
61 // use style_attach
62 //
63 // Revision 1.2  2004/08/20 00:55:28  jordi
64 // fixes button order
65 //
66 // Revision 1.1  2004/08/19 22:27:40  jordi
67 // experimental GTK theme support
68 //
69 //
70 // NOT COMPLETE
71
72 using System;
73 using System.Drawing;
74 using System.Drawing.Drawing2D;
75 using System.Drawing.Imaging;
76 using System.Reflection;
77 using System.Runtime.InteropServices;
78
79 namespace System.Windows.Forms
80 {
81         internal class ThemeGtk : ThemeWin32Classic
82         {               
83                 /* GTK enums */
84                 internal enum StateType 
85                 {
86                         Normal,
87                         Active,
88                         Prelight,
89                         Selected,
90                         Insensitive,
91                 }       
92
93                 internal enum ShadowType 
94                 {
95                         None,
96                         In,
97                         Out,
98                         EtchedIn,
99                         EtchedOut,
100                 }       
101
102                 internal enum ArrowType 
103                 {
104                         Up,
105                         Down,
106                         Left,
107                         Right,
108                 }
109
110                 /* Structs */
111                 [StructLayout(LayoutKind.Sequential)]   
112                 internal struct GdkColorStruct
113                 {
114                         internal int pixel;
115                         internal short red;
116                         internal short green;
117                         internal short blue;
118                 }
119
120                 [StructLayout(LayoutKind.Sequential)]   
121                 internal struct GtkStyleStruct
122                 {
123                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=12)]
124                         internal byte[] obj; /* GObject is 12 bytes*/
125                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
126                         internal GdkColorStruct[] fg;
127                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]               
128                         internal GdkColorStruct[] bg;
129                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
130                         internal GdkColorStruct[] light;
131                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
132                         internal GdkColorStruct[] dark;
133                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
134                         internal GdkColorStruct[] mid;
135                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
136                         internal GdkColorStruct[] text;
137                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
138                         internal GdkColorStruct[] baseclr;
139                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
140                         internal GdkColorStruct[] text_aa;              /* Halfway between text/base */
141   
142                         internal GdkColorStruct black;
143                         internal GdkColorStruct white;
144
145                         /* TODO: There is more stuff that we will add when we need it*/
146                 }
147
148                         
149                 /* GDK imports */
150                 [DllImport("libgdk-x11-2.0.so")]
151                 internal static extern IntPtr gdk_display_manager_get ();
152
153                 [DllImport("libgdk-x11-2.0.so")]
154                 internal static extern IntPtr gdk_display_manager_get_default_display (IntPtr display_manager);
155
156                 [DllImport("libgdk-x11-2.0.so")]
157                 internal static extern void gdk_display_manager_set_default_display (IntPtr display_manager, IntPtr display);
158
159                 [DllImport("libgdk-x11-2.0.so")]
160                 internal static extern IntPtr gdk_x11_display_get_xdisplay (IntPtr display);
161
162                 [DllImport("libgdk-x11-2.0.so")]
163                 static extern IntPtr gdk_window_foreign_new_for_display (IntPtr display, uint anid);
164
165                 [DllImport("libgdk-x11-2.0.so")]
166                 static extern bool gdk_init_check(out int argc, string argv);   
167
168                 /* GTK imports */               
169                 [DllImport("libgtk-x11-2.0.so")]
170                 static extern bool gtk_init_check (out int argc, string argv);
171
172                 [DllImport("libgtk-x11-2.0.so")]
173                 static extern IntPtr gtk_adjustment_new (double value, double lower, double upper, double step_increment, double page_increment, double page_size);
174
175                 [DllImport("libgtk-x11-2.0.so")]
176                 static extern IntPtr gtk_rc_get_style (IntPtr widget);
177
178                 [DllImport("libgtk-x11-2.0.so")]
179                 static extern IntPtr gtk_vscrollbar_new(IntPtr adjustment);
180
181                 [DllImport("libgtk-x11-2.0.so")]
182                 static extern IntPtr gtk_style_attach (IntPtr raw, IntPtr window);
183
184                 [DllImport("libgtk-x11-2.0.so")]
185                 static extern IntPtr gtk_rc_style_new ();
186
187                 [DllImport("libgtk-x11-2.0.so")]
188                 static extern IntPtr gtk_invisible_new ();
189
190                 [DllImport("libgtk-x11-2.0.so")]
191                 static extern void gtk_widget_ensure_style (IntPtr raw);
192
193                 [DllImport("libgtk-x11-2.0.so")]
194                 static extern IntPtr gtk_widget_get_style (IntPtr raw);
195
196                 [DllImport("libgtk-x11-2.0.so")]
197                 static extern void gtk_style_detach (IntPtr raw);
198
199                 /* GTK Drawing */
200                 [DllImport("libgtk-x11-2.0.so")]
201                 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);
202
203                 [DllImport("libgtk-x11-2.0.so")]
204                 static extern void gtk_paint_arrow (IntPtr style, IntPtr window, int state_type, int shadow_type, 
205                         IntPtr area, IntPtr widget, string detail, int arrow_type, bool fill, int x, int y, int width, int height);
206
207                 [DllImport("libgtk-x11-2.0.so")]
208                 static extern void gtk_paint_slider(IntPtr style, IntPtr window, int state_type, int shadow_type, 
209                         IntPtr area, IntPtr widget, string detail, int x, int y, int width, int height, int orientation);
210
211                 [DllImport("libgtk-x11-2.0.so")]
212                 static extern void gtk_paint_box(IntPtr style, IntPtr window, int state_type, int shadow_type, 
213                         IntPtr area, IntPtr widget, string detail, int x, int y, int width, int height);
214
215                 /* Data */
216                 static protected IntPtr dispmgr;
217                 static protected IntPtr gdkdisplay;
218                 static protected IntPtr widget;
219                 static protected IntPtr style;
220                 static protected SolidBrush br_buttonface;
221                 static protected SolidBrush br_buttontext;
222
223                 public static void InitGtk ()
224                 {       
225                         Console.WriteLine ("ThemeGtk Init");            
226                         int argc = 0;
227                         string argv = "";
228                         
229                         gdk_init_check (out argc, argv);        
230
231                         dispmgr =  gdk_display_manager_get ();
232                         gdkdisplay =  gdk_display_manager_get_default_display (dispmgr);
233                         gtk_init_check (out argc, argv);
234
235                         widget = gtk_invisible_new ();
236                         gtk_widget_ensure_style (widget);
237                         style = gtk_widget_get_style (widget);                  
238
239                         XplatUIX11.SetDisplay (gdk_x11_display_get_xdisplay (gdkdisplay));
240                 }
241
242                 public void LoadSysDefaultColors ()
243                 {
244                         GtkStyleStruct style_struct;                    
245                         
246                         style_struct = (GtkStyleStruct) Marshal.PtrToStructure (style, typeof (GtkStyleStruct));                        
247                         defaultWindowBackColor = ColorFromGdkColor (style_struct.bg[0]);
248                         defaultWindowForeColor = ColorFromGdkColor (style_struct.fg[0]);
249                 }
250
251                 public ThemeGtk () : base ()
252                 {
253                         Console.WriteLine ("ThemeGtk constructor");
254                         InitGtk ();
255                         default_font =  new Font (FontFamily.GenericSansSerif, 8.25f);
256                         
257                         LoadSysDefaultColors ();        
258
259                         br_buttonface = new SolidBrush (defaultWindowBackColor);                
260                         br_buttontext = new SolidBrush (defaultWindowForeColor);                        
261                 }       
262
263                 public override bool DoubleBufferingSupported {
264                         get {return false; }
265                 }       
266
267
268                 public void DrawScrollButton (Graphics dc, Rectangle area, ScrollButton type, ButtonState state,
269                         IntPtr gdkwindow, IntPtr style)
270                 {
271                         ArrowType arrow_type = 0;
272
273                         gtk_paint_box (style, 
274                                         gdkwindow, 
275                                         (int) StateType.Normal,
276                                         (int) ShadowType.Out,
277                                         IntPtr.Zero,
278                                         IntPtr.Zero,
279                                         "trough",                                       
280                                         area.X, area.Y,
281                                         area.Width, area.Height);
282                         
283                         /* Calc arrows coordinates */
284                         switch (type) {
285                         case ScrollButton.Up:
286                                 arrow_type = ArrowType.Up;
287                                 break;
288                         case ScrollButton.Down:
289                                 arrow_type = ArrowType.Down;
290                                 break;
291                         case ScrollButton.Right:
292                                 arrow_type = ArrowType.Right;
293                                 break;
294                         case ScrollButton.Left:
295                                 arrow_type = ArrowType.Left;
296                                 break;
297                         default:
298                                 break;
299                         }
300                                 
301
302                         gtk_paint_arrow (style, 
303                                         gdkwindow, 
304                                         (int) StateType.Normal,
305                                         (int) ShadowType.In,
306                                         IntPtr.Zero,
307                                         IntPtr.Zero,
308                                         "",             
309                                         (int) arrow_type, true, 
310                                         area.X + ((area.Width - (area.Width/2) ) / 2), 
311                                         area.Y + ((area.Height - (area.Height/2) ) / 2),
312                                         area.Width / 2, area.Height / 2);                       
313                 
314                 }
315 #if updated             
316                 public override void DrawScrollBar (Graphics dc, Rectangle area, ScrollBar bar,
317                         ref Rectangle thumb_pos, ref Rectangle first_arrow_area, ref Rectangle second_arrow_area, 
318                         ButtonState first_arrow, ButtonState second_arrow, ref int scrollbutton_width, 
319                         ref int scrollbutton_height, bool vert)
320                 {
321                         IntPtr gdkwindow = gdk_window_foreign_new_for_display (gdkdisplay, (uint) bar.Handle);                  
322                         IntPtr adj = gtk_adjustment_new (0, 0, 0, 0, 0, 0);
323                         IntPtr scrollbar = gtk_vscrollbar_new (adj);
324                         IntPtr style;
325                                        
326                         style = gtk_rc_get_style (scrollbar);           
327                         style = gtk_style_attach (style, gdkwindow);  // need it                        
328                         
329                         /* Background */
330                         gtk_paint_box (style, 
331                                 gdkwindow, 
332                                 (int) StateType.Active,
333                                 (int) ShadowType.In,
334                                 IntPtr.Zero,
335                                 IntPtr.Zero,
336                                 "trough",
337                                 area.X, area.Y,
338                                 area.Width, area.Height);
339
340                         /* See gtk_range_expose */
341                         first_arrow_area.X = first_arrow_area. Y = 0;
342                         first_arrow_area.Width = scrollbutton_width;
343                         first_arrow_area.Height = scrollbutton_height;
344
345                         if (vert) {             
346
347                                 second_arrow_area.X = 0;
348                                 second_arrow_area.Y = area.Height - scrollbutton_height;
349                                 second_arrow_area.Width = scrollbutton_width;
350                                 second_arrow_area.Height = scrollbutton_height;
351
352                                 /* First button*/
353                                 DrawScrollButton (dc, first_arrow_area, ScrollButton.Up, first_arrow,
354                                         gdkwindow, style);
355
356                                 /* Second button*/
357                                 DrawScrollButton (dc, second_arrow_area, ScrollButton.Down, second_arrow,
358                                         gdkwindow, style);
359
360                         } else {
361
362                                 second_arrow_area.Y = 0;
363                                 second_arrow_area.X = area.Width - scrollbutton_width;
364                                 second_arrow_area.Width = scrollbutton_width;
365                                 second_arrow_area.Height = scrollbutton_height;
366
367                                 /* First button*/
368                                 DrawScrollButton (dc, first_arrow_area, ScrollButton.Left, first_arrow,
369                                         gdkwindow, style);
370
371                                 /* Second button*/
372                                 DrawScrollButton (dc, second_arrow_area, ScrollButton.Right, second_arrow,
373                                         gdkwindow, style);
374
375                         }
376
377                         /* Slider */
378                         gtk_paint_slider (style, 
379                                 gdkwindow, 
380                                 (int) StateType.Normal,
381                                 (int) ShadowType.Out,
382                                 IntPtr.Zero,
383                                 IntPtr.Zero,
384                                 "",             
385                                 thumb_pos.X, thumb_pos.Y,
386                                 thumb_pos.Width, thumb_pos.Height,
387                                 (int) Orientation.Vertical);
388
389                         //gtk_style_detach (style);
390                 }
391 #endif
392                 
393                 private static Color ColorFromGdkColor (GdkColorStruct gtkcolor)
394                 {
395                         return Color.FromArgb (255, 
396                                 (gtkcolor.red >> 8)  & 0xff, 
397                                 (gtkcolor.green  >> 8) & 0xff,
398                                 (gtkcolor.blue >> 8) & 0xff );
399                 }
400
401         } //class
402 }