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(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
:
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(NULL
, 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
,
677 DrawCheckOrRadioButton(dc
, label
, bitmap
, rect
, flags
, align
, indexAccel
);
679 DrawCheckOrRadioButton(dc
, label
, GetCheckBitmap(flags
), rect
, flags
, align
, indexAccel
);
682 void wxStdRenderer::DrawRadioButton(wxDC
& dc
,
683 const wxString
& label
,
684 const wxBitmap
& bitmap
,
691 DrawCheckOrRadioButton(dc
, label
, bitmap
, rect
, flags
, align
, indexAccel
);
693 DrawCheckOrRadioButton(dc
, label
, GetRadioBitmap(flags
), rect
, flags
, align
, indexAccel
);
697 void wxStdRenderer::DrawCheckOrRadioButton(wxDC
& dc
,
698 const wxString
& label
,
699 const wxBitmap
& bitmap
,
705 // calculate the position of the bitmap and of the label
706 wxCoord heightBmp
= bitmap
.GetHeight();
708 yBmp
= rect
.y
+ (rect
.height
- heightBmp
) / 2;
711 dc
.GetMultiLineTextExtent(label
, NULL
, &rectLabel
.height
);
712 rectLabel
.y
= rect
.y
+ (rect
.height
- rectLabel
.height
) / 2;
714 // align label vertically with the bitmap - looks nicer like this
715 rectLabel
.y
-= (rectLabel
.height
- heightBmp
) % 2;
717 // calc horz position
718 if ( align
== wxALIGN_RIGHT
)
720 xBmp
= rect
.GetRight() - bitmap
.GetWidth();
721 rectLabel
.x
= rect
.x
+ 3;
722 rectLabel
.SetRight(xBmp
);
724 else // normal (checkbox to the left of the text) case
727 rectLabel
.x
= xBmp
+ bitmap
.GetWidth() + 5;
728 rectLabel
.SetRight(rect
.GetRight());
731 dc
.DrawBitmap(bitmap
, xBmp
, yBmp
, true /* use mask */);
733 DrawLabel(dc
, label
, rectLabel
, flags
,
734 wxALIGN_LEFT
| wxALIGN_TOP
, indexAccel
);
739 void wxStdRenderer::DrawTextLine(wxDC
& dc
,
740 const wxString
& text
,
746 if ( (selStart
== -1) || !(flags
& wxCONTROL_FOCUSED
) )
748 // just draw it as is
749 dc
.DrawText(text
, rect
.x
, rect
.y
);
751 else // we have selection
756 // draw the part before selection
757 wxString
s(text
, (size_t)selStart
);
760 dc
.DrawText(s
, x
, rect
.y
);
762 dc
.GetTextExtent(s
, &width
, NULL
);
766 // draw the selection itself
767 s
= wxString(text
.c_str() + selStart
, text
.c_str() + selEnd
);
770 wxColour colFg
= dc
.GetTextForeground(),
771 colBg
= dc
.GetTextBackground();
772 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
773 dc
.SetTextBackground(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
));
774 dc
.SetBackgroundMode(wxSOLID
);
776 dc
.DrawText(s
, x
, rect
.y
);
777 dc
.GetTextExtent(s
, &width
, NULL
);
780 dc
.SetBackgroundMode(wxTRANSPARENT
);
781 dc
.SetTextBackground(colBg
);
782 dc
.SetTextForeground(colFg
);
785 // draw the final part
786 s
= text
.c_str() + selEnd
;
789 dc
.DrawText(s
, x
, rect
.y
);
794 void wxStdRenderer::DrawLineWrapMark(wxDC
& WXUNUSED(dc
),
795 const wxRect
& WXUNUSED(rect
))
797 // nothing by default
800 int wxStdRenderer::GetTextBorderWidth(const wxTextCtrl
* WXUNUSED(text
)) const
806 wxStdRenderer::GetTextTotalArea(const wxTextCtrl
*text
, const wxRect
& rect
) const
808 wxRect rectTotal
= rect
;
809 rectTotal
.Inflate(GetTextBorderWidth(text
));
813 wxRect
wxStdRenderer::GetTextClientArea(const wxTextCtrl
*text
,
815 wxCoord
*extraSpaceBeyond
) const
817 wxRect rectText
= rect
;
818 rectText
.Deflate(GetTextBorderWidth(text
));
820 if ( extraSpaceBeyond
)
821 *extraSpaceBeyond
= 0;
826 #endif // wxUSE_TEXTCTRL
828 // ----------------------------------------------------------------------------
829 // scrollbars drawing
830 // ----------------------------------------------------------------------------
832 void wxStdRenderer::DrawScrollbarArrow(wxDC
& dc
,
837 DrawArrow(dc
, dir
, rect
, flags
);
840 void wxStdRenderer::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
842 DrawSolidRect(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
845 // ----------------------------------------------------------------------------
847 // ----------------------------------------------------------------------------
851 wxSize
wxStdRenderer::GetStatusBarBorders() const
853 // Rendered border may be different depending on field's style, we use
854 // the largest value so that any field certainly fits into the borders
856 wxRect raised
= GetBorderDimensions(wxBORDER_RAISED
);
857 wxRect flat
= GetBorderDimensions(wxBORDER_STATIC
);
858 wxASSERT_MSG( raised
.x
== raised
.width
&& raised
.y
== raised
.height
&&
859 flat
.x
== flat
.width
&& flat
.y
== flat
.height
,
860 _T("this code expects uniform borders, you must override GetStatusBarBorders") );
862 // take the larger of flat/raised values:
863 wxSize
border(wxMax(raised
.x
, flat
.x
), wxMax(raised
.y
, flat
.y
));
868 wxCoord
wxStdRenderer::GetStatusBarBorderBetweenFields() const
873 wxSize
wxStdRenderer::GetStatusBarFieldMargins() const
878 void wxStdRenderer::DrawStatusField(wxDC
& dc
,
880 const wxString
& label
,
886 if ( style
== wxSB_RAISED
)
887 DrawBorder(dc
, wxBORDER_RAISED
, rect
, flags
, &rectIn
);
888 else if ( style
!= wxSB_FLAT
)
889 DrawBorder(dc
, wxBORDER_STATIC
, rect
, flags
, &rectIn
);
891 rectIn
.Deflate(GetStatusBarFieldMargins());
893 wxDCClipper
clipper(dc
, rectIn
);
894 DrawLabel(dc
, label
, rectIn
, flags
, wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
897 #endif // wxUSE_STATUSBAR
899 // ----------------------------------------------------------------------------
901 // ----------------------------------------------------------------------------
903 int wxStdRenderer::HitTestFrame(const wxRect
& rect
, const wxPoint
& pt
, int flags
) const
905 wxRect client
= GetFrameClientArea(rect
, flags
);
907 if ( client
.Contains(pt
) )
908 return wxHT_TOPLEVEL_CLIENT_AREA
;
910 if ( flags
& wxTOPLEVEL_TITLEBAR
)
912 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
914 if ( flags
& wxTOPLEVEL_ICON
)
916 if ( wxRect(client
.GetPosition(), GetFrameIconSize()).Contains(pt
) )
917 return wxHT_TOPLEVEL_ICON
;
920 wxRect
btnRect(client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
,
921 client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2,
922 FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
924 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
926 if ( btnRect
.Contains(pt
) )
927 return wxHT_TOPLEVEL_BUTTON_CLOSE
;
928 btnRect
.x
-= FRAME_BUTTON_WIDTH
+ 2;
930 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
932 if ( btnRect
.Contains(pt
) )
933 return wxHT_TOPLEVEL_BUTTON_MAXIMIZE
;
934 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
936 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
938 if ( btnRect
.Contains(pt
) )
939 return wxHT_TOPLEVEL_BUTTON_RESTORE
;
940 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
942 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
944 if ( btnRect
.Contains(pt
) )
945 return wxHT_TOPLEVEL_BUTTON_ICONIZE
;
946 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
948 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
950 if ( btnRect
.Contains(pt
) )
951 return wxHT_TOPLEVEL_BUTTON_HELP
;
952 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
955 if ( pt
.y
>= client
.y
&& pt
.y
< client
.y
+ FRAME_TITLEBAR_HEIGHT
)
956 return wxHT_TOPLEVEL_TITLEBAR
;
959 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
961 // we are certainly at one of borders, let's decide which one:
964 // dirty trick, relies on the way wxHT_TOPLEVEL_XXX are defined!
965 if ( pt
.x
< client
.x
)
966 border
|= wxHT_TOPLEVEL_BORDER_W
;
967 else if ( pt
.x
>= client
.width
+ client
.x
)
968 border
|= wxHT_TOPLEVEL_BORDER_E
;
969 if ( pt
.y
< client
.y
)
970 border
|= wxHT_TOPLEVEL_BORDER_N
;
971 else if ( pt
.y
>= client
.height
+ client
.y
)
972 border
|= wxHT_TOPLEVEL_BORDER_S
;
979 void wxStdRenderer::DrawFrameTitleBar(wxDC
& dc
,
981 const wxString
& title
,
985 int specialButtonFlags
)
987 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
989 DrawFrameBorder(dc
, rect
, flags
);
991 if ( flags
& wxTOPLEVEL_TITLEBAR
)
993 DrawFrameBackground(dc
, rect
, flags
);
994 if ( flags
& wxTOPLEVEL_ICON
)
995 DrawFrameIcon(dc
, rect
, icon
, flags
);
996 DrawFrameTitle(dc
, rect
, title
, flags
);
998 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1000 x
= client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
;
1001 y
= client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2;
1003 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
1005 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_CLOSE
,
1006 (specialButton
== wxTOPLEVEL_BUTTON_CLOSE
) ?
1007 specialButtonFlags
: 0);
1008 x
-= FRAME_BUTTON_WIDTH
+ 2;
1010 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
1012 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_MAXIMIZE
,
1013 (specialButton
== wxTOPLEVEL_BUTTON_MAXIMIZE
) ?
1014 specialButtonFlags
: 0);
1015 x
-= FRAME_BUTTON_WIDTH
;
1017 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
1019 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_RESTORE
,
1020 (specialButton
== wxTOPLEVEL_BUTTON_RESTORE
) ?
1021 specialButtonFlags
: 0);
1022 x
-= FRAME_BUTTON_WIDTH
;
1024 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
1026 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_ICONIZE
,
1027 (specialButton
== wxTOPLEVEL_BUTTON_ICONIZE
) ?
1028 specialButtonFlags
: 0);
1029 x
-= FRAME_BUTTON_WIDTH
;
1031 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
1033 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_HELP
,
1034 (specialButton
== wxTOPLEVEL_BUTTON_HELP
) ?
1035 specialButtonFlags
: 0);
1040 void wxStdRenderer::DrawFrameBorder(wxDC
& dc
, const wxRect
& rect
, int flags
)
1042 if ( !(flags
& wxTOPLEVEL_BORDER
) )
1047 DrawAntiSunkenBorder(dc
, &r
);
1048 DrawExtraBorder(dc
, &r
);
1049 if ( flags
& wxTOPLEVEL_RESIZEABLE
)
1050 DrawExtraBorder(dc
, &r
);
1053 void wxStdRenderer::DrawFrameBackground(wxDC
& dc
, const wxRect
& rect
, int flags
)
1055 if ( !(flags
& wxTOPLEVEL_TITLEBAR
) )
1058 wxColour col
= m_scheme
->Get(flags
& wxTOPLEVEL_ACTIVE
1059 ? wxColourScheme::TITLEBAR_ACTIVE
1060 : wxColourScheme::TITLEBAR
);
1062 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1063 r
.height
= FRAME_TITLEBAR_HEIGHT
;
1065 DrawBackground(dc
, col
, r
);
1068 void wxStdRenderer::DrawFrameTitle(wxDC
& dc
,
1070 const wxString
& title
,
1073 wxColour col
= m_scheme
->Get(flags
& wxTOPLEVEL_ACTIVE
1074 ? wxColourScheme::TITLEBAR_ACTIVE_TEXT
1075 : wxColourScheme::TITLEBAR_TEXT
);
1076 dc
.SetTextForeground(col
);
1078 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1079 r
.height
= FRAME_TITLEBAR_HEIGHT
;
1080 if ( flags
& wxTOPLEVEL_ICON
)
1082 r
.x
+= FRAME_TITLEBAR_HEIGHT
;
1083 r
.width
-= FRAME_TITLEBAR_HEIGHT
+ 2;
1091 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
1092 r
.width
-= FRAME_BUTTON_WIDTH
+ 2;
1093 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
1094 r
.width
-= FRAME_BUTTON_WIDTH
;
1095 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
1096 r
.width
-= FRAME_BUTTON_WIDTH
;
1097 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
1098 r
.width
-= FRAME_BUTTON_WIDTH
;
1099 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
1100 r
.width
-= FRAME_BUTTON_WIDTH
;
1102 dc
.SetFont(m_titlebarFont
);
1106 dc
.GetTextExtent(title
, &textW
, NULL
);
1107 if ( textW
> r
.width
)
1109 // text is too big, let's shorten it and add "..." after it:
1110 size_t len
= title
.length();
1111 wxCoord WSoFar
, letterW
;
1113 dc
.GetTextExtent(wxT("..."), &WSoFar
, NULL
);
1114 if ( WSoFar
> r
.width
)
1116 // not enough space to draw anything
1121 for (size_t i
= 0; i
< len
; i
++)
1123 dc
.GetTextExtent(title
[i
], &letterW
, NULL
);
1124 if ( letterW
+ WSoFar
> r
.width
)
1131 else // no need to truncate the title
1136 dc
.DrawLabel(s
, wxNullBitmap
, r
, wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
1139 void wxStdRenderer::DrawFrameIcon(wxDC
& dc
,
1146 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1147 dc
.DrawIcon(icon
, r
.x
, r
.y
);
1151 void wxStdRenderer::DrawFrameButton(wxDC
& dc
,
1152 wxCoord x
, wxCoord y
,
1156 FrameButtonType idx
;
1159 case wxTOPLEVEL_BUTTON_CLOSE
: idx
= FrameButton_Close
; break;
1160 case wxTOPLEVEL_BUTTON_MAXIMIZE
: idx
= FrameButton_Maximize
; break;
1161 case wxTOPLEVEL_BUTTON_ICONIZE
: idx
= FrameButton_Minimize
; break;
1162 case wxTOPLEVEL_BUTTON_RESTORE
: idx
= FrameButton_Restore
; break;
1163 case wxTOPLEVEL_BUTTON_HELP
: idx
= FrameButton_Help
; break;
1165 wxFAIL_MSG(wxT("incorrect button specification"));
1169 wxBitmap bmp
= GetFrameButtonBitmap(idx
);
1173 wxRect
rectBtn(x
, y
, FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
1174 if ( flags
& wxCONTROL_PRESSED
)
1176 DrawSunkenBorder(dc
, &rectBtn
);
1178 rectBtn
.Offset(1, 1);
1182 DrawRaisedBorder(dc
, &rectBtn
);
1185 DrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rectBtn
);
1187 wxRect
rectBmp(0, 0, bmp
.GetWidth(), bmp
.GetHeight());
1188 dc
.DrawBitmap(bmp
, rectBmp
.CentreIn(rectBtn
).GetPosition(), true);
1191 int wxStdRenderer::GetFrameBorderWidth(int flags
) const
1193 return flags
& wxTOPLEVEL_RESIZEABLE
? 4 : 3;
1197 wxRect
wxStdRenderer::GetFrameClientArea(const wxRect
& rect
, int flags
) const
1201 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1203 r
.Inflate(-GetFrameBorderWidth(flags
));
1206 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1208 r
.y
+= FRAME_TITLEBAR_HEIGHT
;
1209 r
.height
-= FRAME_TITLEBAR_HEIGHT
;
1216 wxStdRenderer::GetFrameTotalSize(const wxSize
& clientSize
, int flags
) const
1218 wxSize
s(clientSize
);
1220 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1222 s
.IncBy(2*GetFrameBorderWidth(flags
));
1225 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1226 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
1231 wxSize
wxStdRenderer::GetFrameMinSize(int flags
) const
1235 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1237 s
.IncBy(2*GetFrameBorderWidth(flags
));
1240 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1242 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
1244 if ( flags
& wxTOPLEVEL_ICON
)
1245 s
.x
+= FRAME_TITLEBAR_HEIGHT
+ 2;
1246 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
1247 s
.x
+= FRAME_BUTTON_WIDTH
+ 2;
1248 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
1249 s
.x
+= FRAME_BUTTON_WIDTH
;
1250 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
1251 s
.x
+= FRAME_BUTTON_WIDTH
;
1252 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
1253 s
.x
+= FRAME_BUTTON_WIDTH
;
1254 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
1255 s
.x
+= FRAME_BUTTON_WIDTH
;
1261 wxSize
wxStdRenderer::GetFrameIconSize() const
1263 return wxSize(16, 16);