]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/renderer.cpp
call OnExit() even if an exception has been thrown from OnRun()
[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 license
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 #ifndef WX_PRECOMP
28 #endif // WX_PRECOMP
29
30 #include <gtk/gtk.h>
31 #include "wx/gtk/win_gtk.h"
32
33 #include "wx/window.h"
34 #include "wx/dc.h"
35 #include "wx/renderer.h"
36
37 #ifdef __WXGTK20__
38     #include "wx/settings.h"
39 #endif // GTK 2.0
40
41 #ifdef __WXGTK20__
42     #define WXUNUSED_IN_GTK1(arg) arg
43 #else
44     #define WXUNUSED_IN_GTK1(arg)
45 #endif
46
47 // ----------------------------------------------------------------------------
48 // wxRendererGTK: our wxRendererNative implementation
49 // ----------------------------------------------------------------------------
50
51 class WXDLLEXPORT wxRendererGTK : public wxDelegateRendererNative
52 {
53 public:
54     // draw the header control button (used by wxListCtrl)
55     virtual void DrawHeaderButton(wxWindow *win,
56                                   wxDC& dc,
57                                   const wxRect& rect,
58                                   int flags = 0);
59
60 #ifdef __WXGTK20__
61     // draw the expanded/collapsed icon for a tree control item
62     virtual void DrawTreeItemButton(wxWindow *win,
63                                     wxDC& dc,
64                                     const wxRect& rect,
65                                     int flags = 0);
66 #endif // GTK 2.0
67
68     virtual void DrawSplitterBorder(wxWindow *win,
69                                     wxDC& dc,
70                                     const wxRect& rect,
71                                     int flags = 0);
72     virtual void DrawSplitterSash(wxWindow *win,
73                                   wxDC& dc,
74                                   const wxSize& size,
75                                   wxCoord position,
76                                   wxOrientation orient,
77                                   int flags = 0);
78
79     virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win);
80 };
81
82 // ============================================================================
83 // implementation
84 // ============================================================================
85
86 /* static */
87 wxRendererNative& wxRendererNative::GetDefault()
88 {
89     static wxRendererGTK s_rendererGTK;
90
91     return s_rendererGTK;
92 }
93
94 // ----------------------------------------------------------------------------
95 // list/tree controls drawing
96 // ----------------------------------------------------------------------------
97
98 void
99 wxRendererGTK::DrawHeaderButton(wxWindow *win,
100                                 wxDC& dc,
101                                 const wxRect& rect,
102                                 int flags)
103 {
104     gtk_paint_box
105     (
106         win->m_wxwindow->style,
107         GTK_PIZZA(win->m_wxwindow)->bin_window,
108         flags & wxCONTROL_DISABLED ? GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL,
109         GTK_SHADOW_OUT,
110         (GdkRectangle*) NULL,
111         win->m_wxwindow,
112         (char *)"button", // const_cast
113         dc.XLOG2DEV(rect.x) - 1, rect.y - 1, rect.width + 2, rect.height + 2
114     );
115 }
116
117 #ifdef __WXGTK20__
118
119 // draw a ">" or "v" button
120 //
121 // TODO: isn't there a GTK function to draw it?
122 void
123 wxRendererGTK::DrawTreeItemButton(wxWindow* WXUNUSED(win),
124                                   wxDC& dc, const wxRect& rect, int flags)
125 {
126     dc.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT),
127                         wxSOLID));
128     dc.SetPen(*wxBLACK_PEN);
129     wxPoint button[3];
130
131     const wxCoord xMiddle = rect.x + rect.width/2;
132     const wxCoord yMiddle = rect.y + rect.height/2;
133
134     if ( flags & wxCONTROL_EXPANDED )
135     {
136         button[0].x = rect.GetLeft();
137         button[0].y = yMiddle - 2;
138         button[1].x = rect.GetRight();
139         button[1].y = yMiddle - 2;
140         button[2].x = xMiddle;
141         button[2].y = yMiddle + 3;
142     }
143     else // collapsed
144     {
145         button[0].y = rect.GetBottom();
146         button[0].x = xMiddle - 2;
147         button[1].y = rect.GetTop();
148         button[1].x = xMiddle - 2;
149         button[2].y = yMiddle;
150         button[2].x = xMiddle + 3;
151     }
152
153     dc.DrawPolygon(3, button);
154 }
155
156 #endif // GTK 2.0
157
158 // ----------------------------------------------------------------------------
159 // splitter sash drawing
160 // ----------------------------------------------------------------------------
161
162 // all this should probably be read from the current theme settings somehow?
163 #ifdef __WXGTK20__
164     // the full sash size
165     static const wxCoord SASH_FULL_SIZE = 5;
166 #else // GTK+ 1.x
167     // the full sash width (should be even)
168     static const wxCoord SASH_SIZE = 10;
169
170     // margin around the sash
171     static const wxCoord SASH_MARGIN = 5;
172
173     // the full sash size
174     static const wxCoord SASH_FULL_SIZE = SASH_SIZE + SASH_MARGIN;
175 #endif // GTK+ 2.x/1.x
176
177 wxSplitterRenderParams
178 wxRendererGTK::GetSplitterParams(const wxWindow * WXUNUSED(win))
179 {
180     // we don't draw any border, hence 0 for the second field
181     return wxSplitterRenderParams
182            (
183                SASH_FULL_SIZE,
184                0,
185 #ifdef __WXGTK20__
186                true     // hot sensitive
187 #else // GTK+ 1.x
188                false    // not
189 #endif // GTK+ 2.x/1.x
190            );
191 }
192
193 void
194 wxRendererGTK::DrawSplitterBorder(wxWindow * WXUNUSED(win),
195                                   wxDC& WXUNUSED(dc),
196                                   const wxRect& WXUNUSED(rect),
197                                   int WXUNUSED(flags))
198 {
199     // nothing to do
200 }
201
202 void
203 wxRendererGTK::DrawSplitterSash(wxWindow *win,
204                                 wxDC& dc,
205                                 const wxSize& size,
206                                 wxCoord position,
207                                 wxOrientation orient,
208                                 int WXUNUSED_IN_GTK1(flags))
209 {
210     if ( !win->m_wxwindow->window )
211     {
212         // VZ: this happens on startup -- why?
213         return;
214     }
215
216     // are we drawing vertical or horizontal splitter?
217     const bool isVert = orient == wxVERTICAL;
218
219     GdkRectangle rect;
220     if ( isVert )
221     {
222         rect.x = position;
223         rect.y = 0;
224         rect.width = SASH_FULL_SIZE;
225         rect.height = size.y;
226     }
227     else // horz
228     {
229         rect.x = 0;
230         rect.y = position;
231         rect.height = SASH_FULL_SIZE;
232         rect.width = size.x;
233     }
234
235 #ifdef __WXGTK20__
236     gtk_paint_handle
237     (
238         win->m_wxwindow->style,
239         GTK_PIZZA(win->m_wxwindow)->bin_window,
240         flags & wxCONTROL_CURRENT ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL,
241         GTK_SHADOW_NONE,
242         NULL /* no clipping */,
243         win->m_wxwindow,
244         "paned",
245         rect.x,
246         rect.y,
247         rect.width,
248         rect.height,
249         isVert ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL
250     );
251 #else // GTK+ 1.x
252     // we must erase everything first, otherwise the garbage from the old sash
253     // is left when dragging it
254     //
255     // TODO: is this the right way to draw themed background?
256     gtk_paint_flat_box
257     (
258         win->m_wxwindow->style,
259         GTK_PIZZA(win->m_wxwindow)->bin_window,
260         GTK_STATE_NORMAL,
261         GTK_SHADOW_NONE,
262         &rect,
263         win->m_wxwindow,
264         (char *)"base", // const_cast
265         0, 0, -1, -1
266     );
267
268
269     // leave some margin before sash itself
270     position += SASH_MARGIN / 2;
271
272     // and finally draw it using GTK paint functions
273     typedef void (*GtkPaintLineFunc)(GtkStyle *, GdkWindow *,
274                                                 GtkStateType,
275                                                 GdkRectangle *, GtkWidget *,
276                                                 gchar *,
277                                                 gint, gint, gint);
278
279     GtkPaintLineFunc func = isVert ? gtk_paint_vline : gtk_paint_hline;
280
281     (*func)
282     (
283         win->m_wxwindow->style,
284         GTK_PIZZA(win->m_wxwindow)->bin_window,
285         GTK_STATE_NORMAL,
286         NULL,
287         win->m_wxwindow,
288         (char *)"paned", // const_cast
289         0, isVert ? size.y : size.x, position + SASH_SIZE / 2 - 1
290     );
291
292     gtk_paint_box
293     (
294         win->m_wxwindow->style,
295         GTK_PIZZA(win->m_wxwindow)->bin_window,
296         GTK_STATE_NORMAL,
297         GTK_SHADOW_OUT,
298         (GdkRectangle*) NULL,
299         win->m_wxwindow,
300         (char *)"paned", // const_cast
301         isVert ? position : size.x - 2*SASH_SIZE,
302         isVert ? size.y - 2*SASH_SIZE : position,
303         SASH_SIZE, SASH_SIZE
304     );
305 #endif // GTK+ 2.x/1.x
306 }
307