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