implements resource pool for pens, brushes, and hatchbruses
[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.5 $
41 // $Modtime: $
42 // $Log: ThemeGtk.cs,v $
43 // Revision 1.5  2004/09/02 16:32:54  jordi
44 // implements resource pool for pens, brushes, and hatchbruses
45 //
46 // Revision 1.4  2004/08/24 18:37:02  jordi
47 // fixes formmating, methods signature, and adds missing events
48 //
49 // Revision 1.3  2004/08/20 20:39:51  jordi
50 // use style_attach
51 //
52 // Revision 1.2  2004/08/20 00:55:28  jordi
53 // fixes button order
54 //
55 // Revision 1.1  2004/08/19 22:27:40  jordi
56 // experimental GTK theme support
57 //
58 //
59 // NOT COMPLETE
60
61 using System;
62 using System.Drawing;
63 using System.Drawing.Drawing2D;
64 using System.Drawing.Imaging;
65 using System.Reflection;
66 using System.Runtime.InteropServices;
67
68 namespace System.Windows.Forms
69 {
70         internal class ThemeGtk : ThemeWin32Classic
71         {               
72                 /* GTK enums */
73                 internal enum StateType 
74                 {
75                         Normal,
76                         Active,
77                         Prelight,
78                         Selected,
79                         Insensitive,
80                 }       
81
82                 internal enum ShadowType 
83                 {
84                         None,
85                         In,
86                         Out,
87                         EtchedIn,
88                         EtchedOut,
89                 }       
90
91                 internal enum ArrowType 
92                 {
93                         Up,
94                         Down,
95                         Left,
96                         Right,
97                 }
98
99                 /* Structs */
100                 [StructLayout(LayoutKind.Sequential)]   
101                 internal struct GdkColorStruct
102                 {
103                         internal int pixel;
104                         internal short red;
105                         internal short green;
106                         internal short blue;
107                 }
108
109                 [StructLayout(LayoutKind.Sequential)]   
110                 internal struct GtkStyleStruct
111                 {
112                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=12)]
113                         internal byte[] obj; /* GObject is 12 bytes*/
114                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
115                         internal GdkColorStruct[] fg;
116                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]               
117                         internal GdkColorStruct[] bg;
118                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
119                         internal GdkColorStruct[] light;
120                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
121                         internal GdkColorStruct[] dark;
122                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
123                         internal GdkColorStruct[] mid;
124                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
125                         internal GdkColorStruct[] text;
126                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
127                         internal GdkColorStruct[] baseclr;
128                         [MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst=5)]
129                         internal GdkColorStruct[] text_aa;              /* Halfway between text/base */
130   
131                         internal GdkColorStruct black;
132                         internal GdkColorStruct white;
133
134                         /* TODO: There is more stuff that we will add when we need it*/
135                 }
136
137                         
138                 /* GDK imports */
139                 [DllImport("libgdk-x11-2.0.so")]
140                 internal static extern IntPtr gdk_display_manager_get ();
141
142                 [DllImport("libgdk-x11-2.0.so")]
143                 internal static extern IntPtr gdk_display_manager_get_default_display (IntPtr display_manager);
144
145                 [DllImport("libgdk-x11-2.0.so")]
146                 internal static extern void gdk_display_manager_set_default_display (IntPtr display_manager, IntPtr display);
147
148                 [DllImport("libgdk-x11-2.0.so")]
149                 internal static extern IntPtr gdk_x11_display_get_xdisplay (IntPtr display);
150
151                 [DllImport("libgdk-x11-2.0.so")]
152                 static extern IntPtr gdk_window_foreign_new_for_display (IntPtr display, uint anid);
153
154                 [DllImport("libgdk-x11-2.0.so")]
155                 static extern bool gdk_init_check(out int argc, string argv);   
156
157                 /* GTK imports */               
158                 [DllImport("libgtk-x11-2.0.so")]
159                 static extern bool gtk_init_check (out int argc, string argv);
160
161                 [DllImport("libgtk-x11-2.0.so")]
162                 static extern IntPtr gtk_adjustment_new (double value, double lower, double upper, double step_increment, double page_increment, double page_size);
163
164                 [DllImport("libgtk-x11-2.0.so")]
165                 static extern IntPtr gtk_rc_get_style (IntPtr widget);
166
167                 [DllImport("libgtk-x11-2.0.so")]
168                 static extern IntPtr gtk_vscrollbar_new(IntPtr adjustment);
169
170                 [DllImport("libgtk-x11-2.0.so")]
171                 static extern IntPtr gtk_style_attach (IntPtr raw, IntPtr window);
172
173                 [DllImport("libgtk-x11-2.0.so")]
174                 static extern IntPtr gtk_rc_style_new ();
175
176                 [DllImport("libgtk-x11-2.0.so")]
177                 static extern IntPtr gtk_invisible_new ();
178
179                 [DllImport("libgtk-x11-2.0.so")]
180                 static extern void gtk_widget_ensure_style (IntPtr raw);
181
182                 [DllImport("libgtk-x11-2.0.so")]
183                 static extern IntPtr gtk_widget_get_style (IntPtr raw);
184
185                 [DllImport("libgtk-x11-2.0.so")]
186                 static extern void gtk_style_detach (IntPtr raw);
187
188                 /* GTK Drawing */
189                 [DllImport("libgtk-x11-2.0.so")]
190                 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);
191
192                 [DllImport("libgtk-x11-2.0.so")]
193                 static extern void gtk_paint_arrow (IntPtr style, IntPtr window, int state_type, int shadow_type, 
194                         IntPtr area, IntPtr widget, string detail, int arrow_type, bool fill, int x, int y, int width, int height);
195
196                 [DllImport("libgtk-x11-2.0.so")]
197                 static extern void gtk_paint_slider(IntPtr style, IntPtr window, int state_type, int shadow_type, 
198                         IntPtr area, IntPtr widget, string detail, int x, int y, int width, int height, int orientation);
199
200                 [DllImport("libgtk-x11-2.0.so")]
201                 static extern void gtk_paint_box(IntPtr style, IntPtr window, int state_type, int shadow_type, 
202                         IntPtr area, IntPtr widget, string detail, int x, int y, int width, int height);
203
204                 /* Data */
205                 static protected IntPtr dispmgr;
206                 static protected IntPtr gdkdisplay;
207                 static protected IntPtr widget;
208                 static protected IntPtr style;
209                 static protected SolidBrush br_buttonface;
210                 static protected SolidBrush br_buttontext;
211
212                 public static void InitGtk ()
213                 {       
214                         Console.WriteLine ("ThemeGtk Init");            
215                         int argc = 0;
216                         string argv = "";
217                         
218                         gdk_init_check (out argc, argv);        
219
220                         dispmgr =  gdk_display_manager_get ();
221                         gdkdisplay =  gdk_display_manager_get_default_display (dispmgr);
222                         gtk_init_check (out argc, argv);
223
224                         widget = gtk_invisible_new ();
225                         gtk_widget_ensure_style (widget);
226                         style = gtk_widget_get_style (widget);                  
227
228                         XplatUIX11.SetDisplay (gdk_x11_display_get_xdisplay (gdkdisplay));
229                 }
230
231                 public void LoadSysDefaultColors ()
232                 {
233                         GtkStyleStruct style_struct;                    
234                         
235                         style_struct = (GtkStyleStruct) Marshal.PtrToStructure (style, typeof (GtkStyleStruct));                        
236                         defaultWindowBackColor = ColorFromGdkColor (style_struct.bg[0]);
237                         defaultWindowForeColor = ColorFromGdkColor (style_struct.fg[0]);
238                 }
239
240                 public ThemeGtk () : base ()
241                 {
242                         Console.WriteLine ("ThemeGtk constructor");
243                         InitGtk ();
244                         default_font =  new Font (FontFamily.GenericSansSerif, 8.25f);
245                         
246                         LoadSysDefaultColors ();        
247
248                         br_buttonface = new SolidBrush (defaultWindowBackColor);                
249                         br_buttontext = new SolidBrush (defaultWindowForeColor);                        
250                 }       
251
252                 public override bool WriteToWindow {
253                         get {return true; }
254                 }       
255
256
257                 public void DrawScrollButton (Graphics dc, Rectangle area, ScrollButton type, ButtonState state,
258                         IntPtr gdkwindow, IntPtr style)
259                 {
260                         ArrowType arrow_type = 0;
261
262                         gtk_paint_box (style, 
263                                         gdkwindow, 
264                                         (int) StateType.Normal,
265                                         (int) ShadowType.Out,
266                                         IntPtr.Zero,
267                                         IntPtr.Zero,
268                                         "trough",                                       
269                                         area.X, area.Y,
270                                         area.Width, area.Height);
271                         
272                         /* Calc arrows coordinates */
273                         switch (type) {
274                         case ScrollButton.Up:
275                                 arrow_type = ArrowType.Up;
276                                 break;
277                         case ScrollButton.Down:
278                                 arrow_type = ArrowType.Down;
279                                 break;
280                         case ScrollButton.Right:
281                                 arrow_type = ArrowType.Right;
282                                 break;
283                         case ScrollButton.Left:
284                                 arrow_type = ArrowType.Left;
285                                 break;
286                         default:
287                                 break;
288                         }
289                                 
290
291                         gtk_paint_arrow (style, 
292                                         gdkwindow, 
293                                         (int) StateType.Normal,
294                                         (int) ShadowType.In,
295                                         IntPtr.Zero,
296                                         IntPtr.Zero,
297                                         "",             
298                                         (int) arrow_type, true, 
299                                         area.X + ((area.Width - (area.Width/2) ) / 2), 
300                                         area.Y + ((area.Height - (area.Height/2) ) / 2),
301                                         area.Width / 2, area.Height / 2);                       
302                 
303                 }
304                 
305                 public override void DrawScrollBar (Graphics dc, Rectangle area, ScrollBar bar,
306                         ref Rectangle thumb_pos, ref Rectangle first_arrow_area, ref Rectangle second_arrow_area, 
307                         ButtonState first_arrow, ButtonState second_arrow, ref int scrollbutton_width, 
308                         ref int scrollbutton_height, bool vert)
309                 {
310                         IntPtr gdkwindow = gdk_window_foreign_new_for_display (gdkdisplay, (uint) bar.Handle);                  
311                         IntPtr adj = gtk_adjustment_new (0, 0, 0, 0, 0, 0);
312                         IntPtr scrollbar = gtk_vscrollbar_new (adj);
313                         IntPtr style;
314                                        
315                         style = gtk_rc_get_style (scrollbar);           
316                         style = gtk_style_attach (style, gdkwindow);  // need it                        
317                         
318                         /* Background */
319                         gtk_paint_box (style, 
320                                 gdkwindow, 
321                                 (int) StateType.Active,
322                                 (int) ShadowType.In,
323                                 IntPtr.Zero,
324                                 IntPtr.Zero,
325                                 "trough",
326                                 area.X, area.Y,
327                                 area.Width, area.Height);
328
329                         /* See gtk_range_expose */
330                         first_arrow_area.X = first_arrow_area. Y = 0;
331                         first_arrow_area.Width = scrollbutton_width;
332                         first_arrow_area.Height = scrollbutton_height;
333
334                         if (vert) {             
335
336                                 second_arrow_area.X = 0;
337                                 second_arrow_area.Y = area.Height - scrollbutton_height;
338                                 second_arrow_area.Width = scrollbutton_width;
339                                 second_arrow_area.Height = scrollbutton_height;
340
341                                 /* First button*/
342                                 DrawScrollButton (dc, first_arrow_area, ScrollButton.Up, first_arrow,
343                                         gdkwindow, style);
344
345                                 /* Second button*/
346                                 DrawScrollButton (dc, second_arrow_area, ScrollButton.Down, second_arrow,
347                                         gdkwindow, style);
348
349                         } else {
350
351                                 second_arrow_area.Y = 0;
352                                 second_arrow_area.X = area.Width - scrollbutton_width;
353                                 second_arrow_area.Width = scrollbutton_width;
354                                 second_arrow_area.Height = scrollbutton_height;
355
356                                 /* First button*/
357                                 DrawScrollButton (dc, first_arrow_area, ScrollButton.Left, first_arrow,
358                                         gdkwindow, style);
359
360                                 /* Second button*/
361                                 DrawScrollButton (dc, second_arrow_area, ScrollButton.Right, second_arrow,
362                                         gdkwindow, style);
363
364                         }
365
366                         /* Slider */
367                         gtk_paint_slider (style, 
368                                 gdkwindow, 
369                                 (int) StateType.Normal,
370                                 (int) ShadowType.Out,
371                                 IntPtr.Zero,
372                                 IntPtr.Zero,
373                                 "",             
374                                 thumb_pos.X, thumb_pos.Y,
375                                 thumb_pos.Width, thumb_pos.Height,
376                                 (int) Orientation.Vertical);
377
378                         //gtk_style_detach (style);
379                 }
380
381                 
382                 private static Color ColorFromGdkColor (GdkColorStruct gtkcolor)
383                 {
384                         return Color.FromArgb (255, 
385                                 (gtkcolor.red >> 8)  & 0xff, 
386                                 (gtkcolor.green  >> 8) & 0xff,
387                                 (gtkcolor.blue >> 8) & 0xff );
388                 }
389
390         } //class
391 }