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 // ----------------------------------------------------------------------------
94 // ----------------------------------------------------------------------------
96 void wxStdRenderer::DrawBackground(wxDC
& dc
,
102 wxColour colBg
= col
.Ok() ? col
103 : window
? m_scheme
->GetBackground(window
)
104 : wxSCHEME_COLOUR(m_scheme
, CONTROL
);
106 DrawSolidRect(dc
, colBg
, rect
);
110 void wxStdRenderer::DrawButtonSurface(wxDC
& dc
,
115 DrawBackground(dc
, col
, rect
, flags
);
118 // ----------------------------------------------------------------------------
120 // ----------------------------------------------------------------------------
122 void wxStdRenderer::DrawFocusRect(wxDC
& dc
, const wxRect
& rect
)
124 // draw the pixels manually because the "dots" in wxPen with wxDOT style
125 // may be short traits and not really dots
127 // note that to behave in the same manner as DrawRect(), we must exclude
128 // the bottom and right borders from the rectangle
129 wxCoord x1
= rect
.GetLeft(),
131 x2
= rect
.GetRight(),
132 y2
= rect
.GetBottom();
134 dc
.SetPen(m_penBlack
);
136 // this seems to be closer than what Windows does than wxINVERT although
137 // I'm still not sure if it's correct
138 dc
.SetLogicalFunction(wxAND_REVERSE
);
141 for ( z
= x1
+ 1; z
< x2
; z
+= 2 )
142 dc
.DrawPoint(z
, rect
.GetTop());
144 wxCoord shift
= z
== x2
? 0 : 1;
145 for ( z
= y1
+ shift
; z
< y2
; z
+= 2 )
148 shift
= z
== y2
? 0 : 1;
149 for ( z
= x2
- shift
; z
> x1
; z
-= 2 )
152 shift
= z
== x1
? 0 : 1;
153 for ( z
= y2
- shift
; z
> y1
; z
-= 2 )
156 dc
.SetLogicalFunction(wxCOPY
);
159 void wxStdRenderer::DrawLabel(wxDC
& dc
,
160 const wxString
& label
,
167 DrawButtonLabel(dc
, label
, wxNullBitmap
, rect
, flags
,
168 alignment
, indexAccel
, rectBounds
);
171 void wxStdRenderer::DrawButtonLabel(wxDC
& dc
,
172 const wxString
& label
,
173 const wxBitmap
& image
,
180 wxRect rectLabel
= rect
;
181 if ( !label
.empty() && (flags
& wxCONTROL_DISABLED
) )
183 if ( flags
& wxCONTROL_PRESSED
)
185 // shift the label if a button is pressed
186 rectLabel
.Offset(1, 1);
189 // draw shadow of the text
190 dc
.SetTextForeground(m_penHighlight
.GetColour());
191 wxRect rectShadow
= rect
;
192 rectShadow
.Offset(1, 1);
193 dc
.DrawLabel(label
, rectShadow
, alignment
, indexAccel
);
195 // make the main label text grey
196 dc
.SetTextForeground(m_penDarkGrey
.GetColour());
198 if ( flags
& wxCONTROL_FOCUSED
)
200 // leave enough space for the focus rect
201 rectLabel
.Inflate(-2);
205 dc
.DrawLabel(label
, image
, rectLabel
, alignment
, indexAccel
, rectBounds
);
207 if ( !label
.empty() && (flags
& wxCONTROL_FOCUSED
) )
209 rectLabel
.Inflate(-1);
211 DrawFocusRect(dc
, rectLabel
);
215 // ----------------------------------------------------------------------------
217 // ----------------------------------------------------------------------------
220 We implement standard-looking 3D borders which have the following appearance:
224 WWWWWWWWWWWWWWWWWWWWWWB
225 WHHHHHHHHHHHHHHHHHHHHGB
226 WH GB W = white (HILIGHT)
227 WH GB H = light grey (LIGHT)
228 WH GB G = dark grey (SHADOI)
229 WH GB B = black (DKSHADOI)
232 WGGGGGGGGGGGGGGGGGGGGGB
233 BBBBBBBBBBBBBBBBBBBBBBB
235 The sunken border looks like this:
237 GGGGGGGGGGGGGGGGGGGGGGW
238 GBBBBBBBBBBBBBBBBBBBBHW
245 GHHHHHHHHHHHHHHHHHHHHHW
246 WWWWWWWWWWWWWWWWWWWWWWW
248 The static border (used for the controls which don't get focus) is like
251 GGGGGGGGGGGGGGGGGGGGGGW
259 WWWWWWWWWWWWWWWWWWWWWWW
261 The most complicated is the double border which is a combination of special
262 "anti-sunken" border and an extra border inside it:
264 HHHHHHHHHHHHHHHHHHHHHHB
265 HWWWWWWWWWWWWWWWWWWWWGB
266 HWHHHHHHHHHHHHHHHHHHHGB
271 HWHHHHHHHHHHHHHHHHHHHGB
272 HGGGGGGGGGGGGGGGGGGGGGB
273 BBBBBBBBBBBBBBBBBBBBBBB
275 And the simple border is, well, simple:
277 BBBBBBBBBBBBBBBBBBBBBBB
286 BBBBBBBBBBBBBBBBBBBBBBB
289 void wxStdRenderer::DrawRaisedBorder(wxDC
& dc
, wxRect
*rect
)
291 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penBlack
);
292 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penDarkGrey
);
295 void wxStdRenderer::DrawSunkenBorder(wxDC
& dc
, wxRect
*rect
)
297 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
298 DrawShadedRect(dc
, rect
, m_penBlack
, m_penLightGrey
);
301 void wxStdRenderer::DrawAntiSunkenBorder(wxDC
& dc
, wxRect
*rect
)
303 DrawShadedRect(dc
, rect
, m_penLightGrey
, m_penBlack
);
304 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
307 void wxStdRenderer::DrawFrameBorder(wxDC
& dc
, wxRect
*rect
)
309 DrawShadedRect(dc
, rect
, m_penDarkGrey
, m_penHighlight
);
310 DrawShadedRect(dc
, rect
, m_penHighlight
, m_penDarkGrey
);
313 void wxStdRenderer::DrawBorder(wxDC
& dc
,
315 const wxRect
& rectTotal
,
319 wxRect rect
= rectTotal
;
323 case wxBORDER_SUNKEN
:
324 DrawSunkenBorder(dc
, &rect
);
327 case wxBORDER_DOUBLE
:
328 DrawAntiSunkenBorder(dc
, &rect
);
329 DrawRect(dc
, &rect
, m_penLightGrey
);
332 case wxBORDER_STATIC
:
333 DrawShadedRect(dc
, &rect
, m_penDarkGrey
, m_penHighlight
);
336 case wxBORDER_RAISED
:
337 DrawRaisedBorder(dc
, &rect
);
340 case wxBORDER_SIMPLE
:
341 DrawRect(dc
, &rect
, m_penBlack
);
345 wxFAIL_MSG(_T("unknown border type"));
348 case wxBORDER_DEFAULT
:
357 wxRect
wxStdRenderer::GetBorderDimensions(wxBorder border
) const
362 case wxBORDER_SIMPLE
:
363 case wxBORDER_STATIC
:
367 case wxBORDER_RAISED
:
368 case wxBORDER_SUNKEN
:
372 case wxBORDER_DOUBLE
:
377 wxFAIL_MSG(_T("unknown border type"));
380 case wxBORDER_DEFAULT
:
395 bool wxStdRenderer::AreScrollbarsInsideBorder() const
400 void wxStdRenderer::DrawTextBorder(wxDC
& dc
,
406 DrawBorder(dc
, border
, rect
, flags
, rectIn
);
409 // ----------------------------------------------------------------------------
411 // ----------------------------------------------------------------------------
414 wxStdRenderer::DrawHorizontalLine(wxDC
& dc
, wxCoord y
, wxCoord x1
, wxCoord x2
)
416 dc
.SetPen(m_penDarkGrey
);
417 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
419 dc
.SetPen(m_penHighlight
);
421 dc
.DrawLine(x1
, y
, x2
+ 1, y
);
425 wxStdRenderer::DrawVerticalLine(wxDC
& dc
, wxCoord x
, wxCoord y1
, wxCoord y2
)
427 dc
.SetPen(m_penDarkGrey
);
428 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
430 dc
.SetPen(m_penHighlight
);
432 dc
.DrawLine(x
, y1
, x
, y2
+ 1);
435 void wxStdRenderer::DrawFrameWithoutLabel(wxDC
& dc
,
436 const wxRect
& rectFrame
,
437 const wxRect
& rectLabel
)
439 // draw left, bottom and right lines entirely
440 DrawVerticalLine(dc
, rectFrame
.GetLeft(),
441 rectFrame
.GetTop(), rectFrame
.GetBottom() - 2);
442 DrawHorizontalLine(dc
, rectFrame
.GetBottom() - 1,
443 rectFrame
.GetLeft(), rectFrame
.GetRight());
444 DrawVerticalLine(dc
, rectFrame
.GetRight() - 1,
445 rectFrame
.GetTop(), rectFrame
.GetBottom() - 1);
447 // and 2 parts of the top line
448 DrawHorizontalLine(dc
, rectFrame
.GetTop(),
449 rectFrame
.GetLeft() + 1, rectLabel
.GetLeft());
450 DrawHorizontalLine(dc
, rectFrame
.GetTop(),
451 rectLabel
.GetRight(), rectFrame
.GetRight() - 2);
454 void wxStdRenderer::DrawFrameWithLabel(wxDC
& dc
,
455 const wxString
& label
,
456 const wxRect
& rectFrame
,
457 const wxRect
& rectText
,
463 DrawLabel(dc
, label
, rectText
, flags
, alignment
, indexAccel
, &rectLabel
);
465 DrawFrameWithoutLabel(dc
, rectFrame
, rectLabel
);
468 void wxStdRenderer::DrawFrame(wxDC
& dc
,
469 const wxString
& label
,
475 wxCoord height
= 0; // of the label
476 wxRect rectFrame
= rect
;
477 if ( !label
.empty() )
479 // the text should touch the top border of the rect, so the frame
480 // itself should be lower
481 dc
.GetTextExtent(label
, NULL
, &height
);
482 rectFrame
.y
+= height
/ 2;
483 rectFrame
.height
-= height
/ 2;
485 // we have to draw each part of the frame individually as we can't
486 // erase the background beyond the label as it might contain some
487 // pixmap already, so drawing everything and then overwriting part of
488 // the frame with label doesn't work
490 // TODO: the +5 shouldn't be hard coded
492 rectText
.x
= rectFrame
.x
+ 5;
494 rectText
.width
= rectFrame
.width
- 7; // +2 border width
495 rectText
.height
= height
;
497 DrawFrameWithLabel(dc
, label
, rectFrame
, rectText
, flags
,
498 alignment
, indexAccel
);
502 DrawFrameBorder(dc
, &rectFrame
);
506 void wxStdRenderer::DrawItem(wxDC
& dc
,
507 const wxString
& label
,
511 wxDCTextColourChanger
colChanger(dc
);
513 if ( flags
& wxCONTROL_SELECTED
)
515 colChanger
.Set(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
517 const wxColour colBg
= wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
);
520 dc
.DrawRectangle(rect
);
523 wxRect rectText
= rect
;
526 dc
.DrawLabel(label
, wxNullBitmap
, rectText
);
528 if ( flags
& wxCONTROL_FOCUSED
)
530 DrawFocusRect(dc
, rect
);
534 void wxStdRenderer::DrawCheckItemBitmap(wxDC
& dc
,
535 const wxBitmap
& bitmap
,
539 DrawCheckButton(dc
, wxEmptyString
, bitmap
, rect
, flags
);
542 void wxStdRenderer::DrawCheckItem(wxDC
& dc
,
543 const wxString
& label
,
544 const wxBitmap
& bitmap
,
548 wxRect rectBitmap
= rect
;
549 rectBitmap
.width
= GetCheckBitmapSize().x
;
550 DrawCheckItemBitmap(dc
, bitmap
, rectBitmap
, flags
);
552 wxRect rectLabel
= rect
;
553 wxCoord shift
= rectBitmap
.width
+ 2*GetCheckItemMargin();
554 rectLabel
.x
+= shift
;
555 rectLabel
.width
-= shift
;
556 DrawItem(dc
, label
, rectLabel
, flags
);
559 // ----------------------------------------------------------------------------
560 // check and radio bitmaps
561 // ----------------------------------------------------------------------------
564 void wxStdRenderer::GetIndicatorsFromFlags(int flags
,
565 IndicatorState
& state
,
566 IndicatorStatus
& status
)
568 if ( flags
& wxCONTROL_SELECTED
)
569 state
= flags
& wxCONTROL_DISABLED
? IndicatorState_SelectedDisabled
570 : IndicatorState_Selected
;
571 else if ( flags
& wxCONTROL_DISABLED
)
572 state
= IndicatorState_Disabled
;
573 else if ( flags
& wxCONTROL_PRESSED
)
574 state
= IndicatorState_Pressed
;
576 state
= IndicatorState_Normal
;
578 status
= flags
& wxCONTROL_CHECKED
? IndicatorStatus_Checked
579 : flags
& wxCONTROL_UNDETERMINED
580 ? IndicatorStatus_Undetermined
581 : IndicatorStatus_Unchecked
;
584 void wxStdRenderer::DrawCheckButton(wxDC
& dc
,
585 const wxString
& label
,
586 const wxBitmap
& bitmap
,
592 wxBitmap
bmp(bitmap
.Ok() ? bitmap
: GetCheckBitmap(flags
));
594 DrawCheckOrRadioButton(dc
, label
, bmp
, rect
, flags
, align
, indexAccel
);
597 void wxStdRenderer::DrawRadioButton(wxDC
& dc
,
598 const wxString
& label
,
599 const wxBitmap
& bitmap
,
605 wxBitmap
bmp(bitmap
.Ok() ? bitmap
: GetRadioBitmap(flags
));
607 DrawCheckOrRadioButton(dc
, label
, bmp
, rect
, flags
, align
, indexAccel
);
610 void wxStdRenderer::DrawCheckOrRadioButton(wxDC
& dc
,
611 const wxString
& label
,
612 const wxBitmap
& bitmap
,
618 // calculate the position of the bitmap and of the label
619 wxCoord heightBmp
= bitmap
.GetHeight();
621 yBmp
= rect
.y
+ (rect
.height
- heightBmp
) / 2;
624 dc
.GetMultiLineTextExtent(label
, NULL
, &rectLabel
.height
);
625 rectLabel
.y
= rect
.y
+ (rect
.height
- rectLabel
.height
) / 2;
627 // align label vertically with the bitmap - looks nicer like this
628 rectLabel
.y
-= (rectLabel
.height
- heightBmp
) % 2;
630 // calc horz position
631 if ( align
== wxALIGN_RIGHT
)
633 xBmp
= rect
.GetRight() - bitmap
.GetWidth();
634 rectLabel
.x
= rect
.x
+ 3;
635 rectLabel
.SetRight(xBmp
);
637 else // normal (checkbox to the left of the text) case
640 rectLabel
.x
= xBmp
+ bitmap
.GetWidth() + 5;
641 rectLabel
.SetRight(rect
.GetRight());
644 dc
.DrawBitmap(bitmap
, xBmp
, yBmp
, true /* use mask */);
646 DrawLabel(dc
, label
, rectLabel
, flags
,
647 wxALIGN_LEFT
| wxALIGN_TOP
, indexAccel
);
652 void wxStdRenderer::DrawTextLine(wxDC
& dc
,
653 const wxString
& text
,
659 if ( (selStart
== -1) || !(flags
& wxCONTROL_FOCUSED
) )
661 // just draw it as is
662 dc
.DrawText(text
, rect
.x
, rect
.y
);
664 else // we have selection
669 // draw the part before selection
670 wxString
s(text
, (size_t)selStart
);
673 dc
.DrawText(s
, x
, rect
.y
);
675 dc
.GetTextExtent(s
, &width
, NULL
);
679 // draw the selection itself
680 s
= wxString(text
.c_str() + selStart
, text
.c_str() + selEnd
);
683 wxColour colFg
= dc
.GetTextForeground(),
684 colBg
= dc
.GetTextBackground();
685 dc
.SetTextForeground(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT_TEXT
));
686 dc
.SetTextBackground(wxSCHEME_COLOUR(m_scheme
, HIGHLIGHT
));
687 dc
.SetBackgroundMode(wxSOLID
);
689 dc
.DrawText(s
, x
, rect
.y
);
690 dc
.GetTextExtent(s
, &width
, NULL
);
693 dc
.SetBackgroundMode(wxTRANSPARENT
);
694 dc
.SetTextBackground(colBg
);
695 dc
.SetTextForeground(colFg
);
698 // draw the final part
699 s
= text
.c_str() + selEnd
;
702 dc
.DrawText(s
, x
, rect
.y
);
707 void wxStdRenderer::DrawLineWrapMark(wxDC
& WXUNUSED(dc
),
708 const wxRect
& WXUNUSED(rect
))
710 // nothing by default
713 int wxStdRenderer::GetTextBorderWidth(const wxTextCtrl
* WXUNUSED(text
)) const
719 wxStdRenderer::GetTextTotalArea(const wxTextCtrl
*text
, const wxRect
& rect
) const
721 wxRect rectTotal
= rect
;
722 rectTotal
.Inflate(GetTextBorderWidth(text
));
726 wxRect
wxStdRenderer::GetTextClientArea(const wxTextCtrl
*text
,
728 wxCoord
*extraSpaceBeyond
) const
730 wxRect rectText
= rect
;
731 rectText
.Deflate(GetTextBorderWidth(text
));
733 if ( extraSpaceBeyond
)
734 *extraSpaceBeyond
= 0;
739 #endif // wxUSE_TEXTCTRL
741 // ----------------------------------------------------------------------------
742 // scrollbars geometry
743 // ----------------------------------------------------------------------------
748 void wxStdRenderer::GetScrollBarThumbSize(wxCoord length
,
755 // the thumb can't be made less than this number of pixels
756 static const wxCoord thumbMinWidth
= 8; // FIXME: should be configurable
758 *thumbStart
= (length
*thumbPos
) / range
;
759 *thumbEnd
= (length
*(thumbPos
+ thumbSize
)) / range
;
761 if ( *thumbEnd
- *thumbStart
< thumbMinWidth
)
763 // adjust the end if possible
764 if ( *thumbStart
<= length
- thumbMinWidth
)
766 // yes, just make it wider
767 *thumbEnd
= *thumbStart
+ thumbMinWidth
;
769 else // it is at the bottom of the scrollbar
771 // so move it a bit up
772 *thumbStart
= length
- thumbMinWidth
;
778 wxRect
wxStdRenderer::GetScrollbarRect(const wxScrollBar
*scrollbar
,
779 wxScrollBar::Element elem
,
782 if ( thumbPos
== -1 )
784 thumbPos
= scrollbar
->GetThumbPosition();
787 const wxSize sizeArrow
= GetScrollbarArrowSize();
789 wxSize sizeTotal
= scrollbar
->GetClientSize();
790 wxCoord
*start
, *width
;
791 wxCoord length
, arrow
;
793 if ( scrollbar
->IsVertical() )
796 rect
.width
= sizeTotal
.x
;
797 length
= sizeTotal
.y
;
799 width
= &rect
.height
;
805 rect
.height
= sizeTotal
.y
;
806 length
= sizeTotal
.x
;
814 case wxScrollBar::Element_Arrow_Line_1
:
819 case wxScrollBar::Element_Arrow_Line_2
:
820 *start
= length
- arrow
;
824 case wxScrollBar::Element_Arrow_Page_1
:
825 case wxScrollBar::Element_Arrow_Page_2
:
826 // we don't have them at all
829 case wxScrollBar::Element_Thumb
:
830 case wxScrollBar::Element_Bar_1
:
831 case wxScrollBar::Element_Bar_2
:
832 // we need to calculate the thumb position - do it
835 wxCoord thumbStart
, thumbEnd
;
836 int range
= scrollbar
->GetRange();
844 GetScrollBarThumbSize(length
,
846 scrollbar
->GetThumbSize(),
852 if ( elem
== wxScrollBar::Element_Thumb
)
855 *width
= thumbEnd
- thumbStart
;
857 else if ( elem
== wxScrollBar::Element_Bar_1
)
862 else // elem == wxScrollBar::Element_Bar_2
865 *width
= length
- thumbEnd
;
868 // everything is relative to the start of the shaft so far
873 case wxScrollBar::Element_Max
:
875 wxFAIL_MSG( _T("unknown scrollbar element") );
881 wxCoord
wxStdRenderer::GetScrollbarSize(const wxScrollBar
*scrollbar
)
883 const wxSize sizeArrowSB
= GetScrollbarArrowSize();
885 wxCoord sizeArrow
, sizeTotal
;
886 if ( scrollbar
->GetWindowStyle() & wxVERTICAL
)
888 sizeArrow
= sizeArrowSB
.y
;
889 sizeTotal
= scrollbar
->GetSize().y
;
893 sizeArrow
= sizeArrowSB
.x
;
894 sizeTotal
= scrollbar
->GetSize().x
;
897 return sizeTotal
- 2*sizeArrow
;
901 wxStdRenderer::HitTestScrollbar(const wxScrollBar
*scrollbar
, const wxPoint
& pt
) const
903 // we only need to work with either x or y coord depending on the
904 // orientation, choose one (but still check the other one to verify if the
905 // mouse is in the window at all)
906 const wxSize sizeArrowSB
= GetScrollbarArrowSize();
908 wxCoord coord
, sizeArrow
, sizeTotal
;
909 wxSize size
= scrollbar
->GetSize();
910 if ( scrollbar
->GetWindowStyle() & wxVERTICAL
)
912 if ( pt
.x
< 0 || pt
.x
> size
.x
)
916 sizeArrow
= sizeArrowSB
.y
;
921 if ( pt
.y
< 0 || pt
.y
> size
.y
)
925 sizeArrow
= sizeArrowSB
.x
;
929 // test for the arrows first as it's faster
930 if ( coord
< 0 || coord
> sizeTotal
)
934 else if ( coord
< sizeArrow
)
936 return wxHT_SCROLLBAR_ARROW_LINE_1
;
938 else if ( coord
> sizeTotal
- sizeArrow
)
940 return wxHT_SCROLLBAR_ARROW_LINE_2
;
944 // calculate the thumb position in pixels
945 sizeTotal
-= 2*sizeArrow
;
946 wxCoord thumbStart
, thumbEnd
;
947 int range
= scrollbar
->GetRange();
950 // clicking the scrollbar without range has no effect
955 GetScrollBarThumbSize(sizeTotal
,
956 scrollbar
->GetThumbPosition(),
957 scrollbar
->GetThumbSize(),
963 // now compare with the thumb position
965 if ( coord
< thumbStart
)
966 return wxHT_SCROLLBAR_BAR_1
;
967 else if ( coord
> thumbEnd
)
968 return wxHT_SCROLLBAR_BAR_2
;
970 return wxHT_SCROLLBAR_THUMB
;
976 wxStdRenderer::ScrollbarToPixel(const wxScrollBar
*scrollbar
, int thumbPos
)
978 int range
= scrollbar
->GetRange();
981 // the only valid position anyhow
985 if ( thumbPos
== -1 )
987 // by default use the current thumb position
988 thumbPos
= scrollbar
->GetThumbPosition();
991 const wxSize sizeArrow
= GetScrollbarArrowSize();
992 return (thumbPos
*GetScrollbarSize(scrollbar
)) / range
993 + (scrollbar
->IsVertical() ? sizeArrow
.y
: sizeArrow
.x
);
996 int wxStdRenderer::PixelToScrollbar(const wxScrollBar
*scrollbar
, wxCoord coord
)
998 const wxSize sizeArrow
= GetScrollbarArrowSize();
999 return ((coord
- (scrollbar
->IsVertical() ? sizeArrow
.y
: sizeArrow
.x
)) *
1000 scrollbar
->GetRange() ) / GetScrollbarSize(scrollbar
);
1003 #endif // wxUSE_SCROLLBAR