winamp/Src/Wasabi/api/wnd/wndclass/slider.cpp
2024-09-24 14:54:57 +02:00

706 lines
14 KiB
C++

#include <precomp.h>
#include "slider.h"
#include <tataki/canvas/canvas.h>
#include <api/wnd/notifmsg.h>
#include <api/wnd/PaintCanvas.h>
#define DEFAULT_THUMBWIDTH 16
#define DEFAULT_THUMBHEIGHT 16
SliderWnd::SliderWnd()
{
seeking = 0;
enabled = 1;
hilite = 0;
pos = 0;
oldpos = -1;
thumbwidth = DEFAULT_THUMBWIDTH;
captured = 0;
xShift = 0;
yShift = 0;
base_texture = NULL;
use_base_texture = 0;
no_default_background = 0;
drawOnBorders = 0;
hotPosition = -1;
origPos = 0;
vertical = 0;
thumbCentered = 1;
thumbOffset = 0;
thumbStretched = 0;
hotposrange = -1;
setLimits(START, END);
}
SliderWnd::~SliderWnd()
{}
int SliderWnd::onPaint(Canvas *canvas)
{
if (canvas == NULL)
{
PaintBltCanvas paintcanvas;
if (!paintcanvas.beginPaint(this))
return 0;
SliderWnd::onPaint(&paintcanvas);
}
SLIDERWND_PARENT::onPaint(canvas);
RECT r, origr;
getClientRect(&r);
origr = r;
if (use_base_texture)
{
if (!base_texture)
{
renderBaseTexture(canvas, r);
}
else
{
RECT cr;
cr.left = xShift;
cr.top = yShift;
cr.right = cr.left + (r.right - r.left);
cr.bottom = cr.top + (r.bottom - r.top);
base_texture->blitToRect(canvas, &cr, &r);
}
}
if (vertical)
{
RECT br;
br.left = r.left;
br.right = r.right;
if (left.getBitmap())
{
br.top = r.top;
br.bottom = left.getHeight();
left.getBitmap()->stretchToRectAlpha(canvas, &br, getPaintingAlpha());
}
if (right.getBitmap())
{
br.top = r.bottom - right.getHeight();
br.bottom = r.bottom;
right.stretchToRectAlpha(canvas, &br, getPaintingAlpha());
}
if (middle.getBitmap())
{
br.top = r.top + (left.getBitmap() ? left.getHeight() : 0);
br.bottom = r.bottom - (right.getBitmap() ? right.getHeight() : 0);
middle.getBitmap()->stretchToRectAlpha(canvas, &br, getPaintingAlpha());
}
}
else
{
RECT br;
br.top = r.top;
br.bottom = r.bottom;
if (left.getBitmap())
{
br.left = r.left;
br.right = br.left + left.getWidth();
left.getBitmap()->stretchToRectAlpha(canvas, &br, getPaintingAlpha());
}
if (right.getBitmap())
{
br.left = r.right - right.getWidth();
br.right = r.right;
right.getBitmap()->stretchToRectAlpha(canvas, &br, getPaintingAlpha());
}
if (middle.getBitmap())
{
br.left = r.left + (left.getBitmap() ? left.getWidth() : 0);
br.right = r.right - (right.getBitmap() ? right.getWidth() : 0);
middle.getBitmap()->stretchToRectAlpha(canvas, &br, getPaintingAlpha());
}
}
if (vertical)
{
int w = (r.bottom - r.top) - thumbHeight();
// ASSERT(w > 0); // if the control paints off the edge of the screen, this will needlessly assert.
if (w < 0) w = 0;
r.top += (pos * w) / length;
r.bottom = r.top + thumbHeight();
if (!thumbStretched)
{
if (!thumbCentered)
{
r.left = origr.left + thumbOffset;
r.right = origr.left + thumbWidth() + thumbOffset;
}
else
{
int w = ((r.right - r.left) - thumbWidth()) / 2;
r.left = origr.left + w + thumbOffset;
r.right = origr.right - w + thumbOffset;
}
}
else
{
r.left = origr.left;
r.right = origr.right;
}
}
else
{
// offset for left bitmap
if (!drawOnBorders)
{
if (left.getBitmap() != NULL) r.left += left.getWidth();
if (right.getBitmap() != NULL) r.right -= right.getWidth();
}
int w = (r.right - r.left) - thumbWidth();
if (w < 0) w = 0;
r.left += (pos * w) / length;
r.right = r.left + thumbWidth();
if (r.right > origr.right)
{
r.left -= r.right - origr.right;
r.right = origr.right;
}
if (!thumbStretched)
{
int thumbh = thumb.getBitmap() ? thumb.getHeight() : DEFAULT_THUMBWIDTH;
if (thumbCentered)
{
int h = ((r.bottom - r.top) - thumbh) / 2;
r.top = origr.top + h;
r.bottom = origr.bottom - h;
}
else
{
r.top = origr.top + thumbOffset;
r.bottom = origr.top + thumbh + thumbOffset;
}
}
else
{
r.top = origr.top;
r.bottom = origr.bottom;
}
}
SkinBitmap *sb = getSeekStatus() ? (thumbdown.getBitmap() ? thumbdown.getBitmap() : thumb.getBitmap()) : ((hilite && thumbhilite.getBitmap()) ? thumbhilite.getBitmap() : thumb.getBitmap());
if (sb != NULL)
sb->stretchToRectAlpha(canvas, &r, getPaintingAlpha());
else
canvas->fillRect(&r, RGB(255, 0, 0));
return 1;
}
int SliderWnd::onInit()
{
SLIDERWND_PARENT::onInit();
if (!no_default_background)
{
if (vertical)
{
// Please note that these bitmaps here do not yet exist.
if (left.getBitmapName() == NULL) setLeftBmp(L"wasabi.slider.vertical.top");
if (middle.getBitmapName() == NULL) setMiddleBmp(L"wasabi.slider.vertical.middle");
if (right.getBitmapName() == NULL) setRightBmp(L"wasabi.slider.vertical.bottom");
if (thumb.getBitmapName() == NULL) setThumbBmp(L"wasabi.slider.vertical.button");
if (thumbdown.getBitmapName() == NULL) setThumbDownBmp(L"wasabi.slider.vertical.button.pressed");
}
else
{
if (left.getBitmapName() == NULL) setLeftBmp(L"wasabi.slider.horizontal.left");
if (middle.getBitmapName() == NULL) setMiddleBmp(L"wasabi.slider.horizontal.middle");
if (right.getBitmapName() == NULL) setRightBmp(L"wasabi.slider.horizontal.right");
if (thumb.getBitmapName() == NULL) setThumbBmp(L"wasabi.slider.horizontal.button");
if (thumbdown.getBitmapName() == NULL) setThumbDownBmp(L"wasabi.slider.horizontal.button.pressed");
}
}
return 1;
}
int SliderWnd::onLeftButtonDown(int x, int y)
{
SLIDERWND_PARENT::onLeftButtonDown(x, y);
if (!enabled) return 0;
seeking = 1;
origPos = 0;
RECT r;
getClientRect(&r);
if (vertical)
{
int w = (r.bottom - r.top) - thumbHeight();
if (w < 0) w = 0;
r.top += (pos * w) / length;
origPos = (y - r.top) - 1;
/*if(origPos<0 || origPos>thumbHeight())*/ origPos = (thumbHeight() / 2) - 2;
}
else
{
if (!drawOnBorders)
{
if (left.getBitmap() != NULL) r.left += left.getWidth();
if (right.getBitmap() != NULL) r.right -= right.getWidth();
}
int w = (r.right - r.left) - thumbWidth();
if (w < 0) w = 0;
r.left += (pos * w) / length;
origPos = (x - r.left) - 1;
if (origPos < 0 || origPos > thumbWidth()) origPos = (thumbWidth() / 2) - 2;
}
if (!captured)
{
captured = 1;
beginCapture();
}
oldpos = pos;
onMouseMove(x, y);
return 1;
}
//FG>
//removed cross-hierarchy deletion (crashs due to ancestor in common.dll trying to delete pointers in a different
//heap scope than the one in which they were allocated)
void SliderWnd::setBitmaps(const wchar_t *thumbbmp, const wchar_t *thumbdownbmp, const wchar_t *thumbhighbmp, const wchar_t *leftbmp, const wchar_t *middlebmp, const wchar_t *rightbmp)
{
setThumbBmp(thumbbmp);
setThumbDownBmp(thumbdownbmp);
setThumbHiliteBmp(thumbhighbmp);
setLeftBmp(leftbmp);
setRightBmp(rightbmp);
setMiddleBmp(middlebmp);
}
void SliderWnd::setLeftBmp(const wchar_t *name)
{
left = name;
invalidate();
}
void SliderWnd::setMiddleBmp(const wchar_t *name)
{
middle = name;
invalidate();
}
void SliderWnd::setRightBmp(const wchar_t *name)
{
right = name;
invalidate();
}
void SliderWnd::setThumbBmp(const wchar_t *name)
{
thumb = name;
invalidate();
}
void SliderWnd::setThumbDownBmp(const wchar_t *name)
{
thumbdown = name;
invalidate();
}
void SliderWnd::setThumbHiliteBmp(const wchar_t *name)
{
thumbhilite = name;
invalidate();
}
SkinBitmap *SliderWnd::getLeftBitmap()
{
return left;
}
SkinBitmap *SliderWnd::getRightBitmap()
{
return right;
}
SkinBitmap *SliderWnd::getMiddleBitmap()
{
return middle;
}
SkinBitmap *SliderWnd::getThumbBitmap()
{
return thumb;
}
SkinBitmap *SliderWnd::getThumbDownBitmap()
{
return thumbdown;
}
SkinBitmap *SliderWnd::getThumbHiliteBitmap()
{
return thumbhilite;
}
int SliderWnd::getWidth()
{
if (vertical)
return (getThumbBitmap() ? getThumbBitmap()->getWidth() : 0);
else
{
return 64;
}
}
int SliderWnd::getHeight()
{
if (!vertical)
return (getThumbBitmap() ? getThumbBitmap()->getHeight() : 0);
else
{
return 64;
}
}
void SliderWnd::setEnable(int en)
{
if (enabled != en) invalidate();
enabled = en;
}
int SliderWnd::getEnable(void)
{
return enabled;
}
void SliderWnd::setPosition(int newpos, int wantcb)
{
if (newpos < minlimit) newpos = minlimit;
else if (newpos > maxlimit) newpos = maxlimit;
if (vertical) pos = maxlimit - newpos;
else /* horizontal */ pos = newpos - minlimit;
if (wantcb)
onSetPosition();
invalidate();
}
int SliderWnd::onMouseMove(int x, int y)
{
int p, w, mouseover;
SLIDERWND_PARENT::onMouseMove(x, y);
POINT po = {x, y};
clientToScreen(&po);
mouseover = (WASABI_API_WND->rootWndFromPoint(&po) == this);
if (mouseover && !seeking && !captured)
{
beginCapture();
captured = 1;
onEnterArea();
}
int lasthilite = hilite;
hilite = enabled && mouseover;
if (hilite != lasthilite)
{
if (!mouseover && !seeking && captured)
{
endCapture();
captured = 0;
onLeaveArea();
invalidate();
return 0;
}
invalidate();
}
if (!enabled) return 1;
RECT r, origr;
getClientRect(&r);
x -= r.left;
y -= r.top;
origr = r;
if (vertical)
{
w = (r.bottom - r.top) - thumbHeight();
// p = (y - (r.top-origr.top)) - (thumbHeight()/2-2);
p = (y - (r.top - origr.top)) - origPos;
}
else
{
if (!drawOnBorders)
{
if (left != NULL) r.left += left.getWidth();
if (right != NULL) r.right -= right.getWidth();
}
w = (r.right - r.left) - thumbWidth();
// p = (x - (r.left - origr.left)) - (thumbWidth()/2-2);
p = (x - (r.left - origr.left)) - origPos;
}
if (seeking)
{
pos = (p * length) / w;
if (pos < 0) pos = 0;
else if (pos > length) pos = length;
if (hotPosition != -1)
{
int a, c;
if (vertical) a = r.bottom - r.top;
else a = r.right - r.left;
c = getHotPosRange();
if (c == -1)
{
int b = (int)(a * 0.075);
c = (b * length) / a;
}
/**
EQBand: minlimit -127, maxlimit 127, hotpos 0
PanBar: minlimit 0, maxlimit 225, hotpos 127
VSliders pos starts from top by 0 (winamp behaviour reversed!)
*/
if (vertical)
{
//if (pos > (hotPosition - c) && pos < (hotPosition + c)) pos = hotPosition;
if ((maxlimit - pos) > (hotPosition - c) && (maxlimit - pos) < (hotPosition + c)) pos = hotPosition - minlimit; // Hehe, now it works ;)
}
else
{
if (pos > (hotPosition - c) && pos < (hotPosition + c)) pos = hotPosition;
//if ((pos - maxlimit)> (hotPosition - c) && (pos - maxlimit) < (hotPosition + c)) pos = hotPosition - minlimit;
}
}
onSetPosition();
invalidate();
}
return 1;
}
void SliderWnd::onCancelCapture()
{
SLIDERWND_PARENT::onCancelCapture();
if (seeking && captured)
abort();
}
int SliderWnd::onLeftButtonUp(int x, int y)
{
SLIDERWND_PARENT::onLeftButtonUp(x, y);
int wasseeking = seeking;
seeking = 0;
captured = 0;
oldpos = -1;
endCapture();
if (wasseeking)
onSetFinalPosition();
invalidate();
return 1;
}
int SliderWnd::onRightButtonDown(int x, int y)
{
SLIDERWND_PARENT::onRightButtonDown(x, y);
if (seeking && captured)
{
abort();
}
return 1;
}
int SliderWnd::onChar(unsigned int c)
{
SLIDERWND_PARENT::onChar(c);
if (seeking && captured && (c == 27))
{
abort();
}
return 1;
}
int SliderWnd::onSetPosition()
{
if (!isInited()) return 0;
notifyParent(ChildNotify::SLIDER_INTERIM_POSITION, getSliderPosition());
return 0;
}
int SliderWnd::onSetFinalPosition()
{
if (!isInited()) return 0;
notifyParent(ChildNotify::SLIDER_FINAL_POSITION, getSliderPosition());
return 0;
}
int SliderWnd::getSliderPosition()
{
if (vertical) return maxlimit -pos;
else return pos + minlimit;
}
int SliderWnd::getSeekStatus()
{
return seeking;
}
int SliderWnd::thumbWidth()
{
if (thumb.getBitmap() == NULL) return DEFAULT_THUMBWIDTH;
return thumb.getWidth();
}
int SliderWnd::thumbHeight()
{
if (thumb.getBitmap() == NULL) return DEFAULT_THUMBHEIGHT;
return thumb.getHeight();
}
void SliderWnd::setUseBaseTexture(int useit)
{
use_base_texture = useit;
invalidate();
}
void SliderWnd::setBaseTexture(SkinBitmap *bmp, int x, int y)
{
base_texture = bmp;
use_base_texture = TRUE;
xShift = x;
yShift = y;
invalidate();
}
void SliderWnd::setNoDefaultBackground(int no)
{
no_default_background = no;
}
void SliderWnd::setDrawOnBorders(int draw)
{
drawOnBorders = draw;
}
void SliderWnd::onEnterArea()
{
SLIDERWND_PARENT::onEnterArea();
}
void SliderWnd::onLeaveArea()
{
SLIDERWND_PARENT::onLeaveArea();
}
void SliderWnd::setOrientation(int o)
{
vertical = o;
}
void SliderWnd::setHotPosition(int h)
{
hotPosition = h;
}
void SliderWnd::setThumbCentered(int c)
{
thumbCentered = c;
}
void SliderWnd::setThumbStretched(int c)
{
thumbStretched = c;
}
void SliderWnd::setThumbOffset(int o)
{
thumbOffset = o;
}
void SliderWnd::abort()
{
if (oldpos != -1)
{
seeking = 0;
captured = 0;
endCapture();
pos = oldpos;
onSetPosition();
invalidate();
oldpos = -1;
}
return ;
}
void SliderWnd::setLimits(int pminlimit, int pmaxlimit)
{
minlimit = pminlimit;
maxlimit = pmaxlimit;
length = maxlimit - minlimit;
}
int SliderWnd::onKeyDown(int vkcode)
{
switch (vkcode)
{
case VK_LEFT: move_left(Std::keyModifier(STDKEY_CONTROL)); return 1;
case VK_RIGHT: move_right(Std::keyModifier(STDKEY_CONTROL)); return 1;
case VK_HOME: move_start(); return 1;
case VK_END: move_end(); return 1;
default: return SLIDERWND_PARENT::onKeyDown(vkcode);
}
}
void SliderWnd::move_left(int bigstep)
{
int pos = getSliderPosition();
if (!bigstep) pos--; else pos -= (ABS(maxlimit - minlimit) / 10);
if (pos < minlimit) pos = minlimit;
setPosition(pos);
}
void SliderWnd::move_right(int bigstep)
{
int pos = getSliderPosition();
if (!bigstep)
pos++;
else
pos += (ABS(maxlimit - minlimit) / 10);
if (pos > maxlimit)
pos = maxlimit;
setPosition(pos);
}
void SliderWnd::move_start()
{
setPosition(minlimit);
}
void SliderWnd::move_end()
{
setPosition(maxlimit);
}