1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/univ/stdrend.cpp
3 // Purpose: implementation of wxStdRenderer
4 // Author: Vadim Zeitlin
6 // Copyright: (c) 2006 Vadim Zeitlin <vadim@wxwindows.org>
7 // Licence: wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
10 // ============================================================================
12 // ============================================================================
14 // ----------------------------------------------------------------------------
16 // ----------------------------------------------------------------------------
18 // for compilers that support precompilation, includes "wx.h".
19 #include "wx/wxprec.h"
26 #include "wx/settings.h"
29 #include "wx/statusbr.h"
30 #include "wx/toplevel.h"
33 #include "wx/univ/stdrend.h"
34 #include "wx/univ/colschem.h"
36 // ----------------------------------------------------------------------------
38 // ----------------------------------------------------------------------------
40 static const int FRAME_TITLEBAR_HEIGHT
= 18;
41 static const int FRAME_BUTTON_WIDTH
= 16;
42 static const int FRAME_BUTTON_HEIGHT
= 14;
44 // the margin between listbox item text and its rectangle
45 static const int ITEM_MARGIN
= 1;
47 // ============================================================================
48 // wxStdRenderer implementation
49 // ============================================================================
51 // ----------------------------------------------------------------------------
53 // ----------------------------------------------------------------------------
55 wxStdRenderer::wxStdRenderer(const wxColourScheme
*scheme
)
58 m_penBlack
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_DARK
));
59 m_penDarkGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_OUT
));
60 m_penLightGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_IN
));
61 m_penHighlight
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_HIGHLIGHT
));
63 m_titlebarFont
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
);
64 m_titlebarFont
.SetWeight(wxFONTWEIGHT_BOLD
);
67 // ----------------------------------------------------------------------------
69 // ----------------------------------------------------------------------------
72 wxStdRenderer::DrawSolidRect(wxDC
& dc
, const wxColour
& col
, const wxRect
& rect
)
74 wxBrush
brush(col
, wxSOLID
);
76 dc
.SetPen(*wxTRANSPARENT_PEN
);
77 dc
.DrawRectangle(rect
);
80 void wxStdRenderer::DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
84 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
85 dc
.DrawRectangle(*rect
);
91 void wxStdRenderer::DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
92 const wxPen
& pen1
, const wxPen
& pen2
)
96 dc
.DrawLine(rect
->GetLeft(), rect
->GetTop(),
97 rect
->GetLeft(), rect
->GetBottom());
98 dc
.DrawLine(rect
->GetLeft() + 1, rect
->GetTop(),
99 rect
->GetRight(), rect
->GetTop());
101 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
102 rect
->GetRight(), rect
->GetBottom());
103 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
104 rect
->GetRight() + 1, rect
->GetBottom());
110 // ----------------------------------------------------------------------------
111 // translate various flags into corresponding renderer constants
112 // ----------------------------------------------------------------------------
115 void wxStdRenderer::GetIndicatorsFromFlags(int flags
,
116 IndicatorState
& state
,
117 IndicatorStatus
& status
)
119 if ( flags
& wxCONTROL_SELECTED
)
120 state
= flags
& wxCONTROL_DISABLED
? IndicatorState_SelectedDisabled
121 : IndicatorState_Selected
;
122 else if ( flags
& wxCONTROL_DISABLED
)
123 state
= IndicatorState_Disabled
;
124 else if ( flags
& wxCONTROL_PRESSED
)
125 state
= IndicatorState_Pressed
;
127 state
= IndicatorState_Normal
;
129 status
= flags
& wxCONTROL_CHECKED
? IndicatorStatus_Checked
130 : flags
& wxCONTROL_UNDETERMINED
131 ? IndicatorStatus_Undetermined
132 : IndicatorStatus_Unchecked
;
136 wxStdRenderer::ArrowDirection
wxStdRenderer::GetArrowDirection(wxDirection dir
)
153 wxFAIL_MSG(wxT("unknown arrow direction"));
159 // ----------------------------------------------------------------------------
161 // ----------------------------------------------------------------------------
163 void wxStdRenderer::DrawBackground(wxDC
& dc
,
177 colBg
= m_scheme
->GetBackground(window
);
181 colBg
= wxSCHEME_COLOUR(m_scheme
, CONTROL
);
184 DrawSolidRect(dc
, colBg
, rect
);
188 void wxStdRenderer::DrawButtonSurface(wxDC
& dc
,
193 DrawBackground(dc
, col
, rect
, flags
);
196 // ----------------------------------------------------------------------------
198 // ----------------------------------------------------------------------------
201 wxStdRenderer::DrawFocusRect(wxWindow
* WXUNUSED(win
), wxDC
& dc
, const wxRect
& rect
, int WXUNUSED(flags
))
203 // draw the pixels manually because the "dots" in wxPen with wxDOT style
204 // may be short traits and not really dots
206 // note that to behave in the same manner as DrawRect(), we must exclude
207 // the bottom and right borders from the rectangle
208 wxCoord x1
= rect
.GetLeft(),
210 x2
= rect
.GetRight(),
211 y2
= rect
.GetBottom();
213 dc
.SetPen(m_penBlack
);
215 // this seems to be closer than what Windows does than wxINVERT although
216 // I'm still not sure if it's correct
217 dc
.SetLogicalFunction(wxAND_REVERSE
);
220 for ( z
= x1
+ 1; z
< x2
; z
+= 2 )
221 dc
.DrawPoint(z
, rect
.GetTop());
223 wxCoord shift
= z
== x2
? 0 : 1;
224 for ( z
= y1
+ shift
; z
< y2
; z
+= 2 )
227 shift
= z
== y2
? 0 : 1;
228 for ( z
= x2
- shift
; z
> x1
; z
-= 2 )
231 shift
= z
== x1
? 0 : 1;
232 for ( z
= y2
- shift
; z
> y1
; z
-= 2 )
235 dc
.SetLogicalFunction(wxCOPY
);
238 void wxStdRenderer::DrawLabel(wxDC
& dc
,
239 const wxString
& label
,
246 DrawButtonLabel(dc
, label
, wxNullBitmap
, rect
, flags
,
247 alignment
, indexAccel
, rectBounds
);
250 void wxStdRenderer::DrawButtonLabel(wxDC
& dc
,
251 const wxString
& label
,
252 const wxBitmap
& image
,
259 wxDCTextColourChanger
clrChanger(dc
);
261 wxRect rectLabel
= rect
;
262 if ( !label
.empty() && (flags
& wxCONTROL_DISABLED
) )
264 if ( flags
& wxCONTROL_PRESSED
)
266 // shift the label if a button is pressed
267 rectLabel
.Offset(1, 1);
270 // draw shadow of the text
271 clrChanger
.Set(m_penHighlight
.GetColour());
272 wxRect rectShadow
= rect
;
273 rectShadow
.Offset(1, 1);
274 dc
.DrawLabel(label
, rectShadow
, alignment
, indexAccel
);
276 // make the main label text grey
277 clrChanger
.Set(m_penDarkGrey
.GetColour());
279 if ( flags
& wxCONTROL_FOCUSED
)
281 // leave enough space for the focus rect
282 rectLabel
.Inflate(-2);
286 dc
.DrawLabel(label
, image
, rectLabel
, alignment
, indexAccel
, rectBounds
);
288 if ( !label
.empty() && (flags
& wxCONTROL_FOCUSED
) )
290 rectLabel
.Inflate(-1);
292 DrawFocusRect(NULL
, dc
, rectLabel
);
296 // ----------------------------------------------------------------------------
298 // ----------------------------------------------------------------------------
301 We implement standard-looking 3D borders which have the following appearance:
305 WWWWWWWWWWWWWWWWWWWWWWB
306 WHHHHHHHHHHHHHHHHHHHHGB
307 WH GB W = white (HILIGHT)
308 WH GB H = light grey (LIGHT)
309 WH GB G = dark grey (SHADOI)
310 WH GB B = black (DKSHADOI)
313 WGGGGGGGGGGGGGGGGGGGGGB
314 BBBBBBBBBBBBBBBBBBBBBBB
316 The sunken border looks like this:
318 GGGGGGGGGGGGGGGGGGGGGGW
319 GBBBBBBBBBBBBBBBBBBBBHW
326 GHHHHHHHHHHHHHHHHHHHHHW
327 WWWWWWWWWWWWWWWWWWWWWWW
329 The static border (used for the controls which don't get focus) is like
332 GGGGGGGGGGGGGGGGGGGGGGW
340 WWWWWWWWWWWWWWWWWWWWWWW
342 The most complicated is the double border which is a combination of special
343 "anti-sunken" border and an extra border inside it:
345 HHHHHHHHHHHHHHHHHHHHHHB
346 HWWWWWWWWWWWWWWWWWWWWGB
347 HWHHHHHHHHHHHHHHHHHHHGB
352 HWHHHHHHHHHHHHHHHHHHHGB
353 HGGGGGGGGGGGGGGGGGGGGGB
354 BBBBBBBBBBBBBBBBBBBBBBB
356 And the simple border is, well, simple:
358 BBBBBBBBBBBBBBBBBBBBBBB
367 BBBBBBBBBBBBBBBBBBBBBBB
370 void wxStdRenderer::DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
)
372 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penBlack
);
373 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penDarkGrey
);
376 void wxStdRenderer::DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
)
378 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
379 DrawShadedRect(dc
, rect
, m_penBlack
, m_penLightGrey
);
382 void wxStdRenderer::DrawAntiSunkenBorder(wxDC
& dc
, wxRect
*rect
)
384 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penBlack
);
385 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
388 void wxStdRenderer::DrawBoxBorder(wxDC
& dc
, wxRect
*rect
)
390 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
391 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
394 void wxStdRenderer::DrawStaticBorder(wxDC
& dc
, wxRect
*rect
)
396 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
399 void wxStdRenderer::DrawExtraBorder(wxDC
& dc
, wxRect
*rect
)
401 DrawRect(dc
, rect
, m_penLightGrey
);
404 void wxStdRenderer::DrawBorder(wxDC
& dc
,
406 const wxRect
& rectTotal
,
410 wxRect rect
= rectTotal
;
414 case wxBORDER_SUNKEN
:
416 DrawSunkenBorder(dc
, &rect
);
419 // wxBORDER_DOUBLE and wxBORDER_THEME are currently the same value.
421 case wxBORDER_DOUBLE
:
422 DrawAntiSunkenBorder(dc
, &rect
);
423 DrawExtraBorder(dc
, &rect
);
427 case wxBORDER_STATIC
:
428 DrawStaticBorder(dc
, &rect
);
431 case wxBORDER_RAISED
:
432 DrawRaisedBorder(dc
, &rect
);
435 case wxBORDER_SIMPLE
:
436 DrawRect(dc
, &rect
, m_penBlack
);
440 wxFAIL_MSG(wxT("unknown border type"));
443 case wxBORDER_DEFAULT
:
452 wxRect
wxStdRenderer::GetBorderDimensions(wxBorder border
) const
457 case wxBORDER_SIMPLE
:
458 case wxBORDER_STATIC
:
462 case wxBORDER_RAISED
:
463 case wxBORDER_SUNKEN
:
468 case wxBORDER_DOUBLE
:
473 wxFAIL_MSG(wxT("unknown border type"));
476 case wxBORDER_DEFAULT
:
491 void wxStdRenderer::AdjustSize(wxSize
*size
, const wxWindow
*window
)
493 // take into account the border width
494 wxRect rectBorder
= GetBorderDimensions(window
->GetBorder());
495 size
->x
+= rectBorder
.x
+ rectBorder
.width
;
496 size
->y
+= rectBorder
.y
+ rectBorder
.height
;
499 bool wxStdRenderer::AreScrollbarsInsideBorder() const
504 wxCoord
wxStdRenderer::GetListboxItemHeight(wxCoord fontHeight
)
506 return fontHeight
+ 2*ITEM_MARGIN
;
509 void wxStdRenderer::DrawTextBorder(wxDC
& dc
,
515 DrawBorder(dc
, border
, rect
, flags
, rectIn
);
518 // ----------------------------------------------------------------------------
520 // ----------------------------------------------------------------------------
523 wxStdRenderer::DrawHorizontalLine(wxDC
& dc
, wxCoord y
, wxCoord x1
, wxCoord x2
)
525 dc
.SetPen(m_penDarkGrey
);
526 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
528 dc
.SetPen(m_penHighlight
);
530 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
534 wxStdRenderer::DrawVerticalLine(wxDC
& dc
, wxCoord x
, wxCoord y1
, wxCoord y2
)
536 dc
.SetPen(m_penDarkGrey
);
537 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
539 dc
.SetPen(m_penHighlight
);
541 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
544 void wxStdRenderer::DrawFrameWithoutLabel(wxDC
& dc
,
545 const wxRect
& rectFrame
,
546 const wxRect
& rectLabel
)
548 // draw left, bottom and right lines entirely
549 DrawVerticalLine(dc
, rectFrame
.GetLeft(),
550 rectFrame
.GetTop(), rectFrame
.GetBottom() - 2);
551 DrawHorizontalLine(dc
, rectFrame
.GetBottom() - 1,
552 rectFrame
.GetLeft(), rectFrame
.GetRight());
553 DrawVerticalLine(dc
, rectFrame
.GetRight() - 1,
554 rectFrame
.GetTop(), rectFrame
.GetBottom() - 1);
556 // and 2 parts of the top line
557 DrawHorizontalLine(dc
, rectFrame
.GetTop(),
558 rectFrame
.GetLeft() + 1, rectLabel
.GetLeft());
559 DrawHorizontalLine(dc
, rectFrame
.GetTop(),
560 rectLabel
.GetRight(), rectFrame
.GetRight() - 2);
563 void wxStdRenderer::DrawFrameWithLabel(wxDC
& dc
,
564 const wxString
& label
,
565 const wxRect
& rectFrame
,
566 const wxRect
& rectText
,
572 DrawLabel(dc
, label
, rectText
, flags
, alignment
, indexAccel
, &rectLabel
);
574 DrawFrameWithoutLabel(dc
, rectFrame
, rectLabel
);
577 void wxStdRenderer::DrawFrame(wxDC
& dc
,
578 const wxString
& label
,
584 wxCoord height
= 0; // of the label
585 wxRect rectFrame
= rect
;
586 if ( !label
.empty() )
588 // the text should touch the top border of the rect, so the frame
589 // itself should be lower
590 dc
.GetTextExtent(label
, NULL
, &height
);
591 rectFrame
.y
+= height
/ 2;
592 rectFrame
.height
-= height
/ 2;
594 // we have to draw each part of the frame individually as we can't
595 // erase the background beyond the label as it might contain some
596 // pixmap already, so drawing everything and then overwriting part of
597 // the frame with label doesn't work
599 // TODO: the +5 shouldn't be hard coded
601 rectText
.x
= rectFrame
.x
+ 5;
603 rectText
.width
= rectFrame
.width
- 7; // +2 border width
604 rectText
.height
= height
;
606 DrawFrameWithLabel(dc
, label
, rectFrame
, rectText
, flags
,
607 alignment
, indexAccel
);
611 DrawBoxBorder(dc
, &rectFrame
);
615 void wxStdRenderer::DrawItem(wxDC
& dc
,
616 const wxString
& label
,
620 wxDCTextColourChanger
colChanger(dc
);
622 if ( flags
& wxCONTROL_SELECTED
)
624 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
626 const wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
629 dc
.DrawRectangle(rect
);
632 // horizontal adjustment is arbitrary
633 wxRect rectText
= rect
;
634 rectText
.Deflate(2, ITEM_MARGIN
);
635 dc
.DrawLabel(label
, wxNullBitmap
, rectText
);
637 if ( flags
& wxCONTROL_FOCUSED
)
639 DrawFocusRect(NULL
, dc
, rect
, flags
);
643 void wxStdRenderer::DrawCheckItemBitmap(wxDC
& dc
,
644 const wxBitmap
& bitmap
,
648 DrawCheckButton(dc
, wxEmptyString
, bitmap
, rect
, flags
);
651 void wxStdRenderer::DrawCheckItem(wxDC
& dc
,
652 const wxString
& label
,
653 const wxBitmap
& bitmap
,
657 wxRect rectBitmap
= rect
;
658 rectBitmap
.width
= GetCheckBitmapSize().x
;
659 DrawCheckItemBitmap(dc
, bitmap
, rectBitmap
, flags
);
661 wxRect rectLabel
= rect
;
662 wxCoord shift
= rectBitmap
.width
+ 2*GetCheckItemMargin();
663 rectLabel
.x
+= shift
;
664 rectLabel
.width
-= shift
;
665 DrawItem(dc
, label
, rectLabel
, flags
);
668 // ----------------------------------------------------------------------------
669 // check and radio bitmaps
670 // ----------------------------------------------------------------------------
672 void wxStdRenderer::DrawCheckButton(wxDC
& dc
,
673 const wxString
& label
,
674 const wxBitmap
& bitmap
,
681 DrawCheckOrRadioButton(dc
, label
, bitmap
, rect
, flags
, align
, indexAccel
);
683 DrawCheckOrRadioButton(dc
, label
, GetCheckBitmap(flags
), rect
, flags
, align
, indexAccel
);
686 void wxStdRenderer::DrawRadioButton(wxDC
& dc
,
687 const wxString
& label
,
688 const wxBitmap
& bitmap
,
695 DrawCheckOrRadioButton(dc
, label
, bitmap
, rect
, flags
, align
, indexAccel
);
697 DrawCheckOrRadioButton(dc
, label
, GetRadioBitmap(flags
), rect
, flags
, align
, indexAccel
);
701 void wxStdRenderer::DrawCheckOrRadioButton(wxDC
& dc
,
702 const wxString
& label
,
703 const wxBitmap
& bitmap
,
709 // calculate the position of the bitmap and of the label
710 wxCoord heightBmp
= bitmap
.GetHeight();
712 yBmp
= rect
.y
+ (rect
.height
- heightBmp
) / 2;
715 dc
.GetMultiLineTextExtent(label
, NULL
, &rectLabel
.height
);
716 rectLabel
.y
= rect
.y
+ (rect
.height
- rectLabel
.height
) / 2;
718 // align label vertically with the bitmap - looks nicer like this
719 rectLabel
.y
-= (rectLabel
.height
- heightBmp
) % 2;
721 // calc horz position
722 if ( align
== wxALIGN_RIGHT
)
724 xBmp
= rect
.GetRight() - bitmap
.GetWidth();
725 rectLabel
.x
= rect
.x
+ 3;
726 rectLabel
.SetRight(xBmp
);
728 else // normal (checkbox to the left of the text) case
731 rectLabel
.x
= xBmp
+ bitmap
.GetWidth() + 5;
732 rectLabel
.SetRight(rect
.GetRight());
735 dc
.DrawBitmap(bitmap
, xBmp
, yBmp
, true /* use mask */);
737 DrawLabel(dc
, label
, rectLabel
, flags
,
738 wxALIGN_LEFT
| wxALIGN_TOP
, indexAccel
);
743 void wxStdRenderer::DrawTextLine(wxDC
& dc
,
744 const wxString
& text
,
750 if ( (selStart
== -1) || !(flags
& wxCONTROL_FOCUSED
) )
752 // just draw it as is
753 dc
.DrawText(text
, rect
.x
, rect
.y
);
755 else // we have selection
760 // draw the part before selection
761 wxString
s(text
, (size_t)selStart
);
764 dc
.DrawText(s
, x
, rect
.y
);
766 dc
.GetTextExtent(s
, &width
, NULL
);
770 // draw the selection itself
771 s
= wxString(text
.c_str() + selStart
, text
.c_str() + selEnd
);
774 wxColour colFg
= dc
.GetTextForeground(),
775 colBg
= dc
.GetTextBackground();
776 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
777 dc
.SetTextBackground(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
));
778 dc
.SetBackgroundMode(wxSOLID
);
780 dc
.DrawText(s
, x
, rect
.y
);
781 dc
.GetTextExtent(s
, &width
, NULL
);
784 dc
.SetBackgroundMode(wxTRANSPARENT
);
785 dc
.SetTextBackground(colBg
);
786 dc
.SetTextForeground(colFg
);
789 // draw the final part
790 s
= text
.c_str() + selEnd
;
793 dc
.DrawText(s
, x
, rect
.y
);
798 void wxStdRenderer::DrawLineWrapMark(wxDC
& WXUNUSED(dc
),
799 const wxRect
& WXUNUSED(rect
))
801 // nothing by default
804 int wxStdRenderer::GetTextBorderWidth(const wxTextCtrl
* WXUNUSED(text
)) const
810 wxStdRenderer::GetTextTotalArea(const wxTextCtrl
*text
, const wxRect
& rect
) const
812 wxRect rectTotal
= rect
;
813 rectTotal
.Inflate(GetTextBorderWidth(text
));
817 wxRect
wxStdRenderer::GetTextClientArea(const wxTextCtrl
*text
,
819 wxCoord
*extraSpaceBeyond
) const
821 wxRect rectText
= rect
;
822 rectText
.Deflate(GetTextBorderWidth(text
));
824 if ( extraSpaceBeyond
)
825 *extraSpaceBeyond
= 0;
830 #endif // wxUSE_TEXTCTRL
832 // ----------------------------------------------------------------------------
833 // scrollbars drawing
834 // ----------------------------------------------------------------------------
836 void wxStdRenderer::DrawScrollbarArrow(wxDC
& dc
,
841 DrawArrow(dc
, dir
, rect
, flags
);
844 void wxStdRenderer::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
846 DrawSolidRect(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
849 // ----------------------------------------------------------------------------
851 // ----------------------------------------------------------------------------
855 wxSize
wxStdRenderer::GetStatusBarBorders() const
857 // Rendered border may be different depending on field's style, we use
858 // the largest value so that any field certainly fits into the borders
860 wxRect raised
= GetBorderDimensions(wxBORDER_RAISED
);
861 wxRect flat
= GetBorderDimensions(wxBORDER_STATIC
);
862 wxASSERT_MSG( raised
.x
== raised
.width
&& raised
.y
== raised
.height
&&
863 flat
.x
== flat
.width
&& flat
.y
== flat
.height
,
864 wxT("this code expects uniform borders, you must override GetStatusBarBorders") );
866 // take the larger of flat/raised values:
867 wxSize
border(wxMax(raised
.x
, flat
.x
), wxMax(raised
.y
, flat
.y
));
872 wxCoord
wxStdRenderer::GetStatusBarBorderBetweenFields() const
877 wxSize
wxStdRenderer::GetStatusBarFieldMargins() const
882 void wxStdRenderer::DrawStatusField(wxDC
& dc
,
884 const wxString
& label
,
890 if ( style
== wxSB_RAISED
)
891 DrawBorder(dc
, wxBORDER_RAISED
, rect
, flags
, &rectIn
);
892 else if ( style
!= wxSB_FLAT
)
893 DrawBorder(dc
, wxBORDER_STATIC
, rect
, flags
, &rectIn
);
897 rectIn
.Deflate(GetStatusBarFieldMargins());
899 wxDCClipper
clipper(dc
, rectIn
);
900 DrawLabel(dc
, label
, rectIn
, flags
, wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
903 #endif // wxUSE_STATUSBAR
905 // ----------------------------------------------------------------------------
907 // ----------------------------------------------------------------------------
909 int wxStdRenderer::HitTestFrame(const wxRect
& rect
, const wxPoint
& pt
, int flags
) const
911 wxRect client
= GetFrameClientArea(rect
, flags
);
913 if ( client
.Contains(pt
) )
914 return wxHT_TOPLEVEL_CLIENT_AREA
;
916 if ( flags
& wxTOPLEVEL_TITLEBAR
)
918 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
920 if ( flags
& wxTOPLEVEL_ICON
)
922 if ( wxRect(client
.GetPosition(), GetFrameIconSize()).Contains(pt
) )
923 return wxHT_TOPLEVEL_ICON
;
926 wxRect
btnRect(client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
,
927 client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2,
928 FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
930 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
932 if ( btnRect
.Contains(pt
) )
933 return wxHT_TOPLEVEL_BUTTON_CLOSE
;
934 btnRect
.x
-= FRAME_BUTTON_WIDTH
+ 2;
936 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
938 if ( btnRect
.Contains(pt
) )
939 return wxHT_TOPLEVEL_BUTTON_MAXIMIZE
;
940 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
942 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
944 if ( btnRect
.Contains(pt
) )
945 return wxHT_TOPLEVEL_BUTTON_RESTORE
;
946 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
948 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
950 if ( btnRect
.Contains(pt
) )
951 return wxHT_TOPLEVEL_BUTTON_ICONIZE
;
952 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
954 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
956 if ( btnRect
.Contains(pt
) )
957 return wxHT_TOPLEVEL_BUTTON_HELP
;
958 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
961 if ( pt
.y
>= client
.y
&& pt
.y
< client
.y
+ FRAME_TITLEBAR_HEIGHT
)
962 return wxHT_TOPLEVEL_TITLEBAR
;
965 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
967 // we are certainly at one of borders, let's decide which one:
970 // dirty trick, relies on the way wxHT_TOPLEVEL_XXX are defined!
971 if ( pt
.x
< client
.x
)
972 border
|= wxHT_TOPLEVEL_BORDER_W
;
973 else if ( pt
.x
>= client
.width
+ client
.x
)
974 border
|= wxHT_TOPLEVEL_BORDER_E
;
975 if ( pt
.y
< client
.y
)
976 border
|= wxHT_TOPLEVEL_BORDER_N
;
977 else if ( pt
.y
>= client
.height
+ client
.y
)
978 border
|= wxHT_TOPLEVEL_BORDER_S
;
985 void wxStdRenderer::DrawFrameTitleBar(wxDC
& dc
,
987 const wxString
& title
,
991 int specialButtonFlags
)
993 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
995 DrawFrameBorder(dc
, rect
, flags
);
997 if ( flags
& wxTOPLEVEL_TITLEBAR
)
999 DrawFrameBackground(dc
, rect
, flags
);
1000 if ( flags
& wxTOPLEVEL_ICON
)
1001 DrawFrameIcon(dc
, rect
, icon
, flags
);
1002 DrawFrameTitle(dc
, rect
, title
, flags
);
1004 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1006 x
= client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
;
1007 y
= client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2;
1009 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
1011 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_CLOSE
,
1012 (specialButton
== wxTOPLEVEL_BUTTON_CLOSE
) ?
1013 specialButtonFlags
: 0);
1014 x
-= FRAME_BUTTON_WIDTH
+ 2;
1016 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
1018 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_MAXIMIZE
,
1019 (specialButton
== wxTOPLEVEL_BUTTON_MAXIMIZE
) ?
1020 specialButtonFlags
: 0);
1021 x
-= FRAME_BUTTON_WIDTH
;
1023 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
1025 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_RESTORE
,
1026 (specialButton
== wxTOPLEVEL_BUTTON_RESTORE
) ?
1027 specialButtonFlags
: 0);
1028 x
-= FRAME_BUTTON_WIDTH
;
1030 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
1032 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_ICONIZE
,
1033 (specialButton
== wxTOPLEVEL_BUTTON_ICONIZE
) ?
1034 specialButtonFlags
: 0);
1035 x
-= FRAME_BUTTON_WIDTH
;
1037 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
1039 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_HELP
,
1040 (specialButton
== wxTOPLEVEL_BUTTON_HELP
) ?
1041 specialButtonFlags
: 0);
1046 void wxStdRenderer::DrawFrameBorder(wxDC
& dc
, const wxRect
& rect
, int flags
)
1048 if ( !(flags
& wxTOPLEVEL_BORDER
) )
1053 DrawAntiSunkenBorder(dc
, &r
);
1054 DrawExtraBorder(dc
, &r
);
1055 if ( flags
& wxTOPLEVEL_RESIZEABLE
)
1056 DrawExtraBorder(dc
, &r
);
1059 void wxStdRenderer::DrawFrameBackground(wxDC
& dc
, const wxRect
& rect
, int flags
)
1061 if ( !(flags
& wxTOPLEVEL_TITLEBAR
) )
1064 wxColour col
= m_scheme
->Get(flags
& wxTOPLEVEL_ACTIVE
1065 ? wxColourScheme::TITLEBAR_ACTIVE
1066 : wxColourScheme::TITLEBAR
);
1068 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1069 r
.height
= FRAME_TITLEBAR_HEIGHT
;
1071 DrawBackground(dc
, col
, r
);
1074 void wxStdRenderer::DrawFrameTitle(wxDC
& dc
,
1076 const wxString
& title
,
1079 wxColour col
= m_scheme
->Get(flags
& wxTOPLEVEL_ACTIVE
1080 ? wxColourScheme::TITLEBAR_ACTIVE_TEXT
1081 : wxColourScheme::TITLEBAR_TEXT
);
1082 dc
.SetTextForeground(col
);
1084 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1085 r
.height
= FRAME_TITLEBAR_HEIGHT
;
1086 if ( flags
& wxTOPLEVEL_ICON
)
1088 r
.x
+= FRAME_TITLEBAR_HEIGHT
;
1089 r
.width
-= FRAME_TITLEBAR_HEIGHT
+ 2;
1097 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
1098 r
.width
-= FRAME_BUTTON_WIDTH
+ 2;
1099 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
1100 r
.width
-= FRAME_BUTTON_WIDTH
;
1101 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
1102 r
.width
-= FRAME_BUTTON_WIDTH
;
1103 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
1104 r
.width
-= FRAME_BUTTON_WIDTH
;
1105 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
1106 r
.width
-= FRAME_BUTTON_WIDTH
;
1108 dc
.SetFont(m_titlebarFont
);
1112 dc
.GetTextExtent(title
, &textW
, NULL
);
1113 if ( textW
> r
.width
)
1115 // text is too big, let's shorten it and add "..." after it:
1116 size_t len
= title
.length();
1117 wxCoord WSoFar
, letterW
;
1119 dc
.GetTextExtent(wxT("..."), &WSoFar
, NULL
);
1120 if ( WSoFar
> r
.width
)
1122 // not enough space to draw anything
1127 for (size_t i
= 0; i
< len
; i
++)
1129 dc
.GetTextExtent(title
[i
], &letterW
, NULL
);
1130 if ( letterW
+ WSoFar
> r
.width
)
1137 else // no need to truncate the title
1142 dc
.DrawLabel(s
, wxNullBitmap
, r
, wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
1145 void wxStdRenderer::DrawFrameIcon(wxDC
& dc
,
1152 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1153 dc
.DrawIcon(icon
, r
.x
, r
.y
);
1157 void wxStdRenderer::DrawFrameButton(wxDC
& dc
,
1158 wxCoord x
, wxCoord y
,
1162 FrameButtonType idx
;
1165 case wxTOPLEVEL_BUTTON_CLOSE
: idx
= FrameButton_Close
; break;
1166 case wxTOPLEVEL_BUTTON_MAXIMIZE
: idx
= FrameButton_Maximize
; break;
1167 case wxTOPLEVEL_BUTTON_ICONIZE
: idx
= FrameButton_Minimize
; break;
1168 case wxTOPLEVEL_BUTTON_RESTORE
: idx
= FrameButton_Restore
; break;
1169 case wxTOPLEVEL_BUTTON_HELP
: idx
= FrameButton_Help
; break;
1171 wxFAIL_MSG(wxT("incorrect button specification"));
1175 wxBitmap bmp
= GetFrameButtonBitmap(idx
);
1179 wxRect
rectBtn(x
, y
, FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
1180 if ( flags
& wxCONTROL_PRESSED
)
1182 DrawSunkenBorder(dc
, &rectBtn
);
1184 rectBtn
.Offset(1, 1);
1188 DrawRaisedBorder(dc
, &rectBtn
);
1191 DrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rectBtn
);
1193 wxRect
rectBmp(0, 0, bmp
.GetWidth(), bmp
.GetHeight());
1194 dc
.DrawBitmap(bmp
, rectBmp
.CentreIn(rectBtn
).GetPosition(), true);
1197 int wxStdRenderer::GetFrameBorderWidth(int flags
) const
1199 return flags
& wxTOPLEVEL_RESIZEABLE
? 4 : 3;
1203 wxRect
wxStdRenderer::GetFrameClientArea(const wxRect
& rect
, int flags
) const
1207 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1209 r
.Inflate(-GetFrameBorderWidth(flags
));
1212 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1214 r
.y
+= FRAME_TITLEBAR_HEIGHT
;
1215 r
.height
-= FRAME_TITLEBAR_HEIGHT
;
1222 wxStdRenderer::GetFrameTotalSize(const wxSize
& clientSize
, int flags
) const
1224 wxSize
s(clientSize
);
1226 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1228 s
.IncBy(2*GetFrameBorderWidth(flags
));
1231 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1232 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
1237 wxSize
wxStdRenderer::GetFrameMinSize(int flags
) const
1241 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1243 s
.IncBy(2*GetFrameBorderWidth(flags
));
1246 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1248 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
1250 if ( flags
& wxTOPLEVEL_ICON
)
1251 s
.x
+= FRAME_TITLEBAR_HEIGHT
+ 2;
1252 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
1253 s
.x
+= FRAME_BUTTON_WIDTH
+ 2;
1254 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
1255 s
.x
+= FRAME_BUTTON_WIDTH
;
1256 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
1257 s
.x
+= FRAME_BUTTON_WIDTH
;
1258 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
1259 s
.x
+= FRAME_BUTTON_WIDTH
;
1260 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
1261 s
.x
+= FRAME_BUTTON_WIDTH
;
1267 wxSize
wxStdRenderer::GetFrameIconSize() const
1269 return wxSize(16, 16);