void wxScrollBar::SetRange(int range) { SetScrollbar(GetThumbPosition(), GetThumbSize(), range, GetPageSize()); }
wxRect wxScrollBar::GetScrollbarRect(wxScrollBar::Element elem, int thumbPos) const { if ( thumbPos == -1 ) { thumbPos = GetThumbPosition(); } const wxSize sizeArrow = m_renderer->GetScrollbarArrowSize(); wxSize sizeTotal = GetClientSize(); wxCoord *start, *width; wxCoord length, arrow; wxRect rect; if ( IsVertical() ) { rect.x = 0; rect.width = sizeTotal.x; length = sizeTotal.y; start = &rect.y; width = &rect.height; arrow = sizeArrow.y; } else // horizontal { rect.y = 0; rect.height = sizeTotal.y; length = sizeTotal.x; start = &rect.x; width = &rect.width; arrow = sizeArrow.x; } switch ( elem ) { case wxScrollBar::Element_Arrow_Line_1: *start = 0; *width = arrow; break; case wxScrollBar::Element_Arrow_Line_2: *start = length - arrow; *width = arrow; break; case wxScrollBar::Element_Arrow_Page_1: case wxScrollBar::Element_Arrow_Page_2: // we don't have them at all break; case wxScrollBar::Element_Thumb: case wxScrollBar::Element_Bar_1: case wxScrollBar::Element_Bar_2: // we need to calculate the thumb position - do it { length -= 2*arrow; wxCoord thumbStart, thumbEnd; int range = GetRange(); if ( !range ) { thumbStart = thumbEnd = 0; } else { GetScrollBarThumbSize(length, thumbPos, GetThumbSize(), range, &thumbStart, &thumbEnd); } if ( elem == wxScrollBar::Element_Thumb ) { *start = thumbStart; *width = thumbEnd - thumbStart; } else if ( elem == wxScrollBar::Element_Bar_1 ) { *start = 0; *width = thumbStart; } else // elem == wxScrollBar::Element_Bar_2 { *start = thumbEnd; *width = length - thumbEnd; } // everything is relative to the start of the shaft so far *start += arrow; } break; case wxScrollBar::Element_Max: default: wxFAIL_MSG( wxT("unknown scrollbar element") ); } return rect; }
void wxScrollBar::SetPageSize( int pageLength ) { SetScrollbar(GetThumbPosition(), GetThumbSize(), GetRange(), pageLength); }
wxHitTest wxScrollBar::HitTestBar(const wxPoint& pt) const { // we only need to work with either x or y coord depending on the // orientation, choose one (but still check the other one to verify if the // mouse is in the window at all) const wxSize sizeArrowSB = m_renderer->GetScrollbarArrowSize(); wxCoord coord, sizeArrow, sizeTotal; wxSize size = GetSize(); if ( GetWindowStyle() & wxVERTICAL ) { if ( pt.x < 0 || pt.x > size.x ) return wxHT_NOWHERE; coord = pt.y; sizeArrow = sizeArrowSB.y; sizeTotal = size.y; } else // horizontal { if ( pt.y < 0 || pt.y > size.y ) return wxHT_NOWHERE; coord = pt.x; sizeArrow = sizeArrowSB.x; sizeTotal = size.x; } // test for the arrows first as it's faster if ( coord < 0 || coord > sizeTotal ) { return wxHT_NOWHERE; } else if ( coord < sizeArrow ) { return wxHT_SCROLLBAR_ARROW_LINE_1; } else if ( coord > sizeTotal - sizeArrow ) { return wxHT_SCROLLBAR_ARROW_LINE_2; } else { // calculate the thumb position in pixels sizeTotal -= 2*sizeArrow; wxCoord thumbStart, thumbEnd; int range = GetRange(); if ( !range ) { // clicking the scrollbar without range has no effect return wxHT_NOWHERE; } else { GetScrollBarThumbSize(sizeTotal, GetThumbPosition(), GetThumbSize(), range, &thumbStart, &thumbEnd); } // now compare with the thumb position coord -= sizeArrow; if ( coord < thumbStart ) return wxHT_SCROLLBAR_BAR_1; else if ( coord > thumbEnd ) return wxHT_SCROLLBAR_BAR_2; else return wxHT_SCROLLBAR_THUMB; } }
//+--------------------------------------------------------------------------- // // Member: CScrollbarController::MouseMove // // Synopsis: Handle mouse move events. // // Arguments: pt new mouse location // // Notes: // //---------------------------------------------------------------------------- void CScrollbarController::MouseMove(const CPoint& pt) { _ptMouse = pt; _pDispScroller->TransformPoint(&_ptMouse, COORDSYS_GLOBAL, COORDSYS_CONTAINER); switch(_partPressedStart) { case SBP_NONE: case SBP_TRACK: AssertSz(FALSE, "unexpected call to CScrollbarController::MouseMoved"); break; case SBP_THUMB: { LONG contentSize = _pDispScroller->GetContentSize()[_direction]; Assert(contentSize >= 0); LONG trackSize = GetTrackSize(_direction, _rcScrollbar, _buttonWidth) - GetThumbSize(_direction, _rcScrollbar, contentSize, _rcScrollbar.Size(_direction), _buttonWidth, &_drawInfo); if(trackSize <= 0) { break; // can't move thumb } // NOTE: we're not currently checking to see if the mouse point // is out of range perpendicular to the scroll bar axis BOOL fRightToLeft = (_direction==0 && _pDispScroller->IsRightToLeft()); LONG trackPos; if(!fRightToLeft) { trackPos = _ptMouse[_direction] - _rcScrollbar[_direction] - GetScaledButtonWidth(_direction, _rcScrollbar, _buttonWidth) - _mouseInThumb; } else { trackPos = _rcScrollbar.right - GetScaledButtonWidth(_direction, _rcScrollbar, _buttonWidth) - _mouseInThumb - _ptMouse.x; } LONG scrollOffset; if(trackPos <= 0) { scrollOffset = 0; } else { contentSize -= _rcScrollbar.Size(_direction); scrollOffset = MulDivQuick(trackPos, contentSize, trackSize); if(fRightToLeft) { scrollOffset = -scrollOffset; } } _pLayout->OnScroll(_direction, SB_THUMBPOSITION, scrollOffset); } break; default: { // find out what the mouse would be pressing in its new location. // If it's not the same as it used to be, invalidate the part. SCROLLBARPART partPressedOld = _partPressed; LONG contentSize, containerSize, scrollAmount; GetScrollInfo(&contentSize, &containerSize, &scrollAmount); _partPressed = GetPart( _direction, _rcScrollbar, _ptMouse, contentSize, containerSize, scrollAmount, _buttonWidth, &_drawInfo, _pDispScroller->IsRightToLeft()); if(_partPressed != _partPressedStart) { _partPressed = SBP_NONE; } if(_partPressed != partPressedOld) { SCROLLBARPART invalidPart = _partPressed; if(_partPressed != SBP_NONE) { // perform scroll action and set timer OnTick(SB_REPEAT_TIMER); } else { invalidPart = partPressedOld; } Verify(_pLayout->OpenView()); InvalidatePart( invalidPart, _direction, _rcScrollbar, contentSize, containerSize, scrollAmount, _buttonWidth, _pDispScroller, &_drawInfo); } } break; } }
//+--------------------------------------------------------------------------- // // Member: CScrollbarController::StartScrollbarController // // Synopsis: Start a scroll bar controller if necessary. // // Arguments: pLayout layout object to be called on scroll changes // pDispScroller display scroller node // pServerHost server host // buttonWidth custom scroll bar button width // pMessage message that caused creation of controller // // Notes: // //---------------------------------------------------------------------------- void CScrollbarController::StartScrollbarController( CLayout* pLayout, CDispScroller* pDispScroller, CServer* pServerHost, long buttonWidth, CMessage* pMessage) { Assert(pLayout != NULL); Assert(pDispScroller != NULL); Assert(pServerHost != NULL); Assert(pMessage != NULL); BOOL fRightToLeft; CScrollbarController* pSBC = TLS(pSBC); Assert(pSBC != NULL); // just to make sure previous controller is stopped if(pSBC->_pLayout != NULL) { StopScrollbarController(); } pSBC->_direction = (pMessage->htc==HTC_HSCROLLBAR ? 0 : 1); pSBC->_pDispScroller = pDispScroller; pSBC->_drawInfo.Init(pLayout->ElementOwner()); fRightToLeft = (pSBC->_direction==0 && pDispScroller->IsRightToLeft()); // calculate scroll bar rect pDispScroller->GetClientRect( &pSBC->_rcScrollbar, (pSBC->_direction==0?CLIENTRECT_HSCROLLBAR:CLIENTRECT_VSCROLLBAR)); Assert(pSBC->_rcScrollbar.Contains(pMessage->ptContent)); LONG contentSize, containerSize, scrollAmount; pSBC->GetScrollInfo(&contentSize, &containerSize, &scrollAmount); // if the scrollbar is inactive, it doesn't matter what was pressed if(contentSize <= containerSize) { return; } // what was pressed? pSBC->_partPressed = GetPart( pSBC->_direction, pSBC->_rcScrollbar, pMessage->ptContent, contentSize, containerSize, scrollAmount, buttonWidth, pSBC->GetDrawInfo(), pDispScroller->IsRightToLeft()); Assert(pSBC->_partPressed != SBP_NONE); // if inactive track was pressed, no more work to do if(pSBC->_partPressed == SBP_TRACK) { return; } // make scroll bar controller active pSBC->_partPressedStart = pSBC->_partPressed; pSBC->_pLayout = pLayout; pSBC->_pDispScroller = pDispScroller; pSBC->_pServerHost = pServerHost; pSBC->_buttonWidth = buttonWidth; pSBC->_ptMouse = pMessage->ptContent; LONG lScrollTime = MAX_SCROLLTIME; // if thumbing, compute hit point offset from top of thumb if(pSBC->_partPressed == SBP_THUMB) { long trackSize = GetTrackSize( pSBC->_direction, pSBC->_rcScrollbar, pSBC->_buttonWidth); long thumbSize = GetThumbSize( pSBC->_direction, pSBC->_rcScrollbar, contentSize, containerSize, pSBC->_buttonWidth, pSBC->GetDrawInfo()); // _mouseInThumb is the xPos of the mouse in from the left edge of the thumb in LTR cases // and xPos of the mouse in from the right edge of the thumb in RTL HSCROLL cases if(!fRightToLeft) { pSBC->_mouseInThumb = pSBC->_ptMouse[pSBC->_direction] - pSBC->_rcScrollbar[pSBC->_direction] - GetScaledButtonWidth(pSBC->_direction, pSBC->_rcScrollbar, pSBC->_buttonWidth) - GetThumbOffset(contentSize, containerSize, scrollAmount, trackSize, thumbSize); } else { pSBC->_mouseInThumb = pSBC->_rcScrollbar.right - GetScaledButtonWidth(pSBC->_direction, pSBC->_rcScrollbar, pSBC->_buttonWidth) + GetThumbOffset(contentSize, containerSize, scrollAmount, trackSize, thumbSize) - pSBC->_ptMouse.x; } Assert(pSBC->_mouseInThumb >= 0); // no smooth scrolling lScrollTime = 0; } // capture the mouse HWND hwnd = pServerHost->_pInPlace->_hwnd; if(FAILED(GWSetCapture( pSBC, ONMESSAGE_METHOD(CScrollbarController, OnMessage, onmessage), hwnd))) { pSBC->_pLayout = NULL; return; } // set timer for repeating actions if(pSBC->_partPressed != SBP_THUMB) { // perform first action pLayout->OnScroll( pSBC->_direction, TranslateSBAction(pSBC->_partPressed), 0, FALSE, lScrollTime); CSize scrollOffset; pSBC->_pDispScroller->GetScrollOffset(&scrollOffset); scrollAmount = scrollOffset[pSBC->_direction]; // set timer for subsequent action FormsSetTimer( pSBC, ONTICK_METHOD(CScrollbarController, OnTick, ontick), SB_REPEAT_TIMER, GetRepeatDelay()); } // invalidate the part we hit, if necessary pLayout->OpenView(); InvalidatePart( pSBC->_partPressed, pSBC->_direction, pSBC->_rcScrollbar, contentSize, containerSize, scrollAmount, buttonWidth, pDispScroller, pSBC->GetDrawInfo()); }
gg_tl_dat BigScrollBar::GetBigThumbSize() { gg_tl_dat result = (((gg_tl_dat)GetThumbSize())*m_BigRange)/SCROLLBAR_LENGTH; return result; }
//+--------------------------------------------------------------------------- // // Member: CScrollbar::GetPartRect // // Synopsis: Return the rect bounding the given scroll bar part. // // Arguments: prcPart returns part rect // part which scroll bar part // direction 0 for horizontal scroll bar, 1 for vertical // rcScrollbar scroll bar bounds // contentSize size of content controlled by scroll bar // containerSize size of container // scrollAmount current scroll amount // buttonWidth width of scroll bar buttons // fRightToLeft The text flow is RTL...0,0 is at top right // // Notes: // //---------------------------------------------------------------------------- void CScrollbar::GetPartRect( CRect* prcPart, SCROLLBARPART part, int direction, const CRect& rcScrollbar, long contentSize, long containerSize, long scrollAmount, long buttonWidth, CDrawInfo* pDI, BOOL fRightToLeft) { // adjust button width if there isn't room for both buttons at full size long scaledButtonWidth = GetScaledButtonWidth(direction, rcScrollbar, buttonWidth); switch(part) { case SBP_NONE: AssertSz(FALSE, "CScrollbar::GetPartRect called with no part"); prcPart->SetRectEmpty(); break; case SBP_PREVBUTTON: *prcPart = rcScrollbar; (*prcPart)[direction+2] = rcScrollbar[direction] + scaledButtonWidth; break; case SBP_NEXTBUTTON: *prcPart = rcScrollbar; (*prcPart)[direction] = rcScrollbar[direction+2] - scaledButtonWidth; break; case SBP_TRACK: case SBP_PREVTRACK: case SBP_NEXTTRACK: case SBP_THUMB: { if(contentSize<=containerSize && part!=SBP_TRACK) { prcPart->SetRectEmpty(); break; } *prcPart = rcScrollbar; (*prcPart)[direction] += scaledButtonWidth; (*prcPart)[direction+2] -= scaledButtonWidth; if(part == SBP_TRACK) { break; } // calculate thumb size long trackSize = prcPart->Size(direction); long thumbSize = GetThumbSize( direction, rcScrollbar, contentSize, containerSize, buttonWidth, pDI); long thumbOffset = GetThumbOffset( contentSize, containerSize, scrollAmount, trackSize, thumbSize); if(part == SBP_THUMB) { // We need to special case RTL HSCROLL if(direction==0 && fRightToLeft) { prcPart->right += thumbOffset; prcPart->left = prcPart->right - thumbSize; } else { (*prcPart)[direction] += thumbOffset; (*prcPart)[direction+2] = (*prcPart)[direction] + thumbSize; } } else if(part == SBP_PREVTRACK) { if(direction==0 && fRightToLeft) { prcPart->right += thumbOffset - thumbSize; } else { (*prcPart)[direction+2] = (*prcPart)[direction] + thumbOffset; } } else { if(direction==0 && fRightToLeft) { prcPart->left = prcPart->right + thumbOffset; } else { (*prcPart)[direction] += thumbOffset + thumbSize; } } } break; } }