1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/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 void DrawCheckButton(wxWindow
*win
,
86 virtual wxSplitterRenderParams
GetSplitterParams(const wxWindow
*win
);
88 virtual wxRendererVersion
GetVersion() const
90 return wxRendererVersion(wxRendererVersion::Current_Version
,
91 wxRendererVersion::Current_Age
);
95 // Cleanup by deleting standard renderer
96 static void Cleanup();
98 // Get the generic object
99 static wxRendererGeneric
* DoGetGeneric();
102 // draw the rectange using the first pen for the left and top sides and
103 // the second one for the bottom and right ones
104 void DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
105 const wxPen
& pen1
, const wxPen
& pen2
);
113 static wxRendererGeneric
* sm_rendererGeneric
;
116 // ============================================================================
117 // wxRendererGeneric implementation
118 // ============================================================================
120 // Get the generic object
121 wxRendererGeneric
* wxRendererGeneric::DoGetGeneric()
123 if (!sm_rendererGeneric
)
124 sm_rendererGeneric
= new wxRendererGeneric
;
125 return sm_rendererGeneric
;
128 // ----------------------------------------------------------------------------
129 // wxRendererGeneric creation
130 // ----------------------------------------------------------------------------
133 wxRendererNative
& wxRendererNative::GetGeneric()
135 return * wxRendererGeneric::DoGetGeneric();
138 void wxRendererGeneric::Cleanup()
140 if (sm_rendererGeneric
)
141 delete sm_rendererGeneric
;
143 sm_rendererGeneric
= NULL
;
146 wxRendererGeneric
* wxRendererGeneric::sm_rendererGeneric
= NULL
;
148 wxRendererGeneric::wxRendererGeneric()
149 : m_penBlack(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW
)),
150 m_penDarkGrey(wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
)),
151 m_penLightGrey(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
)),
152 m_penHighlight(wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT
))
156 // ----------------------------------------------------------------------------
157 // wxRendererGeneric helpers
158 // ----------------------------------------------------------------------------
161 wxRendererGeneric::DrawShadedRect(wxDC
& dc
,
166 // draw the rectangle
168 dc
.DrawLine(rect
->GetLeft(), rect
->GetTop(),
169 rect
->GetLeft(), rect
->GetBottom());
170 dc
.DrawLine(rect
->GetLeft() + 1, rect
->GetTop(),
171 rect
->GetRight(), rect
->GetTop());
173 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
174 rect
->GetRight(), rect
->GetBottom());
175 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
176 rect
->GetRight() + 1, rect
->GetBottom());
182 // ----------------------------------------------------------------------------
183 // tree/list ctrl drawing
184 // ----------------------------------------------------------------------------
187 wxRendererGeneric::DrawHeaderButton(wxWindow
* WXUNUSED(win
),
192 const int CORNER
= 1;
194 const wxCoord x
= rect
.x
,
199 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
201 dc
.SetPen(m_penBlack
);
202 dc
.DrawLine( x
+w
-CORNER
+1, y
, x
+w
, y
+h
); // right (outer)
203 dc
.DrawRectangle( x
, y
+h
, w
+1, 1 ); // bottom (outer)
205 dc
.SetPen(m_penDarkGrey
);
206 dc
.DrawLine( x
+w
-CORNER
, y
, x
+w
-1, y
+h
); // right (inner)
207 dc
.DrawRectangle( x
+1, y
+h
-1, w
-2, 1 ); // bottom (inner)
209 dc
.SetPen(m_penHighlight
);
210 dc
.DrawRectangle( x
, y
, w
-CORNER
+1, 1 ); // top (outer)
211 dc
.DrawRectangle( x
, y
, 1, h
); // left (outer)
212 dc
.DrawLine( x
, y
+h
-1, x
+1, y
+h
-1 );
213 dc
.DrawLine( x
+w
-1, y
, x
+w
-1, y
+1 );
216 // draw the plus or minus sign
218 wxRendererGeneric::DrawTreeItemButton(wxWindow
* WXUNUSED(win
),
224 dc
.SetPen(*wxGREY_PEN
);
225 dc
.SetBrush(*wxWHITE_BRUSH
);
226 dc
.DrawRectangle(rect
);
229 const wxCoord xMiddle
= rect
.x
+ rect
.width
/2;
230 const wxCoord yMiddle
= rect
.y
+ rect
.height
/2;
232 // half of the length of the horz lines in "-" and "+"
233 const wxCoord halfWidth
= rect
.width
/2 - 2;
234 dc
.SetPen(*wxBLACK_PEN
);
235 dc
.DrawLine(xMiddle
- halfWidth
, yMiddle
,
236 xMiddle
+ halfWidth
+ 1, yMiddle
);
238 if ( !(flags
& wxCONTROL_EXPANDED
) )
241 const wxCoord halfHeight
= rect
.height
/2 - 2;
242 dc
.DrawLine(xMiddle
, yMiddle
- halfHeight
,
243 xMiddle
, yMiddle
+ halfHeight
+ 1);
247 // ----------------------------------------------------------------------------
249 // ----------------------------------------------------------------------------
251 wxSplitterRenderParams
252 wxRendererGeneric::GetSplitterParams(const wxWindow
*win
)
258 if ( win
->HasFlag(wxSP_3DSASH
) )
260 else if ( win
->HasFlag(wxSP_NOSASH
) )
265 if ( win
->HasFlag(wxSP_3DBORDER
) )
270 return wxSplitterRenderParams(sashWidth
, border
, false);
274 wxRendererGeneric::DrawSplitterBorder(wxWindow
*win
,
276 const wxRect
& rectOrig
,
279 if ( win
->HasFlag(wxSP_3DBORDER
) )
281 wxRect rect
= rectOrig
;
282 DrawShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
283 DrawShadedRect(dc
, &rect
, m_penBlack
, m_penLightGrey
);
288 wxRendererGeneric::DrawSplitterSash(wxWindow
*win
,
290 const wxSize
& sizeReal
,
292 wxOrientation orient
,
295 // to avoid duplicating the same code for horizontal and vertical sashes,
296 // simply mirror the DC instead if needed (i.e. if horz splitter)
297 wxMirrorDC
dc(dcReal
, orient
!= wxVERTICAL
);
298 wxSize size
= dc
.Reflect(sizeReal
);
301 // we draw a Win32-like grey sash with possible 3D border here:
303 // ---- this is position
308 // GWGGGDB where G is light grey (face)
309 // GWGGGDB W white (light)
310 // GWGGGDB D dark grey (shadow)
311 // GWGGGDB B black (dark shadow)
313 // GWGGGDB and lower letters are our border (already drawn)
317 // only the middle 3 columns are drawn unless wxSP_3D is specified
319 const wxCoord h
= size
.y
;
322 // If we're drawing the border, draw the sash 3d lines shorter
323 if ( win
->HasFlag(wxSP_3DBORDER
) )
328 dc
.SetPen(*wxTRANSPARENT_PEN
);
329 dc
.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
)));
331 if ( win
->HasFlag(wxSP_3DSASH
) )
334 dc
.DrawRectangle(position
+ 2, 0, 3, h
);
336 dc
.SetPen(m_penLightGrey
);
337 dc
.DrawLine(position
, offset
, position
, h
- offset
);
339 dc
.SetPen(m_penHighlight
);
340 dc
.DrawLine(position
+ 1, 0, position
+ 1, h
);
342 dc
.SetPen(m_penDarkGrey
);
343 dc
.DrawLine(position
+ 5, 0, position
+ 5, h
);
345 dc
.SetPen(m_penBlack
);
346 dc
.DrawLine(position
+ 6, offset
, position
+ 6, h
- offset
);
351 dc
.DrawRectangle(position
, 0, 3, h
);
355 // ----------------------------------------------------------------------------
357 // ----------------------------------------------------------------------------
360 wxRendererGeneric::DrawComboBoxDropButton(wxWindow
*win
,
365 // Creating a generic button background that would actually be
366 // useful is rather difficult to accomplish. Best compromise
367 // is to use window's background colour to achieve transparent'
368 // ish appearance that should look decent in combo box style
370 wxColour col
= win
->GetBackgroundColour();
371 dc
.SetBrush(wxBrush(col
));
372 dc
.SetPen(wxPen(col
));
373 dc
.DrawRectangle(rect
);
374 DrawDropArrow(win
,dc
,rect
);
379 wxRendererGeneric::DrawDropArrow(wxWindow
*win
,
384 // This generic implementation should be good
385 // enough for Windows platforms (including XP).
387 int arrowHalf
= rect
.width
/5;
388 int rectMid
= rect
.width
/ 2;
389 int arrowTopY
= (rect
.height
/2) - (arrowHalf
/2);
391 // This should always result in arrow with odd width.
394 wxPoint(rectMid
- arrowHalf
, arrowTopY
),
395 wxPoint(rectMid
+ arrowHalf
, arrowTopY
),
396 wxPoint(rectMid
, arrowTopY
+ arrowHalf
)
398 dc
.SetBrush(wxBrush(win
->GetForegroundColour()));
399 dc
.SetPen(wxPen(win
->GetForegroundColour()));
400 dc
.DrawPolygon(WXSIZEOF(pt
), pt
, rect
.x
, rect
.y
);
404 wxRendererGeneric::DrawCheckButton(wxWindow
*WXUNUSED(win
),
409 dc
.SetPen(*(flags
& wxCONTROL_DISABLED
? wxGREY_PEN
: wxBLACK_PEN
));
410 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
411 dc
.DrawRectangle(rect
);
413 if ( flags
& wxCONTROL_CHECKED
)
415 dc
.DrawCheckMark(rect
.Deflate(2, 2));
419 // ----------------------------------------------------------------------------
420 // A module to allow cleanup of generic renderer.
421 // ----------------------------------------------------------------------------
423 class wxGenericRendererModule
: public wxModule
425 DECLARE_DYNAMIC_CLASS(wxGenericRendererModule
)
427 wxGenericRendererModule() {}
428 bool OnInit() { return true; };
429 void OnExit() { wxRendererGeneric::Cleanup(); };
432 IMPLEMENT_DYNAMIC_CLASS(wxGenericRendererModule
, wxModule
)