1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/univ/stdrend.cpp
3 // Purpose: implementation of wxStdRenderer
4 // Author: Vadim Zeitlin
7 // Copyright: (c) 2006 Vadim Zeitlin <vadim@wxwindows.org>
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 // for compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
27 #include "wx/settings.h"
30 #include "wx/statusbr.h"
31 #include "wx/toplevel.h"
34 #include "wx/univ/stdrend.h"
35 #include "wx/univ/colschem.h"
37 // ----------------------------------------------------------------------------
39 // ----------------------------------------------------------------------------
41 static const int FRAME_TITLEBAR_HEIGHT
= 18;
42 static const int FRAME_BUTTON_WIDTH
= 16;
43 static const int FRAME_BUTTON_HEIGHT
= 14;
45 // the margin between listbox item text and its rectangle
46 static const int ITEM_MARGIN
= 1;
48 // ============================================================================
49 // wxStdRenderer implementation
50 // ============================================================================
52 // ----------------------------------------------------------------------------
54 // ----------------------------------------------------------------------------
56 wxStdRenderer::wxStdRenderer(const wxColourScheme
*scheme
)
59 m_penBlack
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_DARK
));
60 m_penDarkGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_OUT
));
61 m_penLightGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_IN
));
62 m_penHighlight
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_HIGHLIGHT
));
64 m_titlebarFont
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
);
65 m_titlebarFont
.SetWeight(wxFONTWEIGHT_BOLD
);
68 // ----------------------------------------------------------------------------
70 // ----------------------------------------------------------------------------
73 wxStdRenderer::DrawSolidRect(wxDC
& dc
, const wxColour
& col
, const wxRect
& rect
)
75 wxBrush
brush(col
, wxSOLID
);
77 dc
.SetPen(*wxTRANSPARENT_PEN
);
78 dc
.DrawRectangle(rect
);
81 void wxStdRenderer::DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
85 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
86 dc
.DrawRectangle(*rect
);
92 void wxStdRenderer::DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
93 const wxPen
& pen1
, const wxPen
& pen2
)
97 dc
.DrawLine(rect
->GetLeft(), rect
->GetTop(),
98 rect
->GetLeft(), rect
->GetBottom());
99 dc
.DrawLine(rect
->GetLeft() + 1, rect
->GetTop(),
100 rect
->GetRight(), rect
->GetTop());
102 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
103 rect
->GetRight(), rect
->GetBottom());
104 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
105 rect
->GetRight() + 1, rect
->GetBottom());
111 // ----------------------------------------------------------------------------
112 // translate various flags into corresponding renderer constants
113 // ----------------------------------------------------------------------------
116 void wxStdRenderer::GetIndicatorsFromFlags(int flags
,
117 IndicatorState
& state
,
118 IndicatorStatus
& status
)
120 if ( flags
& wxCONTROL_SELECTED
)
121 state
= flags
& wxCONTROL_DISABLED
? IndicatorState_SelectedDisabled
122 : IndicatorState_Selected
;
123 else if ( flags
& wxCONTROL_DISABLED
)
124 state
= IndicatorState_Disabled
;
125 else if ( flags
& wxCONTROL_PRESSED
)
126 state
= IndicatorState_Pressed
;
128 state
= IndicatorState_Normal
;
130 status
= flags
& wxCONTROL_CHECKED
? IndicatorStatus_Checked
131 : flags
& wxCONTROL_UNDETERMINED
132 ? IndicatorStatus_Undetermined
133 : IndicatorStatus_Unchecked
;
137 wxStdRenderer::ArrowDirection
wxStdRenderer::GetArrowDirection(wxDirection dir
)
154 wxFAIL_MSG(_T("unknown arrow direction"));
160 // ----------------------------------------------------------------------------
162 // ----------------------------------------------------------------------------
164 void wxStdRenderer::DrawBackground(wxDC
& dc
,
178 colBg
= m_scheme
->GetBackground(window
);
182 colBg
= wxSCHEME_COLOUR(m_scheme
, CONTROL
);
185 DrawSolidRect(dc
, colBg
, rect
);
189 void wxStdRenderer::DrawButtonSurface(wxDC
& dc
,
194 DrawBackground(dc
, col
, rect
, flags
);
197 // ----------------------------------------------------------------------------
199 // ----------------------------------------------------------------------------
202 wxStdRenderer::DrawFocusRect(wxDC
& dc
, const wxRect
& rect
, int WXUNUSED(flags
))
204 // draw the pixels manually because the "dots" in wxPen with wxDOT style
205 // may be short traits and not really dots
207 // note that to behave in the same manner as DrawRect(), we must exclude
208 // the bottom and right borders from the rectangle
209 wxCoord x1
= rect
.GetLeft(),
211 x2
= rect
.GetRight(),
212 y2
= rect
.GetBottom();
214 dc
.SetPen(m_penBlack
);
216 // this seems to be closer than what Windows does than wxINVERT although
217 // I'm still not sure if it's correct
218 dc
.SetLogicalFunction(wxAND_REVERSE
);
221 for ( z
= x1
+ 1; z
< x2
; z
+= 2 )
222 dc
.DrawPoint(z
, rect
.GetTop());
224 wxCoord shift
= z
== x2
? 0 : 1;
225 for ( z
= y1
+ shift
; z
< y2
; z
+= 2 )
228 shift
= z
== y2
? 0 : 1;
229 for ( z
= x2
- shift
; z
> x1
; z
-= 2 )
232 shift
= z
== x1
? 0 : 1;
233 for ( z
= y2
- shift
; z
> y1
; z
-= 2 )
236 dc
.SetLogicalFunction(wxCOPY
);
239 void wxStdRenderer::DrawLabel(wxDC
& dc
,
240 const wxString
& label
,
247 DrawButtonLabel(dc
, label
, wxNullBitmap
, rect
, flags
,
248 alignment
, indexAccel
, rectBounds
);
251 void wxStdRenderer::DrawButtonLabel(wxDC
& dc
,
252 const wxString
& label
,
253 const wxBitmap
& image
,
260 wxDCTextColourChanger
clrChanger(dc
);
262 wxRect rectLabel
= rect
;
263 if ( !label
.empty() && (flags
& wxCONTROL_DISABLED
) )
265 if ( flags
& wxCONTROL_PRESSED
)
267 // shift the label if a button is pressed
268 rectLabel
.Offset(1, 1);
271 // draw shadow of the text
272 clrChanger
.Set(m_penHighlight
.GetColour());
273 wxRect rectShadow
= rect
;
274 rectShadow
.Offset(1, 1);
275 dc
.DrawLabel(label
, rectShadow
, alignment
, indexAccel
);
277 // make the main label text grey
278 clrChanger
.Set(m_penDarkGrey
.GetColour());
280 if ( flags
& wxCONTROL_FOCUSED
)
282 // leave enough space for the focus rect
283 rectLabel
.Inflate(-2);
287 dc
.DrawLabel(label
, image
, rectLabel
, alignment
, indexAccel
, rectBounds
);
289 if ( !label
.empty() && (flags
& wxCONTROL_FOCUSED
) )
291 rectLabel
.Inflate(-1);
293 DrawFocusRect(dc
, rectLabel
);
297 // ----------------------------------------------------------------------------
299 // ----------------------------------------------------------------------------
302 We implement standard-looking 3D borders which have the following appearance:
306 WWWWWWWWWWWWWWWWWWWWWWB
307 WHHHHHHHHHHHHHHHHHHHHGB
308 WH GB W = white (HILIGHT)
309 WH GB H = light grey (LIGHT)
310 WH GB G = dark grey (SHADOI)
311 WH GB B = black (DKSHADOI)
314 WGGGGGGGGGGGGGGGGGGGGGB
315 BBBBBBBBBBBBBBBBBBBBBBB
317 The sunken border looks like this:
319 GGGGGGGGGGGGGGGGGGGGGGW
320 GBBBBBBBBBBBBBBBBBBBBHW
327 GHHHHHHHHHHHHHHHHHHHHHW
328 WWWWWWWWWWWWWWWWWWWWWWW
330 The static border (used for the controls which don't get focus) is like
333 GGGGGGGGGGGGGGGGGGGGGGW
341 WWWWWWWWWWWWWWWWWWWWWWW
343 The most complicated is the double border which is a combination of special
344 "anti-sunken" border and an extra border inside it:
346 HHHHHHHHHHHHHHHHHHHHHHB
347 HWWWWWWWWWWWWWWWWWWWWGB
348 HWHHHHHHHHHHHHHHHHHHHGB
353 HWHHHHHHHHHHHHHHHHHHHGB
354 HGGGGGGGGGGGGGGGGGGGGGB
355 BBBBBBBBBBBBBBBBBBBBBBB
357 And the simple border is, well, simple:
359 BBBBBBBBBBBBBBBBBBBBBBB
368 BBBBBBBBBBBBBBBBBBBBBBB
371 void wxStdRenderer::DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
)
373 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penBlack
);
374 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penDarkGrey
);
377 void wxStdRenderer::DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
)
379 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
380 DrawShadedRect(dc
, rect
, m_penBlack
, m_penLightGrey
);
383 void wxStdRenderer::DrawAntiSunkenBorder(wxDC
& dc
, wxRect
*rect
)
385 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penBlack
);
386 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
389 void wxStdRenderer::DrawBoxBorder(wxDC
& dc
, wxRect
*rect
)
391 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
392 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
395 void wxStdRenderer::DrawStaticBorder(wxDC
& dc
, wxRect
*rect
)
397 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
400 void wxStdRenderer::DrawExtraBorder(wxDC
& dc
, wxRect
*rect
)
402 DrawRect(dc
, rect
, m_penLightGrey
);
405 void wxStdRenderer::DrawBorder(wxDC
& dc
,
407 const wxRect
& rectTotal
,
411 wxRect rect
= rectTotal
;
415 case wxBORDER_SUNKEN
:
416 DrawSunkenBorder(dc
, &rect
);
419 case wxBORDER_DOUBLE
:
420 DrawAntiSunkenBorder(dc
, &rect
);
421 DrawExtraBorder(dc
, &rect
);
424 case wxBORDER_STATIC
:
425 DrawStaticBorder(dc
, &rect
);
428 case wxBORDER_RAISED
:
429 DrawRaisedBorder(dc
, &rect
);
432 case wxBORDER_SIMPLE
:
433 DrawRect(dc
, &rect
, m_penBlack
);
437 wxFAIL_MSG(_T("unknown border type"));
440 case wxBORDER_DEFAULT
:
449 wxRect
wxStdRenderer::GetBorderDimensions(wxBorder border
) const
454 case wxBORDER_SIMPLE
:
455 case wxBORDER_STATIC
:
459 case wxBORDER_RAISED
:
460 case wxBORDER_SUNKEN
:
464 case wxBORDER_DOUBLE
:
469 wxFAIL_MSG(_T("unknown border type"));
472 case wxBORDER_DEFAULT
:
487 void wxStdRenderer::AdjustSize(wxSize
*size
, const wxWindow
*window
)
489 // take into account the border width
490 wxRect rectBorder
= GetBorderDimensions(window
->GetBorder());
491 size
->x
+= rectBorder
.x
+ rectBorder
.width
;
492 size
->y
+= rectBorder
.y
+ rectBorder
.height
;
495 bool wxStdRenderer::AreScrollbarsInsideBorder() const
500 wxCoord
wxStdRenderer::GetListboxItemHeight(wxCoord fontHeight
)
502 return fontHeight
+ 2*ITEM_MARGIN
;
505 void wxStdRenderer::DrawTextBorder(wxDC
& dc
,
511 DrawBorder(dc
, border
, rect
, flags
, rectIn
);
514 // ----------------------------------------------------------------------------
516 // ----------------------------------------------------------------------------
519 wxStdRenderer::DrawHorizontalLine(wxDC
& dc
, wxCoord y
, wxCoord x1
, wxCoord x2
)
521 dc
.SetPen(m_penDarkGrey
);
522 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
524 dc
.SetPen(m_penHighlight
);
526 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
530 wxStdRenderer::DrawVerticalLine(wxDC
& dc
, wxCoord x
, wxCoord y1
, wxCoord y2
)
532 dc
.SetPen(m_penDarkGrey
);
533 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
535 dc
.SetPen(m_penHighlight
);
537 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
540 void wxStdRenderer::DrawFrameWithoutLabel(wxDC
& dc
,
541 const wxRect
& rectFrame
,
542 const wxRect
& rectLabel
)
544 // draw left, bottom and right lines entirely
545 DrawVerticalLine(dc
, rectFrame
.GetLeft(),
546 rectFrame
.GetTop(), rectFrame
.GetBottom() - 2);
547 DrawHorizontalLine(dc
, rectFrame
.GetBottom() - 1,
548 rectFrame
.GetLeft(), rectFrame
.GetRight());
549 DrawVerticalLine(dc
, rectFrame
.GetRight() - 1,
550 rectFrame
.GetTop(), rectFrame
.GetBottom() - 1);
552 // and 2 parts of the top line
553 DrawHorizontalLine(dc
, rectFrame
.GetTop(),
554 rectFrame
.GetLeft() + 1, rectLabel
.GetLeft());
555 DrawHorizontalLine(dc
, rectFrame
.GetTop(),
556 rectLabel
.GetRight(), rectFrame
.GetRight() - 2);
559 void wxStdRenderer::DrawFrameWithLabel(wxDC
& dc
,
560 const wxString
& label
,
561 const wxRect
& rectFrame
,
562 const wxRect
& rectText
,
568 DrawLabel(dc
, label
, rectText
, flags
, alignment
, indexAccel
, &rectLabel
);
570 DrawFrameWithoutLabel(dc
, rectFrame
, rectLabel
);
573 void wxStdRenderer::DrawFrame(wxDC
& dc
,
574 const wxString
& label
,
580 wxCoord height
= 0; // of the label
581 wxRect rectFrame
= rect
;
582 if ( !label
.empty() )
584 // the text should touch the top border of the rect, so the frame
585 // itself should be lower
586 dc
.GetTextExtent(label
, NULL
, &height
);
587 rectFrame
.y
+= height
/ 2;
588 rectFrame
.height
-= height
/ 2;
590 // we have to draw each part of the frame individually as we can't
591 // erase the background beyond the label as it might contain some
592 // pixmap already, so drawing everything and then overwriting part of
593 // the frame with label doesn't work
595 // TODO: the +5 shouldn't be hard coded
597 rectText
.x
= rectFrame
.x
+ 5;
599 rectText
.width
= rectFrame
.width
- 7; // +2 border width
600 rectText
.height
= height
;
602 DrawFrameWithLabel(dc
, label
, rectFrame
, rectText
, flags
,
603 alignment
, indexAccel
);
607 DrawBoxBorder(dc
, &rectFrame
);
611 void wxStdRenderer::DrawItem(wxDC
& dc
,
612 const wxString
& label
,
616 wxDCTextColourChanger
colChanger(dc
);
618 if ( flags
& wxCONTROL_SELECTED
)
620 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
622 const wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
625 dc
.DrawRectangle(rect
);
628 // horizontal adjustment is arbitrary
629 wxRect rectText
= rect
;
630 rectText
.Deflate(2, ITEM_MARGIN
);
631 dc
.DrawLabel(label
, wxNullBitmap
, rectText
);
633 if ( flags
& wxCONTROL_FOCUSED
)
635 DrawFocusRect(dc
, rect
, flags
);
639 void wxStdRenderer::DrawCheckItemBitmap(wxDC
& dc
,
640 const wxBitmap
& bitmap
,
644 DrawCheckButton(dc
, wxEmptyString
, bitmap
, rect
, flags
);
647 void wxStdRenderer::DrawCheckItem(wxDC
& dc
,
648 const wxString
& label
,
649 const wxBitmap
& bitmap
,
653 wxRect rectBitmap
= rect
;
654 rectBitmap
.width
= GetCheckBitmapSize().x
;
655 DrawCheckItemBitmap(dc
, bitmap
, rectBitmap
, flags
);
657 wxRect rectLabel
= rect
;
658 wxCoord shift
= rectBitmap
.width
+ 2*GetCheckItemMargin();
659 rectLabel
.x
+= shift
;
660 rectLabel
.width
-= shift
;
661 DrawItem(dc
, label
, rectLabel
, flags
);
664 // ----------------------------------------------------------------------------
665 // check and radio bitmaps
666 // ----------------------------------------------------------------------------
668 void wxStdRenderer::DrawCheckButton(wxDC
& dc
,
669 const wxString
& label
,
670 const wxBitmap
& bitmap
,
676 wxBitmap
bmp(bitmap
.Ok() ? bitmap
: GetCheckBitmap(flags
));
678 DrawCheckOrRadioButton(dc
, label
, bmp
, rect
, flags
, align
, indexAccel
);
681 void wxStdRenderer::DrawRadioButton(wxDC
& dc
,
682 const wxString
& label
,
683 const wxBitmap
& bitmap
,
689 wxBitmap
bmp(bitmap
.Ok() ? bitmap
: GetRadioBitmap(flags
));
691 DrawCheckOrRadioButton(dc
, label
, bmp
, rect
, flags
, align
, indexAccel
);
694 void wxStdRenderer::DrawCheckOrRadioButton(wxDC
& dc
,
695 const wxString
& label
,
696 const wxBitmap
& bitmap
,
702 // calculate the position of the bitmap and of the label
703 wxCoord heightBmp
= bitmap
.GetHeight();
705 yBmp
= rect
.y
+ (rect
.height
- heightBmp
) / 2;
708 dc
.GetMultiLineTextExtent(label
, NULL
, &rectLabel
.height
);
709 rectLabel
.y
= rect
.y
+ (rect
.height
- rectLabel
.height
) / 2;
711 // align label vertically with the bitmap - looks nicer like this
712 rectLabel
.y
-= (rectLabel
.height
- heightBmp
) % 2;
714 // calc horz position
715 if ( align
== wxALIGN_RIGHT
)
717 xBmp
= rect
.GetRight() - bitmap
.GetWidth();
718 rectLabel
.x
= rect
.x
+ 3;
719 rectLabel
.SetRight(xBmp
);
721 else // normal (checkbox to the left of the text) case
724 rectLabel
.x
= xBmp
+ bitmap
.GetWidth() + 5;
725 rectLabel
.SetRight(rect
.GetRight());
728 dc
.DrawBitmap(bitmap
, xBmp
, yBmp
, true /* use mask */);
730 DrawLabel(dc
, label
, rectLabel
, flags
,
731 wxALIGN_LEFT
| wxALIGN_TOP
, indexAccel
);
736 void wxStdRenderer::DrawTextLine(wxDC
& dc
,
737 const wxString
& text
,
743 if ( (selStart
== -1) || !(flags
& wxCONTROL_FOCUSED
) )
745 // just draw it as is
746 dc
.DrawText(text
, rect
.x
, rect
.y
);
748 else // we have selection
753 // draw the part before selection
754 wxString
s(text
, (size_t)selStart
);
757 dc
.DrawText(s
, x
, rect
.y
);
759 dc
.GetTextExtent(s
, &width
, NULL
);
763 // draw the selection itself
764 s
= wxString(text
.c_str() + selStart
, text
.c_str() + selEnd
);
767 wxColour colFg
= dc
.GetTextForeground(),
768 colBg
= dc
.GetTextBackground();
769 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
770 dc
.SetTextBackground(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
));
771 dc
.SetBackgroundMode(wxSOLID
);
773 dc
.DrawText(s
, x
, rect
.y
);
774 dc
.GetTextExtent(s
, &width
, NULL
);
777 dc
.SetBackgroundMode(wxTRANSPARENT
);
778 dc
.SetTextBackground(colBg
);
779 dc
.SetTextForeground(colFg
);
782 // draw the final part
783 s
= text
.c_str() + selEnd
;
786 dc
.DrawText(s
, x
, rect
.y
);
791 void wxStdRenderer::DrawLineWrapMark(wxDC
& WXUNUSED(dc
),
792 const wxRect
& WXUNUSED(rect
))
794 // nothing by default
797 int wxStdRenderer::GetTextBorderWidth(const wxTextCtrl
* WXUNUSED(text
)) const
803 wxStdRenderer::GetTextTotalArea(const wxTextCtrl
*text
, const wxRect
& rect
) const
805 wxRect rectTotal
= rect
;
806 rectTotal
.Inflate(GetTextBorderWidth(text
));
810 wxRect
wxStdRenderer::GetTextClientArea(const wxTextCtrl
*text
,
812 wxCoord
*extraSpaceBeyond
) const
814 wxRect rectText
= rect
;
815 rectText
.Deflate(GetTextBorderWidth(text
));
817 if ( extraSpaceBeyond
)
818 *extraSpaceBeyond
= 0;
823 #endif // wxUSE_TEXTCTRL
825 // ----------------------------------------------------------------------------
826 // scrollbars drawing
827 // ----------------------------------------------------------------------------
829 void wxStdRenderer::DrawScrollbarArrow(wxDC
& dc
,
834 DrawArrow(dc
, dir
, rect
, flags
);
837 void wxStdRenderer::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
839 DrawSolidRect(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
842 // ----------------------------------------------------------------------------
844 // ----------------------------------------------------------------------------
848 wxSize
wxStdRenderer::GetStatusBarBorders() const
850 // Rendered border may be different depending on field's style, we use
851 // the largest value so that any field certainly fits into the borders
853 wxRect raised
= GetBorderDimensions(wxBORDER_RAISED
);
854 wxRect flat
= GetBorderDimensions(wxBORDER_STATIC
);
855 wxASSERT_MSG( raised
.x
== raised
.width
&& raised
.y
== raised
.height
&&
856 flat
.x
== flat
.width
&& flat
.y
== flat
.height
,
857 _T("this code expects uniform borders, you must override GetStatusBarBorders") );
859 // take the larger of flat/raised values:
860 wxSize
border(wxMax(raised
.x
, flat
.x
), wxMax(raised
.y
, flat
.y
));
865 wxCoord
wxStdRenderer::GetStatusBarBorderBetweenFields() const
870 wxSize
wxStdRenderer::GetStatusBarFieldMargins() const
875 void wxStdRenderer::DrawStatusField(wxDC
& dc
,
877 const wxString
& label
,
883 if ( style
== wxSB_RAISED
)
884 DrawBorder(dc
, wxBORDER_RAISED
, rect
, flags
, &rectIn
);
885 else if ( style
!= wxSB_FLAT
)
886 DrawBorder(dc
, wxBORDER_STATIC
, rect
, flags
, &rectIn
);
888 rectIn
.Deflate(GetStatusBarFieldMargins());
890 wxDCClipper
clipper(dc
, rectIn
);
891 DrawLabel(dc
, label
, rectIn
, flags
, wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
894 #endif // wxUSE_STATUSBAR
896 // ----------------------------------------------------------------------------
898 // ----------------------------------------------------------------------------
900 int wxStdRenderer::HitTestFrame(const wxRect
& rect
, const wxPoint
& pt
, int flags
) const
902 wxRect client
= GetFrameClientArea(rect
, flags
);
904 if ( client
.Contains(pt
) )
905 return wxHT_TOPLEVEL_CLIENT_AREA
;
907 if ( flags
& wxTOPLEVEL_TITLEBAR
)
909 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
911 if ( flags
& wxTOPLEVEL_ICON
)
913 if ( wxRect(client
.GetPosition(), GetFrameIconSize()).Contains(pt
) )
914 return wxHT_TOPLEVEL_ICON
;
917 wxRect
btnRect(client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
,
918 client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2,
919 FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
921 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
923 if ( btnRect
.Contains(pt
) )
924 return wxHT_TOPLEVEL_BUTTON_CLOSE
;
925 btnRect
.x
-= FRAME_BUTTON_WIDTH
+ 2;
927 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
929 if ( btnRect
.Contains(pt
) )
930 return wxHT_TOPLEVEL_BUTTON_MAXIMIZE
;
931 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
933 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
935 if ( btnRect
.Contains(pt
) )
936 return wxHT_TOPLEVEL_BUTTON_RESTORE
;
937 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
939 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
941 if ( btnRect
.Contains(pt
) )
942 return wxHT_TOPLEVEL_BUTTON_ICONIZE
;
943 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
945 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
947 if ( btnRect
.Contains(pt
) )
948 return wxHT_TOPLEVEL_BUTTON_HELP
;
949 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
952 if ( pt
.y
>= client
.y
&& pt
.y
< client
.y
+ FRAME_TITLEBAR_HEIGHT
)
953 return wxHT_TOPLEVEL_TITLEBAR
;
956 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
958 // we are certainly at one of borders, let's decide which one:
961 // dirty trick, relies on the way wxHT_TOPLEVEL_XXX are defined!
962 if ( pt
.x
< client
.x
)
963 border
|= wxHT_TOPLEVEL_BORDER_W
;
964 else if ( pt
.x
>= client
.width
+ client
.x
)
965 border
|= wxHT_TOPLEVEL_BORDER_E
;
966 if ( pt
.y
< client
.y
)
967 border
|= wxHT_TOPLEVEL_BORDER_N
;
968 else if ( pt
.y
>= client
.height
+ client
.y
)
969 border
|= wxHT_TOPLEVEL_BORDER_S
;
976 void wxStdRenderer::DrawFrameTitleBar(wxDC
& dc
,
978 const wxString
& title
,
982 int specialButtonFlags
)
984 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
986 DrawFrameBorder(dc
, rect
, flags
);
988 if ( flags
& wxTOPLEVEL_TITLEBAR
)
990 DrawFrameBackground(dc
, rect
, flags
);
991 if ( flags
& wxTOPLEVEL_ICON
)
992 DrawFrameIcon(dc
, rect
, icon
, flags
);
993 DrawFrameTitle(dc
, rect
, title
, flags
);
995 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
997 x
= client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
;
998 y
= client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2;
1000 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
1002 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_CLOSE
,
1003 (specialButton
== wxTOPLEVEL_BUTTON_CLOSE
) ?
1004 specialButtonFlags
: 0);
1005 x
-= FRAME_BUTTON_WIDTH
+ 2;
1007 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
1009 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_MAXIMIZE
,
1010 (specialButton
== wxTOPLEVEL_BUTTON_MAXIMIZE
) ?
1011 specialButtonFlags
: 0);
1012 x
-= FRAME_BUTTON_WIDTH
;
1014 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
1016 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_RESTORE
,
1017 (specialButton
== wxTOPLEVEL_BUTTON_RESTORE
) ?
1018 specialButtonFlags
: 0);
1019 x
-= FRAME_BUTTON_WIDTH
;
1021 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
1023 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_ICONIZE
,
1024 (specialButton
== wxTOPLEVEL_BUTTON_ICONIZE
) ?
1025 specialButtonFlags
: 0);
1026 x
-= FRAME_BUTTON_WIDTH
;
1028 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
1030 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_HELP
,
1031 (specialButton
== wxTOPLEVEL_BUTTON_HELP
) ?
1032 specialButtonFlags
: 0);
1037 void wxStdRenderer::DrawFrameBorder(wxDC
& dc
, const wxRect
& rect
, int flags
)
1039 if ( !(flags
& wxTOPLEVEL_BORDER
) )
1044 DrawAntiSunkenBorder(dc
, &r
);
1045 DrawExtraBorder(dc
, &r
);
1046 if ( flags
& wxTOPLEVEL_RESIZEABLE
)
1047 DrawExtraBorder(dc
, &r
);
1050 void wxStdRenderer::DrawFrameBackground(wxDC
& dc
, const wxRect
& rect
, int flags
)
1052 if ( !(flags
& wxTOPLEVEL_TITLEBAR
) )
1055 wxColour col
= m_scheme
->Get(flags
& wxTOPLEVEL_ACTIVE
1056 ? wxColourScheme::TITLEBAR_ACTIVE
1057 : wxColourScheme::TITLEBAR
);
1059 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1060 r
.height
= FRAME_TITLEBAR_HEIGHT
;
1062 DrawBackground(dc
, col
, r
);
1065 void wxStdRenderer::DrawFrameTitle(wxDC
& dc
,
1067 const wxString
& title
,
1070 wxColour col
= m_scheme
->Get(flags
& wxTOPLEVEL_ACTIVE
1071 ? wxColourScheme::TITLEBAR_ACTIVE_TEXT
1072 : wxColourScheme::TITLEBAR_TEXT
);
1073 dc
.SetTextForeground(col
);
1075 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1076 r
.height
= FRAME_TITLEBAR_HEIGHT
;
1077 if ( flags
& wxTOPLEVEL_ICON
)
1079 r
.x
+= FRAME_TITLEBAR_HEIGHT
;
1080 r
.width
-= FRAME_TITLEBAR_HEIGHT
+ 2;
1088 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
1089 r
.width
-= FRAME_BUTTON_WIDTH
+ 2;
1090 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
1091 r
.width
-= FRAME_BUTTON_WIDTH
;
1092 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
1093 r
.width
-= FRAME_BUTTON_WIDTH
;
1094 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
1095 r
.width
-= FRAME_BUTTON_WIDTH
;
1096 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
1097 r
.width
-= FRAME_BUTTON_WIDTH
;
1099 dc
.SetFont(m_titlebarFont
);
1103 dc
.GetTextExtent(title
, &textW
, NULL
);
1104 if ( textW
> r
.width
)
1106 // text is too big, let's shorten it and add "..." after it:
1107 size_t len
= title
.length();
1108 wxCoord WSoFar
, letterW
;
1110 dc
.GetTextExtent(wxT("..."), &WSoFar
, NULL
);
1111 if ( WSoFar
> r
.width
)
1113 // not enough space to draw anything
1118 for (size_t i
= 0; i
< len
; i
++)
1120 dc
.GetTextExtent(title
[i
], &letterW
, NULL
);
1121 if ( letterW
+ WSoFar
> r
.width
)
1128 else // no need to truncate the title
1133 dc
.DrawLabel(s
, wxNullBitmap
, r
, wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
1136 void wxStdRenderer::DrawFrameIcon(wxDC
& dc
,
1143 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1144 dc
.DrawIcon(icon
, r
.x
, r
.y
);
1148 void wxStdRenderer::DrawFrameButton(wxDC
& dc
,
1149 wxCoord x
, wxCoord y
,
1153 FrameButtonType idx
;
1156 case wxTOPLEVEL_BUTTON_CLOSE
: idx
= FrameButton_Close
; break;
1157 case wxTOPLEVEL_BUTTON_MAXIMIZE
: idx
= FrameButton_Maximize
; break;
1158 case wxTOPLEVEL_BUTTON_ICONIZE
: idx
= FrameButton_Minimize
; break;
1159 case wxTOPLEVEL_BUTTON_RESTORE
: idx
= FrameButton_Restore
; break;
1160 case wxTOPLEVEL_BUTTON_HELP
: idx
= FrameButton_Help
; break;
1162 wxFAIL_MSG(wxT("incorrect button specification"));
1166 wxBitmap bmp
= GetFrameButtonBitmap(idx
);
1170 wxRect
rectBtn(x
, y
, FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
1171 if ( flags
& wxCONTROL_PRESSED
)
1173 DrawSunkenBorder(dc
, &rectBtn
);
1175 rectBtn
.Offset(1, 1);
1179 DrawRaisedBorder(dc
, &rectBtn
);
1182 DrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rectBtn
);
1184 wxRect
rectBmp(0, 0, bmp
.GetWidth(), bmp
.GetHeight());
1185 dc
.DrawBitmap(bmp
, rectBmp
.CentreIn(rectBtn
).GetPosition(), true);
1188 int wxStdRenderer::GetFrameBorderWidth(int flags
) const
1190 return flags
& wxTOPLEVEL_RESIZEABLE
? 4 : 3;
1194 wxRect
wxStdRenderer::GetFrameClientArea(const wxRect
& rect
, int flags
) const
1198 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1200 r
.Inflate(-GetFrameBorderWidth(flags
));
1203 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1205 r
.y
+= FRAME_TITLEBAR_HEIGHT
;
1206 r
.height
-= FRAME_TITLEBAR_HEIGHT
;
1213 wxStdRenderer::GetFrameTotalSize(const wxSize
& clientSize
, int flags
) const
1215 wxSize
s(clientSize
);
1217 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1219 s
.IncBy(2*GetFrameBorderWidth(flags
));
1222 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1223 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
1228 wxSize
wxStdRenderer::GetFrameMinSize(int flags
) const
1232 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1234 s
.IncBy(2*GetFrameBorderWidth(flags
));
1237 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1239 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
1241 if ( flags
& wxTOPLEVEL_ICON
)
1242 s
.x
+= FRAME_TITLEBAR_HEIGHT
+ 2;
1243 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
1244 s
.x
+= FRAME_BUTTON_WIDTH
+ 2;
1245 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
1246 s
.x
+= FRAME_BUTTON_WIDTH
;
1247 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
1248 s
.x
+= FRAME_BUTTON_WIDTH
;
1249 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
1250 s
.x
+= FRAME_BUTTON_WIDTH
;
1251 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
1252 s
.x
+= FRAME_BUTTON_WIDTH
;
1258 wxSize
wxStdRenderer::GetFrameIconSize() const
1260 return wxSize(16, 16);