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
);
896 rectIn
.Deflate(GetStatusBarFieldMargins());
898 wxDCClipper
clipper(dc
, rectIn
);
899 DrawLabel(dc
, label
, rectIn
, flags
, wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
902 #endif // wxUSE_STATUSBAR
904 // ----------------------------------------------------------------------------
906 // ----------------------------------------------------------------------------
908 int wxStdRenderer::HitTestFrame(const wxRect
& rect
, const wxPoint
& pt
, int flags
) const
910 wxRect client
= GetFrameClientArea(rect
, flags
);
912 if ( client
.Contains(pt
) )
913 return wxHT_TOPLEVEL_CLIENT_AREA
;
915 if ( flags
& wxTOPLEVEL_TITLEBAR
)
917 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
919 if ( flags
& wxTOPLEVEL_ICON
)
921 if ( wxRect(client
.GetPosition(), GetFrameIconSize()).Contains(pt
) )
922 return wxHT_TOPLEVEL_ICON
;
925 wxRect
btnRect(client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
,
926 client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2,
927 FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
929 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
931 if ( btnRect
.Contains(pt
) )
932 return wxHT_TOPLEVEL_BUTTON_CLOSE
;
933 btnRect
.x
-= FRAME_BUTTON_WIDTH
+ 2;
935 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
937 if ( btnRect
.Contains(pt
) )
938 return wxHT_TOPLEVEL_BUTTON_MAXIMIZE
;
939 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
941 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
943 if ( btnRect
.Contains(pt
) )
944 return wxHT_TOPLEVEL_BUTTON_RESTORE
;
945 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
947 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
949 if ( btnRect
.Contains(pt
) )
950 return wxHT_TOPLEVEL_BUTTON_ICONIZE
;
951 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
953 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
955 if ( btnRect
.Contains(pt
) )
956 return wxHT_TOPLEVEL_BUTTON_HELP
;
957 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
960 if ( pt
.y
>= client
.y
&& pt
.y
< client
.y
+ FRAME_TITLEBAR_HEIGHT
)
961 return wxHT_TOPLEVEL_TITLEBAR
;
964 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
966 // we are certainly at one of borders, let's decide which one:
969 // dirty trick, relies on the way wxHT_TOPLEVEL_XXX are defined!
970 if ( pt
.x
< client
.x
)
971 border
|= wxHT_TOPLEVEL_BORDER_W
;
972 else if ( pt
.x
>= client
.width
+ client
.x
)
973 border
|= wxHT_TOPLEVEL_BORDER_E
;
974 if ( pt
.y
< client
.y
)
975 border
|= wxHT_TOPLEVEL_BORDER_N
;
976 else if ( pt
.y
>= client
.height
+ client
.y
)
977 border
|= wxHT_TOPLEVEL_BORDER_S
;
984 void wxStdRenderer::DrawFrameTitleBar(wxDC
& dc
,
986 const wxString
& title
,
990 int specialButtonFlags
)
992 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
994 DrawFrameBorder(dc
, rect
, flags
);
996 if ( flags
& wxTOPLEVEL_TITLEBAR
)
998 DrawFrameBackground(dc
, rect
, flags
);
999 if ( flags
& wxTOPLEVEL_ICON
)
1000 DrawFrameIcon(dc
, rect
, icon
, flags
);
1001 DrawFrameTitle(dc
, rect
, title
, flags
);
1003 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1005 x
= client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
;
1006 y
= client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2;
1008 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
1010 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_CLOSE
,
1011 (specialButton
== wxTOPLEVEL_BUTTON_CLOSE
) ?
1012 specialButtonFlags
: 0);
1013 x
-= FRAME_BUTTON_WIDTH
+ 2;
1015 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
1017 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_MAXIMIZE
,
1018 (specialButton
== wxTOPLEVEL_BUTTON_MAXIMIZE
) ?
1019 specialButtonFlags
: 0);
1020 x
-= FRAME_BUTTON_WIDTH
;
1022 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
1024 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_RESTORE
,
1025 (specialButton
== wxTOPLEVEL_BUTTON_RESTORE
) ?
1026 specialButtonFlags
: 0);
1027 x
-= FRAME_BUTTON_WIDTH
;
1029 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
1031 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_ICONIZE
,
1032 (specialButton
== wxTOPLEVEL_BUTTON_ICONIZE
) ?
1033 specialButtonFlags
: 0);
1034 x
-= FRAME_BUTTON_WIDTH
;
1036 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
1038 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_HELP
,
1039 (specialButton
== wxTOPLEVEL_BUTTON_HELP
) ?
1040 specialButtonFlags
: 0);
1045 void wxStdRenderer::DrawFrameBorder(wxDC
& dc
, const wxRect
& rect
, int flags
)
1047 if ( !(flags
& wxTOPLEVEL_BORDER
) )
1052 DrawAntiSunkenBorder(dc
, &r
);
1053 DrawExtraBorder(dc
, &r
);
1054 if ( flags
& wxTOPLEVEL_RESIZEABLE
)
1055 DrawExtraBorder(dc
, &r
);
1058 void wxStdRenderer::DrawFrameBackground(wxDC
& dc
, const wxRect
& rect
, int flags
)
1060 if ( !(flags
& wxTOPLEVEL_TITLEBAR
) )
1063 wxColour col
= m_scheme
->Get(flags
& wxTOPLEVEL_ACTIVE
1064 ? wxColourScheme::TITLEBAR_ACTIVE
1065 : wxColourScheme::TITLEBAR
);
1067 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1068 r
.height
= FRAME_TITLEBAR_HEIGHT
;
1070 DrawBackground(dc
, col
, r
);
1073 void wxStdRenderer::DrawFrameTitle(wxDC
& dc
,
1075 const wxString
& title
,
1078 wxColour col
= m_scheme
->Get(flags
& wxTOPLEVEL_ACTIVE
1079 ? wxColourScheme::TITLEBAR_ACTIVE_TEXT
1080 : wxColourScheme::TITLEBAR_TEXT
);
1081 dc
.SetTextForeground(col
);
1083 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1084 r
.height
= FRAME_TITLEBAR_HEIGHT
;
1085 if ( flags
& wxTOPLEVEL_ICON
)
1087 r
.x
+= FRAME_TITLEBAR_HEIGHT
;
1088 r
.width
-= FRAME_TITLEBAR_HEIGHT
+ 2;
1096 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
1097 r
.width
-= FRAME_BUTTON_WIDTH
+ 2;
1098 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
1099 r
.width
-= FRAME_BUTTON_WIDTH
;
1100 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
1101 r
.width
-= FRAME_BUTTON_WIDTH
;
1102 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
1103 r
.width
-= FRAME_BUTTON_WIDTH
;
1104 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
1105 r
.width
-= FRAME_BUTTON_WIDTH
;
1107 dc
.SetFont(m_titlebarFont
);
1111 dc
.GetTextExtent(title
, &textW
, NULL
);
1112 if ( textW
> r
.width
)
1114 // text is too big, let's shorten it and add "..." after it:
1115 size_t len
= title
.length();
1116 wxCoord WSoFar
, letterW
;
1118 dc
.GetTextExtent(wxT("..."), &WSoFar
, NULL
);
1119 if ( WSoFar
> r
.width
)
1121 // not enough space to draw anything
1126 for (size_t i
= 0; i
< len
; i
++)
1128 dc
.GetTextExtent(title
[i
], &letterW
, NULL
);
1129 if ( letterW
+ WSoFar
> r
.width
)
1136 else // no need to truncate the title
1141 dc
.DrawLabel(s
, wxNullBitmap
, r
, wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
1144 void wxStdRenderer::DrawFrameIcon(wxDC
& dc
,
1151 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1152 dc
.DrawIcon(icon
, r
.x
, r
.y
);
1156 void wxStdRenderer::DrawFrameButton(wxDC
& dc
,
1157 wxCoord x
, wxCoord y
,
1161 FrameButtonType idx
;
1164 case wxTOPLEVEL_BUTTON_CLOSE
: idx
= FrameButton_Close
; break;
1165 case wxTOPLEVEL_BUTTON_MAXIMIZE
: idx
= FrameButton_Maximize
; break;
1166 case wxTOPLEVEL_BUTTON_ICONIZE
: idx
= FrameButton_Minimize
; break;
1167 case wxTOPLEVEL_BUTTON_RESTORE
: idx
= FrameButton_Restore
; break;
1168 case wxTOPLEVEL_BUTTON_HELP
: idx
= FrameButton_Help
; break;
1170 wxFAIL_MSG(wxT("incorrect button specification"));
1174 wxBitmap bmp
= GetFrameButtonBitmap(idx
);
1178 wxRect
rectBtn(x
, y
, FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
1179 if ( flags
& wxCONTROL_PRESSED
)
1181 DrawSunkenBorder(dc
, &rectBtn
);
1183 rectBtn
.Offset(1, 1);
1187 DrawRaisedBorder(dc
, &rectBtn
);
1190 DrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rectBtn
);
1192 wxRect
rectBmp(0, 0, bmp
.GetWidth(), bmp
.GetHeight());
1193 dc
.DrawBitmap(bmp
, rectBmp
.CentreIn(rectBtn
).GetPosition(), true);
1196 int wxStdRenderer::GetFrameBorderWidth(int flags
) const
1198 return flags
& wxTOPLEVEL_RESIZEABLE
? 4 : 3;
1202 wxRect
wxStdRenderer::GetFrameClientArea(const wxRect
& rect
, int flags
) const
1206 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1208 r
.Inflate(-GetFrameBorderWidth(flags
));
1211 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1213 r
.y
+= FRAME_TITLEBAR_HEIGHT
;
1214 r
.height
-= FRAME_TITLEBAR_HEIGHT
;
1221 wxStdRenderer::GetFrameTotalSize(const wxSize
& clientSize
, int flags
) const
1223 wxSize
s(clientSize
);
1225 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1227 s
.IncBy(2*GetFrameBorderWidth(flags
));
1230 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1231 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
1236 wxSize
wxStdRenderer::GetFrameMinSize(int flags
) const
1240 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1242 s
.IncBy(2*GetFrameBorderWidth(flags
));
1245 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1247 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
1249 if ( flags
& wxTOPLEVEL_ICON
)
1250 s
.x
+= FRAME_TITLEBAR_HEIGHT
+ 2;
1251 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
1252 s
.x
+= FRAME_BUTTON_WIDTH
+ 2;
1253 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
1254 s
.x
+= FRAME_BUTTON_WIDTH
;
1255 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
1256 s
.x
+= FRAME_BUTTON_WIDTH
;
1257 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
1258 s
.x
+= FRAME_BUTTON_WIDTH
;
1259 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
1260 s
.x
+= FRAME_BUTTON_WIDTH
;
1266 wxSize
wxStdRenderer::GetFrameIconSize() const
1268 return wxSize(16, 16);