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(wxT("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(wxWindow
* WXUNUSED(win
), 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(NULL
, 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
:
417 DrawSunkenBorder(dc
, &rect
);
420 // wxBORDER_DOUBLE and wxBORDER_THEME are currently the same value.
422 case wxBORDER_DOUBLE
:
423 DrawAntiSunkenBorder(dc
, &rect
);
424 DrawExtraBorder(dc
, &rect
);
428 case wxBORDER_STATIC
:
429 DrawStaticBorder(dc
, &rect
);
432 case wxBORDER_RAISED
:
433 DrawRaisedBorder(dc
, &rect
);
436 case wxBORDER_SIMPLE
:
437 DrawRect(dc
, &rect
, m_penBlack
);
441 wxFAIL_MSG(wxT("unknown border type"));
444 case wxBORDER_DEFAULT
:
453 wxRect
wxStdRenderer::GetBorderDimensions(wxBorder border
) const
458 case wxBORDER_SIMPLE
:
459 case wxBORDER_STATIC
:
463 case wxBORDER_RAISED
:
464 case wxBORDER_SUNKEN
:
469 case wxBORDER_DOUBLE
:
474 wxFAIL_MSG(wxT("unknown border type"));
477 case wxBORDER_DEFAULT
:
492 void wxStdRenderer::AdjustSize(wxSize
*size
, const wxWindow
*window
)
494 // take into account the border width
495 wxRect rectBorder
= GetBorderDimensions(window
->GetBorder());
496 size
->x
+= rectBorder
.x
+ rectBorder
.width
;
497 size
->y
+= rectBorder
.y
+ rectBorder
.height
;
500 bool wxStdRenderer::AreScrollbarsInsideBorder() const
505 wxCoord
wxStdRenderer::GetListboxItemHeight(wxCoord fontHeight
)
507 return fontHeight
+ 2*ITEM_MARGIN
;
510 void wxStdRenderer::DrawTextBorder(wxDC
& dc
,
516 DrawBorder(dc
, border
, rect
, flags
, rectIn
);
519 // ----------------------------------------------------------------------------
521 // ----------------------------------------------------------------------------
524 wxStdRenderer::DrawHorizontalLine(wxDC
& dc
, wxCoord y
, wxCoord x1
, wxCoord x2
)
526 dc
.SetPen(m_penDarkGrey
);
527 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
529 dc
.SetPen(m_penHighlight
);
531 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
535 wxStdRenderer::DrawVerticalLine(wxDC
& dc
, wxCoord x
, wxCoord y1
, wxCoord y2
)
537 dc
.SetPen(m_penDarkGrey
);
538 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
540 dc
.SetPen(m_penHighlight
);
542 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
545 void wxStdRenderer::DrawFrameWithoutLabel(wxDC
& dc
,
546 const wxRect
& rectFrame
,
547 const wxRect
& rectLabel
)
549 // draw left, bottom and right lines entirely
550 DrawVerticalLine(dc
, rectFrame
.GetLeft(),
551 rectFrame
.GetTop(), rectFrame
.GetBottom() - 2);
552 DrawHorizontalLine(dc
, rectFrame
.GetBottom() - 1,
553 rectFrame
.GetLeft(), rectFrame
.GetRight());
554 DrawVerticalLine(dc
, rectFrame
.GetRight() - 1,
555 rectFrame
.GetTop(), rectFrame
.GetBottom() - 1);
557 // and 2 parts of the top line
558 DrawHorizontalLine(dc
, rectFrame
.GetTop(),
559 rectFrame
.GetLeft() + 1, rectLabel
.GetLeft());
560 DrawHorizontalLine(dc
, rectFrame
.GetTop(),
561 rectLabel
.GetRight(), rectFrame
.GetRight() - 2);
564 void wxStdRenderer::DrawFrameWithLabel(wxDC
& dc
,
565 const wxString
& label
,
566 const wxRect
& rectFrame
,
567 const wxRect
& rectText
,
573 DrawLabel(dc
, label
, rectText
, flags
, alignment
, indexAccel
, &rectLabel
);
575 DrawFrameWithoutLabel(dc
, rectFrame
, rectLabel
);
578 void wxStdRenderer::DrawFrame(wxDC
& dc
,
579 const wxString
& label
,
585 wxCoord height
= 0; // of the label
586 wxRect rectFrame
= rect
;
587 if ( !label
.empty() )
589 // the text should touch the top border of the rect, so the frame
590 // itself should be lower
591 dc
.GetTextExtent(label
, NULL
, &height
);
592 rectFrame
.y
+= height
/ 2;
593 rectFrame
.height
-= height
/ 2;
595 // we have to draw each part of the frame individually as we can't
596 // erase the background beyond the label as it might contain some
597 // pixmap already, so drawing everything and then overwriting part of
598 // the frame with label doesn't work
600 // TODO: the +5 shouldn't be hard coded
602 rectText
.x
= rectFrame
.x
+ 5;
604 rectText
.width
= rectFrame
.width
- 7; // +2 border width
605 rectText
.height
= height
;
607 DrawFrameWithLabel(dc
, label
, rectFrame
, rectText
, flags
,
608 alignment
, indexAccel
);
612 DrawBoxBorder(dc
, &rectFrame
);
616 void wxStdRenderer::DrawItem(wxDC
& dc
,
617 const wxString
& label
,
621 wxDCTextColourChanger
colChanger(dc
);
623 if ( flags
& wxCONTROL_SELECTED
)
625 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
627 const wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
630 dc
.DrawRectangle(rect
);
633 // horizontal adjustment is arbitrary
634 wxRect rectText
= rect
;
635 rectText
.Deflate(2, ITEM_MARGIN
);
636 dc
.DrawLabel(label
, wxNullBitmap
, rectText
);
638 if ( flags
& wxCONTROL_FOCUSED
)
640 DrawFocusRect(NULL
, dc
, rect
, flags
);
644 void wxStdRenderer::DrawCheckItemBitmap(wxDC
& dc
,
645 const wxBitmap
& bitmap
,
649 DrawCheckButton(dc
, wxEmptyString
, bitmap
, rect
, flags
);
652 void wxStdRenderer::DrawCheckItem(wxDC
& dc
,
653 const wxString
& label
,
654 const wxBitmap
& bitmap
,
658 wxRect rectBitmap
= rect
;
659 rectBitmap
.width
= GetCheckBitmapSize().x
;
660 DrawCheckItemBitmap(dc
, bitmap
, rectBitmap
, flags
);
662 wxRect rectLabel
= rect
;
663 wxCoord shift
= rectBitmap
.width
+ 2*GetCheckItemMargin();
664 rectLabel
.x
+= shift
;
665 rectLabel
.width
-= shift
;
666 DrawItem(dc
, label
, rectLabel
, flags
);
669 // ----------------------------------------------------------------------------
670 // check and radio bitmaps
671 // ----------------------------------------------------------------------------
673 void wxStdRenderer::DrawCheckButton(wxDC
& dc
,
674 const wxString
& label
,
675 const wxBitmap
& bitmap
,
682 DrawCheckOrRadioButton(dc
, label
, bitmap
, rect
, flags
, align
, indexAccel
);
684 DrawCheckOrRadioButton(dc
, label
, GetCheckBitmap(flags
), rect
, flags
, align
, indexAccel
);
687 void wxStdRenderer::DrawRadioButton(wxDC
& dc
,
688 const wxString
& label
,
689 const wxBitmap
& bitmap
,
696 DrawCheckOrRadioButton(dc
, label
, bitmap
, rect
, flags
, align
, indexAccel
);
698 DrawCheckOrRadioButton(dc
, label
, GetRadioBitmap(flags
), rect
, flags
, align
, indexAccel
);
702 void wxStdRenderer::DrawCheckOrRadioButton(wxDC
& dc
,
703 const wxString
& label
,
704 const wxBitmap
& bitmap
,
710 // calculate the position of the bitmap and of the label
711 wxCoord heightBmp
= bitmap
.GetHeight();
713 yBmp
= rect
.y
+ (rect
.height
- heightBmp
) / 2;
716 dc
.GetMultiLineTextExtent(label
, NULL
, &rectLabel
.height
);
717 rectLabel
.y
= rect
.y
+ (rect
.height
- rectLabel
.height
) / 2;
719 // align label vertically with the bitmap - looks nicer like this
720 rectLabel
.y
-= (rectLabel
.height
- heightBmp
) % 2;
722 // calc horz position
723 if ( align
== wxALIGN_RIGHT
)
725 xBmp
= rect
.GetRight() - bitmap
.GetWidth();
726 rectLabel
.x
= rect
.x
+ 3;
727 rectLabel
.SetRight(xBmp
);
729 else // normal (checkbox to the left of the text) case
732 rectLabel
.x
= xBmp
+ bitmap
.GetWidth() + 5;
733 rectLabel
.SetRight(rect
.GetRight());
736 dc
.DrawBitmap(bitmap
, xBmp
, yBmp
, true /* use mask */);
738 DrawLabel(dc
, label
, rectLabel
, flags
,
739 wxALIGN_LEFT
| wxALIGN_TOP
, indexAccel
);
744 void wxStdRenderer::DrawTextLine(wxDC
& dc
,
745 const wxString
& text
,
751 if ( (selStart
== -1) || !(flags
& wxCONTROL_FOCUSED
) )
753 // just draw it as is
754 dc
.DrawText(text
, rect
.x
, rect
.y
);
756 else // we have selection
761 // draw the part before selection
762 wxString
s(text
, (size_t)selStart
);
765 dc
.DrawText(s
, x
, rect
.y
);
767 dc
.GetTextExtent(s
, &width
, NULL
);
771 // draw the selection itself
772 s
= wxString(text
.c_str() + selStart
, text
.c_str() + selEnd
);
775 wxColour colFg
= dc
.GetTextForeground(),
776 colBg
= dc
.GetTextBackground();
777 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
778 dc
.SetTextBackground(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
));
779 dc
.SetBackgroundMode(wxSOLID
);
781 dc
.DrawText(s
, x
, rect
.y
);
782 dc
.GetTextExtent(s
, &width
, NULL
);
785 dc
.SetBackgroundMode(wxTRANSPARENT
);
786 dc
.SetTextBackground(colBg
);
787 dc
.SetTextForeground(colFg
);
790 // draw the final part
791 s
= text
.c_str() + selEnd
;
794 dc
.DrawText(s
, x
, rect
.y
);
799 void wxStdRenderer::DrawLineWrapMark(wxDC
& WXUNUSED(dc
),
800 const wxRect
& WXUNUSED(rect
))
802 // nothing by default
805 int wxStdRenderer::GetTextBorderWidth(const wxTextCtrl
* WXUNUSED(text
)) const
811 wxStdRenderer::GetTextTotalArea(const wxTextCtrl
*text
, const wxRect
& rect
) const
813 wxRect rectTotal
= rect
;
814 rectTotal
.Inflate(GetTextBorderWidth(text
));
818 wxRect
wxStdRenderer::GetTextClientArea(const wxTextCtrl
*text
,
820 wxCoord
*extraSpaceBeyond
) const
822 wxRect rectText
= rect
;
823 rectText
.Deflate(GetTextBorderWidth(text
));
825 if ( extraSpaceBeyond
)
826 *extraSpaceBeyond
= 0;
831 #endif // wxUSE_TEXTCTRL
833 // ----------------------------------------------------------------------------
834 // scrollbars drawing
835 // ----------------------------------------------------------------------------
837 void wxStdRenderer::DrawScrollbarArrow(wxDC
& dc
,
842 DrawArrow(dc
, dir
, rect
, flags
);
845 void wxStdRenderer::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
847 DrawSolidRect(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
850 // ----------------------------------------------------------------------------
852 // ----------------------------------------------------------------------------
856 wxSize
wxStdRenderer::GetStatusBarBorders() const
858 // Rendered border may be different depending on field's style, we use
859 // the largest value so that any field certainly fits into the borders
861 wxRect raised
= GetBorderDimensions(wxBORDER_RAISED
);
862 wxRect flat
= GetBorderDimensions(wxBORDER_STATIC
);
863 wxASSERT_MSG( raised
.x
== raised
.width
&& raised
.y
== raised
.height
&&
864 flat
.x
== flat
.width
&& flat
.y
== flat
.height
,
865 wxT("this code expects uniform borders, you must override GetStatusBarBorders") );
867 // take the larger of flat/raised values:
868 wxSize
border(wxMax(raised
.x
, flat
.x
), wxMax(raised
.y
, flat
.y
));
873 wxCoord
wxStdRenderer::GetStatusBarBorderBetweenFields() const
878 wxSize
wxStdRenderer::GetStatusBarFieldMargins() const
883 void wxStdRenderer::DrawStatusField(wxDC
& dc
,
885 const wxString
& label
,
891 if ( style
== wxSB_RAISED
)
892 DrawBorder(dc
, wxBORDER_RAISED
, rect
, flags
, &rectIn
);
893 else if ( style
!= wxSB_FLAT
)
894 DrawBorder(dc
, wxBORDER_STATIC
, rect
, flags
, &rectIn
);
898 rectIn
.Deflate(GetStatusBarFieldMargins());
900 wxDCClipper
clipper(dc
, rectIn
);
901 DrawLabel(dc
, label
, rectIn
, flags
, wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
904 #endif // wxUSE_STATUSBAR
906 // ----------------------------------------------------------------------------
908 // ----------------------------------------------------------------------------
910 int wxStdRenderer::HitTestFrame(const wxRect
& rect
, const wxPoint
& pt
, int flags
) const
912 wxRect client
= GetFrameClientArea(rect
, flags
);
914 if ( client
.Contains(pt
) )
915 return wxHT_TOPLEVEL_CLIENT_AREA
;
917 if ( flags
& wxTOPLEVEL_TITLEBAR
)
919 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
921 if ( flags
& wxTOPLEVEL_ICON
)
923 if ( wxRect(client
.GetPosition(), GetFrameIconSize()).Contains(pt
) )
924 return wxHT_TOPLEVEL_ICON
;
927 wxRect
btnRect(client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
,
928 client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2,
929 FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
931 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
933 if ( btnRect
.Contains(pt
) )
934 return wxHT_TOPLEVEL_BUTTON_CLOSE
;
935 btnRect
.x
-= FRAME_BUTTON_WIDTH
+ 2;
937 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
939 if ( btnRect
.Contains(pt
) )
940 return wxHT_TOPLEVEL_BUTTON_MAXIMIZE
;
941 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
943 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
945 if ( btnRect
.Contains(pt
) )
946 return wxHT_TOPLEVEL_BUTTON_RESTORE
;
947 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
949 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
951 if ( btnRect
.Contains(pt
) )
952 return wxHT_TOPLEVEL_BUTTON_ICONIZE
;
953 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
955 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
957 if ( btnRect
.Contains(pt
) )
958 return wxHT_TOPLEVEL_BUTTON_HELP
;
959 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
962 if ( pt
.y
>= client
.y
&& pt
.y
< client
.y
+ FRAME_TITLEBAR_HEIGHT
)
963 return wxHT_TOPLEVEL_TITLEBAR
;
966 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
968 // we are certainly at one of borders, let's decide which one:
971 // dirty trick, relies on the way wxHT_TOPLEVEL_XXX are defined!
972 if ( pt
.x
< client
.x
)
973 border
|= wxHT_TOPLEVEL_BORDER_W
;
974 else if ( pt
.x
>= client
.width
+ client
.x
)
975 border
|= wxHT_TOPLEVEL_BORDER_E
;
976 if ( pt
.y
< client
.y
)
977 border
|= wxHT_TOPLEVEL_BORDER_N
;
978 else if ( pt
.y
>= client
.height
+ client
.y
)
979 border
|= wxHT_TOPLEVEL_BORDER_S
;
986 void wxStdRenderer::DrawFrameTitleBar(wxDC
& dc
,
988 const wxString
& title
,
992 int specialButtonFlags
)
994 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
996 DrawFrameBorder(dc
, rect
, flags
);
998 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1000 DrawFrameBackground(dc
, rect
, flags
);
1001 if ( flags
& wxTOPLEVEL_ICON
)
1002 DrawFrameIcon(dc
, rect
, icon
, flags
);
1003 DrawFrameTitle(dc
, rect
, title
, flags
);
1005 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1007 x
= client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
;
1008 y
= client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2;
1010 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
1012 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_CLOSE
,
1013 (specialButton
== wxTOPLEVEL_BUTTON_CLOSE
) ?
1014 specialButtonFlags
: 0);
1015 x
-= FRAME_BUTTON_WIDTH
+ 2;
1017 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
1019 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_MAXIMIZE
,
1020 (specialButton
== wxTOPLEVEL_BUTTON_MAXIMIZE
) ?
1021 specialButtonFlags
: 0);
1022 x
-= FRAME_BUTTON_WIDTH
;
1024 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
1026 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_RESTORE
,
1027 (specialButton
== wxTOPLEVEL_BUTTON_RESTORE
) ?
1028 specialButtonFlags
: 0);
1029 x
-= FRAME_BUTTON_WIDTH
;
1031 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
1033 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_ICONIZE
,
1034 (specialButton
== wxTOPLEVEL_BUTTON_ICONIZE
) ?
1035 specialButtonFlags
: 0);
1036 x
-= FRAME_BUTTON_WIDTH
;
1038 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
1040 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_HELP
,
1041 (specialButton
== wxTOPLEVEL_BUTTON_HELP
) ?
1042 specialButtonFlags
: 0);
1047 void wxStdRenderer::DrawFrameBorder(wxDC
& dc
, const wxRect
& rect
, int flags
)
1049 if ( !(flags
& wxTOPLEVEL_BORDER
) )
1054 DrawAntiSunkenBorder(dc
, &r
);
1055 DrawExtraBorder(dc
, &r
);
1056 if ( flags
& wxTOPLEVEL_RESIZEABLE
)
1057 DrawExtraBorder(dc
, &r
);
1060 void wxStdRenderer::DrawFrameBackground(wxDC
& dc
, const wxRect
& rect
, int flags
)
1062 if ( !(flags
& wxTOPLEVEL_TITLEBAR
) )
1065 wxColour col
= m_scheme
->Get(flags
& wxTOPLEVEL_ACTIVE
1066 ? wxColourScheme::TITLEBAR_ACTIVE
1067 : wxColourScheme::TITLEBAR
);
1069 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1070 r
.height
= FRAME_TITLEBAR_HEIGHT
;
1072 DrawBackground(dc
, col
, r
);
1075 void wxStdRenderer::DrawFrameTitle(wxDC
& dc
,
1077 const wxString
& title
,
1080 wxColour col
= m_scheme
->Get(flags
& wxTOPLEVEL_ACTIVE
1081 ? wxColourScheme::TITLEBAR_ACTIVE_TEXT
1082 : wxColourScheme::TITLEBAR_TEXT
);
1083 dc
.SetTextForeground(col
);
1085 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1086 r
.height
= FRAME_TITLEBAR_HEIGHT
;
1087 if ( flags
& wxTOPLEVEL_ICON
)
1089 r
.x
+= FRAME_TITLEBAR_HEIGHT
;
1090 r
.width
-= FRAME_TITLEBAR_HEIGHT
+ 2;
1098 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
1099 r
.width
-= FRAME_BUTTON_WIDTH
+ 2;
1100 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
1101 r
.width
-= FRAME_BUTTON_WIDTH
;
1102 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
1103 r
.width
-= FRAME_BUTTON_WIDTH
;
1104 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
1105 r
.width
-= FRAME_BUTTON_WIDTH
;
1106 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
1107 r
.width
-= FRAME_BUTTON_WIDTH
;
1109 dc
.SetFont(m_titlebarFont
);
1113 dc
.GetTextExtent(title
, &textW
, NULL
);
1114 if ( textW
> r
.width
)
1116 // text is too big, let's shorten it and add "..." after it:
1117 size_t len
= title
.length();
1118 wxCoord WSoFar
, letterW
;
1120 dc
.GetTextExtent(wxT("..."), &WSoFar
, NULL
);
1121 if ( WSoFar
> r
.width
)
1123 // not enough space to draw anything
1128 for (size_t i
= 0; i
< len
; i
++)
1130 dc
.GetTextExtent(title
[i
], &letterW
, NULL
);
1131 if ( letterW
+ WSoFar
> r
.width
)
1138 else // no need to truncate the title
1143 dc
.DrawLabel(s
, wxNullBitmap
, r
, wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
1146 void wxStdRenderer::DrawFrameIcon(wxDC
& dc
,
1153 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1154 dc
.DrawIcon(icon
, r
.x
, r
.y
);
1158 void wxStdRenderer::DrawFrameButton(wxDC
& dc
,
1159 wxCoord x
, wxCoord y
,
1163 FrameButtonType idx
;
1166 case wxTOPLEVEL_BUTTON_CLOSE
: idx
= FrameButton_Close
; break;
1167 case wxTOPLEVEL_BUTTON_MAXIMIZE
: idx
= FrameButton_Maximize
; break;
1168 case wxTOPLEVEL_BUTTON_ICONIZE
: idx
= FrameButton_Minimize
; break;
1169 case wxTOPLEVEL_BUTTON_RESTORE
: idx
= FrameButton_Restore
; break;
1170 case wxTOPLEVEL_BUTTON_HELP
: idx
= FrameButton_Help
; break;
1172 wxFAIL_MSG(wxT("incorrect button specification"));
1176 wxBitmap bmp
= GetFrameButtonBitmap(idx
);
1180 wxRect
rectBtn(x
, y
, FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
1181 if ( flags
& wxCONTROL_PRESSED
)
1183 DrawSunkenBorder(dc
, &rectBtn
);
1185 rectBtn
.Offset(1, 1);
1189 DrawRaisedBorder(dc
, &rectBtn
);
1192 DrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rectBtn
);
1194 wxRect
rectBmp(0, 0, bmp
.GetWidth(), bmp
.GetHeight());
1195 dc
.DrawBitmap(bmp
, rectBmp
.CentreIn(rectBtn
).GetPosition(), true);
1198 int wxStdRenderer::GetFrameBorderWidth(int flags
) const
1200 return flags
& wxTOPLEVEL_RESIZEABLE
? 4 : 3;
1204 wxRect
wxStdRenderer::GetFrameClientArea(const wxRect
& rect
, int flags
) const
1208 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1210 r
.Inflate(-GetFrameBorderWidth(flags
));
1213 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1215 r
.y
+= FRAME_TITLEBAR_HEIGHT
;
1216 r
.height
-= FRAME_TITLEBAR_HEIGHT
;
1223 wxStdRenderer::GetFrameTotalSize(const wxSize
& clientSize
, int flags
) const
1225 wxSize
s(clientSize
);
1227 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1229 s
.IncBy(2*GetFrameBorderWidth(flags
));
1232 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1233 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
1238 wxSize
wxStdRenderer::GetFrameMinSize(int flags
) const
1242 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1244 s
.IncBy(2*GetFrameBorderWidth(flags
));
1247 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1249 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
1251 if ( flags
& wxTOPLEVEL_ICON
)
1252 s
.x
+= FRAME_TITLEBAR_HEIGHT
+ 2;
1253 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
1254 s
.x
+= FRAME_BUTTON_WIDTH
+ 2;
1255 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
1256 s
.x
+= FRAME_BUTTON_WIDTH
;
1257 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
1258 s
.x
+= FRAME_BUTTON_WIDTH
;
1259 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
1260 s
.x
+= FRAME_BUTTON_WIDTH
;
1261 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
1262 s
.x
+= FRAME_BUTTON_WIDTH
;
1268 wxSize
wxStdRenderer::GetFrameIconSize() const
1270 return wxSize(16, 16);