1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: generic/renderg.cpp
3 // Purpose: generic implementation of wxRendererNative (for any platform)
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
9 // License: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // for compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
28 #include "wx/string.h"
31 #include "wx/gdicmn.h"
34 #include "wx/settings.h"
35 #include "wx/splitter.h"
36 #include "wx/dcmirror.h"
37 #include "wx/module.h"
38 #include "wx/renderer.h"
40 // ----------------------------------------------------------------------------
41 // wxRendererGeneric: our wxRendererNative implementation
42 // ----------------------------------------------------------------------------
44 class WXDLLEXPORT wxRendererGeneric
: public wxRendererNative
49 virtual void DrawHeaderButton(wxWindow
*win
,
54 virtual void DrawTreeItemButton(wxWindow
*win
,
59 virtual void DrawSplitterBorder(wxWindow
*win
,
64 virtual void DrawSplitterSash(wxWindow
*win
,
71 virtual void DrawComboBoxDropButton(wxWindow
*win
,
76 virtual void DrawDropArrow(wxWindow
*win
,
81 virtual wxSplitterRenderParams
GetSplitterParams(const wxWindow
*win
);
83 virtual wxRendererVersion
GetVersion() const
85 return wxRendererVersion(wxRendererVersion::Current_Version
,
86 wxRendererVersion::Current_Age
);
90 // Cleanup by deleting standard renderer
91 static void Cleanup();
93 // Get the generic object
94 static wxRendererGeneric
* DoGetGeneric();
97 // draw the rectange using the first pen for the left and top sides and
98 // the second one for the bottom and right ones
99 void DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
100 const wxPen
& pen1
, const wxPen
& pen2
);
108 static wxRendererGeneric
* sm_rendererGeneric
;
111 // ============================================================================
112 // wxRendererGeneric implementation
113 // ============================================================================
115 // Get the generic object
116 wxRendererGeneric
* wxRendererGeneric::DoGetGeneric()
118 if (!sm_rendererGeneric
)
119 sm_rendererGeneric
= new wxRendererGeneric
;
120 return sm_rendererGeneric
;
123 // ----------------------------------------------------------------------------
124 // wxRendererGeneric creation
125 // ----------------------------------------------------------------------------
128 wxRendererNative
& wxRendererNative::GetGeneric()
130 return * wxRendererGeneric::DoGetGeneric();
133 void wxRendererGeneric::Cleanup()
135 if (sm_rendererGeneric
)
136 delete sm_rendererGeneric
;
138 sm_rendererGeneric
= NULL
;
141 wxRendererGeneric
* wxRendererGeneric::sm_rendererGeneric
= NULL
;
143 wxRendererGeneric::wxRendererGeneric()
144 : m_penBlack(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW
)),
145 m_penDarkGrey(wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
)),
146 m_penLightGrey(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
)),
147 m_penHighlight(wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT
))
151 // ----------------------------------------------------------------------------
152 // wxRendererGeneric helpers
153 // ----------------------------------------------------------------------------
156 wxRendererGeneric::DrawShadedRect(wxDC
& dc
,
161 // draw the rectangle
163 dc
.DrawLine(rect
->GetLeft(), rect
->GetTop(),
164 rect
->GetLeft(), rect
->GetBottom());
165 dc
.DrawLine(rect
->GetLeft() + 1, rect
->GetTop(),
166 rect
->GetRight(), rect
->GetTop());
168 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
169 rect
->GetRight(), rect
->GetBottom());
170 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
171 rect
->GetRight() + 1, rect
->GetBottom());
177 // ----------------------------------------------------------------------------
178 // tree/list ctrl drawing
179 // ----------------------------------------------------------------------------
182 wxRendererGeneric::DrawHeaderButton(wxWindow
* WXUNUSED(win
),
187 const int CORNER
= 1;
189 const wxCoord x
= rect
.x
,
194 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
196 dc
.SetPen(m_penBlack
);
197 dc
.DrawLine( x
+w
-CORNER
+1, y
, x
+w
, y
+h
); // right (outer)
198 dc
.DrawRectangle( x
, y
+h
, w
+1, 1 ); // bottom (outer)
200 dc
.SetPen(m_penDarkGrey
);
201 dc
.DrawLine( x
+w
-CORNER
, y
, x
+w
-1, y
+h
); // right (inner)
202 dc
.DrawRectangle( x
+1, y
+h
-1, w
-2, 1 ); // bottom (inner)
204 dc
.SetPen(m_penHighlight
);
205 dc
.DrawRectangle( x
, y
, w
-CORNER
+1, 1 ); // top (outer)
206 dc
.DrawRectangle( x
, y
, 1, h
); // left (outer)
207 dc
.DrawLine( x
, y
+h
-1, x
+1, y
+h
-1 );
208 dc
.DrawLine( x
+w
-1, y
, x
+w
-1, y
+1 );
211 // draw the plus or minus sign
213 wxRendererGeneric::DrawTreeItemButton(wxWindow
* WXUNUSED(win
),
219 dc
.SetPen(*wxGREY_PEN
);
220 dc
.SetBrush(*wxWHITE_BRUSH
);
221 dc
.DrawRectangle(rect
);
224 const wxCoord xMiddle
= rect
.x
+ rect
.width
/2;
225 const wxCoord yMiddle
= rect
.y
+ rect
.height
/2;
227 // half of the length of the horz lines in "-" and "+"
228 const wxCoord halfWidth
= rect
.width
/2 - 2;
229 dc
.SetPen(*wxBLACK_PEN
);
230 dc
.DrawLine(xMiddle
- halfWidth
, yMiddle
,
231 xMiddle
+ halfWidth
+ 1, yMiddle
);
233 if ( !(flags
& wxCONTROL_EXPANDED
) )
236 const wxCoord halfHeight
= rect
.height
/2 - 2;
237 dc
.DrawLine(xMiddle
, yMiddle
- halfHeight
,
238 xMiddle
, yMiddle
+ halfHeight
+ 1);
242 // ----------------------------------------------------------------------------
244 // ----------------------------------------------------------------------------
246 wxSplitterRenderParams
247 wxRendererGeneric::GetSplitterParams(const wxWindow
*win
)
253 if ( win
->HasFlag(wxSP_3DSASH
) )
255 else if ( win
->HasFlag(wxSP_NOSASH
) )
260 if ( win
->HasFlag(wxSP_3DBORDER
) )
265 return wxSplitterRenderParams(sashWidth
, border
, false);
269 wxRendererGeneric::DrawSplitterBorder(wxWindow
*win
,
271 const wxRect
& rectOrig
,
274 if ( win
->HasFlag(wxSP_3DBORDER
) )
276 wxRect rect
= rectOrig
;
277 DrawShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
278 DrawShadedRect(dc
, &rect
, m_penBlack
, m_penLightGrey
);
283 wxRendererGeneric::DrawSplitterSash(wxWindow
*win
,
285 const wxSize
& sizeReal
,
287 wxOrientation orient
,
290 // to avoid duplicating the same code for horizontal and vertical sashes,
291 // simply mirror the DC instead if needed (i.e. if horz splitter)
292 wxMirrorDC
dc(dcReal
, orient
!= wxVERTICAL
);
293 wxSize size
= dc
.Reflect(sizeReal
);
296 // we draw a Win32-like grey sash with possible 3D border here:
298 // ---- this is position
303 // GWGGGDB where G is light grey (face)
304 // GWGGGDB W white (light)
305 // GWGGGDB D dark grey (shadow)
306 // GWGGGDB B black (dark shadow)
308 // GWGGGDB and lower letters are our border (already drawn)
312 // only the middle 3 columns are drawn unless wxSP_3D is specified
314 const wxCoord h
= size
.y
;
317 // If we're drawing the border, draw the sash 3d lines shorter
318 if ( win
->HasFlag(wxSP_3DBORDER
) )
323 dc
.SetPen(*wxTRANSPARENT_PEN
);
324 dc
.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
)));
326 if ( win
->HasFlag(wxSP_3DSASH
) )
329 dc
.DrawRectangle(position
+ 2, 0, 3, h
);
331 dc
.SetPen(m_penLightGrey
);
332 dc
.DrawLine(position
, offset
, position
, h
- offset
);
334 dc
.SetPen(m_penHighlight
);
335 dc
.DrawLine(position
+ 1, 0, position
+ 1, h
);
337 dc
.SetPen(m_penDarkGrey
);
338 dc
.DrawLine(position
+ 5, 0, position
+ 5, h
);
340 dc
.SetPen(m_penBlack
);
341 dc
.DrawLine(position
+ 6, offset
, position
+ 6, h
- offset
);
346 dc
.DrawRectangle(position
, 0, 3, h
);
350 // ----------------------------------------------------------------------------
352 // ----------------------------------------------------------------------------
355 wxRendererGeneric::DrawComboBoxDropButton(wxWindow
*win
,
360 // Creating a generic button background that would actually be
361 // useful is rather difficult to accomplish. Best compromise
362 // is to use window's background colour to achieve transparent'
363 // ish appearance that should look decent in combo box style
365 wxColour col
= win
->GetBackgroundColour();
366 dc
.SetBrush(wxBrush(col
));
367 dc
.SetPen(wxPen(col
));
368 dc
.DrawRectangle(rect
);
369 DrawDropArrow(win
,dc
,rect
);
374 wxRendererGeneric::DrawDropArrow(wxWindow
*win
,
379 // This generic implementation should be good
380 // enough for Windows platforms (including XP).
382 int arrowHalf
= rect
.width
/5;
383 int rectMid
= rect
.width
/ 2;
384 int arrowTopY
= (rect
.height
/2) - (arrowHalf
/2);
386 // This should always result in arrow with odd width.
389 wxPoint(rectMid
- arrowHalf
, arrowTopY
),
390 wxPoint(rectMid
+ arrowHalf
, arrowTopY
),
391 wxPoint(rectMid
, arrowTopY
+ arrowHalf
)
393 dc
.SetBrush(wxBrush(win
->GetForegroundColour()));
394 dc
.SetPen(wxPen(win
->GetForegroundColour()));
395 dc
.DrawPolygon(WXSIZEOF(pt
), pt
, rect
.x
, rect
.y
);
398 // ----------------------------------------------------------------------------
399 // A module to allow cleanup of generic renderer.
400 // ----------------------------------------------------------------------------
402 class wxGenericRendererModule
: public wxModule
404 DECLARE_DYNAMIC_CLASS(wxGenericRendererModule
)
406 wxGenericRendererModule() {}
407 bool OnInit() { return true; };
408 void OnExit() { wxRendererGeneric::Cleanup(); };
411 IMPLEMENT_DYNAMIC_CLASS(wxGenericRendererModule
, wxModule
)