]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/renderer.cpp
[1001483] Added wxPasswordEntryDialog analagous to wxTextEntryDialog, allows detectin...
[wxWidgets.git] / src / gtk1 / renderer.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        gtk/renderer.cpp
3 // Purpose:     implementation of wxRendererNative for wxGTK
4 // Author:      Vadim Zeitlin
5 // Modified by:
6 // Created:     20.07.2003
7 // RCS-ID:      $Id$
8 // Copyright:   (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
9 // License:     wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // for compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24     #pragma hdrstop
25 #endif
26
27 #include "wx/renderer.h"
28 #include <gtk/gtk.h>
29 #include "wx/gtk/win_gtk.h"
30
31 #include "wx/window.h"
32 #include "wx/dc.h"
33
34 #ifdef __WXGTK20__
35     #include "wx/settings.h"
36 #endif // GTK 2.0
37
38 #ifdef __WXGTK20__
39     #define WXUNUSED_IN_GTK1(arg) arg
40 #else
41     #define WXUNUSED_IN_GTK1(arg)
42 #endif
43
44 // ----------------------------------------------------------------------------
45 // wxRendererGTK: our wxRendererNative implementation
46 // ----------------------------------------------------------------------------
47
48 class WXDLLEXPORT wxRendererGTK : public wxDelegateRendererNative
49 {
50 public:
51     // draw the header control button (used by wxListCtrl)
52     virtual void DrawHeaderButton(wxWindow *win,
53                                   wxDC& dc,
54                                   const wxRect& rect,
55                                   int flags = 0);
56
57 #ifdef __WXGTK20__
58     // draw the expanded/collapsed icon for a tree control item
59     virtual void DrawTreeItemButton(wxWindow *win,
60                                     wxDC& dc,
61                                     const wxRect& rect,
62                                     int flags = 0);
63 #endif // GTK 2.0
64
65     virtual void DrawSplitterBorder(wxWindow *win,
66                                     wxDC& dc,
67                                     const wxRect& rect,
68                                     int flags = 0);
69     virtual void DrawSplitterSash(wxWindow *win,
70                                   wxDC& dc,
71                                   const wxSize& size,
72                                   wxCoord position,
73                                   wxOrientation orient,
74                                   int flags = 0);
75
76     virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win);
77 };
78
79 // ============================================================================
80 // implementation
81 // ============================================================================
82
83 /* static */
84 wxRendererNative& wxRendererNative::GetDefault()
85 {
86     static wxRendererGTK s_rendererGTK;
87
88     return s_rendererGTK;
89 }
90
91 // ----------------------------------------------------------------------------
92 // list/tree controls drawing
93 // ----------------------------------------------------------------------------
94
95 void
96 wxRendererGTK::DrawHeaderButton(wxWindow *win,
97                                 wxDC& dc,
98                                 const wxRect& rect,
99                                 int flags)
100 {
101
102     static GtkWidget *s_button = NULL;
103     static GtkWidget *s_window = NULL;
104     if (s_button == NULL)
105     {
106         s_window = gtk_window_new( GTK_WINDOW_POPUP );
107     gtk_widget_realize( s_window );
108     s_button = gtk_button_new();
109     gtk_container_add( GTK_CONTAINER(s_window), s_button );
110     gtk_widget_realize( s_button );
111     }
112
113     gtk_paint_box
114     (
115     s_button->style,
116         GTK_PIZZA(win->m_wxwindow)->bin_window,
117         flags & wxCONTROL_DISABLED ? GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL,
118         GTK_SHADOW_OUT,
119     NULL,
120         s_button,
121         "button",
122         dc.XLOG2DEV(rect.x) -1, rect.y -1, rect.width +2, rect.height +2
123     );
124 }
125
126 #ifdef __WXGTK20__
127
128 // draw a ">" or "v" button
129 //
130 // TODO: isn't there a GTK function to draw it?
131 void
132 wxRendererGTK::DrawTreeItemButton(wxWindow* win,
133                                   wxDC& dc, const wxRect& rect, int flags)
134 {
135 #if 1
136
137 #define PM_SIZE 8
138
139     GtkPizza *pizza = GTK_PIZZA( win->m_wxwindow );
140     GtkStyle *style = win->m_widget->style;
141     int x = rect.x;
142     int y = rect.y;
143     y = dc.LogicalToDeviceY( y );
144     x = dc.LogicalToDeviceX( x );
145
146 #if 1
147     // This draws the GTK+ 2.2.4 triangle
148     x--;
149     GdkPoint points[3];
150     
151     if ( flags & wxCONTROL_EXPANDED )
152     {
153         points[0].x = x;
154         points[0].y = y + (PM_SIZE + 2) / 6;
155         points[1].x = points[0].x + (PM_SIZE + 2);
156         points[1].y = points[0].y;
157         points[2].x = (points[0].x + (PM_SIZE + 2) / 2);
158         points[2].y = y + 2 * (PM_SIZE + 2) / 3;
159     }
160     else
161     {  
162         points[0].x = x + ((PM_SIZE + 2) / 6 + 2);
163         points[0].y = y - 1;
164         points[1].x = points[0].x;
165         points[1].y = points[0].y + (PM_SIZE + 2);
166         points[2].x = (points[0].x +
167              (2 * (PM_SIZE + 2) / 3 - 1));
168         points[2].y = points[0].y + (PM_SIZE + 2) / 2;
169     }
170
171     if ( flags & wxCONTROL_CURRENT )
172         gdk_draw_polygon( pizza->bin_window, style->fg_gc[GTK_STATE_PRELIGHT], TRUE, points, 3);
173     else
174         gdk_draw_polygon( pizza->bin_window, style->base_gc[GTK_STATE_NORMAL], TRUE, points, 3);
175     gdk_draw_polygon( pizza->bin_window, style->fg_gc[GTK_STATE_NORMAL], FALSE, points, 3 );
176 #else
177     // this draws the GTK+ 2.2.3 tree item square    
178     gdk_draw_rectangle( pizza->bin_window,
179         style->base_gc[GTK_STATE_NORMAL], TRUE,
180         x, y, PM_SIZE, PM_SIZE);
181     gdk_draw_rectangle( pizza->bin_window,
182         style->fg_gc[GTK_STATE_NORMAL], FALSE,
183         x, y, PM_SIZE, PM_SIZE);
184
185     gdk_draw_line( pizza->bin_window, style->fg_gc[GTK_STATE_NORMAL],
186         x + 2, y + PM_SIZE / 2, x + PM_SIZE - 2, y + PM_SIZE / 2);
187
188     if ( flags & wxCONTROL_EXPANDED )
189     {
190         gdk_draw_line( pizza->bin_window, style->fg_gc[GTK_STATE_NORMAL],
191                x + PM_SIZE / 2, y + 2,
192                x + PM_SIZE / 2, y + PM_SIZE - 2);
193     }
194 #endif    
195     
196     
197 #else
198     dc.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT),
199                         wxSOLID));
200     dc.SetPen(*wxBLACK_PEN);
201     wxPoint button[3];
202
203     const wxCoord xMiddle = rect.x + rect.width/2;
204     const wxCoord yMiddle = rect.y + rect.height/2;
205
206     if ( flags & wxCONTROL_EXPANDED )
207     {
208         button[0].x = rect.GetLeft();
209         button[0].y = yMiddle - 2;
210         button[1].x = rect.GetRight();
211         button[1].y = yMiddle - 2;
212         button[2].x = xMiddle;
213         button[2].y = yMiddle + 3;
214     }
215     else // collapsed
216     {
217         button[0].y = rect.GetBottom();
218         button[0].x = xMiddle - 2;
219         button[1].y = rect.GetTop();
220         button[1].x = xMiddle - 2;
221         button[2].y = yMiddle;
222         button[2].x = xMiddle + 3;
223     }
224
225     dc.DrawPolygon(3, button);
226 #endif
227 }
228
229 #endif // GTK 2.0
230
231 // ----------------------------------------------------------------------------
232 // splitter sash drawing
233 // ----------------------------------------------------------------------------
234
235 // all this should probably be read from the current theme settings somehow?
236 #ifdef __WXGTK20__
237     // the full sash size
238     static const wxCoord SASH_FULL_SIZE = 5;
239 #else // GTK+ 1.x
240     // the full sash width (should be even)
241     static const wxCoord SASH_SIZE = 8;
242
243     // margin around the sash
244     static const wxCoord SASH_MARGIN = 2;
245
246     // the full sash size
247     static const wxCoord SASH_FULL_SIZE = SASH_SIZE + SASH_MARGIN;
248 #endif // GTK+ 2.x/1.x
249
250 wxSplitterRenderParams
251 wxRendererGTK::GetSplitterParams(const wxWindow * WXUNUSED(win))
252 {
253     // we don't draw any border, hence 0 for the second field
254     return wxSplitterRenderParams
255            (
256                SASH_FULL_SIZE,
257                0,
258 #ifdef __WXGTK20__
259                true     // hot sensitive
260 #else // GTK+ 1.x
261                false    // not
262 #endif // GTK+ 2.x/1.x
263            );
264 }
265
266 void
267 wxRendererGTK::DrawSplitterBorder(wxWindow * WXUNUSED(win),
268                                   wxDC& WXUNUSED(dc),
269                                   const wxRect& WXUNUSED(rect),
270                                   int WXUNUSED(flags))
271 {
272     // nothing to do
273 }
274
275 void
276 wxRendererGTK::DrawSplitterSash(wxWindow *win,
277                                 wxDC& dc,
278                                 const wxSize& size,
279                                 wxCoord position,
280                                 wxOrientation orient,
281                                 int WXUNUSED_IN_GTK1(flags))
282 {
283     if ( !win->m_wxwindow->window )
284     {
285         // window not realized yet
286         return;
287     }
288
289     // are we drawing vertical or horizontal splitter?
290     const bool isVert = orient == wxVERTICAL;
291
292     GdkRectangle rect;
293     GdkRectangle erase_rect;
294     if ( isVert )
295     {
296         int h = win->GetClientSize().GetHeight();
297     
298         rect.x = position;
299         rect.y = 0;
300         rect.width = SASH_FULL_SIZE;
301         rect.height = h;
302     
303         erase_rect.x = position;
304         erase_rect.y = 0;
305         erase_rect.width = SASH_FULL_SIZE;
306         erase_rect.height = h;
307     }
308     else // horz
309     {
310         int w = win->GetClientSize().GetWidth();
311     
312         rect.x = 0;
313         rect.y = position;
314         rect.height = SASH_FULL_SIZE;
315         rect.width = w;
316     
317         erase_rect.y = position;
318         erase_rect.x = 0;
319         erase_rect.height = SASH_FULL_SIZE;
320         erase_rect.width = w;
321     }
322
323     // we must erase everything first, otherwise the garbage from the old sash
324     // is left when dragging it
325     //
326     // TODO: is this the right way to draw themed background?
327     gtk_paint_flat_box
328     (
329         win->m_wxwindow->style,
330         GTK_PIZZA(win->m_wxwindow)->bin_window,
331         GTK_STATE_NORMAL,
332         GTK_SHADOW_NONE,
333         NULL,
334         win->m_wxwindow,
335         (char *)"base", // const_cast
336         erase_rect.x,
337         erase_rect.y,
338         erase_rect.width,
339         erase_rect.height
340     );
341
342 #ifdef __WXGTK20__
343     gtk_paint_handle
344     (
345         win->m_wxwindow->style,
346         GTK_PIZZA(win->m_wxwindow)->bin_window,
347         flags & wxCONTROL_CURRENT ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL,
348         GTK_SHADOW_NONE,
349         NULL /* no clipping */,
350         win->m_wxwindow,
351         "paned",
352         rect.x,
353         rect.y,
354         rect.width,
355         rect.height,
356         isVert ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL
357     );
358 #else // GTK+ 1.x
359
360     // leave some margin before sash itself
361     position += SASH_MARGIN / 2;
362
363     // and finally draw it using GTK paint functions
364     typedef void (*GtkPaintLineFunc)(GtkStyle *, GdkWindow *,
365                                                 GtkStateType,
366                                                 GdkRectangle *, GtkWidget *,
367                                                 gchar *,
368                                                 gint, gint, gint);
369
370     GtkPaintLineFunc func = isVert ? gtk_paint_vline : gtk_paint_hline;
371
372     (*func)
373     (
374         win->m_wxwindow->style,
375         GTK_PIZZA(win->m_wxwindow)->bin_window,
376         GTK_STATE_NORMAL,
377         NULL,
378         win->m_wxwindow,
379         (char *)"paned", // const_cast
380         0, isVert ? size.y : size.x, position + SASH_SIZE / 2 - 1
381     );
382
383     gtk_paint_box
384     (
385         win->m_wxwindow->style,
386         GTK_PIZZA(win->m_wxwindow)->bin_window,
387         GTK_STATE_NORMAL,
388         GTK_SHADOW_OUT,
389         (GdkRectangle*) NULL,
390         win->m_wxwindow,
391         (char *)"paned", // const_cast
392         isVert ? position : size.x - 2*SASH_SIZE,
393         isVert ? size.y - 2*SASH_SIZE : position,
394         SASH_SIZE, SASH_SIZE
395     );
396 #endif // GTK+ 2.x/1.x
397 }
398