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