261 lines
6.3 KiB
C++
261 lines
6.3 KiB
C++
/*
|
|
* Copyright (c) 2016-2022 Vera Visions LLC.
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
|
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
class CScrollbar:CWidget
|
|
{
|
|
int m_hold;
|
|
int m_hover;
|
|
|
|
int m_height;
|
|
int m_theight;
|
|
int m_scroll;
|
|
int m_minus;
|
|
int m_maxvisible;
|
|
int m_totalentries;
|
|
int m_itemheight;
|
|
virtual void(int) m_changed = 0;
|
|
resource_t m_resUp;
|
|
resource_t m_resDown;
|
|
|
|
int m_up_hover;
|
|
int m_up_hold;
|
|
int m_dn_hover;
|
|
int m_dn_hold;
|
|
|
|
void(void) CScrollbar;
|
|
virtual void(void) Draw;
|
|
virtual void(float, float, float, float) Input;
|
|
|
|
virtual void(int) SetScroll;
|
|
virtual void(int) SetMax;
|
|
virtual void(int) SetHeight;
|
|
virtual void(int) SetItemheight;
|
|
virtual void(void(int)) SetCallback;
|
|
|
|
nonvirtual void DrawArrowUp(vector);
|
|
nonvirtual void DrawArrowDown(vector);
|
|
};
|
|
|
|
void
|
|
CScrollbar::CScrollbar(void)
|
|
{
|
|
/* There's the physical length (t_length) and the actual length
|
|
* (border, etc. ignored) */
|
|
SetItemheight(15);
|
|
SetHeight(128);
|
|
m_resUp = Resource_Check(strcat(g_bmp[UPARROWD], ".bmp"));
|
|
m_resDown = Resource_Check(strcat(g_bmp[DNARROWD], ".bmp"));
|
|
}
|
|
|
|
void
|
|
CScrollbar::DrawArrowUp(vector vecPos)
|
|
{
|
|
if (Resource_Available(m_resUp)) {
|
|
if (m_up_hold) {
|
|
drawpic(vecPos, g_bmp[UPARROWP], [16,16], [1,1,1], 1.0f, 0);
|
|
} else if (m_up_hover) {
|
|
drawpic(vecPos, g_bmp[UPARROWF], [16,16], [1,1,1], 1.0f, 0);
|
|
} else {
|
|
drawpic(vecPos, g_bmp[UPARROWD], [16,16], [1,1,1], 1.0f, 0);
|
|
}
|
|
} else {
|
|
drawfill(vecPos, [16,16], [0.25,0.25,0.25], 1.0f);
|
|
drawfill(vecPos + [3,3], [10,10], [0,0,0], 1.0f);
|
|
|
|
if (m_up_hold) {
|
|
drawfill(vecPos, [16,16], [1,1,1], 1.0f);
|
|
} else if (m_up_hover) {
|
|
drawfill(vecPos, [16,16], [1,1,1], 0.75f);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
CScrollbar::DrawArrowDown(vector vecPos)
|
|
{
|
|
if (Resource_Available(m_resDown)) {
|
|
if (m_dn_hold) {
|
|
drawpic(vecPos, g_bmp[DNARROWP], [16,16], [1,1,1], 1.0f, 0);
|
|
} else if (m_dn_hover) {
|
|
drawpic(vecPos, g_bmp[DNARROWF], [16,16], [1,1,1], 1.0f, 0);
|
|
} else {
|
|
drawpic(vecPos, g_bmp[DNARROWD], [16,16], [1,1,1], 1.0f, 0);
|
|
}
|
|
} else {
|
|
drawfill(vecPos, [16,16], [0.25,0.25,0.25], 1.0f);
|
|
drawfill(vecPos + [3,3], [10,10], [0,0,0], 1.0f);
|
|
|
|
if (m_dn_hold) {
|
|
drawfill(vecPos, [16,16], [1,1,1], 1.0f);
|
|
} else if (m_dn_hover) {
|
|
drawfill(vecPos, [16,16], [1,1,1], 0.75f);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
CScrollbar::Draw(void)
|
|
{
|
|
int barheight = 0;
|
|
float barstep = 0;
|
|
|
|
DrawArrowUp([g_menuofs[0]+m_x,g_menuofs[1]+m_y]);
|
|
DrawArrowDown([g_menuofs[0]+m_x,g_menuofs[1]+m_y+m_theight + 16]);
|
|
|
|
barheight = (float)(m_minus) / (float)(m_totalentries) * m_theight;
|
|
|
|
if (barheight < 20)
|
|
barheight = 20;
|
|
|
|
barstep = m_theight - barheight;
|
|
barstep *= (float)(m_scroll) / (float)(m_maxvisible);
|
|
|
|
/* too few entries? don't even bother */
|
|
if (m_totalentries * m_itemheight < m_height) {
|
|
drawfill([g_menuofs[0]+m_x,g_menuofs[1]+m_y+16], [16,m_theight], [0.25,0.25,0.25], 1.0f);
|
|
return;
|
|
}
|
|
|
|
if (!m_hold) {
|
|
drawfill([g_menuofs[0]+m_x,g_menuofs[1]+m_y+16], [16,m_theight], [0.25,0.25,0.25], 1.0f);
|
|
if (!m_hover) {
|
|
drawfill([g_menuofs[0]+m_x+4,g_menuofs[1]+m_y+16+4+barstep], [8,barheight-8], [0,0,0], 1.0f);
|
|
} else {
|
|
drawfill([g_menuofs[0]+m_x+4,g_menuofs[1]+m_y+16+4+barstep], [8,barheight-8], [1,0.5,0.25], 1.0f);
|
|
}
|
|
} else {
|
|
drawfill([g_menuofs[0]+m_x,g_menuofs[1]+m_y+16], [16,m_theight], [0,0,0], 1.0f);
|
|
drawfill([g_menuofs[0]+m_x+4,g_menuofs[1]+m_y+16+4+barstep], [8,barheight-8], [1,0.5,0.25], 1.0f);
|
|
}
|
|
}
|
|
|
|
void
|
|
CScrollbar::Input(float type, float x, float y, float devid)
|
|
{
|
|
int barheight = 0;
|
|
float barstep = 0;
|
|
|
|
/* too few entries? don't even bother */
|
|
if (m_totalentries * m_itemheight < m_height) {
|
|
return;
|
|
}
|
|
|
|
/* Up Arrow */
|
|
if (Util_CheckMouse(m_x, m_y, 16, 16)) {
|
|
m_up_hover = TRUE;
|
|
} else {
|
|
m_up_hover = FALSE;
|
|
}
|
|
if (m_up_hover && type == IE_KEYDOWN && x == K_MOUSE1) {
|
|
m_up_hold = TRUE;
|
|
} else if (type == IE_KEYUP && x == K_MOUSE1) {
|
|
m_up_hold = FALSE;
|
|
}
|
|
if (m_up_hold) {
|
|
SetScroll(m_scroll - 1);
|
|
}
|
|
|
|
/* Down Arrow */
|
|
if (Util_CheckMouse(m_x, m_y + m_theight + 16, 16, 16)) {
|
|
m_dn_hover = TRUE;
|
|
} else {
|
|
m_dn_hover = FALSE;
|
|
}
|
|
if (m_dn_hover && type == IE_KEYDOWN && x == K_MOUSE1) {
|
|
m_dn_hold = TRUE;
|
|
} else if (type == IE_KEYUP && x == K_MOUSE1) {
|
|
m_dn_hold = FALSE;
|
|
}
|
|
if (m_dn_hold) {
|
|
SetScroll(m_scroll + 1);
|
|
}
|
|
|
|
barheight = (float)(m_minus) / (float)(m_totalentries) * m_theight;
|
|
|
|
if (barheight < 20)
|
|
barheight = 20;
|
|
|
|
barstep = m_theight - barheight;
|
|
barstep *= (float)(m_scroll) / (float)(m_maxvisible);
|
|
|
|
if (Util_CheckMouse(m_x, m_y + 16 + barstep, 16, barheight)) {
|
|
m_hover = TRUE;
|
|
} else {
|
|
m_hover = FALSE;
|
|
}
|
|
|
|
if (m_hover && type == IE_KEYDOWN && x == K_MOUSE1) {
|
|
m_hold = TRUE;
|
|
} else if (type == IE_KEYUP && x == K_MOUSE1) {
|
|
m_hold = FALSE;
|
|
}
|
|
|
|
if (m_hold) {
|
|
if (g_mousepos[0] != g_lastmousepos[0] || g_mousepos[1] != g_lastmousepos[1]) {
|
|
int mdelta;
|
|
float m_value;
|
|
/* The - 10 is putting the slider in the middle of the cursor */
|
|
mdelta = (g_mousepos[1] - (barheight / 2)) - (g_menuofs[1]+m_y);
|
|
m_value = ((float)mdelta / (float)m_theight);
|
|
m_value = bound(0.0f, m_value, 1.0f);
|
|
|
|
SetScroll(rint(m_totalentries * m_value));
|
|
g_lastmousepos[0] = g_mousepos[0];
|
|
g_lastmousepos[1] = g_mousepos[1];
|
|
|
|
/*if (m_changed) {
|
|
m_changed(m_value);
|
|
}*/
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
CScrollbar::SetScroll(int val)
|
|
{
|
|
m_scroll = bound(0,val,m_maxvisible);
|
|
|
|
if (m_changed) {
|
|
m_changed(m_scroll);
|
|
}
|
|
}
|
|
|
|
void
|
|
CScrollbar::SetMax(int val)
|
|
{
|
|
m_minus = m_height / m_itemheight;
|
|
m_totalentries = val;
|
|
m_maxvisible = m_totalentries - m_minus;
|
|
}
|
|
|
|
void
|
|
CScrollbar::SetHeight(int val)
|
|
{
|
|
m_height = val;
|
|
m_theight = m_height - 32;
|
|
}
|
|
|
|
void
|
|
CScrollbar::SetItemheight(int val)
|
|
{
|
|
m_itemheight = val;
|
|
}
|
|
|
|
void
|
|
CScrollbar::SetCallback(void(int val) vFunc)
|
|
{
|
|
m_changed = vFunc;
|
|
}
|