1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        src/generic/renderg.cpp
3 // Purpose:     generic implementation of wxRendererNative (for any platform)
4 // Author:      Vadim Zeitlin
5 // Modified by:
6 // Created:     20.07.2003
7 // RCS-ID:      $Id: renderg.cpp 45498 2007-04-16 13:03:05Z VZ $
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 #include "wx/renderer.h"
28 
29 #ifndef WX_PRECOMP
30     #include "wx/string.h"
31     #include "wx/dc.h"
32     #include "wx/settings.h"
33     #include "wx/gdicmn.h"
34     #include "wx/module.h"
35 #endif //WX_PRECOMP
36 
37 #include "wx/splitter.h"
38 #include "wx/dcmirror.h"
39 
40 // ----------------------------------------------------------------------------
41 // wxRendererGeneric: our wxRendererNative implementation
42 // ----------------------------------------------------------------------------
43 
44 class WXDLLEXPORT wxRendererGeneric : public wxRendererNative
45 {
46 public:
47     wxRendererGeneric();
48 
49     virtual int  DrawHeaderButton(wxWindow *win,
50                                   wxDC& dc,
51                                   const wxRect& rect,
52                                   int flags = 0,
53                                   wxHeaderSortIconType sortArrow = wxHDR_SORT_ICON_NONE,
54                                   wxHeaderButtonParams* params = NULL);
55 
56     virtual int  DrawHeaderButtonContents(wxWindow *win,
57                                           wxDC& dc,
58                                           const wxRect& rect,
59                                           int flags = 0,
60                                           wxHeaderSortIconType sortArrow = wxHDR_SORT_ICON_NONE,
61                                           wxHeaderButtonParams* params = NULL);
62 
63     virtual int GetHeaderButtonHeight(wxWindow *win);
64 
65     virtual void DrawTreeItemButton(wxWindow *win,
66                                     wxDC& dc,
67                                     const wxRect& rect,
68                                     int flags = 0);
69 
70     virtual void DrawSplitterBorder(wxWindow *win,
71                                     wxDC& dc,
72                                     const wxRect& rect,
73                                     int flags = 0);
74 
75     virtual void DrawSplitterSash(wxWindow *win,
76                                   wxDC& dc,
77                                   const wxSize& size,
78                                   wxCoord position,
79                                   wxOrientation orient,
80                                   int flags = 0);
81 
82     virtual void DrawComboBoxDropButton(wxWindow *win,
83                                         wxDC& dc,
84                                         const wxRect& rect,
85                                         int flags = 0);
86 
87     virtual void DrawDropArrow(wxWindow *win,
88                                wxDC& dc,
89                                const wxRect& rect,
90                                int flags = 0);
91 
92     virtual void DrawCheckBox(wxWindow *win,
93                               wxDC& dc,
94                               const wxRect& rect,
95                               int flags = 0);
96 
97     virtual void DrawPushButton(wxWindow *win,
98                                 wxDC& dc,
99                                 const wxRect& rect,
100                                 int flags = 0);
101 
102     virtual void DrawItemSelectionRect(wxWindow *win,
103                                        wxDC& dc,
104                                        const wxRect& rect,
105                                        int flags = 0);
106 
107     virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win);
108 
GetVersion() const109     virtual wxRendererVersion GetVersion() const
110     {
111         return wxRendererVersion(wxRendererVersion::Current_Version,
112                                  wxRendererVersion::Current_Age);
113     }
114 
115 
116     // Cleanup by deleting standard renderer
117     static void Cleanup();
118 
119     // Get the generic object
120     static wxRendererGeneric* DoGetGeneric();
121 
122 protected:
123     // draw the rectange using the first pen for the left and top sides and
124     // the second one for the bottom and right ones
125     void DrawShadedRect(wxDC& dc, wxRect *rect,
126                         const wxPen& pen1, const wxPen& pen2);
127 
128     // the standard pens
129     wxPen m_penBlack,
130           m_penDarkGrey,
131           m_penLightGrey,
132           m_penHighlight;
133 
134     static wxRendererGeneric* sm_rendererGeneric;
135 };
136 
137 // ============================================================================
138 // wxRendererGeneric implementation
139 // ============================================================================
140 
141 // Get the generic object
DoGetGeneric()142 wxRendererGeneric* wxRendererGeneric::DoGetGeneric()
143 {
144     if (!sm_rendererGeneric)
145         sm_rendererGeneric = new wxRendererGeneric;
146     return sm_rendererGeneric;
147 }
148 
149 // ----------------------------------------------------------------------------
150 // wxRendererGeneric creation
151 // ----------------------------------------------------------------------------
152 
153 /* static */
GetGeneric()154 wxRendererNative& wxRendererNative::GetGeneric()
155 {
156     return * wxRendererGeneric::DoGetGeneric();
157 }
158 
Cleanup()159 void wxRendererGeneric::Cleanup()
160 {
161     if (sm_rendererGeneric)
162         delete sm_rendererGeneric;
163 
164     sm_rendererGeneric = NULL;
165 }
166 
167 wxRendererGeneric* wxRendererGeneric::sm_rendererGeneric = NULL;
168 
wxRendererGeneric()169 wxRendererGeneric::wxRendererGeneric()
170     : m_penBlack(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW)),
171       m_penDarkGrey(wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW)),
172       m_penLightGrey(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)),
173       m_penHighlight(wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT))
174 {
175 }
176 
177 // ----------------------------------------------------------------------------
178 // wxRendererGeneric helpers
179 // ----------------------------------------------------------------------------
180 
181 void
DrawShadedRect(wxDC & dc,wxRect * rect,const wxPen & pen1,const wxPen & pen2)182 wxRendererGeneric::DrawShadedRect(wxDC& dc,
183                                   wxRect *rect,
184                                   const wxPen& pen1,
185                                   const wxPen& pen2)
186 {
187     // draw the rectangle
188     dc.SetPen(pen1);
189     dc.DrawLine(rect->GetLeft(), rect->GetTop(),
190                 rect->GetLeft(), rect->GetBottom());
191     dc.DrawLine(rect->GetLeft() + 1, rect->GetTop(),
192                 rect->GetRight(), rect->GetTop());
193     dc.SetPen(pen2);
194     dc.DrawLine(rect->GetRight(), rect->GetTop(),
195                 rect->GetRight(), rect->GetBottom());
196     dc.DrawLine(rect->GetLeft(), rect->GetBottom(),
197                 rect->GetRight() + 1, rect->GetBottom());
198 
199     // adjust the rect
200     rect->Inflate(-1);
201 }
202 
203 // ----------------------------------------------------------------------------
204 // tree/list ctrl drawing
205 // ----------------------------------------------------------------------------
206 
207 int
DrawHeaderButton(wxWindow * win,wxDC & dc,const wxRect & rect,int flags,wxHeaderSortIconType sortArrow,wxHeaderButtonParams * params)208 wxRendererGeneric::DrawHeaderButton(wxWindow* win,
209                                     wxDC& dc,
210                                     const wxRect& rect,
211                                     int flags,
212                                     wxHeaderSortIconType sortArrow,
213                                     wxHeaderButtonParams* params)
214 {
215     const int CORNER = 1;
216 
217     const wxCoord x = rect.x,
218                   y = rect.y,
219                   w = rect.width,
220                   h = rect.height;
221 
222     dc.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)));
223     dc.SetPen(*wxTRANSPARENT_PEN);
224     dc.DrawRectangle(rect);
225 
226     dc.SetBrush(*wxTRANSPARENT_BRUSH);
227 
228     dc.SetPen(m_penBlack);
229     dc.DrawLine( x+w-CORNER+1, y, x+w, y+h );  // right (outer)
230     dc.DrawRectangle( x, y+h, w+1, 1 );        // bottom (outer)
231 
232     dc.SetPen(m_penDarkGrey);
233     dc.DrawLine( x+w-CORNER, y, x+w-1, y+h );  // right (inner)
234     dc.DrawRectangle( x+1, y+h-1, w-2, 1 );    // bottom (inner)
235 
236     dc.SetPen(m_penHighlight);
237     dc.DrawRectangle( x, y, w-CORNER+1, 1 );   // top (outer)
238     dc.DrawRectangle( x, y, 1, h );            // left (outer)
239     dc.DrawLine( x, y+h-1, x+1, y+h-1 );
240     dc.DrawLine( x+w-1, y, x+w-1, y+1 );
241 
242     return DrawHeaderButtonContents(win, dc, rect, flags, sortArrow, params);
243 }
244 
245 
246 int
DrawHeaderButtonContents(wxWindow * win,wxDC & dc,const wxRect & rect,int flags,wxHeaderSortIconType sortArrow,wxHeaderButtonParams * params)247 wxRendererGeneric::DrawHeaderButtonContents(wxWindow *win,
248                                             wxDC& dc,
249                                             const wxRect& rect,
250                                             int flags,
251                                             wxHeaderSortIconType sortArrow,
252                                             wxHeaderButtonParams* params)
253 {
254     int labelWidth = 0;
255 
256     // Mark this item as selected.  For the generic version we'll just draw an
257     // underline
258     if ( flags & wxCONTROL_SELECTED )
259     {
260         // draw a line at the bottom of the header button, overlaying the
261         // native hot-tracking line (on XP)
262         const int penwidth = 3;
263         int y = rect.y + rect.height + 1 - penwidth;
264         wxColour c = (params && params->m_selectionColour.Ok()) ?
265             params->m_selectionColour : wxColour(0x66, 0x66, 0x66);
266         wxPen pen(c, penwidth);
267         pen.SetCap(wxCAP_BUTT);
268         dc.SetPen(pen);
269         dc.DrawLine(rect.x, y, rect.x + rect.width, y);
270     }
271 
272     // Draw an up or down arrow
273     int arrowSpace = 0;
274     if (sortArrow != wxHDR_SORT_ICON_NONE )
275     {
276         wxRect ar = rect;
277 
278         // make a rect for the arrow
279         ar.height = 4;
280         ar.width = 8;
281         ar.y += (rect.height - ar.height)/2;
282         ar.x = ar.x + rect.width - 3*ar.width/2;
283         arrowSpace = 3*ar.width/2; // space to preserve when drawing the label
284 
285         wxPoint triPt[3];
286         if ( sortArrow & wxHDR_SORT_ICON_UP )
287         {
288             triPt[0].x = ar.width / 2;
289             triPt[0].y = 0;
290             triPt[1].x = ar.width;
291             triPt[1].y = ar.height;
292             triPt[2].x = 0;
293             triPt[2].y = ar.height;
294         }
295         else
296         {
297             triPt[0].x = 0;
298             triPt[0].y = 0;
299             triPt[1].x = ar.width;
300             triPt[1].y = 0;
301             triPt[2].x = ar.width / 2;
302             triPt[2].y = ar.height;
303         }
304 
305         wxColour c = (params && params->m_arrowColour.Ok()) ?
306             params->m_arrowColour : wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW);
307         dc.SetPen(wxPen(c));
308         dc.SetBrush(wxBrush(c));
309         dc.DrawPolygon( 3, triPt, ar.x, ar.y);
310     }
311     labelWidth += arrowSpace;
312 
313     const int margin = 5;   // number of pixels to reserve on either side of the label
314     int bmpWidth = 0;
315     int txtEnd = 0;
316 
317     if ( params && params->m_labelBitmap.Ok() )
318         bmpWidth = params->m_labelBitmap.GetWidth() + 2;
319 
320     labelWidth += bmpWidth + 2*margin;
321 
322     // Draw a label if one is given
323     if ( params && !params->m_labelText.empty() )
324     {
325         wxFont font  = params->m_labelFont.Ok() ?
326             params->m_labelFont : win->GetFont();
327         wxColour clr = params->m_labelColour.Ok() ?
328             params->m_labelColour : win->GetForegroundColour();
329 
330         wxString label( params->m_labelText );
331 
332         dc.SetFont(font);
333         dc.SetTextForeground(clr);
334         dc.SetBackgroundMode(wxTRANSPARENT);
335 
336         int tw, th, td, x, y;
337         dc.GetTextExtent( label, &tw, &th, &td);
338         labelWidth += tw;
339         y = rect.y + wxMax(0, (rect.height - (th+td)) / 2);
340 
341         // truncate and add an ellipsis (...) if the text is too wide.
342         int targetWidth = rect.width - arrowSpace - bmpWidth - 2*margin;
343         if ( tw > targetWidth )
344         {
345             int ellipsisWidth;
346             dc.GetTextExtent( wxT("..."), &ellipsisWidth, NULL);
347             do {
348                 label.Truncate( label.length() - 1 );
349                 dc.GetTextExtent( label, &tw, &th);
350             } while (tw + ellipsisWidth > targetWidth && label.length() );
351             label.append( wxT("...") );
352             tw += ellipsisWidth;
353         }
354 
355         switch (params->m_labelAlignment)
356         {
357             default:
358             case wxALIGN_LEFT:
359                 x = rect.x + margin;
360                 break;
361             case wxALIGN_CENTER:
362                 x = rect.x + wxMax(0, (rect.width - arrowSpace  - tw - bmpWidth)/2);
363                 break;
364             case wxALIGN_RIGHT:
365                 x = rect.x + wxMax(0, rect.width - arrowSpace - margin - tw - bmpWidth);
366                 break;
367         }
368 
369         dc.DrawText(label, x, y);
370         txtEnd = x + tw + 2;
371     }
372 
373     // draw the bitmap if there is one
374     if ( params && params->m_labelBitmap.Ok() )
375     {
376         int w, h, x, y;
377         w = params->m_labelBitmap.GetWidth();
378         h = params->m_labelBitmap.GetHeight();
379 
380         y = rect.y + wxMax(1, (rect.height - h) / 2);
381 
382         // if there is a text label, then put the bitmap at the end of the label
383         if ( txtEnd != 0 )
384         {
385             x = txtEnd;
386         }
387         // otherwise use the alignment flags
388         else
389         {
390             switch (params->m_labelAlignment)
391             {
392                 default:
393                 case wxALIGN_LEFT:
394                     x = rect.x + margin;
395                     break;
396                 case wxALIGN_CENTER:
397                     x = rect.x + wxMax(1, (rect.width - arrowSpace - w)/2);
398                     break;
399                 case wxALIGN_RIGHT:
400                     x = rect.x + wxMax(1, rect.width - arrowSpace - margin - w);
401                     break;
402             }
403         }
404         dc.DrawBitmap(params->m_labelBitmap, x, y, true);
405     }
406     return labelWidth;
407 }
408 
409 
GetHeaderButtonHeight(wxWindow * win)410 int wxRendererGeneric::GetHeaderButtonHeight(wxWindow *win)
411 {
412     // Copied and adapted from src/generic/listctrl.cpp
413     const int HEADER_OFFSET_Y = 1;
414     const int EXTRA_HEIGHT = 4;
415 
416     int w=0, h=14, d=0;
417     if (win)
418         win->GetTextExtent(wxT("Hg"), &w, &h, &d);
419 
420     return h + d + 2 * HEADER_OFFSET_Y + EXTRA_HEIGHT;
421 }
422 
423 
424 // draw the plus or minus sign
425 void
DrawTreeItemButton(wxWindow * WXUNUSED (win),wxDC & dc,const wxRect & rect,int flags)426 wxRendererGeneric::DrawTreeItemButton(wxWindow * WXUNUSED(win),
427                                       wxDC& dc,
428                                       const wxRect& rect,
429                                       int flags)
430 {
431     // store settings
432     wxDCPenChanger penChanger(dc, *wxGREY_PEN);
433     wxDCBrushChanger brushChanger(dc, *wxWHITE_BRUSH);
434 
435     dc.DrawRectangle(rect);
436 
437     // black lines
438     const wxCoord xMiddle = rect.x + rect.width/2;
439     const wxCoord yMiddle = rect.y + rect.height/2;
440 
441     // half of the length of the horz lines in "-" and "+"
442     const wxCoord halfWidth = rect.width/2 - 2;
443     dc.SetPen(*wxBLACK_PEN);
444     dc.DrawLine(xMiddle - halfWidth, yMiddle,
445                 xMiddle + halfWidth + 1, yMiddle);
446 
447     if ( !(flags & wxCONTROL_EXPANDED) )
448     {
449         // turn "-" into "+"
450         const wxCoord halfHeight = rect.height/2 - 2;
451         dc.DrawLine(xMiddle, yMiddle - halfHeight,
452                     xMiddle, yMiddle + halfHeight + 1);
453     }
454 }
455 
456 // ----------------------------------------------------------------------------
457 // sash drawing
458 // ----------------------------------------------------------------------------
459 
460 wxSplitterRenderParams
GetSplitterParams(const wxWindow * win)461 wxRendererGeneric::GetSplitterParams(const wxWindow *win)
462 {
463     // see below
464     wxCoord sashWidth,
465             border;
466 
467     if ( win->HasFlag(wxSP_3DSASH) )
468         sashWidth = 7;
469     else if ( win->HasFlag(wxSP_NOSASH) )
470         sashWidth = 0;
471     else // no 3D effect
472         sashWidth = 3;
473 
474     if ( win->HasFlag(wxSP_3DBORDER) )
475         border = 2;
476     else // no 3D effect
477         border = 0;
478 
479     return wxSplitterRenderParams(sashWidth, border, false);
480 }
481 
482 void
DrawSplitterBorder(wxWindow * win,wxDC & dc,const wxRect & rectOrig,int WXUNUSED (falgs))483 wxRendererGeneric::DrawSplitterBorder(wxWindow *win,
484                                       wxDC& dc,
485                                       const wxRect& rectOrig,
486                                       int WXUNUSED(falgs))
487 {
488     if ( win->HasFlag(wxSP_3DBORDER) )
489     {
490         wxRect rect = rectOrig;
491         DrawShadedRect(dc, &rect, m_penDarkGrey, m_penHighlight);
492         DrawShadedRect(dc, &rect, m_penBlack, m_penLightGrey);
493     }
494 }
495 
496 void
DrawSplitterSash(wxWindow * win,wxDC & dcReal,const wxSize & sizeReal,wxCoord position,wxOrientation orient,int WXUNUSED (flags))497 wxRendererGeneric::DrawSplitterSash(wxWindow *win,
498                                     wxDC& dcReal,
499                                     const wxSize& sizeReal,
500                                     wxCoord position,
501                                     wxOrientation orient,
502                                     int WXUNUSED(flags))
503 {
504     // to avoid duplicating the same code for horizontal and vertical sashes,
505     // simply mirror the DC instead if needed (i.e. if horz splitter)
506     wxMirrorDC dc(dcReal, orient != wxVERTICAL);
507     wxSize size = dc.Reflect(sizeReal);
508 
509 
510     // we draw a Win32-like grey sash with possible 3D border here:
511     //
512     //   ---- this is position
513     //  /
514     // v
515     // dWGGGDd
516     // GWGGGDB
517     // GWGGGDB  where G is light grey (face)
518     // GWGGGDB        W    white      (light)
519     // GWGGGDB        D    dark grey  (shadow)
520     // GWGGGDB        B    black      (dark shadow)
521     // GWGGGDB
522     // GWGGGDB  and lower letters are our border (already drawn)
523     // GWGGGDB
524     // wWGGGDd
525     //
526     // only the middle 3 columns are drawn unless wxSP_3D is specified
527 
528     const wxCoord h = size.y;
529     wxCoord offset = 0;
530 
531     // If we're drawing the border, draw the sash 3d lines shorter
532     if ( win->HasFlag(wxSP_3DBORDER) )
533     {
534         offset = 1;
535     }
536 
537     dc.SetPen(*wxTRANSPARENT_PEN);
538     dc.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)));
539 
540     if ( win->HasFlag(wxSP_3DSASH) )
541     {
542         // Draw the 3D sash
543         dc.DrawRectangle(position + 2, 0, 3, h);
544 
545         dc.SetPen(m_penLightGrey);
546         dc.DrawLine(position, offset, position, h - offset);
547 
548         dc.SetPen(m_penHighlight);
549         dc.DrawLine(position + 1, 0, position + 1, h);
550 
551         dc.SetPen(m_penDarkGrey);
552         dc.DrawLine(position + 5, 0, position + 5, h);
553 
554         dc.SetPen(m_penBlack);
555         dc.DrawLine(position + 6, offset, position + 6, h - offset);
556     }
557     else
558     {
559         // Draw a flat sash
560         dc.DrawRectangle(position, 0, 3, h);
561     }
562 }
563 
564 // ----------------------------------------------------------------------------
565 // button drawing
566 // ----------------------------------------------------------------------------
567 
568 void
DrawComboBoxDropButton(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)569 wxRendererGeneric::DrawComboBoxDropButton(wxWindow *win,
570                                           wxDC& dc,
571                                           const wxRect& rect,
572                                           int flags)
573 {
574     DrawPushButton(win,dc,rect,flags);
575     DrawDropArrow(win,dc,rect,flags);
576 }
577 
578 void
DrawDropArrow(wxWindow * win,wxDC & dc,const wxRect & rect,int WXUNUSED (flags))579 wxRendererGeneric::DrawDropArrow(wxWindow *win,
580                                  wxDC& dc,
581                                  const wxRect& rect,
582                                  int WXUNUSED(flags))
583 {
584     // This generic implementation should be good
585     // enough for Windows platforms (including XP).
586 
587     int arrowHalf = rect.width/5;
588     int rectMid = rect.width / 2;
589     int arrowTopY = (rect.height/2) - (arrowHalf/2);
590 
591     // This should always result in arrow with odd width.
592     wxPoint pt[] =
593     {
594         wxPoint(rectMid - arrowHalf, arrowTopY),
595         wxPoint(rectMid + arrowHalf, arrowTopY),
596         wxPoint(rectMid, arrowTopY + arrowHalf)
597     };
598     dc.SetBrush(wxBrush(win->GetForegroundColour()));
599     dc.SetPen(wxPen(win->GetForegroundColour()));
600     dc.DrawPolygon(WXSIZEOF(pt), pt, rect.x, rect.y);
601 }
602 
603 void
DrawCheckBox(wxWindow * WXUNUSED (win),wxDC & dc,const wxRect & rect,int flags)604 wxRendererGeneric::DrawCheckBox(wxWindow *WXUNUSED(win),
605                                 wxDC& dc,
606                                 const wxRect& rect,
607                                 int flags)
608 {
609     dc.SetPen(*(flags & wxCONTROL_DISABLED ? wxGREY_PEN : wxBLACK_PEN));
610     dc.SetBrush( *wxTRANSPARENT_BRUSH );
611     dc.DrawRectangle(rect);
612 
613     if ( flags & wxCONTROL_CHECKED )
614     {
615         dc.DrawCheckMark(rect.Deflate(2, 2));
616     }
617 }
618 
619 void
DrawPushButton(wxWindow * win,wxDC & dc,const wxRect & rect,int flags)620 wxRendererGeneric::DrawPushButton(wxWindow *win,
621                                   wxDC& dc,
622                                   const wxRect& rect,
623                                   int flags)
624 {
625     // Don't try anything too fancy. It'll just turn out looking
626     // out-of-place on most platforms.
627     wxColour bgCol = flags & wxCONTROL_DISABLED ?
628                         wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE) :
629                         win->GetBackgroundColour();
630     dc.SetBrush(wxBrush(bgCol));
631     dc.SetPen(wxPen(bgCol));
632     dc.DrawRectangle(rect);
633 }
634 
635 void
DrawItemSelectionRect(wxWindow * WXUNUSED (win),wxDC & dc,const wxRect & rect,int flags)636 wxRendererGeneric::DrawItemSelectionRect(wxWindow * WXUNUSED(win),
637                                          wxDC& dc,
638                                          const wxRect& rect,
639                                          int flags)
640 {
641     wxBrush brush;
642     if ( flags & wxCONTROL_SELECTED )
643     {
644         if ( flags & wxCONTROL_FOCUSED )
645         {
646             brush = wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT));
647         }
648         else // !focused
649         {
650             brush = wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW));
651         }
652     }
653     else // !selected
654     {
655         brush = *wxTRANSPARENT_BRUSH;
656     }
657 
658     dc.SetBrush(brush);
659     dc.SetPen(flags & wxCONTROL_CURRENT ? *wxBLACK_PEN : *wxTRANSPARENT_PEN);
660 
661     dc.DrawRectangle( rect );
662 }
663 
664 
665 // ----------------------------------------------------------------------------
666 // A module to allow cleanup of generic renderer.
667 // ----------------------------------------------------------------------------
668 
669 class wxGenericRendererModule: public wxModule
670 {
671 DECLARE_DYNAMIC_CLASS(wxGenericRendererModule)
672 public:
wxGenericRendererModule()673     wxGenericRendererModule() {}
OnInit()674     bool OnInit() { return true; }
OnExit()675     void OnExit() { wxRendererGeneric::Cleanup(); }
676 };
677 
678 IMPLEMENT_DYNAMIC_CLASS(wxGenericRendererModule, wxModule)
679