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"
29 #include "wx/univ/stdrend.h"
30 #include "wx/univ/colschem.h"
32 // ----------------------------------------------------------------------------
34 // ----------------------------------------------------------------------------
36 static const int FRAME_BORDER_THICKNESS
= 3;
37 static const int RESIZEABLE_FRAME_BORDER_THICKNESS
= 4;
38 static const int FRAME_TITLEBAR_HEIGHT
= 18;
39 static const int FRAME_BUTTON_WIDTH
= 16;
40 static const int FRAME_BUTTON_HEIGHT
= 14;
42 // ============================================================================
43 // wxStdRenderer implementation
44 // ============================================================================
46 // ----------------------------------------------------------------------------
48 // ----------------------------------------------------------------------------
50 wxStdRenderer::wxStdRenderer(const wxColourScheme
*scheme
)
53 m_penBlack
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_DARK
));
54 m_penDarkGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_OUT
));
55 m_penLightGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_IN
));
56 m_penHighlight
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_HIGHLIGHT
));
58 m_titlebarFont
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
);
59 m_titlebarFont
.SetWeight(wxFONTWEIGHT_BOLD
);
62 // ----------------------------------------------------------------------------
64 // ----------------------------------------------------------------------------
67 wxStdRenderer::DrawSolidRect(wxDC
& dc
, const wxColour
& col
, const wxRect
& rect
)
69 wxBrush
brush(col
, wxSOLID
);
71 dc
.SetPen(*wxTRANSPARENT_PEN
);
72 dc
.DrawRectangle(rect
);
75 void wxStdRenderer::DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
79 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
80 dc
.DrawRectangle(*rect
);
86 void wxStdRenderer::DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
87 const wxPen
& pen1
, const wxPen
& pen2
)
91 dc
.DrawLine(rect
->GetLeft(), rect
->GetTop(),
92 rect
->GetLeft(), rect
->GetBottom());
93 dc
.DrawLine(rect
->GetLeft() + 1, rect
->GetTop(),
94 rect
->GetRight(), rect
->GetTop());
96 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
97 rect
->GetRight(), rect
->GetBottom());
98 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
99 rect
->GetRight() + 1, rect
->GetBottom());
105 // ----------------------------------------------------------------------------
106 // translate various flags into corresponding renderer constants
107 // ----------------------------------------------------------------------------
110 void wxStdRenderer::GetIndicatorsFromFlags(int flags
,
111 IndicatorState
& state
,
112 IndicatorStatus
& status
)
114 if ( flags
& wxCONTROL_SELECTED
)
115 state
= flags
& wxCONTROL_DISABLED
? IndicatorState_SelectedDisabled
116 : IndicatorState_Selected
;
117 else if ( flags
& wxCONTROL_DISABLED
)
118 state
= IndicatorState_Disabled
;
119 else if ( flags
& wxCONTROL_PRESSED
)
120 state
= IndicatorState_Pressed
;
122 state
= IndicatorState_Normal
;
124 status
= flags
& wxCONTROL_CHECKED
? IndicatorStatus_Checked
125 : flags
& wxCONTROL_UNDETERMINED
126 ? IndicatorStatus_Undetermined
127 : IndicatorStatus_Unchecked
;
131 wxStdRenderer::ArrowDirection
wxStdRenderer::GetArrowDirection(wxDirection dir
)
148 wxFAIL_MSG(_T("unknown arrow direction"));
154 // ----------------------------------------------------------------------------
156 // ----------------------------------------------------------------------------
158 void wxStdRenderer::DrawBackground(wxDC
& dc
,
164 wxColour colBg
= col
.Ok() ? col
165 : window
? m_scheme
->GetBackground(window
)
166 : wxSCHEME_COLOUR(m_scheme
, CONTROL
);
168 DrawSolidRect(dc
, colBg
, rect
);
172 void wxStdRenderer::DrawButtonSurface(wxDC
& dc
,
177 DrawBackground(dc
, col
, rect
, flags
);
180 // ----------------------------------------------------------------------------
182 // ----------------------------------------------------------------------------
184 void wxStdRenderer::DrawFocusRect(wxDC
& dc
, const wxRect
& rect
)
186 // draw the pixels manually because the "dots" in wxPen with wxDOT style
187 // may be short traits and not really dots
189 // note that to behave in the same manner as DrawRect(), we must exclude
190 // the bottom and right borders from the rectangle
191 wxCoord x1
= rect
.GetLeft(),
193 x2
= rect
.GetRight(),
194 y2
= rect
.GetBottom();
196 dc
.SetPen(m_penBlack
);
198 // this seems to be closer than what Windows does than wxINVERT although
199 // I'm still not sure if it's correct
200 dc
.SetLogicalFunction(wxAND_REVERSE
);
203 for ( z
= x1
+ 1; z
< x2
; z
+= 2 )
204 dc
.DrawPoint(z
, rect
.GetTop());
206 wxCoord shift
= z
== x2
? 0 : 1;
207 for ( z
= y1
+ shift
; z
< y2
; z
+= 2 )
210 shift
= z
== y2
? 0 : 1;
211 for ( z
= x2
- shift
; z
> x1
; z
-= 2 )
214 shift
= z
== x1
? 0 : 1;
215 for ( z
= y2
- shift
; z
> y1
; z
-= 2 )
218 dc
.SetLogicalFunction(wxCOPY
);
221 void wxStdRenderer::DrawLabel(wxDC
& dc
,
222 const wxString
& label
,
229 DrawButtonLabel(dc
, label
, wxNullBitmap
, rect
, flags
,
230 alignment
, indexAccel
, rectBounds
);
233 void wxStdRenderer::DrawButtonLabel(wxDC
& dc
,
234 const wxString
& label
,
235 const wxBitmap
& image
,
242 wxRect rectLabel
= rect
;
243 if ( !label
.empty() && (flags
& wxCONTROL_DISABLED
) )
245 if ( flags
& wxCONTROL_PRESSED
)
247 // shift the label if a button is pressed
248 rectLabel
.Offset(1, 1);
251 // draw shadow of the text
252 dc
.SetTextForeground(m_penHighlight
.GetColour());
253 wxRect rectShadow
= rect
;
254 rectShadow
.Offset(1, 1);
255 dc
.DrawLabel(label
, rectShadow
, alignment
, indexAccel
);
257 // make the main label text grey
258 dc
.SetTextForeground(m_penDarkGrey
.GetColour());
260 if ( flags
& wxCONTROL_FOCUSED
)
262 // leave enough space for the focus rect
263 rectLabel
.Inflate(-2);
267 dc
.DrawLabel(label
, image
, rectLabel
, alignment
, indexAccel
, rectBounds
);
269 if ( !label
.empty() && (flags
& wxCONTROL_FOCUSED
) )
271 rectLabel
.Inflate(-1);
273 DrawFocusRect(dc
, rectLabel
);
277 // ----------------------------------------------------------------------------
279 // ----------------------------------------------------------------------------
282 We implement standard-looking 3D borders which have the following appearance:
286 WWWWWWWWWWWWWWWWWWWWWWB
287 WHHHHHHHHHHHHHHHHHHHHGB
288 WH GB W = white (HILIGHT)
289 WH GB H = light grey (LIGHT)
290 WH GB G = dark grey (SHADOI)
291 WH GB B = black (DKSHADOI)
294 WGGGGGGGGGGGGGGGGGGGGGB
295 BBBBBBBBBBBBBBBBBBBBBBB
297 The sunken border looks like this:
299 GGGGGGGGGGGGGGGGGGGGGGW
300 GBBBBBBBBBBBBBBBBBBBBHW
307 GHHHHHHHHHHHHHHHHHHHHHW
308 WWWWWWWWWWWWWWWWWWWWWWW
310 The static border (used for the controls which don't get focus) is like
313 GGGGGGGGGGGGGGGGGGGGGGW
321 WWWWWWWWWWWWWWWWWWWWWWW
323 The most complicated is the double border which is a combination of special
324 "anti-sunken" border and an extra border inside it:
326 HHHHHHHHHHHHHHHHHHHHHHB
327 HWWWWWWWWWWWWWWWWWWWWGB
328 HWHHHHHHHHHHHHHHHHHHHGB
333 HWHHHHHHHHHHHHHHHHHHHGB
334 HGGGGGGGGGGGGGGGGGGGGGB
335 BBBBBBBBBBBBBBBBBBBBBBB
337 And the simple border is, well, simple:
339 BBBBBBBBBBBBBBBBBBBBBBB
348 BBBBBBBBBBBBBBBBBBBBBBB
351 void wxStdRenderer::DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
)
353 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penBlack
);
354 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penDarkGrey
);
357 void wxStdRenderer::DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
)
359 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
360 DrawShadedRect(dc
, rect
, m_penBlack
, m_penLightGrey
);
363 void wxStdRenderer::DrawAntiSunkenBorder(wxDC
& dc
, wxRect
*rect
)
365 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penBlack
);
366 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
369 void wxStdRenderer::DrawBoxBorder(wxDC
& dc
, wxRect
*rect
)
371 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
372 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
375 void wxStdRenderer::DrawStaticBorder(wxDC
& dc
, wxRect
*rect
)
377 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
380 void wxStdRenderer::DrawExtraBorder(wxDC
& dc
, wxRect
*rect
)
382 DrawRect(dc
, rect
, m_penLightGrey
);
385 void wxStdRenderer::DrawBorder(wxDC
& dc
,
387 const wxRect
& rectTotal
,
391 wxRect rect
= rectTotal
;
395 case wxBORDER_SUNKEN
:
396 DrawSunkenBorder(dc
, &rect
);
399 case wxBORDER_DOUBLE
:
400 DrawAntiSunkenBorder(dc
, &rect
);
401 DrawExtraBorder(dc
, &rect
);
404 case wxBORDER_STATIC
:
405 DrawStaticBorder(dc
, &rect
);
408 case wxBORDER_RAISED
:
409 DrawRaisedBorder(dc
, &rect
);
412 case wxBORDER_SIMPLE
:
413 DrawRect(dc
, &rect
, m_penBlack
);
417 wxFAIL_MSG(_T("unknown border type"));
420 case wxBORDER_DEFAULT
:
429 wxRect
wxStdRenderer::GetBorderDimensions(wxBorder border
) const
434 case wxBORDER_SIMPLE
:
435 case wxBORDER_STATIC
:
439 case wxBORDER_RAISED
:
440 case wxBORDER_SUNKEN
:
444 case wxBORDER_DOUBLE
:
449 wxFAIL_MSG(_T("unknown border type"));
452 case wxBORDER_DEFAULT
:
467 void wxStdRenderer::AdjustSize(wxSize
*size
, const wxWindow
*window
)
469 // take into account the border width
470 wxRect rectBorder
= GetBorderDimensions(window
->GetBorder());
471 size
->x
+= rectBorder
.x
+ rectBorder
.width
;
472 size
->y
+= rectBorder
.y
+ rectBorder
.height
;
475 bool wxStdRenderer::AreScrollbarsInsideBorder() const
480 wxCoord
wxStdRenderer::GetListboxItemHeight(wxCoord fontHeight
)
482 return fontHeight
+ 2;
485 void wxStdRenderer::DrawTextBorder(wxDC
& dc
,
491 DrawBorder(dc
, border
, rect
, flags
, rectIn
);
494 // ----------------------------------------------------------------------------
496 // ----------------------------------------------------------------------------
499 wxStdRenderer::DrawHorizontalLine(wxDC
& dc
, wxCoord y
, wxCoord x1
, wxCoord x2
)
501 dc
.SetPen(m_penDarkGrey
);
502 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
504 dc
.SetPen(m_penHighlight
);
506 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
510 wxStdRenderer::DrawVerticalLine(wxDC
& dc
, wxCoord x
, wxCoord y1
, wxCoord y2
)
512 dc
.SetPen(m_penDarkGrey
);
513 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
515 dc
.SetPen(m_penHighlight
);
517 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
520 void wxStdRenderer::DrawFrameWithoutLabel(wxDC
& dc
,
521 const wxRect
& rectFrame
,
522 const wxRect
& rectLabel
)
524 // draw left, bottom and right lines entirely
525 DrawVerticalLine(dc
, rectFrame
.GetLeft(),
526 rectFrame
.GetTop(), rectFrame
.GetBottom() - 2);
527 DrawHorizontalLine(dc
, rectFrame
.GetBottom() - 1,
528 rectFrame
.GetLeft(), rectFrame
.GetRight());
529 DrawVerticalLine(dc
, rectFrame
.GetRight() - 1,
530 rectFrame
.GetTop(), rectFrame
.GetBottom() - 1);
532 // and 2 parts of the top line
533 DrawHorizontalLine(dc
, rectFrame
.GetTop(),
534 rectFrame
.GetLeft() + 1, rectLabel
.GetLeft());
535 DrawHorizontalLine(dc
, rectFrame
.GetTop(),
536 rectLabel
.GetRight(), rectFrame
.GetRight() - 2);
539 void wxStdRenderer::DrawFrameWithLabel(wxDC
& dc
,
540 const wxString
& label
,
541 const wxRect
& rectFrame
,
542 const wxRect
& rectText
,
548 DrawLabel(dc
, label
, rectText
, flags
, alignment
, indexAccel
, &rectLabel
);
550 DrawFrameWithoutLabel(dc
, rectFrame
, rectLabel
);
553 void wxStdRenderer::DrawFrame(wxDC
& dc
,
554 const wxString
& label
,
560 wxCoord height
= 0; // of the label
561 wxRect rectFrame
= rect
;
562 if ( !label
.empty() )
564 // the text should touch the top border of the rect, so the frame
565 // itself should be lower
566 dc
.GetTextExtent(label
, NULL
, &height
);
567 rectFrame
.y
+= height
/ 2;
568 rectFrame
.height
-= height
/ 2;
570 // we have to draw each part of the frame individually as we can't
571 // erase the background beyond the label as it might contain some
572 // pixmap already, so drawing everything and then overwriting part of
573 // the frame with label doesn't work
575 // TODO: the +5 shouldn't be hard coded
577 rectText
.x
= rectFrame
.x
+ 5;
579 rectText
.width
= rectFrame
.width
- 7; // +2 border width
580 rectText
.height
= height
;
582 DrawFrameWithLabel(dc
, label
, rectFrame
, rectText
, flags
,
583 alignment
, indexAccel
);
587 DrawBoxBorder(dc
, &rectFrame
);
591 void wxStdRenderer::DrawItem(wxDC
& dc
,
592 const wxString
& label
,
596 wxDCTextColourChanger
colChanger(dc
);
598 if ( flags
& wxCONTROL_SELECTED
)
600 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
602 const wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
605 dc
.DrawRectangle(rect
);
608 wxRect rectText
= rect
;
611 dc
.DrawLabel(label
, wxNullBitmap
, rectText
);
613 if ( flags
& wxCONTROL_FOCUSED
)
615 DrawFocusRect(dc
, rect
);
619 void wxStdRenderer::DrawCheckItemBitmap(wxDC
& dc
,
620 const wxBitmap
& bitmap
,
624 DrawCheckButton(dc
, wxEmptyString
, bitmap
, rect
, flags
);
627 void wxStdRenderer::DrawCheckItem(wxDC
& dc
,
628 const wxString
& label
,
629 const wxBitmap
& bitmap
,
633 wxRect rectBitmap
= rect
;
634 rectBitmap
.width
= GetCheckBitmapSize().x
;
635 DrawCheckItemBitmap(dc
, bitmap
, rectBitmap
, flags
);
637 wxRect rectLabel
= rect
;
638 wxCoord shift
= rectBitmap
.width
+ 2*GetCheckItemMargin();
639 rectLabel
.x
+= shift
;
640 rectLabel
.width
-= shift
;
641 DrawItem(dc
, label
, rectLabel
, flags
);
644 // ----------------------------------------------------------------------------
645 // check and radio bitmaps
646 // ----------------------------------------------------------------------------
648 void wxStdRenderer::DrawCheckButton(wxDC
& dc
,
649 const wxString
& label
,
650 const wxBitmap
& bitmap
,
656 wxBitmap
bmp(bitmap
.Ok() ? bitmap
: GetCheckBitmap(flags
));
658 DrawCheckOrRadioButton(dc
, label
, bmp
, rect
, flags
, align
, indexAccel
);
661 void wxStdRenderer::DrawRadioButton(wxDC
& dc
,
662 const wxString
& label
,
663 const wxBitmap
& bitmap
,
669 wxBitmap
bmp(bitmap
.Ok() ? bitmap
: GetRadioBitmap(flags
));
671 DrawCheckOrRadioButton(dc
, label
, bmp
, rect
, flags
, align
, indexAccel
);
674 void wxStdRenderer::DrawCheckOrRadioButton(wxDC
& dc
,
675 const wxString
& label
,
676 const wxBitmap
& bitmap
,
682 // calculate the position of the bitmap and of the label
683 wxCoord heightBmp
= bitmap
.GetHeight();
685 yBmp
= rect
.y
+ (rect
.height
- heightBmp
) / 2;
688 dc
.GetMultiLineTextExtent(label
, NULL
, &rectLabel
.height
);
689 rectLabel
.y
= rect
.y
+ (rect
.height
- rectLabel
.height
) / 2;
691 // align label vertically with the bitmap - looks nicer like this
692 rectLabel
.y
-= (rectLabel
.height
- heightBmp
) % 2;
694 // calc horz position
695 if ( align
== wxALIGN_RIGHT
)
697 xBmp
= rect
.GetRight() - bitmap
.GetWidth();
698 rectLabel
.x
= rect
.x
+ 3;
699 rectLabel
.SetRight(xBmp
);
701 else // normal (checkbox to the left of the text) case
704 rectLabel
.x
= xBmp
+ bitmap
.GetWidth() + 5;
705 rectLabel
.SetRight(rect
.GetRight());
708 dc
.DrawBitmap(bitmap
, xBmp
, yBmp
, true /* use mask */);
710 DrawLabel(dc
, label
, rectLabel
, flags
,
711 wxALIGN_LEFT
| wxALIGN_TOP
, indexAccel
);
716 void wxStdRenderer::DrawTextLine(wxDC
& dc
,
717 const wxString
& text
,
723 if ( (selStart
== -1) || !(flags
& wxCONTROL_FOCUSED
) )
725 // just draw it as is
726 dc
.DrawText(text
, rect
.x
, rect
.y
);
728 else // we have selection
733 // draw the part before selection
734 wxString
s(text
, (size_t)selStart
);
737 dc
.DrawText(s
, x
, rect
.y
);
739 dc
.GetTextExtent(s
, &width
, NULL
);
743 // draw the selection itself
744 s
= wxString(text
.c_str() + selStart
, text
.c_str() + selEnd
);
747 wxColour colFg
= dc
.GetTextForeground(),
748 colBg
= dc
.GetTextBackground();
749 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
750 dc
.SetTextBackground(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
));
751 dc
.SetBackgroundMode(wxSOLID
);
753 dc
.DrawText(s
, x
, rect
.y
);
754 dc
.GetTextExtent(s
, &width
, NULL
);
757 dc
.SetBackgroundMode(wxTRANSPARENT
);
758 dc
.SetTextBackground(colBg
);
759 dc
.SetTextForeground(colFg
);
762 // draw the final part
763 s
= text
.c_str() + selEnd
;
766 dc
.DrawText(s
, x
, rect
.y
);
771 void wxStdRenderer::DrawLineWrapMark(wxDC
& WXUNUSED(dc
),
772 const wxRect
& WXUNUSED(rect
))
774 // nothing by default
777 int wxStdRenderer::GetTextBorderWidth(const wxTextCtrl
* WXUNUSED(text
)) const
783 wxStdRenderer::GetTextTotalArea(const wxTextCtrl
*text
, const wxRect
& rect
) const
785 wxRect rectTotal
= rect
;
786 rectTotal
.Inflate(GetTextBorderWidth(text
));
790 wxRect
wxStdRenderer::GetTextClientArea(const wxTextCtrl
*text
,
792 wxCoord
*extraSpaceBeyond
) const
794 wxRect rectText
= rect
;
795 rectText
.Deflate(GetTextBorderWidth(text
));
797 if ( extraSpaceBeyond
)
798 *extraSpaceBeyond
= 0;
803 #endif // wxUSE_TEXTCTRL
805 // ----------------------------------------------------------------------------
806 // scrollbars drawing
807 // ----------------------------------------------------------------------------
809 void wxStdRenderer::DrawScrollbarArrow(wxDC
& dc
,
814 DrawArrow(dc
, dir
, rect
, flags
);
817 void wxStdRenderer::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
819 DrawSolidRect(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
822 // ----------------------------------------------------------------------------
823 // scrollbars geometry
824 // ----------------------------------------------------------------------------
829 void wxStdRenderer::GetScrollBarThumbSize(wxCoord length
,
836 // the thumb can't be made less than this number of pixels
837 static const wxCoord thumbMinWidth
= 8; // FIXME: should be configurable
839 *thumbStart
= (length
*thumbPos
) / range
;
840 *thumbEnd
= (length
*(thumbPos
+ thumbSize
)) / range
;
842 if ( *thumbEnd
- *thumbStart
< thumbMinWidth
)
844 // adjust the end if possible
845 if ( *thumbStart
<= length
- thumbMinWidth
)
847 // yes, just make it wider
848 *thumbEnd
= *thumbStart
+ thumbMinWidth
;
850 else // it is at the bottom of the scrollbar
852 // so move it a bit up
853 *thumbStart
= length
- thumbMinWidth
;
859 wxRect
wxStdRenderer::GetScrollbarRect(const wxScrollBar
*scrollbar
,
860 wxScrollBar::Element elem
,
863 if ( thumbPos
== -1 )
865 thumbPos
= scrollbar
->GetThumbPosition();
868 const wxSize sizeArrow
= GetScrollbarArrowSize();
870 wxSize sizeTotal
= scrollbar
->GetClientSize();
871 wxCoord
*start
, *width
;
872 wxCoord length
, arrow
;
874 if ( scrollbar
->IsVertical() )
877 rect
.width
= sizeTotal
.x
;
878 length
= sizeTotal
.y
;
880 width
= &rect
.height
;
886 rect
.height
= sizeTotal
.y
;
887 length
= sizeTotal
.x
;
895 case wxScrollBar::Element_Arrow_Line_1
:
900 case wxScrollBar::Element_Arrow_Line_2
:
901 *start
= length
- arrow
;
905 case wxScrollBar::Element_Arrow_Page_1
:
906 case wxScrollBar::Element_Arrow_Page_2
:
907 // we don't have them at all
910 case wxScrollBar::Element_Thumb
:
911 case wxScrollBar::Element_Bar_1
:
912 case wxScrollBar::Element_Bar_2
:
913 // we need to calculate the thumb position - do it
916 wxCoord thumbStart
, thumbEnd
;
917 int range
= scrollbar
->GetRange();
925 GetScrollBarThumbSize(length
,
927 scrollbar
->GetThumbSize(),
933 if ( elem
== wxScrollBar::Element_Thumb
)
936 *width
= thumbEnd
- thumbStart
;
938 else if ( elem
== wxScrollBar::Element_Bar_1
)
943 else // elem == wxScrollBar::Element_Bar_2
946 *width
= length
- thumbEnd
;
949 // everything is relative to the start of the shaft so far
954 case wxScrollBar::Element_Max
:
956 wxFAIL_MSG( _T("unknown scrollbar element") );
962 wxCoord
wxStdRenderer::GetScrollbarSize(const wxScrollBar
*scrollbar
)
964 const wxSize sizeArrowSB
= GetScrollbarArrowSize();
966 wxCoord sizeArrow
, sizeTotal
;
967 if ( scrollbar
->GetWindowStyle() & wxVERTICAL
)
969 sizeArrow
= sizeArrowSB
.y
;
970 sizeTotal
= scrollbar
->GetSize().y
;
974 sizeArrow
= sizeArrowSB
.x
;
975 sizeTotal
= scrollbar
->GetSize().x
;
978 return sizeTotal
- 2*sizeArrow
;
982 wxStdRenderer::HitTestScrollbar(const wxScrollBar
*scrollbar
, const wxPoint
& pt
) const
984 // we only need to work with either x or y coord depending on the
985 // orientation, choose one (but still check the other one to verify if the
986 // mouse is in the window at all)
987 const wxSize sizeArrowSB
= GetScrollbarArrowSize();
989 wxCoord coord
, sizeArrow
, sizeTotal
;
990 wxSize size
= scrollbar
->GetSize();
991 if ( scrollbar
->GetWindowStyle() & wxVERTICAL
)
993 if ( pt
.x
< 0 || pt
.x
> size
.x
)
997 sizeArrow
= sizeArrowSB
.y
;
1002 if ( pt
.y
< 0 || pt
.y
> size
.y
)
1003 return wxHT_NOWHERE
;
1006 sizeArrow
= sizeArrowSB
.x
;
1010 // test for the arrows first as it's faster
1011 if ( coord
< 0 || coord
> sizeTotal
)
1013 return wxHT_NOWHERE
;
1015 else if ( coord
< sizeArrow
)
1017 return wxHT_SCROLLBAR_ARROW_LINE_1
;
1019 else if ( coord
> sizeTotal
- sizeArrow
)
1021 return wxHT_SCROLLBAR_ARROW_LINE_2
;
1025 // calculate the thumb position in pixels
1026 sizeTotal
-= 2*sizeArrow
;
1027 wxCoord thumbStart
, thumbEnd
;
1028 int range
= scrollbar
->GetRange();
1031 // clicking the scrollbar without range has no effect
1032 return wxHT_NOWHERE
;
1036 GetScrollBarThumbSize(sizeTotal
,
1037 scrollbar
->GetThumbPosition(),
1038 scrollbar
->GetThumbSize(),
1044 // now compare with the thumb position
1046 if ( coord
< thumbStart
)
1047 return wxHT_SCROLLBAR_BAR_1
;
1048 else if ( coord
> thumbEnd
)
1049 return wxHT_SCROLLBAR_BAR_2
;
1051 return wxHT_SCROLLBAR_THUMB
;
1057 wxStdRenderer::ScrollbarToPixel(const wxScrollBar
*scrollbar
, int thumbPos
)
1059 int range
= scrollbar
->GetRange();
1062 // the only valid position anyhow
1066 if ( thumbPos
== -1 )
1068 // by default use the current thumb position
1069 thumbPos
= scrollbar
->GetThumbPosition();
1072 const wxSize sizeArrow
= GetScrollbarArrowSize();
1073 return (thumbPos
*GetScrollbarSize(scrollbar
)) / range
1074 + (scrollbar
->IsVertical() ? sizeArrow
.y
: sizeArrow
.x
);
1077 int wxStdRenderer::PixelToScrollbar(const wxScrollBar
*scrollbar
, wxCoord coord
)
1079 const wxSize sizeArrow
= GetScrollbarArrowSize();
1080 return ((coord
- (scrollbar
->IsVertical() ? sizeArrow
.y
: sizeArrow
.x
)) *
1081 scrollbar
->GetRange() ) / GetScrollbarSize(scrollbar
);
1084 #endif // wxUSE_SCROLLBAR
1086 // ----------------------------------------------------------------------------
1088 // ----------------------------------------------------------------------------
1092 wxSize
wxStdRenderer::GetStatusBarBorders(wxCoord
*borderBetweenFields
) const
1094 if ( borderBetweenFields
)
1095 *borderBetweenFields
= 2;
1097 return wxSize(2, 2);
1100 void wxStdRenderer::DrawStatusField(wxDC
& dc
,
1102 const wxString
& label
,
1108 if ( style
== wxSB_RAISED
)
1109 DrawBorder(dc
, wxBORDER_RAISED
, rect
, flags
, &rectIn
);
1110 else if ( style
!= wxSB_FLAT
)
1111 DrawBorder(dc
, wxBORDER_STATIC
, rect
, flags
, &rectIn
);
1113 rectIn
.Deflate(GetStatusBarBorders(NULL
));
1115 wxDCClipper
clipper(dc
, rectIn
);
1116 DrawLabel(dc
, label
, rectIn
, flags
, wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
1119 #endif // wxUSE_STATUSBAR
1121 // ----------------------------------------------------------------------------
1122 // top level windows
1123 // ----------------------------------------------------------------------------
1125 int wxStdRenderer::HitTestFrame(const wxRect
& rect
, const wxPoint
& pt
, int flags
) const
1127 wxRect client
= GetFrameClientArea(rect
, flags
);
1129 if ( client
.Contains(pt
) )
1130 return wxHT_TOPLEVEL_CLIENT_AREA
;
1132 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1134 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1136 if ( flags
& wxTOPLEVEL_ICON
)
1138 if ( wxRect(client
.GetPosition(), GetFrameIconSize()).Contains(pt
) )
1139 return wxHT_TOPLEVEL_ICON
;
1142 wxRect
btnRect(client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
,
1143 client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2,
1144 FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
1146 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
1148 if ( btnRect
.Contains(pt
) )
1149 return wxHT_TOPLEVEL_BUTTON_CLOSE
;
1150 btnRect
.x
-= FRAME_BUTTON_WIDTH
+ 2;
1152 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
1154 if ( btnRect
.Contains(pt
) )
1155 return wxHT_TOPLEVEL_BUTTON_MAXIMIZE
;
1156 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
1158 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
1160 if ( btnRect
.Contains(pt
) )
1161 return wxHT_TOPLEVEL_BUTTON_RESTORE
;
1162 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
1164 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
1166 if ( btnRect
.Contains(pt
) )
1167 return wxHT_TOPLEVEL_BUTTON_ICONIZE
;
1168 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
1170 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
1172 if ( btnRect
.Contains(pt
) )
1173 return wxHT_TOPLEVEL_BUTTON_HELP
;
1174 btnRect
.x
-= FRAME_BUTTON_WIDTH
;
1177 if ( pt
.y
>= client
.y
&& pt
.y
< client
.y
+ FRAME_TITLEBAR_HEIGHT
)
1178 return wxHT_TOPLEVEL_TITLEBAR
;
1181 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1183 // we are certainly at one of borders, let's decide which one:
1186 // dirty trick, relies on the way wxHT_TOPLEVEL_XXX are defined!
1187 if ( pt
.x
< client
.x
)
1188 border
|= wxHT_TOPLEVEL_BORDER_W
;
1189 else if ( pt
.x
>= client
.width
+ client
.x
)
1190 border
|= wxHT_TOPLEVEL_BORDER_E
;
1191 if ( pt
.y
< client
.y
)
1192 border
|= wxHT_TOPLEVEL_BORDER_N
;
1193 else if ( pt
.y
>= client
.height
+ client
.y
)
1194 border
|= wxHT_TOPLEVEL_BORDER_S
;
1198 return wxHT_NOWHERE
;
1201 void wxStdRenderer::DrawFrameTitleBar(wxDC
& dc
,
1203 const wxString
& title
,
1207 int specialButtonFlags
)
1209 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1211 DrawFrameBorder(dc
, rect
, flags
);
1213 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1215 DrawFrameBackground(dc
, rect
, flags
);
1216 if ( flags
& wxTOPLEVEL_ICON
)
1217 DrawFrameIcon(dc
, rect
, icon
, flags
);
1218 DrawFrameTitle(dc
, rect
, title
, flags
);
1220 wxRect client
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1222 x
= client
.GetRight() - 2 - FRAME_BUTTON_WIDTH
;
1223 y
= client
.GetTop() + (FRAME_TITLEBAR_HEIGHT
-FRAME_BUTTON_HEIGHT
)/2;
1225 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
1227 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_CLOSE
,
1228 (specialButton
== wxTOPLEVEL_BUTTON_CLOSE
) ?
1229 specialButtonFlags
: 0);
1230 x
-= FRAME_BUTTON_WIDTH
+ 2;
1232 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
1234 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_MAXIMIZE
,
1235 (specialButton
== wxTOPLEVEL_BUTTON_MAXIMIZE
) ?
1236 specialButtonFlags
: 0);
1237 x
-= FRAME_BUTTON_WIDTH
;
1239 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
1241 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_RESTORE
,
1242 (specialButton
== wxTOPLEVEL_BUTTON_RESTORE
) ?
1243 specialButtonFlags
: 0);
1244 x
-= FRAME_BUTTON_WIDTH
;
1246 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
1248 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_ICONIZE
,
1249 (specialButton
== wxTOPLEVEL_BUTTON_ICONIZE
) ?
1250 specialButtonFlags
: 0);
1251 x
-= FRAME_BUTTON_WIDTH
;
1253 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
1255 DrawFrameButton(dc
, x
, y
, wxTOPLEVEL_BUTTON_HELP
,
1256 (specialButton
== wxTOPLEVEL_BUTTON_HELP
) ?
1257 specialButtonFlags
: 0);
1262 void wxStdRenderer::DrawFrameBorder(wxDC
& dc
, const wxRect
& rect
, int flags
)
1264 if ( !(flags
& wxTOPLEVEL_BORDER
) )
1269 DrawAntiSunkenBorder(dc
, &r
);
1270 DrawExtraBorder(dc
, &r
);
1271 if ( flags
& wxTOPLEVEL_RESIZEABLE
)
1272 DrawExtraBorder(dc
, &r
);
1275 void wxStdRenderer::DrawFrameBackground(wxDC
& dc
, const wxRect
& rect
, int flags
)
1277 if ( !(flags
& wxTOPLEVEL_TITLEBAR
) )
1280 wxColour col
= m_scheme
->Get(flags
& wxTOPLEVEL_ACTIVE
1281 ? wxColourScheme::TITLEBAR_ACTIVE
1282 : wxColourScheme::TITLEBAR
);
1284 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1285 r
.height
= FRAME_TITLEBAR_HEIGHT
;
1287 DrawBackground(dc
, col
, r
);
1290 void wxStdRenderer::DrawFrameTitle(wxDC
& dc
,
1292 const wxString
& title
,
1295 wxColour col
= m_scheme
->Get(flags
& wxTOPLEVEL_ACTIVE
1296 ? wxColourScheme::TITLEBAR_ACTIVE_TEXT
1297 : wxColourScheme::TITLEBAR_TEXT
);
1298 dc
.SetTextForeground(col
);
1300 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1301 r
.height
= FRAME_TITLEBAR_HEIGHT
;
1302 if ( flags
& wxTOPLEVEL_ICON
)
1304 r
.x
+= FRAME_TITLEBAR_HEIGHT
;
1305 r
.width
-= FRAME_TITLEBAR_HEIGHT
+ 2;
1313 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
1314 r
.width
-= FRAME_BUTTON_WIDTH
+ 2;
1315 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
1316 r
.width
-= FRAME_BUTTON_WIDTH
;
1317 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
1318 r
.width
-= FRAME_BUTTON_WIDTH
;
1319 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
1320 r
.width
-= FRAME_BUTTON_WIDTH
;
1321 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
1322 r
.width
-= FRAME_BUTTON_WIDTH
;
1324 dc
.SetFont(m_titlebarFont
);
1328 dc
.GetTextExtent(title
, &textW
, NULL
);
1329 if ( textW
> r
.width
)
1331 // text is too big, let's shorten it and add "..." after it:
1332 size_t len
= title
.length();
1333 wxCoord WSoFar
, letterW
;
1335 dc
.GetTextExtent(wxT("..."), &WSoFar
, NULL
);
1336 if ( WSoFar
> r
.width
)
1338 // not enough space to draw anything
1343 for (size_t i
= 0; i
< len
; i
++)
1345 dc
.GetTextExtent(title
[i
], &letterW
, NULL
);
1346 if ( letterW
+ WSoFar
> r
.width
)
1353 else // no need to truncate the title
1358 dc
.DrawLabel(s
, wxNullBitmap
, r
, wxALIGN_LEFT
| wxALIGN_CENTRE_VERTICAL
);
1361 void wxStdRenderer::DrawFrameIcon(wxDC
& dc
,
1368 wxRect r
= GetFrameClientArea(rect
, flags
& ~wxTOPLEVEL_TITLEBAR
);
1369 dc
.DrawIcon(icon
, r
.x
, r
.y
);
1373 void wxStdRenderer::DrawFrameButton(wxDC
& dc
,
1374 wxCoord x
, wxCoord y
,
1378 FrameButtonType idx
;
1381 case wxTOPLEVEL_BUTTON_CLOSE
: idx
= FrameButton_Close
; break;
1382 case wxTOPLEVEL_BUTTON_MAXIMIZE
: idx
= FrameButton_Maximize
; break;
1383 case wxTOPLEVEL_BUTTON_ICONIZE
: idx
= FrameButton_Minimize
; break;
1384 case wxTOPLEVEL_BUTTON_RESTORE
: idx
= FrameButton_Restore
; break;
1385 case wxTOPLEVEL_BUTTON_HELP
: idx
= FrameButton_Help
; break;
1387 wxFAIL_MSG(wxT("incorrect button specification"));
1391 wxBitmap bmp
= GetFrameButtonBitmap(idx
);
1395 wxRect
rectBtn(x
, y
, FRAME_BUTTON_WIDTH
, FRAME_BUTTON_HEIGHT
);
1396 if ( flags
& wxCONTROL_PRESSED
)
1398 DrawSunkenBorder(dc
, &rectBtn
);
1400 rectBtn
.Offset(1, 1);
1404 DrawRaisedBorder(dc
, &rectBtn
);
1407 DrawBackground(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rectBtn
);
1409 wxRect
rectBmp(0, 0, bmp
.GetWidth(), bmp
.GetHeight());
1410 dc
.DrawBitmap(bmp
, rectBmp
.CentreIn(rectBtn
).GetPosition(), true);
1414 wxRect
wxStdRenderer::GetFrameClientArea(const wxRect
& rect
, int flags
) const
1418 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1420 int border
= flags
& wxTOPLEVEL_RESIZEABLE
1421 ? RESIZEABLE_FRAME_BORDER_THICKNESS
1422 : FRAME_BORDER_THICKNESS
;
1426 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1428 r
.y
+= FRAME_TITLEBAR_HEIGHT
;
1429 r
.height
-= FRAME_TITLEBAR_HEIGHT
;
1436 wxStdRenderer::GetFrameTotalSize(const wxSize
& clientSize
, int flags
) const
1438 wxSize
s(clientSize
);
1440 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1442 int border
= flags
& wxTOPLEVEL_RESIZEABLE
1443 ? RESIZEABLE_FRAME_BORDER_THICKNESS
1444 : FRAME_BORDER_THICKNESS
;
1449 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1450 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
1455 wxSize
wxStdRenderer::GetFrameMinSize(int flags
) const
1459 if ( (flags
& wxTOPLEVEL_BORDER
) && !(flags
& wxTOPLEVEL_MAXIMIZED
) )
1461 int border
= (flags
& wxTOPLEVEL_RESIZEABLE
) ?
1462 RESIZEABLE_FRAME_BORDER_THICKNESS
:
1463 FRAME_BORDER_THICKNESS
;
1468 if ( flags
& wxTOPLEVEL_TITLEBAR
)
1470 s
.y
+= FRAME_TITLEBAR_HEIGHT
;
1472 if ( flags
& wxTOPLEVEL_ICON
)
1473 s
.x
+= FRAME_TITLEBAR_HEIGHT
+ 2;
1474 if ( flags
& wxTOPLEVEL_BUTTON_CLOSE
)
1475 s
.x
+= FRAME_BUTTON_WIDTH
+ 2;
1476 if ( flags
& wxTOPLEVEL_BUTTON_MAXIMIZE
)
1477 s
.x
+= FRAME_BUTTON_WIDTH
;
1478 if ( flags
& wxTOPLEVEL_BUTTON_RESTORE
)
1479 s
.x
+= FRAME_BUTTON_WIDTH
;
1480 if ( flags
& wxTOPLEVEL_BUTTON_ICONIZE
)
1481 s
.x
+= FRAME_BUTTON_WIDTH
;
1482 if ( flags
& wxTOPLEVEL_BUTTON_HELP
)
1483 s
.x
+= FRAME_BUTTON_WIDTH
;
1489 wxSize
wxStdRenderer::GetFrameIconSize() const
1491 return wxSize(16, 16);