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 wxRect rectLabel
= rect
;
261 if ( !label
.empty() && (flags
& wxCONTROL_DISABLED
) )
263 if ( flags
& wxCONTROL_PRESSED
)
265 // shift the label if a button is pressed
266 rectLabel
.Offset(1, 1);
269 // draw shadow of the text
270 dc
.SetTextForeground(m_penHighlight
.GetColour());
271 wxRect rectShadow
= rect
;
272 rectShadow
.Offset(1, 1);
273 dc
.DrawLabel(label
, rectShadow
, alignment
, indexAccel
);
275 // make the main label text grey
276 dc
.SetTextForeground(m_penDarkGrey
.GetColour());
278 if ( flags
& wxCONTROL_FOCUSED
)
280 // leave enough space for the focus rect
281 rectLabel
.Inflate(-2);
285 dc
.DrawLabel(label
, image
, rectLabel
, alignment
, indexAccel
, rectBounds
);
287 if ( !label
.empty() && (flags
& wxCONTROL_FOCUSED
) )
289 rectLabel
.Inflate(-1);
291 DrawFocusRect(dc
, rectLabel
);
295 // ----------------------------------------------------------------------------
297 // ----------------------------------------------------------------------------
300 We implement standard-looking 3D borders which have the following appearance:
304 WWWWWWWWWWWWWWWWWWWWWWB
305 WHHHHHHHHHHHHHHHHHHHHGB
306 WH GB W = white (HILIGHT)
307 WH GB H = light grey (LIGHT)
308 WH GB G = dark grey (SHADOI)
309 WH GB B = black (DKSHADOI)
312 WGGGGGGGGGGGGGGGGGGGGGB
313 BBBBBBBBBBBBBBBBBBBBBBB
315 The sunken border looks like this:
317 GGGGGGGGGGGGGGGGGGGGGGW
318 GBBBBBBBBBBBBBBBBBBBBHW
325 GHHHHHHHHHHHHHHHHHHHHHW
326 WWWWWWWWWWWWWWWWWWWWWWW
328 The static border (used for the controls which don't get focus) is like
331 GGGGGGGGGGGGGGGGGGGGGGW
339 WWWWWWWWWWWWWWWWWWWWWWW
341 The most complicated is the double border which is a combination of special
342 "anti-sunken" border and an extra border inside it:
344 HHHHHHHHHHHHHHHHHHHHHHB
345 HWWWWWWWWWWWWWWWWWWWWGB
346 HWHHHHHHHHHHHHHHHHHHHGB
351 HWHHHHHHHHHHHHHHHHHHHGB
352 HGGGGGGGGGGGGGGGGGGGGGB
353 BBBBBBBBBBBBBBBBBBBBBBB
355 And the simple border is, well, simple:
357 BBBBBBBBBBBBBBBBBBBBBBB
366 BBBBBBBBBBBBBBBBBBBBBBB
369 void wxStdRenderer::DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
)
371 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penBlack
);
372 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penDarkGrey
);
375 void wxStdRenderer::DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
)
377 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
378 DrawShadedRect(dc
, rect
, m_penBlack
, m_penLightGrey
);
381 void wxStdRenderer::DrawAntiSunkenBorder(wxDC
& dc
, wxRect
*rect
)
383 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penBlack
);
384 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
387 void wxStdRenderer::DrawBoxBorder(wxDC
& dc
, wxRect
*rect
)
389 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
390 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
393 void wxStdRenderer::DrawStaticBorder(wxDC
& dc
, wxRect
*rect
)
395 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
398 void wxStdRenderer::DrawExtraBorder(wxDC
& dc
, wxRect
*rect
)
400 DrawRect(dc
, rect
, m_penLightGrey
);
403 void wxStdRenderer::DrawBorder(wxDC
& dc
,
405 const wxRect
& rectTotal
,
409 wxRect rect
= rectTotal
;
413 case wxBORDER_SUNKEN
:
414 DrawSunkenBorder(dc
, &rect
);
417 case wxBORDER_DOUBLE
:
418 DrawAntiSunkenBorder(dc
, &rect
);
419 DrawExtraBorder(dc
, &rect
);
422 case wxBORDER_STATIC
:
423 DrawStaticBorder(dc
, &rect
);
426 case wxBORDER_RAISED
:
427 DrawRaisedBorder(dc
, &rect
);
430 case wxBORDER_SIMPLE
:
431 DrawRect(dc
, &rect
, m_penBlack
);
435 wxFAIL_MSG(_T("unknown border type"));
438 case wxBORDER_DEFAULT
:
447 wxRect
wxStdRenderer::GetBorderDimensions(wxBorder border
) const
452 case wxBORDER_SIMPLE
:
453 case wxBORDER_STATIC
:
457 case wxBORDER_RAISED
:
458 case wxBORDER_SUNKEN
:
462 case wxBORDER_DOUBLE
:
467 wxFAIL_MSG(_T("unknown border type"));
470 case wxBORDER_DEFAULT
:
485 void wxStdRenderer::AdjustSize(wxSize
*size
, const wxWindow
*window
)
487 // take into account the border width
488 wxRect rectBorder
= GetBorderDimensions(window
->GetBorder());
489 size
->x
+= rectBorder
.x
+ rectBorder
.width
;
490 size
->y
+= rectBorder
.y
+ rectBorder
.height
;
493 bool wxStdRenderer::AreScrollbarsInsideBorder() const
498 wxCoord
wxStdRenderer::GetListboxItemHeight(wxCoord fontHeight
)
500 return fontHeight
+ 2*ITEM_MARGIN
;
503 void wxStdRenderer::DrawTextBorder(wxDC
& dc
,
509 DrawBorder(dc
, border
, rect
, flags
, rectIn
);
512 // ----------------------------------------------------------------------------
514 // ----------------------------------------------------------------------------
517 wxStdRenderer::DrawHorizontalLine(wxDC
& dc
, wxCoord y
, wxCoord x1
, wxCoord x2
)
519 dc
.SetPen(m_penDarkGrey
);
520 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
522 dc
.SetPen(m_penHighlight
);
524 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
528 wxStdRenderer::DrawVerticalLine(wxDC
& dc
, wxCoord x
, wxCoord y1
, wxCoord y2
)
530 dc
.SetPen(m_penDarkGrey
);
531 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
533 dc
.SetPen(m_penHighlight
);
535 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
538 void wxStdRenderer::DrawFrameWithoutLabel(wxDC
& dc
,
539 const wxRect
& rectFrame
,
540 const wxRect
& rectLabel
)
542 // draw left, bottom and right lines entirely
543 DrawVerticalLine(dc
, rectFrame
.GetLeft(),
544 rectFrame
.GetTop(), rectFrame
.GetBottom() - 2);
545 DrawHorizontalLine(dc
, rectFrame
.GetBottom() - 1,
546 rectFrame
.GetLeft(), rectFrame
.GetRight());
547 DrawVerticalLine(dc
, rectFrame
.GetRight() - 1,
548 rectFrame
.GetTop(), rectFrame
.GetBottom() - 1);
550 // and 2 parts of the top line
551 DrawHorizontalLine(dc
, rectFrame
.GetTop(),
552 rectFrame
.GetLeft() + 1, rectLabel
.GetLeft());
553 DrawHorizontalLine(dc
, rectFrame
.GetTop(),
554 rectLabel
.GetRight(), rectFrame
.GetRight() - 2);
557 void wxStdRenderer::DrawFrameWithLabel(wxDC
& dc
,
558 const wxString
& label
,
559 const wxRect
& rectFrame
,
560 const wxRect
& rectText
,
566 DrawLabel(dc
, label
, rectText
, flags
, alignment
, indexAccel
, &rectLabel
);
568 DrawFrameWithoutLabel(dc
, rectFrame
, rectLabel
);
571 void wxStdRenderer::DrawFrame(wxDC
& dc
,
572 const wxString
& label
,
578 wxCoord height
= 0; // of the label
579 wxRect rectFrame
= rect
;
580 if ( !label
.empty() )
582 // the text should touch the top border of the rect, so the frame
583 // itself should be lower
584 dc
.GetTextExtent(label
, NULL
, &height
);
585 rectFrame
.y
+= height
/ 2;
586 rectFrame
.height
-= height
/ 2;
588 // we have to draw each part of the frame individually as we can't
589 // erase the background beyond the label as it might contain some
590 // pixmap already, so drawing everything and then overwriting part of
591 // the frame with label doesn't work
593 // TODO: the +5 shouldn't be hard coded
595 rectText
.x
= rectFrame
.x
+ 5;
597 rectText
.width
= rectFrame
.width
- 7; // +2 border width
598 rectText
.height
= height
;
600 DrawFrameWithLabel(dc
, label
, rectFrame
, rectText
, flags
,
601 alignment
, indexAccel
);
605 DrawBoxBorder(dc
, &rectFrame
);
609 void wxStdRenderer::DrawItem(wxDC
& dc
,
610 const wxString
& label
,
614 wxDCTextColourChanger
colChanger(dc
);
616 if ( flags
& wxCONTROL_SELECTED
)
618 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
620 const wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
623 dc
.DrawRectangle(rect
);
626 // horizontal adjustment is arbitrary
627 wxRect rectText
= rect
;
628 rectText
.Deflate(2, ITEM_MARGIN
);
629 dc
.DrawLabel(label
, wxNullBitmap
, rectText
);
631 if ( flags
& wxCONTROL_FOCUSED
)
633 DrawFocusRect(dc
, rect
, flags
);
637 void wxStdRenderer::DrawCheckItemBitmap(wxDC
& dc
,
638 const wxBitmap
& bitmap
,
642 DrawCheckButton(dc
, wxEmptyString
, bitmap
, rect
, flags
);
645 void wxStdRenderer::DrawCheckItem(wxDC
& dc
,
646 const wxString
& label
,
647 const wxBitmap
& bitmap
,
651 wxRect rectBitmap
= rect
;
652 rectBitmap
.width
= GetCheckBitmapSize().x
;
653 DrawCheckItemBitmap(dc
, bitmap
, rectBitmap
, flags
);
655 wxRect rectLabel
= rect
;
656 wxCoord shift
= rectBitmap
.width
+ 2*GetCheckItemMargin();
657 rectLabel
.x
+= shift
;
658 rectLabel
.width
-= shift
;
659 DrawItem(dc
, label
, rectLabel
, flags
);
662 // ----------------------------------------------------------------------------
663 // check and radio bitmaps
664 // ----------------------------------------------------------------------------
666 void wxStdRenderer::DrawCheckButton(wxDC
& dc
,
667 const wxString
& label
,
668 const wxBitmap
& bitmap
,
674 wxBitmap
bmp(bitmap
.Ok() ? bitmap
: GetCheckBitmap(flags
));
676 DrawCheckOrRadioButton(dc
, label
, bmp
, rect
, flags
, align
, indexAccel
);
679 void wxStdRenderer::DrawRadioButton(wxDC
& dc
,
680 const wxString
& label
,
681 const wxBitmap
& bitmap
,
687 wxBitmap
bmp(bitmap
.Ok() ? bitmap
: GetRadioBitmap(flags
));
689 DrawCheckOrRadioButton(dc
, label
, bmp
, rect
, flags
, align
, indexAccel
);
692 void wxStdRenderer::DrawCheckOrRadioButton(wxDC
& dc
,
693 const wxString
& label
,
694 const wxBitmap
& bitmap
,
700 // calculate the position of the bitmap and of the label
701 wxCoord heightBmp
= bitmap
.GetHeight();
703 yBmp
= rect
.y
+ (rect
.height
- heightBmp
) / 2;
706 dc
.GetMultiLineTextExtent(label
, NULL
, &rectLabel
.height
);
707 rectLabel
.y
= rect
.y
+ (rect
.height
- rectLabel
.height
) / 2;
709 // align label vertically with the bitmap - looks nicer like this
710 rectLabel
.y
-= (rectLabel
.height
- heightBmp
) % 2;
712 // calc horz position
713 if ( align
== wxALIGN_RIGHT
)
715 xBmp
= rect
.GetRight() - bitmap
.GetWidth();
716 rectLabel
.x
= rect
.x
+ 3;
717 rectLabel
.SetRight(xBmp
);
719 else // normal (checkbox to the left of the text) case
722 rectLabel
.x
= xBmp
+ bitmap
.GetWidth() + 5;
723 rectLabel
.SetRight(rect
.GetRight());
726 dc
.DrawBitmap(bitmap
, xBmp
, yBmp
, true /* use mask */);
728 DrawLabel(dc
, label
, rectLabel
, flags
,
729 wxALIGN_LEFT
| wxALIGN_TOP
, indexAccel
);
734 void wxStdRenderer::DrawTextLine(wxDC
& dc
,
735 const wxString
& text
,
741 if ( (selStart
== -1) || !(flags
& wxCONTROL_FOCUSED
) )
743 // just draw it as is
744 dc
.DrawText(text
, rect
.x
, rect
.y
);
746 else // we have selection
751 // draw the part before selection
752 wxString
s(text
, (size_t)selStart
);
755 dc
.DrawText(s
, x
, rect
.y
);
757 dc
.GetTextExtent(s
, &width
, NULL
);
761 // draw the selection itself
762 s
= wxString(text
.c_str() + selStart
, text
.c_str() + selEnd
);
765 wxColour colFg
= dc
.GetTextForeground(),
766 colBg
= dc
.GetTextBackground();
767 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
768 dc
.SetTextBackground(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
));
769 dc
.SetBackgroundMode(wxSOLID
);
771 dc
.DrawText(s
, x
, rect
.y
);
772 dc
.GetTextExtent(s
, &width
, NULL
);
775 dc
.SetBackgroundMode(wxTRANSPARENT
);
776 dc
.SetTextBackground(colBg
);
777 dc
.SetTextForeground(colFg
);
780 // draw the final part
781 s
= text
.c_str() + selEnd
;
784 dc
.DrawText(s
, x
, rect
.y
);
789 void wxStdRenderer::DrawLineWrapMark(wxDC
& WXUNUSED(dc
),
790 const wxRect
& WXUNUSED(rect
))
792 // nothing by default
795 int wxStdRenderer::GetTextBorderWidth(const wxTextCtrl
* WXUNUSED(text
)) const
801 wxStdRenderer::GetTextTotalArea(const wxTextCtrl
*text
, const wxRect
& rect
) const
803 wxRect rectTotal
= rect
;
804 rectTotal
.Inflate(GetTextBorderWidth(text
));
808 wxRect
wxStdRenderer::GetTextClientArea(const wxTextCtrl
*text
,
810 wxCoord
*extraSpaceBeyond
) const
812 wxRect rectText
= rect
;
813 rectText
.Deflate(GetTextBorderWidth(text
));
815 if ( extraSpaceBeyond
)
816 *extraSpaceBeyond
= 0;
821 #endif // wxUSE_TEXTCTRL
823 // ----------------------------------------------------------------------------
824 // scrollbars drawing
825 // ----------------------------------------------------------------------------
827 void wxStdRenderer::DrawScrollbarArrow(wxDC
& dc
,
832 DrawArrow(dc
, dir
, rect
, flags
);
835 void wxStdRenderer::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
837 DrawSolidRect(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
840 // ----------------------------------------------------------------------------
842 // ----------------------------------------------------------------------------
846 wxSize
wxStdRenderer::GetStatusBarBorders() const
848 // Rendered border may be different depending on field's style, we use
849 // the largest value so that any field certainly fits into the borders
851 wxRect raised
= GetBorderDimensions(wxBORDER_RAISED
);
852 wxRect flat
= GetBorderDimensions(wxBORDER_STATIC
);
853 wxASSERT_MSG( raised
.x
== raised
.width
&& raised
.y
== raised
.height
&&
854 flat
.x
== flat
.width
&& flat
.y
== flat
.height
,
855 _T("this code expects uniform borders, you must override GetStatusBarBorders") );
857 // take the larger of flat/raised values:
858 wxSize
border(wxMax(raised
.x
, flat
.x
), wxMax(raised
.y
, flat
.y
));
863 wxCoord
wxStdRenderer::GetStatusBarBorderBetweenFields() const
868 wxSize
wxStdRenderer::GetStatusBarFieldMargins() const
873 void wxStdRenderer::DrawStatusField(wxDC
& dc
,
875 const wxString
& label
,
881 if ( style
== wxSB_RAISED
)
882 DrawBorder(dc
, wxBORDER_RAISED
, rect
, flags
, &rectIn
);
883 else if ( style
!= wxSB_FLAT
)
884 DrawBorder(dc
, wxBORDER_STATIC
, rect
, flags
, &rectIn
);
886 rectIn
.Deflate(GetStatusBarFieldMargins());
888 wxDCClipper
clipper(dc
, rectIn
);
889 DrawLabel(dc
, label
, rectIn
, flags
, wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
892 #endif // wxUSE_STATUSBAR
894 // ----------------------------------------------------------------------------
896 // ----------------------------------------------------------------------------
898 int wxStdRenderer::HitTestFrame(const wxRect
& rect
, const wxPoint
& pt
, int flags
) const
900 wxRect client
= GetFrameClientArea(rect
, flags
);
902 if ( client
.Contains(pt
) )
903 return wxHT_TOPLEVEL_CLIENT_AREA
;
905 if ( flags
& wxTOPLEVEL_TITLEBAR
)
907 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
909 if ( flags
& wxTOPLEVEL_ICON
)
911 if ( wxRect(client
.GetPosition(), GetFrameIconSize()).Contains(pt
) )
912 return wxHT_TOPLEVEL_ICON
;
915 wxRect
btnRect(client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
,
916 client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2,
917 FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
919 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
921 if ( btnRect
.Contains(pt
) )
922 return wxHT_TOPLEVEL_BUTTON_CLOSE
;
923 btnRect
.x
-= FRAME_BUTTON_WIDTH
+ 2;
925 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
927 if ( btnRect
.Contains(pt
) )
928 return wxHT_TOPLEVEL_BUTTON_MAXIMIZE
;
929 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
931 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
933 if ( btnRect
.Contains(pt
) )
934 return wxHT_TOPLEVEL_BUTTON_RESTORE
;
935 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
937 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
939 if ( btnRect
.Contains(pt
) )
940 return wxHT_TOPLEVEL_BUTTON_ICONIZE
;
941 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
943 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
945 if ( btnRect
.Contains(pt
) )
946 return wxHT_TOPLEVEL_BUTTON_HELP
;
947 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
950 if ( pt
.y
>= client
.y
&& pt
.y
< client
.y
+ FRAME_TITLEBAR_HEIGHT
)
951 return wxHT_TOPLEVEL_TITLEBAR
;
954 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
956 // we are certainly at one of borders, let's decide which one:
959 // dirty trick, relies on the way wxHT_TOPLEVEL_XXX are defined!
960 if ( pt
.x
< client
.x
)
961 border
|= wxHT_TOPLEVEL_BORDER_W
;
962 else if ( pt
.x
>= client
.width
+ client
.x
)
963 border
|= wxHT_TOPLEVEL_BORDER_E
;
964 if ( pt
.y
< client
.y
)
965 border
|= wxHT_TOPLEVEL_BORDER_N
;
966 else if ( pt
.y
>= client
.height
+ client
.y
)
967 border
|= wxHT_TOPLEVEL_BORDER_S
;
974 void wxStdRenderer::DrawFrameTitleBar(wxDC
& dc
,
976 const wxString
& title
,
980 int specialButtonFlags
)
982 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
984 DrawFrameBorder(dc
, rect
, flags
);
986 if ( flags
& wxTOPLEVEL_TITLEBAR
)
988 DrawFrameBackground(dc
, rect
, flags
);
989 if ( flags
& wxTOPLEVEL_ICON
)
990 DrawFrameIcon(dc
, rect
, icon
, flags
);
991 DrawFrameTitle(dc
, rect
, title
, flags
);
993 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
995 x
= client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
;
996 y
= client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2;
998 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
1000 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_CLOSE
,
1001 (specialButton
== wxTOPLEVEL_BUTTON_CLOSE
) ?
1002 specialButtonFlags
: 0);
1003 x
-= FRAME_BUTTON_WIDTH
+ 2;
1005 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
1007 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_MAXIMIZE
,
1008 (specialButton
== wxTOPLEVEL_BUTTON_MAXIMIZE
) ?
1009 specialButtonFlags
: 0);
1010 x
-= FRAME_BUTTON_WIDTH
;
1012 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
1014 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_RESTORE
,
1015 (specialButton
== wxTOPLEVEL_BUTTON_RESTORE
) ?
1016 specialButtonFlags
: 0);
1017 x
-= FRAME_BUTTON_WIDTH
;
1019 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
1021 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_ICONIZE
,
1022 (specialButton
== wxTOPLEVEL_BUTTON_ICONIZE
) ?
1023 specialButtonFlags
: 0);
1024 x
-= FRAME_BUTTON_WIDTH
;
1026 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
1028 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_HELP
,
1029 (specialButton
== wxTOPLEVEL_BUTTON_HELP
) ?
1030 specialButtonFlags
: 0);
1035 void wxStdRenderer::DrawFrameBorder(wxDC
& dc
, const wxRect
& rect
, int flags
)
1037 if ( !(flags
& wxTOPLEVEL_BORDER
) )
1042 DrawAntiSunkenBorder(dc
, &r
);
1043 DrawExtraBorder(dc
, &r
);
1044 if ( flags
& wxTOPLEVEL_RESIZEABLE
)
1045 DrawExtraBorder(dc
, &r
);
1048 void wxStdRenderer::DrawFrameBackground(wxDC
& dc
, const wxRect
& rect
, int flags
)
1050 if ( !(flags
& wxTOPLEVEL_TITLEBAR
) )
1053 wxColour col
= m_scheme
->Get(flags
& wxTOPLEVEL_ACTIVE
1054 ? wxColourScheme::TITLEBAR_ACTIVE
1055 : wxColourScheme::TITLEBAR
);
1057 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1058 r
.height
= FRAME_TITLEBAR_HEIGHT
;
1060 DrawBackground(dc
, col
, r
);
1063 void wxStdRenderer::DrawFrameTitle(wxDC
& dc
,
1065 const wxString
& title
,
1068 wxColour col
= m_scheme
->Get(flags
& wxTOPLEVEL_ACTIVE
1069 ? wxColourScheme::TITLEBAR_ACTIVE_TEXT
1070 : wxColourScheme::TITLEBAR_TEXT
);
1071 dc
.SetTextForeground(col
);
1073 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1074 r
.height
= FRAME_TITLEBAR_HEIGHT
;
1075 if ( flags
& wxTOPLEVEL_ICON
)
1077 r
.x
+= FRAME_TITLEBAR_HEIGHT
;
1078 r
.width
-= FRAME_TITLEBAR_HEIGHT
+ 2;
1086 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
1087 r
.width
-= FRAME_BUTTON_WIDTH
+ 2;
1088 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
1089 r
.width
-= FRAME_BUTTON_WIDTH
;
1090 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
1091 r
.width
-= FRAME_BUTTON_WIDTH
;
1092 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
1093 r
.width
-= FRAME_BUTTON_WIDTH
;
1094 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
1095 r
.width
-= FRAME_BUTTON_WIDTH
;
1097 dc
.SetFont(m_titlebarFont
);
1101 dc
.GetTextExtent(title
, &textW
, NULL
);
1102 if ( textW
> r
.width
)
1104 // text is too big, let's shorten it and add "..." after it:
1105 size_t len
= title
.length();
1106 wxCoord WSoFar
, letterW
;
1108 dc
.GetTextExtent(wxT("..."), &WSoFar
, NULL
);
1109 if ( WSoFar
> r
.width
)
1111 // not enough space to draw anything
1116 for (size_t i
= 0; i
< len
; i
++)
1118 dc
.GetTextExtent(title
[i
], &letterW
, NULL
);
1119 if ( letterW
+ WSoFar
> r
.width
)
1126 else // no need to truncate the title
1131 dc
.DrawLabel(s
, wxNullBitmap
, r
, wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
1134 void wxStdRenderer::DrawFrameIcon(wxDC
& dc
,
1141 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1142 dc
.DrawIcon(icon
, r
.x
, r
.y
);
1146 void wxStdRenderer::DrawFrameButton(wxDC
& dc
,
1147 wxCoord x
, wxCoord y
,
1151 FrameButtonType idx
;
1154 case wxTOPLEVEL_BUTTON_CLOSE
: idx
= FrameButton_Close
; break;
1155 case wxTOPLEVEL_BUTTON_MAXIMIZE
: idx
= FrameButton_Maximize
; break;
1156 case wxTOPLEVEL_BUTTON_ICONIZE
: idx
= FrameButton_Minimize
; break;
1157 case wxTOPLEVEL_BUTTON_RESTORE
: idx
= FrameButton_Restore
; break;
1158 case wxTOPLEVEL_BUTTON_HELP
: idx
= FrameButton_Help
; break;
1160 wxFAIL_MSG(wxT("incorrect button specification"));
1164 wxBitmap bmp
= GetFrameButtonBitmap(idx
);
1168 wxRect
rectBtn(x
, y
, FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
1169 if ( flags
& wxCONTROL_PRESSED
)
1171 DrawSunkenBorder(dc
, &rectBtn
);
1173 rectBtn
.Offset(1, 1);
1177 DrawRaisedBorder(dc
, &rectBtn
);
1180 DrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rectBtn
);
1182 wxRect
rectBmp(0, 0, bmp
.GetWidth(), bmp
.GetHeight());
1183 dc
.DrawBitmap(bmp
, rectBmp
.CentreIn(rectBtn
).GetPosition(), true);
1186 int wxStdRenderer::GetFrameBorderWidth(int flags
) const
1188 return flags
& wxTOPLEVEL_RESIZEABLE
? 4 : 3;
1192 wxRect
wxStdRenderer::GetFrameClientArea(const wxRect
& rect
, int flags
) const
1196 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1198 r
.Inflate(-GetFrameBorderWidth(flags
));
1201 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1203 r
.y
+= FRAME_TITLEBAR_HEIGHT
;
1204 r
.height
-= FRAME_TITLEBAR_HEIGHT
;
1211 wxStdRenderer::GetFrameTotalSize(const wxSize
& clientSize
, int flags
) const
1213 wxSize
s(clientSize
);
1215 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1217 s
.IncBy(2*GetFrameBorderWidth(flags
));
1220 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1221 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
1226 wxSize
wxStdRenderer::GetFrameMinSize(int flags
) const
1230 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1232 s
.IncBy(2*GetFrameBorderWidth(flags
));
1235 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1237 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
1239 if ( flags
& wxTOPLEVEL_ICON
)
1240 s
.x
+= FRAME_TITLEBAR_HEIGHT
+ 2;
1241 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
1242 s
.x
+= FRAME_BUTTON_WIDTH
+ 2;
1243 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
1244 s
.x
+= FRAME_BUTTON_WIDTH
;
1245 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
1246 s
.x
+= FRAME_BUTTON_WIDTH
;
1247 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
1248 s
.x
+= FRAME_BUTTON_WIDTH
;
1249 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
1250 s
.x
+= FRAME_BUTTON_WIDTH
;
1256 wxSize
wxStdRenderer::GetFrameIconSize() const
1258 return wxSize(16, 16);