190 lines
5.5 KiB
C++
190 lines
5.5 KiB
C++
//
|
|
// scrollbar.cpp
|
|
// BoE
|
|
//
|
|
// Created by Celtic Minstrel on 14-03-28.
|
|
//
|
|
//
|
|
|
|
#include "scrollbar.h"
|
|
#include "restypes.hpp"
|
|
#include "graphtool.h"
|
|
#include "mathutil.h"
|
|
|
|
sf::Texture cScrollbar::scroll_gw;
|
|
|
|
cScrollbar::cScrollbar(cDialog& parent) : cControl(CTRL_SCROLL, parent) {}
|
|
|
|
cScrollbar::cScrollbar(sf::RenderWindow& parent) : cControl(CTRL_SCROLL, parent), pos(0), max(0), pgsz(10) {}
|
|
|
|
void cScrollbar::init() {
|
|
scroll_gw.loadFromImage(*ResMgr::get<ImageRsrc>("dlogscroll"));
|
|
}
|
|
|
|
bool cScrollbar::isClickable(){
|
|
return true;
|
|
}
|
|
|
|
void cScrollbar::setPosition(long newPos) {
|
|
pos = minmax(0,max,newPos);
|
|
}
|
|
|
|
void cScrollbar::setMaximum(long newMax) {
|
|
max = ::max(1,newMax);
|
|
}
|
|
|
|
void cScrollbar::setPageSize(long newSize) {
|
|
pgsz = newSize;
|
|
}
|
|
|
|
long cScrollbar::getPosition() {
|
|
return pos;
|
|
}
|
|
|
|
long cScrollbar::getMaximum() {
|
|
return max;
|
|
}
|
|
|
|
long cScrollbar::getPageSize() {
|
|
return pgsz;
|
|
}
|
|
|
|
void cScrollbar::attachClickHandler(click_callback_t f) throw(xHandlerNotSupported) {
|
|
onClick = f;
|
|
}
|
|
|
|
void cScrollbar::attachFocusHandler(focus_callback_t f) throw(xHandlerNotSupported) {
|
|
throw xHandlerNotSupported(true);
|
|
}
|
|
|
|
bool cScrollbar::triggerClickHandler(cDialog& me, std::string id, eKeyMod mods, location where) {
|
|
// TODO: Implement detection of scrolling stuff, maybe even dragging the thumb
|
|
if(onClick != NULL) return onClick(me,id,mods);
|
|
return false;
|
|
}
|
|
|
|
bool cScrollbar::handleClick(location where) {
|
|
sf::Event e;
|
|
bool done = false, clicked = false;
|
|
inWindow->setActive();
|
|
depressed = true;
|
|
int bar_height = frame.height() - 32;
|
|
RECT thumbRect = frame;
|
|
thumbRect.top += 16 + pos * (bar_height - 16) / max;
|
|
thumbRect.height() = 16;
|
|
if(where.y < frame.top + 16)
|
|
pressedPart = PART_UP;
|
|
else if(where.y < thumbRect.top)
|
|
pressedPart = PART_PGUP;
|
|
else if(where.y < thumbRect.bottom)
|
|
pressedPart = PART_THUMB;
|
|
else if(where.y < frame.bottom - 16)
|
|
pressedPart = PART_PGDN;
|
|
else pressedPart = PART_DOWN;
|
|
int dy = where.y - thumbRect.top;
|
|
while(!done){
|
|
// If there's no parent dialog, we're not responsible for redrawing
|
|
if(parent) parent->draw();
|
|
if(!inWindow->pollEvent(e)) continue;
|
|
if(e.type == sf::Event::MouseButtonReleased){
|
|
done = true;
|
|
clicked = frame.contains(e.mouseButton.x, e.mouseButton.y);
|
|
depressed = false;
|
|
switch(pressedPart) {
|
|
case PART_UP: pos--; break;
|
|
case PART_PGUP: pos -= pgsz; break;
|
|
case PART_PGDN: pos += pgsz; break;
|
|
case PART_DOWN: pos++; break;
|
|
case PART_THUMB: break;
|
|
}
|
|
} else if(e.type == sf::Event::MouseMoved){
|
|
switch(pressedPart) {
|
|
case PART_UP:
|
|
depressed = e.mouseMove.y < frame.top + 16;
|
|
break;
|
|
case PART_PGUP:
|
|
depressed = e.mouseMove.y >= frame.top + 16 && e.mouseMove.y < thumbRect.top;
|
|
break;
|
|
case PART_THUMB:
|
|
depressed = true;
|
|
// We want the pos that will make thumbRect.top = mousePos.y - dy
|
|
// In draw(), thumbRect.top is calculated as frame.top + 16 + pos * (bar_height - 16) / max
|
|
// So solving for pos gives (mousePos.y - dy - frame.top - 16) * max / (bar_height - 16)
|
|
pos = (sf::Mouse::getPosition(*inWindow).y - dy - frame.top - 16) * max / (bar_height - 16);
|
|
break;
|
|
case PART_PGDN:
|
|
depressed = e.mouseMove.y >= thumbRect.bottom && e.mouseMove.y < frame.bottom - 16;
|
|
break;
|
|
case PART_DOWN:
|
|
depressed = e.mouseMove.y >= frame.bottom - 16;
|
|
break;
|
|
}
|
|
if(pressedPart != PART_THUMB && !frame.contains(e.mouseMove.x, e.mouseMove.y)) depressed = false;
|
|
}
|
|
pos = minmax(0,max,pos);
|
|
thumbRect.top = frame.top;
|
|
thumbRect.top += 16 + pos * (bar_height - 16) / max;
|
|
thumbRect.top = minmax(sf::Mouse::getPosition(*inWindow).y,frame.bottom - 32,thumbRect.top);
|
|
thumbRect.height() = 16;
|
|
}
|
|
if(parent) parent->draw();
|
|
return clicked;
|
|
}
|
|
|
|
void cScrollbar::setFormat(eFormat prop, short val) throw(xUnsupportedProp) {
|
|
throw xUnsupportedProp(prop);
|
|
}
|
|
|
|
short cScrollbar::getFormat(eFormat prop) throw(xUnsupportedProp) {
|
|
throw xUnsupportedProp(prop);
|
|
}
|
|
|
|
void cScrollbar::setColour(sf::Color clr) throw(xUnsupportedProp) {
|
|
// TODO: Colour is unsupported
|
|
}
|
|
|
|
sf::Color cScrollbar::getColour() throw(xUnsupportedProp) {
|
|
// TODO: Colour is unsupported
|
|
return sf::Color();
|
|
}
|
|
|
|
void cScrollbar::draw() {
|
|
if(!isVisible()) return;
|
|
static const RECT up_rect = {0,0,16,16}, down_rect = {0,16,16,32}, thumb_rect = {0,32,16,48}, bar_rect = {0,48,16,64};
|
|
int bar_height = frame.height() - 32;
|
|
inWindow->setActive();
|
|
RECT draw_rect = frame, from_rect = up_rect;
|
|
draw_rect.height() = 16;
|
|
if(depressed && pressedPart == PART_UP)
|
|
from_rect.offset(0,16);
|
|
rect_draw_some_item(scroll_gw, from_rect, *inWindow, draw_rect);
|
|
if(pos > 0) {
|
|
draw_rect.top = draw_rect.bottom;
|
|
draw_rect.height() = pos * (bar_height - 16) / max;
|
|
from_rect = bar_rect;
|
|
if(depressed && pressedPart == PART_PGUP)
|
|
from_rect.offset(0,16);
|
|
tileImage(*inWindow, draw_rect, scroll_gw, from_rect);
|
|
}
|
|
draw_rect.top = draw_rect.bottom;
|
|
draw_rect.height() = 16;
|
|
from_rect = thumb_rect;
|
|
if(depressed && pressedPart == PART_THUMB)
|
|
from_rect.offset(0,16);
|
|
rect_draw_some_item(scroll_gw, from_rect, *inWindow, draw_rect);
|
|
if(pos < max) {
|
|
draw_rect.top = draw_rect.bottom;
|
|
draw_rect.bottom = frame.bottom - 16;
|
|
from_rect = bar_rect;
|
|
if(depressed && pressedPart == PART_PGDN)
|
|
from_rect.offset(0,16);
|
|
tileImage(*inWindow, draw_rect, scroll_gw, from_rect);
|
|
}
|
|
draw_rect = frame;
|
|
draw_rect.top = draw_rect.bottom - 16;
|
|
from_rect = down_rect;
|
|
if(depressed && pressedPart == PART_DOWN)
|
|
from_rect.offset(0,16);
|
|
rect_draw_some_item(scroll_gw, from_rect, *inWindow, draw_rect);
|
|
}
|