tbool CScrollBar::OnMouse(EMouseMsg MouseMsg, const SPos& Pos) { if (!IsVisible()) { return false; } if (CPane::OnMouse(MouseMsg, Pos)) { return true; } if (mbScrolling) { // We're currently scrolling switch(MouseMsg) { case MouseMove: { switch(mType) { case TypeHorizontal: { // Calculate the mouse delta tint iMouseDelta = Pos.iX - mMousePosOrg.iX; // Calculate where we want the handle to be tint iHandlePosX = mScrollBarRectOrg.iX + iMouseDelta; // Calculate movememt from mouse delta std::list<IControl*>::iterator it = mControls.begin(); if (mControls.size() > 2) { it++; } IControl* pControl = *it++; SRect RctArrowLeft; pControl->GetRect(RctArrowLeft); // Left-most possible handle position SPos PosLeftMost(RctArrowLeft.iX + RctArrowLeft.iCX, RctArrowLeft.iY); pControl = *it; SPos PosRightArrow; pControl->GetPos(PosRightArrow); tint iMaxWidth = PosRightArrow.iX - PosLeftMost.iX; // Calculate the relative width we occupy tfloat64 fWidthRelative = mScrollPos.VisibleRect.iCX / (double)mScrollPos.AreaSize.iCX; // Calculate the ralative position to be tfloat64 fPositionRelative = (iHandlePosX - PosLeftMost.iX) / (iMaxWidth - (fWidthRelative * iMaxWidth)); // Update scrolling position mScrollPos = mScrollPosOrg; mScrollPos.VisibleRect.iX = (int)((fPositionRelative * (mScrollPos.AreaSize.iCX - mScrollPos.VisibleRect.iCX)) + 0.5f); // Limit scrolling position if (mScrollPos.VisibleRect.iX < 0) { mScrollPos.VisibleRect.iX = 0; } if (mScrollPos.VisibleRect.iX > mScrollPos.AreaSize.iCX - mScrollPos.VisibleRect.iCX) { mScrollPos.VisibleRect.iX = mScrollPos.AreaSize.iCX - mScrollPos.VisibleRect.iCX; } // Redraw and set scroll pos (which will cause scroll pane to redraw) CControl::Redraw(); mpScrollPane->SetScrollPos(mScrollPos); SetValue(0); } break; case TypeVertical: { // Calculate the mouse delta tint iMouseDelta = Pos.iY - mMousePosOrg.iY; // Calculate where we want the handle to be tint iHandlePosY = mScrollBarRectOrg.iY + iMouseDelta; // Calculate movememt from mouse delta std::list<IControl*>::iterator it = mControls.begin(); if (mControls.size() > 2) { it++; } IControl* pControl = *it++; SRect RctArrowTop; pControl->GetRect(RctArrowTop); // Top-most possible handle position SPos PosTopMost(RctArrowTop.iX, RctArrowTop.iY + RctArrowTop.iCY); pControl = *it; SPos PosBottomArrow; pControl->GetPos(PosBottomArrow); tint iMaxHeight = PosBottomArrow.iY - PosTopMost.iY; // Calculate the relative height we occupy tfloat64 fHeightRelative = mScrollPos.VisibleRect.iCY / (double)mScrollPos.AreaSize.iCY; // Calculate the ralative position to be tfloat64 fPositionRelative = (iHandlePosY - PosTopMost.iY) / (iMaxHeight - (fHeightRelative * iMaxHeight)); // Update scrolling position mScrollPos = mScrollPosOrg; mScrollPos.VisibleRect.iY = (int)((fPositionRelative * (mScrollPos.AreaSize.iCY - mScrollPos.VisibleRect.iCY)) + 0.5f); // Limit scrolling position if (mScrollPos.VisibleRect.iY < 0) { mScrollPos.VisibleRect.iY = 0; } if (mScrollPos.VisibleRect.iY > mScrollPos.AreaSize.iCY - mScrollPos.VisibleRect.iCY) { mScrollPos.VisibleRect.iY = mScrollPos.AreaSize.iCY - mScrollPos.VisibleRect.iCY; } // Redraw and set scroll pos (which will cause scroll pane to redraw) CControl::Redraw(); mpScrollPane->SetScrollPos(mScrollPos); SetValue(0); } break; } } break; case LeftButtonUp: { dynamic_cast<CWindow*>(GetParentWindow())->ReleaseMouseFocus(); mbScrolling = false; return true; } break; } } SRect rctHandle = GetHandleRect(); if (rctHandle.Inside(Pos)) { // We hit the handle with the mouse if (MouseMsg == LeftButtonDown) { mMousePosOrg = Pos; mScrollPosOrg = mScrollPos; mScrollBarRectOrg = rctHandle; dynamic_cast<CWindow*>(GetParentWindow())->GetMouseFocus(dynamic_cast<IControl*>(this)); mbScrolling = true; return true; } } else { if (MouseMsg == LeftButtonDown) { SRect RctThis; GetRect(RctThis); if (RctThis.Inside(Pos)) { // We hit inside the control (but not the handle) switch(mType) { case TypeHorizontal: { // Calculate the mouse delta tint iMouseDelta; if (Pos.iX < rctHandle.iX) { iMouseDelta = -rctHandle.iCX; } else { iMouseDelta = rctHandle.iCX; } // Calculate where we want the handle to be tint iHandlePosX = rctHandle.iX + iMouseDelta; // Calculate movememt from mouse delta std::list<IControl*>::iterator it = mControls.begin(); if (mControls.size() > 2) { it++; } IControl* pControl = *it++; SRect RctArrowLeft; pControl->GetRect(RctArrowLeft); // Left-most possible handle position SPos PosLeftMost(RctArrowLeft.iX + RctArrowLeft.iCX, RctArrowLeft.iY); pControl = *it; SPos PosRightArrow; pControl->GetPos(PosRightArrow); tint iMaxWidth = PosRightArrow.iX - PosLeftMost.iX; // Calculate the relative width we occupy tfloat64 fWidthRelative = mScrollPos.VisibleRect.iCX / (double)mScrollPos.AreaSize.iCX; // Calculate the ralative position to be tfloat64 fPositionRelative = (iHandlePosX - PosLeftMost.iX) / (iMaxWidth - (fWidthRelative * iMaxWidth)); // Update scrolling position mScrollPos = mScrollPos; mScrollPos.VisibleRect.iX = (int)((fPositionRelative * (mScrollPos.AreaSize.iCX - mScrollPos.VisibleRect.iCX)) + 0.5f); // Limit scrolling position if (mScrollPos.VisibleRect.iX < 0) { mScrollPos.VisibleRect.iX = 0; } if (mScrollPos.VisibleRect.iX > mScrollPos.AreaSize.iCX - mScrollPos.VisibleRect.iCX) { mScrollPos.VisibleRect.iX = mScrollPos.AreaSize.iCX - mScrollPos.VisibleRect.iCX; } // Redraw and set scroll pos (which will cause scroll pane to redraw) CControl::Redraw(); mpScrollPane->SetScrollPos(mScrollPos); // Lasse, added 2008-04-17 - bug-fix, didn't fire listeners' EventValueChange SetValue(0); // .. Lasse } break; case TypeVertical: { // Calculate the mouse delta tint iMouseDelta; if (Pos.iY < rctHandle.iY) { iMouseDelta = -rctHandle.iCY; } else { iMouseDelta = rctHandle.iCY; } // Calculate where we want the handle to be tint iHandlePosY = rctHandle.iY + iMouseDelta; // Calculate movememt from mouse delta std::list<IControl*>::iterator it = mControls.begin(); if (mControls.size() > 2) { it++; } IControl* pControl = *it++; SRect RctArrowTop; pControl->GetRect(RctArrowTop); // Top-most possible handle position SPos PosTopMost(RctArrowTop.iX, RctArrowTop.iY + RctArrowTop.iCY); pControl = *it; SPos PosBottomArrow; pControl->GetPos(PosBottomArrow); tint iMaxHeight = PosBottomArrow.iY - PosTopMost.iY; // Calculate the relative height we occupy tfloat64 fHeightRelative = mScrollPos.VisibleRect.iCY / (double)mScrollPos.AreaSize.iCY; // Calculate the ralative position to be tfloat64 fPositionRelative = (iHandlePosY - PosTopMost.iY) / (iMaxHeight - (fHeightRelative * iMaxHeight)); // Update scrolling position mScrollPos = mScrollPos; mScrollPos.VisibleRect.iY = (int)((fPositionRelative * (mScrollPos.AreaSize.iCY - mScrollPos.VisibleRect.iCY)) + 0.5f); // Limit scrolling position if (mScrollPos.VisibleRect.iY < 0) { mScrollPos.VisibleRect.iY = 0; } if (mScrollPos.VisibleRect.iY > mScrollPos.AreaSize.iCY - mScrollPos.VisibleRect.iCY) { mScrollPos.VisibleRect.iY = mScrollPos.AreaSize.iCY - mScrollPos.VisibleRect.iCY; } // Redraw and set scroll pos (which will cause scroll pane to redraw) CControl::Redraw(); mpScrollPane->SetScrollPos(mScrollPos); // Lasse, added 2008-04-17 - bug-fix, didn't fire listeners' EventValueChange SetValue(0); // .. Lasse } break; } } } } return false; }
void CScrollBar::EventValueChange(IControl *pSender, tint32 /*iValueNew*/) { // Lasse, add 2008-05-09 if ((mpScrollPane) && (pSender == mpScrollPane)) { SScrollPos sp; mpScrollPane->GetScrollPos(sp); if (mScrollPos != sp) { SRect rectTest1 = GetHandleRect(); SetScrollPos(sp, true); //PositionControls(); Redraw(GetRect()); SRect rectTest2 = GetHandleRect(); int iDummy = 0; } return; } // .. Lasse // Figure out which one of the controls it is std::list<IControl*>::iterator it = mControls.begin(); if (mControls.size() > 2) { it++; } tint iDelta; if (pSender == *it) { // Up / left iDelta = -10; } else { // Down / right iDelta = 10; } SRect rctHandle = GetHandleRect(); switch(mType) { case TypeHorizontal: { // Calculate where we want the handle to be tint iHandlePosX = rctHandle.iX + iDelta; // Calculate movememt from mouse delta std::list<IControl*>::iterator it = mControls.begin(); if (mControls.size() > 2) { it++; } IControl* pControl = *it++; SRect RctArrowLeft; pControl->GetRect(RctArrowLeft); // Left-most possible handle position SPos PosLeftMost(RctArrowLeft.iX + RctArrowLeft.iCX, RctArrowLeft.iY); pControl = *it; SPos PosRightArrow; pControl->GetPos(PosRightArrow); tint iMaxWidth = PosRightArrow.iX - PosLeftMost.iX; // Calculate the relative width we occupy tfloat64 fWidthRelative = mScrollPos.VisibleRect.iCX / (double)mScrollPos.AreaSize.iCX; // Calculate the ralative position to be tfloat64 fPositionRelative = (iHandlePosX - PosLeftMost.iX) / (iMaxWidth - (fWidthRelative * iMaxWidth)); // Update scrolling position mScrollPos.VisibleRect.iX = (int)((fPositionRelative * (mScrollPos.AreaSize.iCX - mScrollPos.VisibleRect.iCX)) + 0.5f); // Limit scrolling position if (mScrollPos.VisibleRect.iX < 0) { mScrollPos.VisibleRect.iX = 0; } if (mScrollPos.VisibleRect.iX > mScrollPos.AreaSize.iCX - mScrollPos.VisibleRect.iCX) { mScrollPos.VisibleRect.iX = mScrollPos.AreaSize.iCX - mScrollPos.VisibleRect.iCX; } // Redraw and set scroll pos (which will cause scroll pane to redraw) CControl::Redraw(); mpScrollPane->SetScrollPos(mScrollPos); } break; case TypeVertical: { // Calculate where we want the handle to be tint iHandlePosY = rctHandle.iY + iDelta; // Calculate movememt from mouse delta std::list<IControl*>::iterator it = mControls.begin(); if (mControls.size() > 2) { it++; } IControl* pControl = *it++; SRect RctArrowTop; pControl->GetRect(RctArrowTop); // Top-most possible handle position SPos PosTopMost(RctArrowTop.iX, RctArrowTop.iY + RctArrowTop.iCY); pControl = *it; SPos PosBottomArrow; pControl->GetPos(PosBottomArrow); tint iMaxHeight = PosBottomArrow.iY - PosTopMost.iY; // Calculate the relative height we occupy tfloat64 fHeightRelative = mScrollPos.VisibleRect.iCY / (double)mScrollPos.AreaSize.iCY; // Calculate the ralative position to be tfloat64 fPositionRelative = (iHandlePosY - PosTopMost.iY) / (iMaxHeight - (fHeightRelative * iMaxHeight)); // Update scrolling position mScrollPos.VisibleRect.iY = (int)((fPositionRelative * (mScrollPos.AreaSize.iCY - mScrollPos.VisibleRect.iCY)) + 0.5f); // Limit scrolling position if (mScrollPos.VisibleRect.iY < 0) { mScrollPos.VisibleRect.iY = 0; } if (mScrollPos.VisibleRect.iY > mScrollPos.AreaSize.iCY - mScrollPos.VisibleRect.iCY) { mScrollPos.VisibleRect.iY = mScrollPos.AreaSize.iCY - mScrollPos.VisibleRect.iCY; } // Redraw and set scroll pos (which will cause scroll pane to redraw) CControl::Redraw(); mpScrollPane->SetScrollPos(mScrollPos); } break; } }
SRect CScrollBar::GetHandleRect() { SRect rctHandle; if (mpScrollPane) mpScrollPane->GetScrollPos(mScrollPos); switch(mType) { case TypeHorizontal: { // The leftmost top-left point is 1 pixel to the right of the top-right point of the left arrow std::list<IControl*>::iterator it = mControls.begin(); if (mControls.size() > 2) { it++; } IControl* pControl = *it++; SRect RctArrow; pControl->GetRect(RctArrow); SPos Pos(RctArrow.iX + RctArrow.iCX, RctArrow.iY); // Calculate the relative position (top-left point) tint iDiff = mScrollPos.AreaSize.iCX - mScrollPos.VisibleRect.iCX; tfloat64 fPositionRelative; if (iDiff == 0) { fPositionRelative = 0; } else { fPositionRelative = (double)mScrollPos.VisibleRect.iX / iDiff; } // Calculate the maximum width of the handle pControl = *it; SPos PosRightArrow; pControl->GetPos(PosRightArrow); tint iMaxWidth = PosRightArrow.iX - Pos.iX; // Calculate the relative width we occupy tfloat64 fWidthRelative = mScrollPos.VisibleRect.iCX / (double)mScrollPos.AreaSize.iCX; // Calculate the absolute size rctHandle = SRect(Pos, SSize(0, 0)); rctHandle.iCY = mpBitmapSizes[BitmapCenterHandle].iCY; rctHandle.iCX = (int)((fWidthRelative * iMaxWidth) + 0.5); // Calculate the absolute position rctHandle.iX += (int)((fPositionRelative * (iMaxWidth - rctHandle.iCX)) + 0.5); if (rctHandle.iCX < mpBitmapSizes[BitmapLeftTopHandle].iCX + mpBitmapSizes[BitmapRightDownHandle].iCX) { rctHandle.iCX = mpBitmapSizes[BitmapLeftTopHandle].iCX + mpBitmapSizes[BitmapRightDownHandle].iCX; } } break; case TypeVertical: { // The topmost top-left point is 1 pixel below the bottom-left point of the up arrow std::list<IControl*>::iterator it = mControls.begin(); if (mControls.size() > 2) { it++; } IControl* pControl = *it++; SRect RctArrow; pControl->GetRect(RctArrow); SPos Pos(RctArrow.iX, RctArrow.iY + RctArrow.iCY); // Calculate the relative position (top-left point) tint iDiff = mScrollPos.AreaSize.iCY - mScrollPos.VisibleRect.iCY; tfloat64 fPositionRelative; if (iDiff == 0) { fPositionRelative = 0; } else { fPositionRelative = (double)mScrollPos.VisibleRect.iY / iDiff; } // Calculate the maximum height of the handle pControl = *it; SPos PosDownArrow; pControl->GetPos(PosDownArrow); tint iMaxHeight = PosDownArrow.iY - Pos.iY; // Calculate the relative height we occupy tfloat64 fHeightRelative = mScrollPos.VisibleRect.iCY / (double)mScrollPos.AreaSize.iCY; // Calculate the absolute size rctHandle = SRect(Pos, SSize(0, 0)); rctHandle.iCX = mpBitmapSizes[BitmapCenterHandle].iCX; rctHandle.iCY = (int)((fHeightRelative * iMaxHeight) + 0.5); // Calculate the absolute position rctHandle.iY += (int)((fPositionRelative * (iMaxHeight - rctHandle.iCY)) + 0.5); if (rctHandle.iCY < mpBitmapSizes[BitmapLeftTopHandle].iCY + mpBitmapSizes[BitmapRightDownHandle].iCY) { rctHandle.iCY = mpBitmapSizes[BitmapLeftTopHandle].iCY + mpBitmapSizes[BitmapRightDownHandle].iCY; } } break; } return rctHandle; }