490 lines
11 KiB
C++
490 lines
11 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "bagel/spacebar/boflib/app.h"
|
|
#include "bagel/spacebar/boflib/gui/scroll_bar.h"
|
|
|
|
namespace Bagel {
|
|
namespace SpaceBar {
|
|
|
|
#define BMP_SCROLL_TIMER 9999
|
|
#define DEF_TIMER_INTERVAL 100
|
|
|
|
|
|
CBofScrollBar::CBofScrollBar() {
|
|
_pLeftBtnUp = nullptr;
|
|
_pRightBtnUp = nullptr;
|
|
_pLeftBtnDn = nullptr;
|
|
_pRightBtnDn = nullptr;
|
|
_pThumb = nullptr;
|
|
_nMin = 0;
|
|
_nMax = 10;
|
|
_nPos = 0;
|
|
_nLineDelta = 1;
|
|
_nPageDelta = 1;
|
|
|
|
_pScrollText = nullptr;
|
|
_szScrollText[0] = '\0';
|
|
|
|
_cThumbSize.cx = 0;
|
|
_cThumbSize.cy = 0;
|
|
_cBkSize.cx = 0;
|
|
_cBkSize.cy = 0;
|
|
_cCurPoint.x = 0;
|
|
_cCurPoint.y = 0;
|
|
_cThumbPos.x = 0;
|
|
_cThumbPos.y = 0;
|
|
|
|
_nOffset = 0;
|
|
_nScrollWidth = 0;
|
|
_nRange = 0;
|
|
_bMouseCaptured = false;
|
|
_nScrollState = 0;
|
|
|
|
_nTimerCount = DEF_TIMER_INTERVAL;
|
|
}
|
|
|
|
|
|
CBofScrollBar::~CBofScrollBar() {
|
|
assert(isValidObject(this));
|
|
|
|
_szScrollText[0] = '\0';
|
|
|
|
delete _pScrollText;
|
|
_pScrollText = nullptr;
|
|
|
|
delete _pThumb;
|
|
_pThumb = nullptr;
|
|
|
|
delete _pLeftBtnUp;
|
|
_pLeftBtnUp = nullptr;
|
|
|
|
delete _pRightBtnUp;
|
|
_pRightBtnUp = nullptr;
|
|
|
|
delete _pLeftBtnDn;
|
|
_pLeftBtnDn = nullptr;
|
|
|
|
delete _pRightBtnDn;
|
|
_pRightBtnDn = nullptr;
|
|
}
|
|
|
|
|
|
void CBofScrollBar::onPaint(CBofRect *pDirtyRect) {
|
|
assert(isValidObject(this));
|
|
|
|
paint(pDirtyRect);
|
|
}
|
|
|
|
|
|
ErrorCode CBofScrollBar::setText(const char *pszText, int nJustify) {
|
|
assert(isValidObject(this));
|
|
|
|
_szScrollText[0] = '\0';
|
|
|
|
if ((pszText != nullptr) && (_parent != nullptr)) {
|
|
Common::strlcpy(_szScrollText, pszText, MAX_TEXT);
|
|
|
|
if (_pScrollText == nullptr) {
|
|
|
|
CBofPoint cPoint = _parent->getWindowRect().topLeft();
|
|
CBofRect cTempRect = _cWindowRect - cPoint;
|
|
|
|
cTempRect -= CBofPoint(0, 20);
|
|
cTempRect.right += 20;
|
|
|
|
_pScrollText = new CBofText(&cTempRect, nJustify);
|
|
}
|
|
|
|
if (_pScrollText != nullptr) {
|
|
_pScrollText->display(_parent, _szScrollText, FONT_DEFAULT_SIZE, TEXT_DEFAULT_FACE);
|
|
}
|
|
}
|
|
|
|
return _errCode;
|
|
}
|
|
|
|
|
|
ErrorCode CBofScrollBar::setPos(const int nPos, bool bRepaint, bool isInitial) {
|
|
assert(isValidObject(this));
|
|
|
|
// Save old position
|
|
int nOriginalPos = _nPos;
|
|
|
|
_nPos = nPos;
|
|
if (nPos < _nMin)
|
|
_nPos = _nMin;
|
|
if (nPos > _nMax)
|
|
_nPos = _nMax;
|
|
|
|
assert(_nRange != 0);
|
|
|
|
_cThumbPos.x = (int)(((int32)(_nScrollWidth - _cThumbSize.cx) * _nPos) / (_nRange - 1)) + _nOffset;
|
|
_cThumbPos.y = (int)(_cBkSize.cy / 2) - (int)(_cThumbSize.cy / 2);
|
|
|
|
if (_cThumbPos.x < 0)
|
|
_cThumbPos.x = 0;
|
|
if (_cThumbPos.x > (_nScrollWidth - _cThumbSize.cx + _nOffset))
|
|
_cThumbPos.x = _nScrollWidth - _cThumbSize.cx + _nOffset;
|
|
|
|
// If forced to repaint
|
|
if (bRepaint) {
|
|
|
|
paint();
|
|
|
|
} else if (_nPos != nOriginalPos) {
|
|
// Otherwise, only paint the thumb if it's position changed
|
|
if (_pThumb != nullptr) {
|
|
if (_pThumb->paintSprite(this, _cThumbPos) == false) {
|
|
reportError(ERR_UNKNOWN, "_pThumb->paintSprite() failed");
|
|
}
|
|
}
|
|
}
|
|
|
|
// If the thumb actually moved, then tell our parent about it
|
|
if (_nPos != nOriginalPos && !isInitial) {
|
|
_parent->onBofScrollBar(this, _nPos);
|
|
}
|
|
|
|
return _errCode;
|
|
}
|
|
|
|
|
|
void CBofScrollBar::getScrollRange(int &nMin, int &nMax) {
|
|
assert(isValidObject(this));
|
|
|
|
nMin = _nMin;
|
|
nMax = _nMax;
|
|
}
|
|
|
|
|
|
void CBofScrollBar::setScrollRange(int nMin, int nMax, bool bRepaint) {
|
|
assert(isValidObject(this));
|
|
|
|
_nMin = nMin;
|
|
_nMax = nMax;
|
|
|
|
_nRange = _nMax - _nMin + 1;
|
|
|
|
// Should we repaint the scroll bar now?
|
|
if (bRepaint) {
|
|
paint();
|
|
}
|
|
}
|
|
|
|
|
|
ErrorCode CBofScrollBar::loadBitmaps(const char *pszBack, const char *pszThumb, const char *pszLeftBtnUp, const char *pszRightBtnUp, const char *pszLeftBtnDn, const char *pszRightBtnDn) {
|
|
assert(isValidObject(this));
|
|
|
|
if ((pszBack == nullptr) || (pszThumb == nullptr))
|
|
return _errCode;
|
|
|
|
_cLeftBtnRect.setRect(0, 0, 0, 0);
|
|
_cRightBtnRect.setRect(0, 0, 0, 0);
|
|
|
|
if (_pThumb != nullptr) {
|
|
_pThumb->eraseSprite(this);
|
|
delete _pThumb;
|
|
_pThumb = nullptr;
|
|
}
|
|
|
|
killBackdrop();
|
|
setBackdrop(pszBack);
|
|
|
|
CBofPalette *pPalette = CBofApp::getApp()->getPalette();
|
|
|
|
_cBkSize = _pBackdrop->getSize();
|
|
_nScrollWidth = _cBkSize.cx;
|
|
|
|
_pThumb = new CBofSprite;
|
|
|
|
if (_pThumb->loadSprite(pszThumb) != false) {
|
|
_pThumb->setMaskColor(COLOR_WHITE);
|
|
_cThumbSize = _pThumb->getSize();
|
|
}
|
|
|
|
delete _pLeftBtnUp;
|
|
_pLeftBtnUp = nullptr;
|
|
|
|
CBofPoint cPoint;
|
|
if (pszLeftBtnUp != nullptr) {
|
|
_pLeftBtnUp = new CBofBitmap(pszLeftBtnUp, pPalette);
|
|
|
|
cPoint.x = 0;
|
|
cPoint.y = (_pBackdrop->height() / 2) - (_pLeftBtnUp->height() / 2);
|
|
|
|
_cLeftBtnRect = _pLeftBtnUp->getRect() + cPoint;
|
|
|
|
_nOffset = _pLeftBtnUp->width();
|
|
_nScrollWidth -= _nOffset;
|
|
}
|
|
|
|
delete _pRightBtnUp;
|
|
_pRightBtnUp = nullptr;
|
|
|
|
if (pszRightBtnUp != nullptr) {
|
|
_pRightBtnUp = new CBofBitmap(pszRightBtnUp, pPalette);
|
|
|
|
cPoint.x = _pBackdrop->width() - _pRightBtnUp->width();
|
|
cPoint.y = (_pBackdrop->height() / 2) - (_pRightBtnUp->height() / 2);
|
|
_cRightBtnRect = _pLeftBtnUp->getRect() + cPoint;
|
|
|
|
_nScrollWidth -= _cRightBtnRect.width();
|
|
}
|
|
|
|
delete _pLeftBtnDn;
|
|
_pLeftBtnDn = nullptr;
|
|
|
|
if (pszLeftBtnDn != nullptr) {
|
|
_pLeftBtnDn = new CBofBitmap(pszLeftBtnDn, pPalette);
|
|
}
|
|
|
|
delete _pRightBtnDn;
|
|
_pRightBtnDn = nullptr;
|
|
|
|
if (pszRightBtnDn != nullptr) {
|
|
_pRightBtnDn = new CBofBitmap(pszRightBtnDn, pPalette);
|
|
}
|
|
|
|
return _errCode;
|
|
}
|
|
|
|
|
|
ErrorCode CBofScrollBar::paint(CBofRect *pDirtyRect) {
|
|
assert(isValidObject(this));
|
|
|
|
if (!errorOccurred()) {
|
|
CBofPalette *pPalette = CBofApp::getApp()->getPalette();
|
|
|
|
//
|
|
// This function needs to be optimized to paint only the section that is
|
|
// invalidated. Right now it just repaints the entire scroll bar each time.
|
|
//
|
|
|
|
if ((_pBackdrop != nullptr) && (_pThumb != nullptr)) {
|
|
// Do all painting offscreen
|
|
CBofBitmap *pBmp = new CBofBitmap(_cBkSize.cx, _cBkSize.cy, pPalette);
|
|
_pBackdrop->paint(pBmp, 0, 0, nullptr, COLOR_WHITE);
|
|
|
|
if ((_nScrollState == 1) && (_pLeftBtnDn != nullptr)) {
|
|
CBofPoint cPoint = _cLeftBtnRect.topLeft();
|
|
_pLeftBtnDn->paint(pBmp, cPoint.x, cPoint.y, nullptr, COLOR_WHITE);
|
|
|
|
} else if (_pLeftBtnUp != nullptr) {
|
|
CBofPoint cPoint = _cLeftBtnRect.topLeft();
|
|
_pLeftBtnUp->paint(pBmp, cPoint.x, cPoint.y, nullptr, COLOR_WHITE);
|
|
}
|
|
|
|
if ((_nScrollState == 4) && (_pRightBtnDn != nullptr)) {
|
|
CBofPoint cPoint = _cRightBtnRect.topLeft();
|
|
_pRightBtnDn->paint(pBmp, cPoint.x, cPoint.y, nullptr, COLOR_WHITE);
|
|
|
|
} else if (_pRightBtnUp != nullptr) {
|
|
CBofPoint cPoint = _cRightBtnRect.topLeft();
|
|
_pRightBtnUp->paint(pBmp, cPoint.x, cPoint.y, nullptr, COLOR_WHITE);
|
|
}
|
|
|
|
_cThumbPos.x = (int)(((int32)(_nScrollWidth - _cThumbSize.cx) * _nPos) / (_nRange - 1)) + _nOffset;
|
|
_cThumbPos.y = (int)(_cBkSize.cy / 2) - (int)(_cThumbSize.cy / 2);
|
|
|
|
if (_cThumbPos.x < 0)
|
|
_cThumbPos.x = 0;
|
|
if (_cThumbPos.x > (_nScrollWidth - _cThumbSize.cx + _nOffset))
|
|
_cThumbPos.x = _nScrollWidth - _cThumbSize.cx + _nOffset;
|
|
|
|
_pThumb->paintSprite(pBmp, _cThumbPos);
|
|
|
|
// now we can paint the offscreen buffer to the screen
|
|
pBmp->paint(this, 0, 0);
|
|
|
|
delete pBmp;
|
|
}
|
|
|
|
if ((_pScrollText != nullptr) && (_parent != nullptr)) {
|
|
_pScrollText->display(_parent, _szScrollText, FONT_DEFAULT_SIZE, TEXT_DEFAULT_FACE);
|
|
}
|
|
}
|
|
|
|
return _errCode;
|
|
}
|
|
|
|
|
|
void CBofScrollBar::onLButtonDown(uint32 nFlags, CBofPoint *pPoint, void *) {
|
|
assert(isValidObject(this));
|
|
|
|
CBofRect cLeftPageRect, cRightPageRect;
|
|
|
|
bool bDoNothing = false;
|
|
|
|
cLeftPageRect.setRect(_nOffset, 0, (_nScrollWidth / _nRange) * _nPos + _nOffset - 1, _cBkSize.cy - 1);
|
|
cRightPageRect.setRect(((_nScrollWidth / _nRange) * _nPos) + _nOffset + _cThumbSize.cx, 0, _nOffset + _nScrollWidth - 1, _cBkSize.cy - 1);
|
|
|
|
_cCurPoint = *pPoint;
|
|
|
|
if (_pLeftBtnUp != nullptr && _cLeftBtnRect.ptInRect(*pPoint)) {
|
|
// Let timer know what happened
|
|
_nScrollState = 1;
|
|
|
|
// Set new thumb position
|
|
setPos(_nPos - _nLineDelta, true);
|
|
|
|
} else if (_pThumb->getRect().ptInRect(*pPoint)) {
|
|
_nScrollState = 5;
|
|
|
|
} else if (cLeftPageRect.ptInRect(*pPoint)) {
|
|
_nScrollState = 2;
|
|
|
|
// Set new thumb position
|
|
setPos(_nPos - _nPageDelta, true);
|
|
|
|
} else if (cRightPageRect.ptInRect(*pPoint)) {
|
|
_nScrollState = 3;
|
|
|
|
// Set new thumb position
|
|
setPos(_nPos + _nPageDelta, true);
|
|
|
|
} else if (_pRightBtnUp != nullptr && _cRightBtnRect.ptInRect(*pPoint)) {
|
|
// Let timer know what happened
|
|
_nScrollState = 4;
|
|
|
|
// Set new thumb position
|
|
setPos(_nPos + _nLineDelta, true);
|
|
|
|
} else {
|
|
bDoNothing = true;
|
|
}
|
|
|
|
if (!bDoNothing) {
|
|
_bMouseCaptured = true;
|
|
setCapture();
|
|
if (_nScrollState != 5)
|
|
setTimer(BMP_SCROLL_TIMER, _nTimerCount);
|
|
}
|
|
|
|
CBofWindow::onLButtonDown(nFlags, pPoint);
|
|
}
|
|
|
|
|
|
int CBofScrollBar::pointToPos(CBofPoint *pPoint) {
|
|
assert(isValidObject(this));
|
|
assert(pPoint != nullptr);
|
|
|
|
int nPos = _nPos;
|
|
|
|
if (_cRect.ptInRect(*pPoint)) {
|
|
nPos = (pPoint->x - _nOffset) / (int)(_nScrollWidth / _nRange);
|
|
}
|
|
|
|
return nPos;
|
|
}
|
|
|
|
|
|
void CBofScrollBar::onLButtonUp(uint32 nFlags, CBofPoint *pPoint, void *) {
|
|
assert(isValidObject(this));
|
|
|
|
if (_bMouseCaptured) {
|
|
killTimer(BMP_SCROLL_TIMER);
|
|
_bMouseCaptured = false;
|
|
releaseCapture();
|
|
|
|
int x, y;
|
|
|
|
switch (_nScrollState) {
|
|
case 5:
|
|
setPos(pointToPos(pPoint));
|
|
break;
|
|
|
|
case 1:
|
|
if (_pLeftBtnUp != nullptr) {
|
|
x = 0;
|
|
y = (int)(_cBkSize.cy / 2) - (int)(_cLeftBtnRect.height() / 2);
|
|
_pLeftBtnUp->paint(this, x, y, nullptr, COLOR_WHITE);
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
if (_pRightBtnUp != nullptr) {
|
|
x = _cBkSize.cx - _cRightBtnRect.width();
|
|
y = (int)(_cBkSize.cy / 2) - (int)(_cRightBtnRect.height() / 2);
|
|
_pRightBtnUp->paint(this, x, y, nullptr, COLOR_WHITE);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
_nScrollState = 0;
|
|
}
|
|
|
|
CBofWindow::onLButtonUp(nFlags, pPoint);
|
|
}
|
|
|
|
|
|
void CBofScrollBar::onMouseMove(uint32 nFlags, CBofPoint *pPoint, void *) {
|
|
assert(isValidObject(this));
|
|
|
|
if (_bMouseCaptured) {
|
|
_cCurPoint = *pPoint;
|
|
|
|
if (_nScrollState == 5) {
|
|
setPos(pointToPos(pPoint));
|
|
}
|
|
}
|
|
|
|
CBofWindow::onMouseMove(nFlags, pPoint);
|
|
}
|
|
|
|
|
|
void CBofScrollBar::setRepeatTimer(uint32 nTimerInt) {
|
|
assert(isValidObject(this));
|
|
|
|
_nTimerCount = nTimerInt;
|
|
}
|
|
|
|
|
|
void CBofScrollBar::onTimer(uint32 nWhichTimer) {
|
|
assert(isValidObject(this));
|
|
|
|
CBofRect cLeftPageRect, cRightPageRect;
|
|
|
|
cLeftPageRect.setRect(_nOffset, 0, (_nScrollWidth / _nRange) * _nPos + _nOffset - 1, _cBkSize.cy - 1);
|
|
cRightPageRect.setRect(((_nScrollWidth / _nRange) * _nPos) + _nOffset + _cThumbSize.cx, 0, _nOffset + _nScrollWidth - 1, _cBkSize.cy - 1);
|
|
|
|
if (nWhichTimer == BMP_SCROLL_TIMER) {
|
|
if ((_nScrollState == 1) && _cLeftBtnRect.ptInRect(_cCurPoint)) {
|
|
lineLeft();
|
|
|
|
} else if ((_nScrollState == 2) && cLeftPageRect.ptInRect(_cCurPoint)) {
|
|
pageLeft();
|
|
|
|
} else if ((_nScrollState == 3) && cRightPageRect.ptInRect(_cCurPoint)) {
|
|
pageRight();
|
|
|
|
} else if ((_nScrollState == 4) && _cRightBtnRect.ptInRect(_cCurPoint)) {
|
|
lineRight();
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace SpaceBar
|
|
} // namespace Bagel
|