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 // ============================================================================
33 // wxStdRenderer implementation
34 // ============================================================================
36 // ----------------------------------------------------------------------------
38 // ----------------------------------------------------------------------------
40 wxStdRenderer::wxStdRenderer(const wxColourScheme
*scheme
)
43 m_penBlack
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_DARK
));
44 m_penDarkGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_OUT
));
45 m_penLightGrey
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_IN
));
46 m_penHighlight
= wxPen(wxSCHEME_COLOUR(scheme
, SHADOW_HIGHLIGHT
));
49 // ----------------------------------------------------------------------------
51 // ----------------------------------------------------------------------------
54 wxStdRenderer::DrawSolidRect(wxDC
& dc
, const wxColour
& col
, const wxRect
& rect
)
56 wxBrush
brush(col
, wxSOLID
);
58 dc
.SetPen(*wxTRANSPARENT_PEN
);
59 dc
.DrawRectangle(rect
);
62 void wxStdRenderer::DrawRect(wxDC
& dc
, wxRect
*rect
, const wxPen
& pen
)
66 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
67 dc
.DrawRectangle(*rect
);
73 void wxStdRenderer::DrawShadedRect(wxDC
& dc
, wxRect
*rect
,
74 const wxPen
& pen1
, const wxPen
& pen2
)
78 dc
.DrawLine(rect
->GetLeft(), rect
->GetTop(),
79 rect
->GetLeft(), rect
->GetBottom());
80 dc
.DrawLine(rect
->GetLeft() + 1, rect
->GetTop(),
81 rect
->GetRight(), rect
->GetTop());
83 dc
.DrawLine(rect
->GetRight(), rect
->GetTop(),
84 rect
->GetRight(), rect
->GetBottom());
85 dc
.DrawLine(rect
->GetLeft(), rect
->GetBottom(),
86 rect
->GetRight() + 1, rect
->GetBottom());
92 // ----------------------------------------------------------------------------
93 // translate various flags into corresponding renderer constants
94 // ----------------------------------------------------------------------------
97 void wxStdRenderer::GetIndicatorsFromFlags(int flags
,
98 IndicatorState
& state
,
99 IndicatorStatus
& status
)
101 if ( flags
& wxCONTROL_SELECTED
)
102 state
= flags
& wxCONTROL_DISABLED
? IndicatorState_SelectedDisabled
103 : IndicatorState_Selected
;
104 else if ( flags
& wxCONTROL_DISABLED
)
105 state
= IndicatorState_Disabled
;
106 else if ( flags
& wxCONTROL_PRESSED
)
107 state
= IndicatorState_Pressed
;
109 state
= IndicatorState_Normal
;
111 status
= flags
& wxCONTROL_CHECKED
? IndicatorStatus_Checked
112 : flags
& wxCONTROL_UNDETERMINED
113 ? IndicatorStatus_Undetermined
114 : IndicatorStatus_Unchecked
;
118 wxStdRenderer::ArrowDirection
wxStdRenderer::GetArrowDirection(wxDirection dir
)
135 wxFAIL_MSG(_T("unknown arrow direction"));
141 // ----------------------------------------------------------------------------
143 // ----------------------------------------------------------------------------
145 void wxStdRenderer::DrawBackground(wxDC
& dc
,
151 wxColour colBg
= col
.Ok() ? col
152 : window
? m_scheme
->GetBackground(window
)
153 : wxSCHEME_COLOUR(m_scheme
, CONTROL
);
155 DrawSolidRect(dc
, colBg
, rect
);
159 void wxStdRenderer::DrawButtonSurface(wxDC
& dc
,
164 DrawBackground(dc
, col
, rect
, flags
);
167 // ----------------------------------------------------------------------------
169 // ----------------------------------------------------------------------------
171 void wxStdRenderer::DrawFocusRect(wxDC
& dc
, const wxRect
& rect
)
173 // draw the pixels manually because the "dots" in wxPen with wxDOT style
174 // may be short traits and not really dots
176 // note that to behave in the same manner as DrawRect(), we must exclude
177 // the bottom and right borders from the rectangle
178 wxCoord x1
= rect
.GetLeft(),
180 x2
= rect
.GetRight(),
181 y2
= rect
.GetBottom();
183 dc
.SetPen(m_penBlack
);
185 // this seems to be closer than what Windows does than wxINVERT although
186 // I'm still not sure if it's correct
187 dc
.SetLogicalFunction(wxAND_REVERSE
);
190 for ( z
= x1
+ 1; z
< x2
; z
+= 2 )
191 dc
.DrawPoint(z
, rect
.GetTop());
193 wxCoord shift
= z
== x2
? 0 : 1;
194 for ( z
= y1
+ shift
; z
< y2
; z
+= 2 )
197 shift
= z
== y2
? 0 : 1;
198 for ( z
= x2
- shift
; z
> x1
; z
-= 2 )
201 shift
= z
== x1
? 0 : 1;
202 for ( z
= y2
- shift
; z
> y1
; z
-= 2 )
205 dc
.SetLogicalFunction(wxCOPY
);
208 void wxStdRenderer::DrawLabel(wxDC
& dc
,
209 const wxString
& label
,
216 DrawButtonLabel(dc
, label
, wxNullBitmap
, rect
, flags
,
217 alignment
, indexAccel
, rectBounds
);
220 void wxStdRenderer::DrawButtonLabel(wxDC
& dc
,
221 const wxString
& label
,
222 const wxBitmap
& image
,
229 wxRect rectLabel
= rect
;
230 if ( !label
.empty() && (flags
& wxCONTROL_DISABLED
) )
232 if ( flags
& wxCONTROL_PRESSED
)
234 // shift the label if a button is pressed
235 rectLabel
.Offset(1, 1);
238 // draw shadow of the text
239 dc
.SetTextForeground(m_penHighlight
.GetColour());
240 wxRect rectShadow
= rect
;
241 rectShadow
.Offset(1, 1);
242 dc
.DrawLabel(label
, rectShadow
, alignment
, indexAccel
);
244 // make the main label text grey
245 dc
.SetTextForeground(m_penDarkGrey
.GetColour());
247 if ( flags
& wxCONTROL_FOCUSED
)
249 // leave enough space for the focus rect
250 rectLabel
.Inflate(-2);
254 dc
.DrawLabel(label
, image
, rectLabel
, alignment
, indexAccel
, rectBounds
);
256 if ( !label
.empty() && (flags
& wxCONTROL_FOCUSED
) )
258 rectLabel
.Inflate(-1);
260 DrawFocusRect(dc
, rectLabel
);
264 // ----------------------------------------------------------------------------
266 // ----------------------------------------------------------------------------
269 We implement standard-looking 3D borders which have the following appearance:
273 WWWWWWWWWWWWWWWWWWWWWWB
274 WHHHHHHHHHHHHHHHHHHHHGB
275 WH GB W = white (HILIGHT)
276 WH GB H = light grey (LIGHT)
277 WH GB G = dark grey (SHADOI)
278 WH GB B = black (DKSHADOI)
281 WGGGGGGGGGGGGGGGGGGGGGB
282 BBBBBBBBBBBBBBBBBBBBBBB
284 The sunken border looks like this:
286 GGGGGGGGGGGGGGGGGGGGGGW
287 GBBBBBBBBBBBBBBBBBBBBHW
294 GHHHHHHHHHHHHHHHHHHHHHW
295 WWWWWWWWWWWWWWWWWWWWWWW
297 The static border (used for the controls which don't get focus) is like
300 GGGGGGGGGGGGGGGGGGGGGGW
308 WWWWWWWWWWWWWWWWWWWWWWW
310 The most complicated is the double border which is a combination of special
311 "anti-sunken" border and an extra border inside it:
313 HHHHHHHHHHHHHHHHHHHHHHB
314 HWWWWWWWWWWWWWWWWWWWWGB
315 HWHHHHHHHHHHHHHHHHHHHGB
320 HWHHHHHHHHHHHHHHHHHHHGB
321 HGGGGGGGGGGGGGGGGGGGGGB
322 BBBBBBBBBBBBBBBBBBBBBBB
324 And the simple border is, well, simple:
326 BBBBBBBBBBBBBBBBBBBBBBB
335 BBBBBBBBBBBBBBBBBBBBBBB
338 void wxStdRenderer::DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
)
340 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penBlack
);
341 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penDarkGrey
);
344 void wxStdRenderer::DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
)
346 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
347 DrawShadedRect(dc
, rect
, m_penBlack
, m_penLightGrey
);
350 void wxStdRenderer::DrawAntiSunkenBorder(wxDC
& dc
, wxRect
*rect
)
352 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penBlack
);
353 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
356 void wxStdRenderer::DrawFrameBorder(wxDC
& dc
, wxRect
*rect
)
358 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
359 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
362 void wxStdRenderer::DrawBorder(wxDC
& dc
,
364 const wxRect
& rectTotal
,
368 wxRect rect
= rectTotal
;
372 case wxBORDER_SUNKEN
:
373 DrawSunkenBorder(dc
, &rect
);
376 case wxBORDER_DOUBLE
:
377 DrawAntiSunkenBorder(dc
, &rect
);
378 DrawRect(dc
, &rect
, m_penLightGrey
);
381 case wxBORDER_STATIC
:
382 DrawShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
385 case wxBORDER_RAISED
:
386 DrawRaisedBorder(dc
, &rect
);
389 case wxBORDER_SIMPLE
:
390 DrawRect(dc
, &rect
, m_penBlack
);
394 wxFAIL_MSG(_T("unknown border type"));
397 case wxBORDER_DEFAULT
:
406 wxRect
wxStdRenderer::GetBorderDimensions(wxBorder border
) const
411 case wxBORDER_SIMPLE
:
412 case wxBORDER_STATIC
:
416 case wxBORDER_RAISED
:
417 case wxBORDER_SUNKEN
:
421 case wxBORDER_DOUBLE
:
426 wxFAIL_MSG(_T("unknown border type"));
429 case wxBORDER_DEFAULT
:
444 bool wxStdRenderer::AreScrollbarsInsideBorder() const
449 void wxStdRenderer::DrawTextBorder(wxDC
& dc
,
455 DrawBorder(dc
, border
, rect
, flags
, rectIn
);
458 // ----------------------------------------------------------------------------
460 // ----------------------------------------------------------------------------
463 wxStdRenderer::DrawHorizontalLine(wxDC
& dc
, wxCoord y
, wxCoord x1
, wxCoord x2
)
465 dc
.SetPen(m_penDarkGrey
);
466 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
468 dc
.SetPen(m_penHighlight
);
470 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
474 wxStdRenderer::DrawVerticalLine(wxDC
& dc
, wxCoord x
, wxCoord y1
, wxCoord y2
)
476 dc
.SetPen(m_penDarkGrey
);
477 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
479 dc
.SetPen(m_penHighlight
);
481 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
484 void wxStdRenderer::DrawFrameWithoutLabel(wxDC
& dc
,
485 const wxRect
& rectFrame
,
486 const wxRect
& rectLabel
)
488 // draw left, bottom and right lines entirely
489 DrawVerticalLine(dc
, rectFrame
.GetLeft(),
490 rectFrame
.GetTop(), rectFrame
.GetBottom() - 2);
491 DrawHorizontalLine(dc
, rectFrame
.GetBottom() - 1,
492 rectFrame
.GetLeft(), rectFrame
.GetRight());
493 DrawVerticalLine(dc
, rectFrame
.GetRight() - 1,
494 rectFrame
.GetTop(), rectFrame
.GetBottom() - 1);
496 // and 2 parts of the top line
497 DrawHorizontalLine(dc
, rectFrame
.GetTop(),
498 rectFrame
.GetLeft() + 1, rectLabel
.GetLeft());
499 DrawHorizontalLine(dc
, rectFrame
.GetTop(),
500 rectLabel
.GetRight(), rectFrame
.GetRight() - 2);
503 void wxStdRenderer::DrawFrameWithLabel(wxDC
& dc
,
504 const wxString
& label
,
505 const wxRect
& rectFrame
,
506 const wxRect
& rectText
,
512 DrawLabel(dc
, label
, rectText
, flags
, alignment
, indexAccel
, &rectLabel
);
514 DrawFrameWithoutLabel(dc
, rectFrame
, rectLabel
);
517 void wxStdRenderer::DrawFrame(wxDC
& dc
,
518 const wxString
& label
,
524 wxCoord height
= 0; // of the label
525 wxRect rectFrame
= rect
;
526 if ( !label
.empty() )
528 // the text should touch the top border of the rect, so the frame
529 // itself should be lower
530 dc
.GetTextExtent(label
, NULL
, &height
);
531 rectFrame
.y
+= height
/ 2;
532 rectFrame
.height
-= height
/ 2;
534 // we have to draw each part of the frame individually as we can't
535 // erase the background beyond the label as it might contain some
536 // pixmap already, so drawing everything and then overwriting part of
537 // the frame with label doesn't work
539 // TODO: the +5 shouldn't be hard coded
541 rectText
.x
= rectFrame
.x
+ 5;
543 rectText
.width
= rectFrame
.width
- 7; // +2 border width
544 rectText
.height
= height
;
546 DrawFrameWithLabel(dc
, label
, rectFrame
, rectText
, flags
,
547 alignment
, indexAccel
);
551 DrawFrameBorder(dc
, &rectFrame
);
555 void wxStdRenderer::DrawItem(wxDC
& dc
,
556 const wxString
& label
,
560 wxDCTextColourChanger
colChanger(dc
);
562 if ( flags
& wxCONTROL_SELECTED
)
564 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
566 const wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
569 dc
.DrawRectangle(rect
);
572 wxRect rectText
= rect
;
575 dc
.DrawLabel(label
, wxNullBitmap
, rectText
);
577 if ( flags
& wxCONTROL_FOCUSED
)
579 DrawFocusRect(dc
, rect
);
583 void wxStdRenderer::DrawCheckItemBitmap(wxDC
& dc
,
584 const wxBitmap
& bitmap
,
588 DrawCheckButton(dc
, wxEmptyString
, bitmap
, rect
, flags
);
591 void wxStdRenderer::DrawCheckItem(wxDC
& dc
,
592 const wxString
& label
,
593 const wxBitmap
& bitmap
,
597 wxRect rectBitmap
= rect
;
598 rectBitmap
.width
= GetCheckBitmapSize().x
;
599 DrawCheckItemBitmap(dc
, bitmap
, rectBitmap
, flags
);
601 wxRect rectLabel
= rect
;
602 wxCoord shift
= rectBitmap
.width
+ 2*GetCheckItemMargin();
603 rectLabel
.x
+= shift
;
604 rectLabel
.width
-= shift
;
605 DrawItem(dc
, label
, rectLabel
, flags
);
608 // ----------------------------------------------------------------------------
609 // check and radio bitmaps
610 // ----------------------------------------------------------------------------
612 void wxStdRenderer::DrawCheckButton(wxDC
& dc
,
613 const wxString
& label
,
614 const wxBitmap
& bitmap
,
620 wxBitmap
bmp(bitmap
.Ok() ? bitmap
: GetCheckBitmap(flags
));
622 DrawCheckOrRadioButton(dc
, label
, bmp
, rect
, flags
, align
, indexAccel
);
625 void wxStdRenderer::DrawRadioButton(wxDC
& dc
,
626 const wxString
& label
,
627 const wxBitmap
& bitmap
,
633 wxBitmap
bmp(bitmap
.Ok() ? bitmap
: GetRadioBitmap(flags
));
635 DrawCheckOrRadioButton(dc
, label
, bmp
, rect
, flags
, align
, indexAccel
);
638 void wxStdRenderer::DrawCheckOrRadioButton(wxDC
& dc
,
639 const wxString
& label
,
640 const wxBitmap
& bitmap
,
646 // calculate the position of the bitmap and of the label
647 wxCoord heightBmp
= bitmap
.GetHeight();
649 yBmp
= rect
.y
+ (rect
.height
- heightBmp
) / 2;
652 dc
.GetMultiLineTextExtent(label
, NULL
, &rectLabel
.height
);
653 rectLabel
.y
= rect
.y
+ (rect
.height
- rectLabel
.height
) / 2;
655 // align label vertically with the bitmap - looks nicer like this
656 rectLabel
.y
-= (rectLabel
.height
- heightBmp
) % 2;
658 // calc horz position
659 if ( align
== wxALIGN_RIGHT
)
661 xBmp
= rect
.GetRight() - bitmap
.GetWidth();
662 rectLabel
.x
= rect
.x
+ 3;
663 rectLabel
.SetRight(xBmp
);
665 else // normal (checkbox to the left of the text) case
668 rectLabel
.x
= xBmp
+ bitmap
.GetWidth() + 5;
669 rectLabel
.SetRight(rect
.GetRight());
672 dc
.DrawBitmap(bitmap
, xBmp
, yBmp
, true /* use mask */);
674 DrawLabel(dc
, label
, rectLabel
, flags
,
675 wxALIGN_LEFT
| wxALIGN_TOP
, indexAccel
);
680 void wxStdRenderer::DrawTextLine(wxDC
& dc
,
681 const wxString
& text
,
687 if ( (selStart
== -1) || !(flags
& wxCONTROL_FOCUSED
) )
689 // just draw it as is
690 dc
.DrawText(text
, rect
.x
, rect
.y
);
692 else // we have selection
697 // draw the part before selection
698 wxString
s(text
, (size_t)selStart
);
701 dc
.DrawText(s
, x
, rect
.y
);
703 dc
.GetTextExtent(s
, &width
, NULL
);
707 // draw the selection itself
708 s
= wxString(text
.c_str() + selStart
, text
.c_str() + selEnd
);
711 wxColour colFg
= dc
.GetTextForeground(),
712 colBg
= dc
.GetTextBackground();
713 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
714 dc
.SetTextBackground(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
));
715 dc
.SetBackgroundMode(wxSOLID
);
717 dc
.DrawText(s
, x
, rect
.y
);
718 dc
.GetTextExtent(s
, &width
, NULL
);
721 dc
.SetBackgroundMode(wxTRANSPARENT
);
722 dc
.SetTextBackground(colBg
);
723 dc
.SetTextForeground(colFg
);
726 // draw the final part
727 s
= text
.c_str() + selEnd
;
730 dc
.DrawText(s
, x
, rect
.y
);
735 void wxStdRenderer::DrawLineWrapMark(wxDC
& WXUNUSED(dc
),
736 const wxRect
& WXUNUSED(rect
))
738 // nothing by default
741 int wxStdRenderer::GetTextBorderWidth(const wxTextCtrl
* WXUNUSED(text
)) const
747 wxStdRenderer::GetTextTotalArea(const wxTextCtrl
*text
, const wxRect
& rect
) const
749 wxRect rectTotal
= rect
;
750 rectTotal
.Inflate(GetTextBorderWidth(text
));
754 wxRect
wxStdRenderer::GetTextClientArea(const wxTextCtrl
*text
,
756 wxCoord
*extraSpaceBeyond
) const
758 wxRect rectText
= rect
;
759 rectText
.Deflate(GetTextBorderWidth(text
));
761 if ( extraSpaceBeyond
)
762 *extraSpaceBeyond
= 0;
767 #endif // wxUSE_TEXTCTRL
769 // ----------------------------------------------------------------------------
770 // scrollbars drawing
771 // ----------------------------------------------------------------------------
773 void wxStdRenderer::DrawScrollbarArrow(wxDC
& dc
,
778 DrawArrow(dc
, dir
, rect
, flags
);
781 void wxStdRenderer::DrawScrollCorner(wxDC
& dc
, const wxRect
& rect
)
783 DrawSolidRect(dc
, wxSCHEME_COLOUR(m_scheme
, CONTROL
), rect
);
786 // ----------------------------------------------------------------------------
787 // scrollbars geometry
788 // ----------------------------------------------------------------------------
793 void wxStdRenderer::GetScrollBarThumbSize(wxCoord length
,
800 // the thumb can't be made less than this number of pixels
801 static const wxCoord thumbMinWidth
= 8; // FIXME: should be configurable
803 *thumbStart
= (length
*thumbPos
) / range
;
804 *thumbEnd
= (length
*(thumbPos
+ thumbSize
)) / range
;
806 if ( *thumbEnd
- *thumbStart
< thumbMinWidth
)
808 // adjust the end if possible
809 if ( *thumbStart
<= length
- thumbMinWidth
)
811 // yes, just make it wider
812 *thumbEnd
= *thumbStart
+ thumbMinWidth
;
814 else // it is at the bottom of the scrollbar
816 // so move it a bit up
817 *thumbStart
= length
- thumbMinWidth
;
823 wxRect
wxStdRenderer::GetScrollbarRect(const wxScrollBar
*scrollbar
,
824 wxScrollBar::Element elem
,
827 if ( thumbPos
== -1 )
829 thumbPos
= scrollbar
->GetThumbPosition();
832 const wxSize sizeArrow
= GetScrollbarArrowSize();
834 wxSize sizeTotal
= scrollbar
->GetClientSize();
835 wxCoord
*start
, *width
;
836 wxCoord length
, arrow
;
838 if ( scrollbar
->IsVertical() )
841 rect
.width
= sizeTotal
.x
;
842 length
= sizeTotal
.y
;
844 width
= &rect
.height
;
850 rect
.height
= sizeTotal
.y
;
851 length
= sizeTotal
.x
;
859 case wxScrollBar::Element_Arrow_Line_1
:
864 case wxScrollBar::Element_Arrow_Line_2
:
865 *start
= length
- arrow
;
869 case wxScrollBar::Element_Arrow_Page_1
:
870 case wxScrollBar::Element_Arrow_Page_2
:
871 // we don't have them at all
874 case wxScrollBar::Element_Thumb
:
875 case wxScrollBar::Element_Bar_1
:
876 case wxScrollBar::Element_Bar_2
:
877 // we need to calculate the thumb position - do it
880 wxCoord thumbStart
, thumbEnd
;
881 int range
= scrollbar
->GetRange();
889 GetScrollBarThumbSize(length
,
891 scrollbar
->GetThumbSize(),
897 if ( elem
== wxScrollBar::Element_Thumb
)
900 *width
= thumbEnd
- thumbStart
;
902 else if ( elem
== wxScrollBar::Element_Bar_1
)
907 else // elem == wxScrollBar::Element_Bar_2
910 *width
= length
- thumbEnd
;
913 // everything is relative to the start of the shaft so far
918 case wxScrollBar::Element_Max
:
920 wxFAIL_MSG( _T("unknown scrollbar element") );
926 wxCoord
wxStdRenderer::GetScrollbarSize(const wxScrollBar
*scrollbar
)
928 const wxSize sizeArrowSB
= GetScrollbarArrowSize();
930 wxCoord sizeArrow
, sizeTotal
;
931 if ( scrollbar
->GetWindowStyle() & wxVERTICAL
)
933 sizeArrow
= sizeArrowSB
.y
;
934 sizeTotal
= scrollbar
->GetSize().y
;
938 sizeArrow
= sizeArrowSB
.x
;
939 sizeTotal
= scrollbar
->GetSize().x
;
942 return sizeTotal
- 2*sizeArrow
;
946 wxStdRenderer::HitTestScrollbar(const wxScrollBar
*scrollbar
, const wxPoint
& pt
) const
948 // we only need to work with either x or y coord depending on the
949 // orientation, choose one (but still check the other one to verify if the
950 // mouse is in the window at all)
951 const wxSize sizeArrowSB
= GetScrollbarArrowSize();
953 wxCoord coord
, sizeArrow
, sizeTotal
;
954 wxSize size
= scrollbar
->GetSize();
955 if ( scrollbar
->GetWindowStyle() & wxVERTICAL
)
957 if ( pt
.x
< 0 || pt
.x
> size
.x
)
961 sizeArrow
= sizeArrowSB
.y
;
966 if ( pt
.y
< 0 || pt
.y
> size
.y
)
970 sizeArrow
= sizeArrowSB
.x
;
974 // test for the arrows first as it's faster
975 if ( coord
< 0 || coord
> sizeTotal
)
979 else if ( coord
< sizeArrow
)
981 return wxHT_SCROLLBAR_ARROW_LINE_1
;
983 else if ( coord
> sizeTotal
- sizeArrow
)
985 return wxHT_SCROLLBAR_ARROW_LINE_2
;
989 // calculate the thumb position in pixels
990 sizeTotal
-= 2*sizeArrow
;
991 wxCoord thumbStart
, thumbEnd
;
992 int range
= scrollbar
->GetRange();
995 // clicking the scrollbar without range has no effect
1000 GetScrollBarThumbSize(sizeTotal
,
1001 scrollbar
->GetThumbPosition(),
1002 scrollbar
->GetThumbSize(),
1008 // now compare with the thumb position
1010 if ( coord
< thumbStart
)
1011 return wxHT_SCROLLBAR_BAR_1
;
1012 else if ( coord
> thumbEnd
)
1013 return wxHT_SCROLLBAR_BAR_2
;
1015 return wxHT_SCROLLBAR_THUMB
;
1021 wxStdRenderer::ScrollbarToPixel(const wxScrollBar
*scrollbar
, int thumbPos
)
1023 int range
= scrollbar
->GetRange();
1026 // the only valid position anyhow
1030 if ( thumbPos
== -1 )
1032 // by default use the current thumb position
1033 thumbPos
= scrollbar
->GetThumbPosition();
1036 const wxSize sizeArrow
= GetScrollbarArrowSize();
1037 return (thumbPos
*GetScrollbarSize(scrollbar
)) / range
1038 + (scrollbar
->IsVertical() ? sizeArrow
.y
: sizeArrow
.x
);
1041 int wxStdRenderer::PixelToScrollbar(const wxScrollBar
*scrollbar
, wxCoord coord
)
1043 const wxSize sizeArrow
= GetScrollbarArrowSize();
1044 return ((coord
- (scrollbar
->IsVertical() ? sizeArrow
.y
: sizeArrow
.x
)) *
1045 scrollbar
->GetRange() ) / GetScrollbarSize(scrollbar
);
1048 #endif // wxUSE_SCROLLBAR