870 lines
20 KiB
C++
870 lines
20 KiB
C++
|
#include <precomp.h>
|
||
|
#include "scbkgwnd.h"
|
||
|
#include <api/wnd/notifmsg.h>
|
||
|
#include <bfc/wasabi_std_wnd.h>
|
||
|
#include <api/wnd/PaintCanvas.h>
|
||
|
|
||
|
#define SCROLLBAR_SEP 4
|
||
|
#define TIMER_SMOOTHSCROLLY 8873
|
||
|
#define TIMER_SMOOTHSCROLLX 8874
|
||
|
#define SMOOTH_STEPS 5
|
||
|
#define DEFAULT_BGCOLOR RGB(0,0,0)
|
||
|
|
||
|
ScrlBkgWnd::ScrlBkgWnd()
|
||
|
{
|
||
|
inDestroy = FALSE;
|
||
|
bmp = NULL;
|
||
|
bgColor = DEFAULT_BGCOLOR;
|
||
|
scrollX = 0;
|
||
|
scrollY = 0;
|
||
|
dbbuffer = 1;
|
||
|
needSetSliders = FALSE;
|
||
|
lineHeight = 16;
|
||
|
wantsep = 0;
|
||
|
wantTileBg = true;
|
||
|
lastratio = 1.0;
|
||
|
MEMSET(&smsqr, 0, sizeof(RECT));
|
||
|
in_set_slider_position = 0;
|
||
|
|
||
|
smoothScrollYInc = smoothScrollXInc = 0;
|
||
|
smoothScrollYCur = smoothScrollXCur = 0;
|
||
|
smoothScrollYTimerCount = smoothScrollXTimerCount = 0;
|
||
|
smoothYTimer = smoothXTimer = 0;
|
||
|
}
|
||
|
|
||
|
ScrlBkgWnd::~ScrlBkgWnd()
|
||
|
{
|
||
|
inDestroy = TRUE;
|
||
|
}
|
||
|
|
||
|
int ScrlBkgWnd::onInit()
|
||
|
{
|
||
|
|
||
|
SCRLBKGWND_PARENT::onInit();
|
||
|
|
||
|
scrollY = 0;
|
||
|
scrollX = 0;
|
||
|
|
||
|
hSep.setOrientation(SEP_HORIZONTAL);
|
||
|
|
||
|
hScroll.setBitmaps(L"wasabi.scrollbar.horizontal.left",
|
||
|
L"wasabi.scrollbar.horizontal.left.pressed",
|
||
|
L"wasabi.scrollbar.horizontal.left.hover",
|
||
|
L"wasabi.scrollbar.horizontal.right",
|
||
|
L"wasabi.scrollbar.horizontal.right.pressed",
|
||
|
L"wasabi.scrollbar.horizontal.right.hover",
|
||
|
L"wasabi.scrollbar.horizontal.button",
|
||
|
L"wasabi.scrollbar.horizontal.button.pressed",
|
||
|
L"wasabi.scrollbar.horizontal.button.hover");
|
||
|
|
||
|
hScroll.setBackgroundBitmaps(L"wasabi.scrollbar.horizontal.background.left",
|
||
|
L"wasabi.scrollbar.horizontal.background.middle",
|
||
|
L"wasabi.scrollbar.horizontal.background.right");
|
||
|
|
||
|
vSep.setOrientation(SEP_VERTICAL);
|
||
|
|
||
|
vScroll.setBitmaps(L"wasabi.scrollbar.vertical.left",
|
||
|
L"wasabi.scrollbar.vertical.left.pressed",
|
||
|
L"wasabi.scrollbar.vertical.left.hover",
|
||
|
L"wasabi.scrollbar.vertical.right",
|
||
|
L"wasabi.scrollbar.vertical.right.pressed",
|
||
|
L"wasabi.scrollbar.vertical.right.hover",
|
||
|
L"wasabi.scrollbar.vertical.button",
|
||
|
L"wasabi.scrollbar.vertical.button.pressed",
|
||
|
L"wasabi.scrollbar.vertical.button.hover");
|
||
|
|
||
|
vScroll.setBackgroundBitmaps(L"wasabi.scrollbar.vertical.background.top",
|
||
|
L"wasabi.scrollbar.vertical.background.middle",
|
||
|
L"wasabi.scrollbar.vertical.background.bottom");
|
||
|
|
||
|
// hScroll->setVertical(FALSE);
|
||
|
vScroll.setVertical(TRUE);
|
||
|
|
||
|
hScroll.setStartHidden(TRUE); // prevent showing window at creation
|
||
|
vScroll.setStartHidden(TRUE);
|
||
|
hSep.setStartHidden(TRUE);
|
||
|
vSep.setStartHidden(TRUE);
|
||
|
|
||
|
hScroll.setParent(this);
|
||
|
vScroll.setParent(this);
|
||
|
hSep.setParent(this);
|
||
|
vSep.setParent(this);
|
||
|
|
||
|
hScroll.init(getOsModuleHandle(), getOsWindowHandle());
|
||
|
vScroll.init(getOsModuleHandle(), getOsWindowHandle());
|
||
|
hSep.init(getOsModuleHandle(), getOsWindowHandle());
|
||
|
vSep.init(getOsModuleHandle(), getOsWindowHandle());
|
||
|
|
||
|
hScroll.setPosition(0);
|
||
|
vScroll.setPosition(0);
|
||
|
|
||
|
setSlidersPosition(); // position sliders and show them if needed
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
void ScrlBkgWnd::setBgBitmap(const wchar_t *b)
|
||
|
{
|
||
|
bmp = b;
|
||
|
if (b) setBgColor(DEFAULT_BGCOLOR);
|
||
|
}
|
||
|
|
||
|
void ScrlBkgWnd::setBgColor(ARGB32 rgb)
|
||
|
{
|
||
|
bgColor = rgb;
|
||
|
}
|
||
|
|
||
|
SkinBitmap *ScrlBkgWnd::getBgBitmap(void)
|
||
|
{
|
||
|
return bmp;
|
||
|
}
|
||
|
|
||
|
ARGB32 ScrlBkgWnd::getBgColor(void)
|
||
|
{
|
||
|
return bgColor;
|
||
|
}
|
||
|
|
||
|
// Scroll to a specified Y-pixels
|
||
|
void ScrlBkgWnd::scrollToY(int y, int signal)
|
||
|
{
|
||
|
|
||
|
WndCanvas *canvas = NULL;
|
||
|
RECT r;
|
||
|
int offset;
|
||
|
int dor2 = 0;
|
||
|
RECT r2 = {0, 0, 0, 0};
|
||
|
int focused = gotFocus();
|
||
|
|
||
|
if (isVirtual() || renderRatioActive())
|
||
|
{
|
||
|
scrollY = y;
|
||
|
invalidateRect(&clientRect());
|
||
|
onScrollY(y);
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
if (!Wasabi::Std::Wnd::isValidWnd(getOsWindowHandle())) return ; // no need to paint
|
||
|
|
||
|
if (y > scrollY)
|
||
|
{ // tree scrolling up, scroller going down. invalidating from the bottom. bitblting from bottom to top
|
||
|
int lines = y - scrollY;
|
||
|
offset = -lines;
|
||
|
getClientRect(&r);
|
||
|
canvas = new WndCanvas();
|
||
|
canvas->attachToClient(this);
|
||
|
|
||
|
RegionI reg;
|
||
|
makeWindowOverlayMask(®);
|
||
|
RegionI clip(&r);
|
||
|
reg.offset(0, offset);
|
||
|
clip.subtractRegion(®);
|
||
|
canvas->selectClipRgn(&clip);
|
||
|
|
||
|
int b = hScroll.isVisible() ? hScroll.getHeight() : 0;
|
||
|
int c = vScroll.isVisible() ? vScroll.getWidth() : 0;
|
||
|
int a = focused && (!b);
|
||
|
if (r.bottom-r.top-lines > 0)
|
||
|
canvas->blit(r.left, r.top+lines, canvas, r.left, r.top, r.right-r.left- c, r.bottom-r.top-lines-a - b);
|
||
|
|
||
|
// int a = focused && (!hScroll->isVisible());
|
||
|
//if (r.bottom - r.top - lines > 0)
|
||
|
// canvas->blit(r.left, r.top + lines, canvas, r.left, r.top, r.right - r.left, r.bottom - r.top - lines - a);
|
||
|
|
||
|
canvas->selectClipRgn(NULL);
|
||
|
if (!clip.isEmpty())
|
||
|
invalidateRgn(&clip);
|
||
|
|
||
|
|
||
|
getClientRect(&r2);
|
||
|
r2.bottom = r2.top + 1;
|
||
|
dor2 = 1;
|
||
|
r.top = r.bottom - lines - 1;
|
||
|
}
|
||
|
if (y < scrollY)
|
||
|
{ // tree scrolling down, scroller going up. invalidating from the top. bitblting from top to bottom
|
||
|
int lines = scrollY - y;
|
||
|
offset = lines;
|
||
|
getClientRect(&r);
|
||
|
canvas = new WndCanvas();
|
||
|
canvas->attachToClient(this);
|
||
|
|
||
|
RegionI reg;
|
||
|
makeWindowOverlayMask(®);
|
||
|
RegionI clip(&r);
|
||
|
reg.offset(0, offset);
|
||
|
clip.subtractRegion(®);
|
||
|
canvas->selectClipRgn(&clip);
|
||
|
|
||
|
int c = vScroll.isVisible() ? vScroll.getWidth() : 0;
|
||
|
canvas->blit(r.left, r.top+focused, canvas, r.left, r.top+lines+focused, r.right-r.left-c, r.bottom-r.top-lines-focused);
|
||
|
//canvas->blit(r.left, r.top + focused, canvas, r.left, r.top + lines + focused, r.right - r.left, r.bottom - r.top - lines - focused);
|
||
|
|
||
|
canvas->selectClipRgn(NULL);
|
||
|
if (!clip.isEmpty())
|
||
|
invalidateRgn(&clip);
|
||
|
|
||
|
getClientRect(&r2);
|
||
|
r2.top = r2.bottom - 1;
|
||
|
dor2 = 1;
|
||
|
r.bottom = r.top + lines + 1;
|
||
|
}
|
||
|
if (canvas)
|
||
|
{
|
||
|
delete canvas;
|
||
|
scrollY = y;
|
||
|
|
||
|
// in case we have a virtualCanvas, we need to tell BaseWnd to call us to paint on it next time it's needed coz we blited directly to the screen
|
||
|
RECT cr;
|
||
|
getClientRect(&cr);
|
||
|
cr.top -= getHeaderHeight();
|
||
|
RECT screenblit;
|
||
|
SubtractRect(&screenblit, &cr, &r);
|
||
|
|
||
|
// invalidate what's needed
|
||
|
if (dor2 && focused)
|
||
|
cascadeRepaintRect(&r2, 0);
|
||
|
cascadeRepaintRect(&r);
|
||
|
|
||
|
deferedInvalidateRect(&screenblit);
|
||
|
|
||
|
//dbbuffer = 1;
|
||
|
//repaint();
|
||
|
}
|
||
|
|
||
|
if (signal)
|
||
|
updateVScroll(y);
|
||
|
|
||
|
onScrollY(y);
|
||
|
}
|
||
|
|
||
|
// Scroll to a specified X-pixel
|
||
|
void ScrlBkgWnd::scrollToX(int x, int signal)
|
||
|
{
|
||
|
WndCanvas *canvas = NULL;
|
||
|
RECT r;
|
||
|
int offset;
|
||
|
int dor2 = 0;
|
||
|
RECT r2 = {0, 0, 0, 0};
|
||
|
int focused = gotFocus();
|
||
|
|
||
|
if (isVirtual() || ABS(getRenderRatio() - 1.0) > 0.01)
|
||
|
{
|
||
|
scrollX = x;
|
||
|
getClientRect(&r);
|
||
|
invalidateRect(&r);
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
if (x > scrollX)
|
||
|
{ // tree scrolling left, scroller going right. invalidating from the right. bitblting from right to left
|
||
|
int lines = x - scrollX;
|
||
|
offset = -lines;
|
||
|
getClientRect(&r);
|
||
|
r.top -= getHeaderHeight();
|
||
|
canvas = new WndCanvas();
|
||
|
canvas->attachToClient(this);
|
||
|
|
||
|
RegionI reg;
|
||
|
makeWindowOverlayMask(®);
|
||
|
RegionI clip(&r);
|
||
|
reg.offset(offset, 0);
|
||
|
clip.subtractRegion(®);
|
||
|
canvas->selectClipRgn(&clip);
|
||
|
|
||
|
int c = vScroll.isVisible() ? vScroll.getWidth() : 0;
|
||
|
canvas->blit(r.left+lines, r.top, canvas, r.left, r.top, r.right-r.left-lines-focused-c, r.bottom-r.top);
|
||
|
//canvas->blit(r.left + lines, r.top, canvas, r.left, r.top, r.right - r.left - lines - focused, r.bottom - r.top);
|
||
|
|
||
|
canvas->selectClipRgn(NULL);
|
||
|
if (!reg.isEmpty())
|
||
|
invalidateRgn(®);
|
||
|
|
||
|
getClientRect(&r2);
|
||
|
r2.right = r2.left + 1;
|
||
|
dor2 = 1;
|
||
|
r.left = r.right - lines - 1;
|
||
|
}
|
||
|
if (x < scrollX)
|
||
|
{ // tree scrolling right, scroller going left. invalidating from the left. bitblting from left to right
|
||
|
int lines = scrollX - x;
|
||
|
offset = lines;
|
||
|
getClientRect(&r);
|
||
|
r.top -= getHeaderHeight();
|
||
|
canvas = new WndCanvas();
|
||
|
canvas->attachToClient(this);
|
||
|
|
||
|
RegionI reg;
|
||
|
makeWindowOverlayMask(®);
|
||
|
RegionI clip(&r);
|
||
|
reg.offset(offset, 0);
|
||
|
clip.subtractRegion(®);
|
||
|
canvas->selectClipRgn(&clip);
|
||
|
|
||
|
int a = focused && (!vScroll.isVisible());
|
||
|
int c = hScroll.isVisible() ? hScroll.getHeight()-focused : 0;
|
||
|
canvas->blit(r.left+a, r.top, canvas, r.left+lines, r.top, r.right-r.left-lines-a, r.bottom-r.top-c);
|
||
|
|
||
|
//int a = focused && (!vScroll->isVisible());
|
||
|
// canvas->blit(r.left + a, r.top, canvas, r.left + lines, r.top, r.right - r.left - lines - a, r.bottom - r.top);
|
||
|
|
||
|
canvas->selectClipRgn(NULL);
|
||
|
if (!reg.isEmpty())
|
||
|
invalidateRgn(®);
|
||
|
|
||
|
getClientRect(&r2);
|
||
|
r2.left = r2.right - 1;
|
||
|
dor2 = 1;
|
||
|
r.right = r.left + lines + 1;
|
||
|
}
|
||
|
if (canvas)
|
||
|
{
|
||
|
delete canvas;
|
||
|
scrollX = x;
|
||
|
|
||
|
// in case we have a virtualCanvas, we need to tell BaseWnd to call us to paint on it next time it's needed coz we blited directly to the screen
|
||
|
RECT cr;
|
||
|
getClientRect(&cr);
|
||
|
cr.top -= getHeaderHeight();
|
||
|
RECT screenblit;
|
||
|
SubtractRect(&screenblit, &cr, &r);
|
||
|
deferedInvalidateRect(&screenblit);
|
||
|
|
||
|
if (dor2 && focused)
|
||
|
cascadeRepaintRect(&r2, 0);
|
||
|
// invalidate what's needed
|
||
|
cascadeRepaintRect(&r);
|
||
|
|
||
|
//dbbuffer = 1;
|
||
|
//repaint();
|
||
|
}
|
||
|
|
||
|
if (signal)
|
||
|
updateHScroll(x);
|
||
|
}
|
||
|
|
||
|
void ScrlBkgWnd::setSlidersPosition()
|
||
|
{
|
||
|
if (in_set_slider_position) return ;
|
||
|
in_set_slider_position = 1;
|
||
|
_setSlidersPosition();
|
||
|
in_set_slider_position = 0;
|
||
|
}
|
||
|
|
||
|
void ScrlBkgWnd::_setSlidersPosition()
|
||
|
{
|
||
|
|
||
|
if (!isInited()) return ;
|
||
|
|
||
|
RECT d;
|
||
|
getClientRect(&d);
|
||
|
if ((d.left >= d.right) || (d.top >= d.bottom))
|
||
|
return ;
|
||
|
|
||
|
RECT r;
|
||
|
if (inDestroy) return ;
|
||
|
if (!isVisible())
|
||
|
{
|
||
|
needSetSliders = TRUE;
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
needSetSliders = FALSE;
|
||
|
|
||
|
if (needHScroll())
|
||
|
{
|
||
|
SCRLBKGWND_PARENT::getClientRect(&r);
|
||
|
r.top = r.bottom - getScrollbarWidth();
|
||
|
if (needVScroll())
|
||
|
r.right -= getScrollbarWidth() + (wantsep ? SCROLLBAR_SEP : 0);
|
||
|
RECT z; hScroll.getClientRect(&z);
|
||
|
if (!Wasabi::Std::rectEqual(r, z))
|
||
|
{ // assumes ScrollBars are virtual
|
||
|
hScroll.resizeToRect(&r);
|
||
|
RECT s = r;
|
||
|
s.bottom = s.top;
|
||
|
s.top -= (wantsep ? SCROLLBAR_SEP : 0);
|
||
|
hSep.resizeToRect(&s);
|
||
|
}
|
||
|
if (!hScroll.isVisible())
|
||
|
{
|
||
|
hScroll.setVisible(TRUE);
|
||
|
if (wantsep) hSep.setVisible(TRUE);
|
||
|
onHScrollToggle(1);
|
||
|
}
|
||
|
hScroll.setNPages(((int)(getContentsWidth() / (r.right - r.left))) + 1);
|
||
|
hScroll.setUpDownValue((int)(((float)lineHeight / (getContentsWidth() - (r.right - r.left)))*SCROLLBAR_FULL));
|
||
|
hScroll.setPosition((int)((float)scrollX / getMaxScrollX() * SCROLLBAR_FULL));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (hScroll.isVisible())
|
||
|
{
|
||
|
hScroll.setVisible(FALSE);
|
||
|
if (wantsep) hSep.setVisible(FALSE);
|
||
|
onHScrollToggle(0);
|
||
|
}
|
||
|
hScroll.setPosition(0);
|
||
|
scrollToX(0);
|
||
|
}
|
||
|
|
||
|
if (needVScroll())
|
||
|
{
|
||
|
SCRLBKGWND_PARENT::getClientRect(&r);
|
||
|
r.left = r.right - getScrollbarWidth();
|
||
|
if (needHScroll())
|
||
|
r.bottom -= getScrollbarWidth();
|
||
|
RECT z; vScroll.getNonClientRect(&z);
|
||
|
if (!Wasabi::Std::rectEqual(r, z))
|
||
|
{
|
||
|
vScroll.resizeToRect(&r);
|
||
|
RECT s = r;
|
||
|
s.right = s.left;
|
||
|
s.left -= (wantsep ? SCROLLBAR_SEP : 0);
|
||
|
vSep.resizeToRect(&s);
|
||
|
}
|
||
|
if (!vScroll.isVisible())
|
||
|
{
|
||
|
vScroll.setVisible(TRUE);
|
||
|
if (wantsep) vSep.setVisible(TRUE);
|
||
|
onVScrollToggle(1);
|
||
|
}
|
||
|
vScroll.setNPages(((int)(getContentsHeight() / (r.bottom - r.top))) + 1);
|
||
|
vScroll.setUpDownValue((int)(((float)lineHeight / (getContentsHeight() - (r.bottom - r.top)))*SCROLLBAR_FULL));
|
||
|
vScroll.setPosition((int)((float)scrollY / getMaxScrollY() * SCROLLBAR_FULL));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (vScroll.isVisible())
|
||
|
{
|
||
|
vScroll.setVisible(FALSE);
|
||
|
if (wantsep) vSep.setVisible(FALSE);
|
||
|
onVScrollToggle(0);
|
||
|
}
|
||
|
vScroll.setPosition(0);
|
||
|
scrollToY(0);
|
||
|
}
|
||
|
|
||
|
hSep.invalidate();
|
||
|
vSep.invalidate();
|
||
|
|
||
|
if (needHScroll() && needVScroll())
|
||
|
{
|
||
|
getNonClientRect(&smsqr);
|
||
|
smsqr.left = smsqr.right - getScrollbarWidth();
|
||
|
smsqr.top = smsqr.bottom - getScrollbarWidth();
|
||
|
invalidateRect(&smsqr);
|
||
|
}
|
||
|
else
|
||
|
ZERO(smsqr);
|
||
|
}
|
||
|
|
||
|
void ScrlBkgWnd::onHScrollToggle(int set)
|
||
|
{}
|
||
|
|
||
|
void ScrlBkgWnd::onVScrollToggle(int set)
|
||
|
{}
|
||
|
|
||
|
int ScrlBkgWnd::onPaint(Canvas *canvas)
|
||
|
{
|
||
|
RECT d;
|
||
|
getClientRect(&d);
|
||
|
if (d.right > d.left + 0xFFFF || d.bottom > d.top + 0xFFFF) return 1;
|
||
|
if ((d.left >= d.right) || (d.top >= d.bottom))
|
||
|
{
|
||
|
return SCRLBKGWND_PARENT::onPaint(canvas);
|
||
|
}
|
||
|
|
||
|
if (needSetSliders) setSlidersPosition();
|
||
|
|
||
|
// RECT z;
|
||
|
// GetUpdateRect(gethWnd(), &z, FALSE);
|
||
|
|
||
|
PaintCanvas paintcanvas;
|
||
|
PaintBltCanvas paintbcanvas;
|
||
|
|
||
|
if (canvas == NULL)
|
||
|
{
|
||
|
if (dbbuffer)
|
||
|
{
|
||
|
if (!paintbcanvas.beginPaintNC(this)) return 0;
|
||
|
canvas = &paintbcanvas;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (!paintcanvas.beginPaint(this)) return 0;
|
||
|
canvas = &paintcanvas;
|
||
|
}
|
||
|
}
|
||
|
//dbbuffer=1;
|
||
|
SCRLBKGWND_PARENT::onPaint(canvas);
|
||
|
|
||
|
RegionI *smsq = NULL;
|
||
|
|
||
|
if (needHScroll() && needVScroll())
|
||
|
{
|
||
|
renderBaseTexture(canvas, smsqr);
|
||
|
smsq = new RegionI(&smsqr);
|
||
|
}
|
||
|
|
||
|
RECT r;
|
||
|
LabelWnd::getNonClientRect(&r);
|
||
|
RECT c = {r.left, r.top, r.right, r.top + getLabelHeight()}; // create label rect
|
||
|
|
||
|
|
||
|
RegionI *clip = new RegionI();
|
||
|
if (canvas->getClipRgn(clip) == 0)
|
||
|
{
|
||
|
delete clip;
|
||
|
clip = new RegionI(&r);
|
||
|
if (smsq) clip->subtractRegion(smsq);
|
||
|
canvas->selectClipRgn(clip);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
RegionI reg(&c);
|
||
|
clip->subtractRegion(®);
|
||
|
if (smsq) clip->subtractRegion(smsq);
|
||
|
canvas->selectClipRgn(clip);
|
||
|
}
|
||
|
delete smsq;
|
||
|
|
||
|
drawBackground(canvas);
|
||
|
delete clip;
|
||
|
|
||
|
if (getRenderRatio() != lastratio) { invalidate(); lastratio = getRenderRatio(); } // todo: make that an event
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
int ScrlBkgWnd::needDoubleBuffer()
|
||
|
{
|
||
|
return dbbuffer;
|
||
|
}
|
||
|
|
||
|
int ScrlBkgWnd::onEraseBkgnd(HDC dc)
|
||
|
{
|
||
|
|
||
|
/* DCCanvas canvas;
|
||
|
canvas.cloneDC(dc);
|
||
|
|
||
|
drawBackground(&canvas);*/
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
// Draws tiled background
|
||
|
void ScrlBkgWnd::drawBackground(Canvas *canvas)
|
||
|
{
|
||
|
RECT r(clientRect());
|
||
|
RegionI reg(&r);
|
||
|
RegionI old;
|
||
|
canvas->getClipRgn(&old);
|
||
|
reg.andRegion(&old);
|
||
|
canvas->selectClipRgn(®);
|
||
|
if (bmp.getBitmap() && bgColor == DEFAULT_BGCOLOR)
|
||
|
{
|
||
|
r.top -= scrollY % bmp.getBitmap()->getHeight();
|
||
|
r.left -= scrollX % bmp.getBitmap()->getWidth();
|
||
|
if (wantTileBg)
|
||
|
bmp.getBitmap()->blitTile(canvas, &r);
|
||
|
else
|
||
|
bmp.getBitmap()->stretchToRect(canvas, &r);
|
||
|
}
|
||
|
else if (bgColor != DEFAULT_BGCOLOR)
|
||
|
{
|
||
|
canvas->fillRect(&r, bgColor);
|
||
|
}
|
||
|
canvas->selectClipRgn(&old);
|
||
|
|
||
|
}
|
||
|
|
||
|
bool ScrlBkgWnd::needHScroll()
|
||
|
{
|
||
|
if (!wantHScroll()) return FALSE;
|
||
|
RECT r;
|
||
|
getNonClientRect(&r);
|
||
|
if (vScroll.isVisible())
|
||
|
r.right -= getScrollbarWidth();
|
||
|
return (getContentsWidth() > r.right - r.left);
|
||
|
}
|
||
|
|
||
|
bool ScrlBkgWnd::needVScroll()
|
||
|
{
|
||
|
if (!wantVScroll()) return FALSE;
|
||
|
RECT r;
|
||
|
getNonClientRect(&r);
|
||
|
r.top += getHeaderHeight();
|
||
|
if (hScroll.isVisible())
|
||
|
r.bottom -= getScrollbarWidth();
|
||
|
return (getContentsHeight() > r.bottom - r.top);
|
||
|
}
|
||
|
|
||
|
// Returns the current tree width in pixels
|
||
|
int ScrlBkgWnd::getContentsWidth()
|
||
|
{
|
||
|
/*RECT r;
|
||
|
ScrlBkgWnd::getClientRect(&r);
|
||
|
return r.right-r.left;*/
|
||
|
return 10000;
|
||
|
}
|
||
|
|
||
|
// Returns the current tree height in pixels
|
||
|
int ScrlBkgWnd::getContentsHeight()
|
||
|
{
|
||
|
/*RECT r;
|
||
|
ScrlBkgWnd::getClientRect(&r);
|
||
|
return r.bottom-r.top;*/
|
||
|
return 10000;
|
||
|
}
|
||
|
|
||
|
int ScrlBkgWnd::getMaxScrollY()
|
||
|
{
|
||
|
RECT r;
|
||
|
getClientRect(&r);
|
||
|
return MAX<int>(0, getContentsHeight() - (r.bottom - r.top));
|
||
|
}
|
||
|
|
||
|
int ScrlBkgWnd::getMaxScrollX()
|
||
|
{
|
||
|
RECT r;
|
||
|
getClientRect(&r);
|
||
|
return MAX<int>(0, getContentsWidth() - (r.right - r.left));
|
||
|
}
|
||
|
|
||
|
void ScrlBkgWnd::updateVScroll(int y)
|
||
|
{
|
||
|
if (getMaxScrollY() == 0) { vScroll.setPosition(0); return ; }
|
||
|
int z = (int)((float)y / getMaxScrollY() * SCROLLBAR_FULL);
|
||
|
vScroll.setPosition(z);
|
||
|
}
|
||
|
|
||
|
void ScrlBkgWnd::updateHScroll(int x)
|
||
|
{
|
||
|
if (getMaxScrollX() == 0) { hScroll.setPosition(0); return ; }
|
||
|
int z = (int)((float)x / getMaxScrollX() * SCROLLBAR_FULL);
|
||
|
hScroll.setPosition(z);
|
||
|
}
|
||
|
|
||
|
void ScrlBkgWnd::updateScrollY(bool smooth)
|
||
|
{
|
||
|
if (getMaxScrollY() == 0) { scrollToY(0); return ; }
|
||
|
int y = (int)((float)(vScroll.getPosition()) / SCROLLBAR_FULL * getMaxScrollY());
|
||
|
if (!smooth)
|
||
|
scrollToY(y /*& ~3*/);
|
||
|
else
|
||
|
smoothScrollToY(y);
|
||
|
}
|
||
|
|
||
|
void ScrlBkgWnd::updateScrollX(bool smooth)
|
||
|
{
|
||
|
if (getMaxScrollX() == 0) { scrollToX(0); return ; }
|
||
|
int x = (int)((float)(hScroll.getPosition()) / SCROLLBAR_FULL * getMaxScrollX());
|
||
|
if (!smooth)
|
||
|
scrollToX(x /*& ~3*/);
|
||
|
else
|
||
|
smoothScrollToX(x);
|
||
|
}
|
||
|
|
||
|
void ScrlBkgWnd::smoothScrollToX(int x)
|
||
|
{
|
||
|
killSmoothXTimer();
|
||
|
smoothScrollXInc = -(float)(scrollX - x) / SMOOTH_STEPS;
|
||
|
smoothScrollXCur = (float)scrollX;
|
||
|
smoothScrollXTimerCount = 0;
|
||
|
smoothXTimer = 1;
|
||
|
setTimer(TIMER_SMOOTHSCROLLX, 25);
|
||
|
}
|
||
|
|
||
|
void ScrlBkgWnd::killSmoothYTimer()
|
||
|
{
|
||
|
if (smoothYTimer)
|
||
|
{
|
||
|
killTimer(TIMER_SMOOTHSCROLLY);
|
||
|
smoothScrollYCur += smoothScrollYInc * (SMOOTH_STEPS - smoothScrollYTimerCount);
|
||
|
scrollToY((int)smoothScrollYCur);
|
||
|
smoothYTimer = 0;
|
||
|
updateVScroll(scrollY);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ScrlBkgWnd::killSmoothXTimer()
|
||
|
{
|
||
|
if (smoothXTimer)
|
||
|
{
|
||
|
killTimer(TIMER_SMOOTHSCROLLX);
|
||
|
smoothScrollXCur += smoothScrollXInc * (SMOOTH_STEPS - smoothScrollXTimerCount);
|
||
|
scrollToX((int)smoothScrollXCur);
|
||
|
smoothXTimer = 0;
|
||
|
updateHScroll(scrollX);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ScrlBkgWnd::smoothScrollToY(int y)
|
||
|
{
|
||
|
killSmoothYTimer();
|
||
|
smoothScrollYInc = -(float)(scrollY - y) / SMOOTH_STEPS;
|
||
|
smoothScrollYCur = (float)scrollY;
|
||
|
smoothScrollYTimerCount = 0;
|
||
|
smoothYTimer = 1;
|
||
|
setTimer(TIMER_SMOOTHSCROLLY, 25);
|
||
|
}
|
||
|
|
||
|
void ScrlBkgWnd::timerCallback(int id)
|
||
|
{
|
||
|
switch (id)
|
||
|
{
|
||
|
case TIMER_SMOOTHSCROLLY:
|
||
|
smoothScrollYCur += smoothScrollYInc;
|
||
|
scrollToY((int)smoothScrollYCur, FALSE);
|
||
|
if (++smoothScrollYTimerCount == SMOOTH_STEPS)
|
||
|
killSmoothYTimer();
|
||
|
return ;
|
||
|
case TIMER_SMOOTHSCROLLX:
|
||
|
smoothScrollXCur += smoothScrollXInc;
|
||
|
scrollToX((int)smoothScrollXCur, FALSE);
|
||
|
if (++smoothScrollXTimerCount == SMOOTH_STEPS)
|
||
|
killSmoothXTimer();
|
||
|
return ;
|
||
|
}
|
||
|
SCRLBKGWND_PARENT::timerCallback(id);
|
||
|
}
|
||
|
|
||
|
// Gets notification from sliders
|
||
|
int ScrlBkgWnd::childNotify(ifc_window *child, int msg, intptr_t param1, intptr_t param2)
|
||
|
{
|
||
|
switch (msg)
|
||
|
{
|
||
|
case ChildNotify::SCROLLBAR_SETPOSITION:
|
||
|
if (child == &vScroll)
|
||
|
{
|
||
|
updateScrollY(!!param1);
|
||
|
return 1;
|
||
|
}
|
||
|
if (child == &hScroll)
|
||
|
{
|
||
|
updateScrollX(!!param1);
|
||
|
return 1;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return SCRLBKGWND_PARENT::childNotify(child, msg, param1, param2);
|
||
|
}
|
||
|
|
||
|
int ScrlBkgWnd::onResize()
|
||
|
{
|
||
|
int rt = SCRLBKGWND_PARENT::onResize();
|
||
|
if (!isInited()) return rt;
|
||
|
invalidateRect(&smsqr);
|
||
|
setSlidersPosition();
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
void ScrlBkgWnd::onSetVisible(int show)
|
||
|
{
|
||
|
SCRLBKGWND_PARENT::onSetVisible(show);
|
||
|
if (show)
|
||
|
setSlidersPosition();
|
||
|
}
|
||
|
|
||
|
void ScrlBkgWnd::getClientRect(RECT *r)
|
||
|
{
|
||
|
SCRLBKGWND_PARENT::getClientRect(r);
|
||
|
if (vScroll.isVisible(1))
|
||
|
r->right -= getScrollbarWidth() + (wantsep ? SCROLLBAR_SEP : 0);
|
||
|
if (hScroll.isVisible(1))
|
||
|
r->bottom -= getScrollbarWidth() + (wantsep ? SCROLLBAR_SEP : 0);
|
||
|
r->top += getHeaderHeight();
|
||
|
}
|
||
|
|
||
|
/*void ScrlBkgWnd::getNonClientRect(RECT *r) {
|
||
|
SCRLBKGWND_PARENT::getClientRect(r); // my non client rect is my parent's client rect
|
||
|
return;
|
||
|
}*/
|
||
|
|
||
|
int ScrlBkgWnd::getHeaderHeight()
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void ScrlBkgWnd::setLineHeight(int h)
|
||
|
{
|
||
|
lineHeight = h;
|
||
|
}
|
||
|
|
||
|
int ScrlBkgWnd::getLinesPerPage()
|
||
|
{
|
||
|
RECT r;
|
||
|
getClientRect(&r);
|
||
|
int h = r.bottom - r.top;
|
||
|
return h / lineHeight;
|
||
|
}
|
||
|
|
||
|
int ScrlBkgWnd::getScrollX()
|
||
|
{
|
||
|
return scrollX;
|
||
|
}
|
||
|
|
||
|
int ScrlBkgWnd::getScrollY()
|
||
|
{
|
||
|
return scrollY;
|
||
|
}
|
||
|
|
||
|
int ScrlBkgWnd::getScrollbarWidth()
|
||
|
{
|
||
|
// TODO: maybe do if (hScroll.isVisible())
|
||
|
return hScroll.getWidth();
|
||
|
return vScroll.getWidth();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/*void ScrlBkgWnd::clientToScreen(RECT *r) {
|
||
|
POINT p;
|
||
|
p.x = r->left;
|
||
|
p.y = r->top;
|
||
|
SCRLBKGWND_PARENT::clientToScreen((int *)&p.x, (int*)&p.y);
|
||
|
r->left = p.x;
|
||
|
r->top = p.y;
|
||
|
|
||
|
p.x = r->right;
|
||
|
p.y = r->bottom;
|
||
|
SCRLBKGWND_PARENT::clientToScreen((int *)&p.x, (int*)&p.y);
|
||
|
r->right = p.x;
|
||
|
r->bottom = p.y;
|
||
|
}
|
||
|
|
||
|
void ScrlBkgWnd::clientToScreen(int *x, int *y) {
|
||
|
SCRLBKGWND_PARENT::clientToScreen(x, y);
|
||
|
}
|
||
|
|
||
|
void ScrlBkgWnd::clientToScreen(POINT *p) {
|
||
|
TREEWND_PARENT::clientToScreen((int *)&p->x, (int *)&p->y);
|
||
|
}*/
|
||
|
|
||
|
void ScrlBkgWnd::makeWindowOverlayMask(api_region *r)
|
||
|
{
|
||
|
|
||
|
return ;
|
||
|
#ifdef WIN32
|
||
|
// With this routine empty, I'm just nuking the code from x-plat builds < KP
|
||
|
HDC dc = GetDC(getOsWindowHandle());
|
||
|
|
||
|
//if (getRandomRgn)
|
||
|
{
|
||
|
RECT cr;
|
||
|
getClientRect(&cr);
|
||
|
RECT wr;
|
||
|
getWindowRect(&wr);
|
||
|
|
||
|
RegionI sr;
|
||
|
Wasabi::Std::Wnd::getRandomRegion(dc, sr.getOSHandle());
|
||
|
sr.offset( -wr.left, -wr.top);
|
||
|
|
||
|
r->setRect(&cr);
|
||
|
r->subtractRegion(&sr);
|
||
|
|
||
|
}
|
||
|
|
||
|
ReleaseDC(getOsWindowHandle(), dc);
|
||
|
#endif
|
||
|
}
|