nuclide/src/menu-fn/w_scrollbar.qc

262 lines
6.3 KiB
Plaintext

/*
* 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;
}