246 lines
6.3 KiB
C++
246 lines
6.3 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 "common/textconsole.h"
|
|
#include "bagel/mfc/afxwin.h"
|
|
|
|
namespace Bagel {
|
|
namespace MFC {
|
|
|
|
IMPLEMENT_DYNAMIC(CScrollBar, CWnd)
|
|
BEGIN_MESSAGE_MAP(CScrollBar, CWnd)
|
|
ON_WM_PAINT()
|
|
ON_WM_LBUTTONDOWN()
|
|
ON_WM_LBUTTONUP()
|
|
ON_WM_MOUSEMOVE()
|
|
ON_WM_MOUSELEAVE()
|
|
END_MESSAGE_MAP()
|
|
|
|
bool CScrollBar::Create(uint32 dwStyle, const RECT &rect, CWnd *pParentWnd, unsigned int nID) {
|
|
return CWnd::Create("SCROLLBAR", nullptr, dwStyle,
|
|
rect, pParentWnd, nID);
|
|
}
|
|
|
|
int CScrollBar::GetScrollPos() const {
|
|
return _value;
|
|
}
|
|
|
|
int CScrollBar::SetScrollPos(int nPos, bool bRedraw) {
|
|
int oldPos = _value;
|
|
_value = CLIP(nPos, _minValue, _maxValue);
|
|
Invalidate();
|
|
return oldPos;
|
|
}
|
|
|
|
void CScrollBar::GetScrollRange(int *lpMinPos, int *lpMaxPos) const {
|
|
if (lpMinPos)
|
|
*lpMinPos = _minValue;
|
|
if (lpMaxPos)
|
|
*lpMaxPos = _maxValue;
|
|
}
|
|
|
|
void CScrollBar::SetScrollRange(int nMinPos, int nMaxPos, bool bRedraw) {
|
|
_minValue = nMinPos;
|
|
_maxValue = nMaxPos;
|
|
_pageSize = MAX<int>((_maxValue - _minValue + 1) / 10, 1);
|
|
|
|
Invalidate();
|
|
}
|
|
|
|
bool CScrollBar::SetScrollInfo(LPSCROLLINFO lpScrollInfo, bool bRedraw) {
|
|
assert(lpScrollInfo->cbSize == sizeof(SCROLLINFO));
|
|
_minValue = lpScrollInfo->nMin;
|
|
_maxValue = lpScrollInfo->nMax;
|
|
_pageSize = lpScrollInfo->nPage;
|
|
_value = lpScrollInfo->nPos;
|
|
|
|
if (bRedraw)
|
|
Invalidate();
|
|
return true;
|
|
}
|
|
|
|
void CScrollBar::ShowScrollBar(bool bShow) {
|
|
warning("TODO: CScrollBar::ShowScrollBar");
|
|
}
|
|
|
|
void CScrollBar::OnPaint() {
|
|
CPaintDC dc(this);
|
|
CRect clientRect;
|
|
GetClientRect(&clientRect);
|
|
const int thumbSize = clientRect.bottom;
|
|
|
|
// Clear background and draw border edge
|
|
dc.FillSolidRect(&clientRect, RGB(211, 211, 211));
|
|
CBrush borderBrush(RGB(0, 0, 0));
|
|
dc.FrameRect(&clientRect, &borderBrush);
|
|
|
|
CRect left(0, 0, thumbSize, clientRect.bottom);
|
|
drawSquare(dc, left);
|
|
drawArrow(dc, left, true);
|
|
CRect right(clientRect.right - thumbSize, 0,
|
|
clientRect.right, clientRect.bottom);
|
|
drawSquare(dc, right);
|
|
drawArrow(dc, right, false);
|
|
|
|
drawSquare(dc, getThumbRect());
|
|
}
|
|
|
|
void CScrollBar::drawSquare(CPaintDC &dc, const CRect &r) {
|
|
CBrush black(RGB(0, 0, 0));
|
|
dc.FrameRect(&r, &black);
|
|
|
|
CBrush darkGrey(RGB(169, 169, 169));
|
|
CBrush white(RGB(255, 255, 255));
|
|
CBrush *oldBrush = dc.SelectObject(&darkGrey);
|
|
|
|
dc.MoveTo(r.left + 2, r.bottom - 3);
|
|
dc.LineTo(r.right - 2, r.bottom - 3);
|
|
dc.MoveTo(r.left + 1, r.bottom - 2);
|
|
dc.LineTo(r.right - 2, r.bottom - 2);
|
|
dc.MoveTo(r.right - 3, r.top + 1);
|
|
dc.LineTo(r.right - 3, r.bottom - 2);
|
|
dc.MoveTo(r.right - 2, r.top + 1);
|
|
dc.LineTo(r.right - 2, r.bottom - 2);
|
|
|
|
dc.MoveTo(r.left + 1, r.top + 1);
|
|
dc.LineTo(r.right - 3, r.top + 1);
|
|
dc.MoveTo(r.left + 1, r.top + 1);
|
|
dc.MoveTo(r.left + 1, r.bottom - 3);
|
|
|
|
dc.SelectObject(oldBrush);
|
|
}
|
|
|
|
void CScrollBar::drawArrow(CPaintDC &dc, const CRect &r, bool leftArrow) {
|
|
int xCenter = (r.left + r.right) / 2;
|
|
int yCenter = r.bottom / 2;
|
|
int xDelta = leftArrow ? 1 : -1;
|
|
int x = leftArrow ? xCenter - 3 : xCenter + 3;
|
|
|
|
CBrush black(RGB(0, 0, 0));
|
|
CBrush *oldBrush = dc.SelectObject(&black);
|
|
|
|
for (int xCtr = 0; xCtr < 7; ++xCtr, x += xDelta) {
|
|
int yDiff = (xCtr >= 4) ? 1 : xCtr;
|
|
dc.MoveTo(x, yCenter - yDiff);
|
|
dc.LineTo(x, yCenter + yDiff);
|
|
}
|
|
|
|
dc.SelectObject(oldBrush);
|
|
}
|
|
|
|
CRect CScrollBar::getThumbRect() const {
|
|
CRect clientRect;
|
|
GetClientRect(&clientRect);
|
|
|
|
// The thumb will start after the left arrow button,
|
|
// and at most, it will be drawn before the right arrow
|
|
int slideArea = clientRect.right -
|
|
(clientRect.bottom * 3) + 1;
|
|
|
|
int xStart = clientRect.bottom +
|
|
slideArea * (_value - _minValue) /
|
|
(_maxValue - _minValue);
|
|
|
|
return CRect(xStart, 0, xStart + clientRect.bottom,
|
|
clientRect.bottom);
|
|
}
|
|
|
|
int CScrollBar::getIndexFromX(int xp) const {
|
|
CRect clientRect;
|
|
GetClientRect(&clientRect);
|
|
|
|
int slideStart = clientRect.bottom;
|
|
int slideFinish = clientRect.right - (clientRect.bottom * 2) + 1;
|
|
int slideArea = clientRect.right - (clientRect.bottom * 3) + 1;
|
|
|
|
if (xp < slideStart)
|
|
return _minValue;
|
|
if (xp >= slideFinish)
|
|
return _maxValue;
|
|
|
|
return _minValue + (xp - slideStart)
|
|
* (_maxValue - _minValue) / slideArea;
|
|
}
|
|
|
|
void CScrollBar::OnLButtonDown(unsigned int nFlags, CPoint point) {
|
|
CRect clientRect;
|
|
GetClientRect(&clientRect);
|
|
|
|
if (point.x < clientRect.bottom) {
|
|
// Left arrow button
|
|
if (_value > _minValue) {
|
|
SetScrollPos(_value - 1);
|
|
scrollEvent(SB_LINELEFT);
|
|
}
|
|
|
|
} else if (point.x >= (clientRect.right - clientRect.bottom)) {
|
|
// Right arrow button
|
|
if (_value < _maxValue) {
|
|
SetScrollPos(_value + 1);
|
|
scrollEvent(SB_LINERIGHT);
|
|
}
|
|
|
|
} else {
|
|
// We're in the slider area
|
|
CRect thumbRect = getThumbRect();
|
|
|
|
if (point.x < thumbRect.left) {
|
|
// Left of thumb, page left
|
|
SetScrollPos(_value - _pageSize);
|
|
scrollEvent(SB_PAGELEFT);
|
|
} else if (point.x >= thumbRect.right) {
|
|
// Right of thumb, page right
|
|
SetScrollPos(_value + _pageSize);
|
|
scrollEvent(SB_PAGERIGHT);
|
|
} else {
|
|
// Directly on thumb, so start dragging it
|
|
SetScrollPos(getIndexFromX(point.x));
|
|
SetCapture();
|
|
scrollEvent(SB_THUMBTRACK);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CScrollBar::OnLButtonUp(unsigned int nFlags, CPoint point) {
|
|
if (GetCapture() == m_hWnd) {
|
|
ReleaseCapture();
|
|
scrollEvent(SB_THUMBPOSITION);
|
|
}
|
|
|
|
scrollEvent(SB_ENDSCROLL);
|
|
}
|
|
|
|
void CScrollBar::OnMouseMove(unsigned int, CPoint point) {
|
|
if (GetCapture() == m_hWnd) {
|
|
SetScrollPos(getIndexFromX(point.x));
|
|
scrollEvent(SB_THUMBTRACK);
|
|
}
|
|
}
|
|
|
|
void CScrollBar::scrollEvent(int action) {
|
|
m_pParentWnd->SendMessage(WM_HSCROLL,
|
|
MAKEWPARAM(action, _value),
|
|
(LPARAM)m_hWnd);
|
|
}
|
|
|
|
} // namespace MFC
|
|
} // namespace Bagel
|