Implement scrollbars
- They work almost as you'd expect, though holding the mouse down on an arrow only scrolls once, and it's a little jerky - Add an additional refresh option to redraw_screen, currently only partially implemented - Scrollbars now have a page size in addition to pos and max - cControl::handleClick() now takes the location clicked as a parameter, though the default implementation doesn't use it - cControl::handleClick() is no longer responsible for redrawing the control when there is no parent dialog - Fix cTextMsg not allowing retrieval of frame style
This commit is contained in:
@@ -454,6 +454,7 @@
|
||||
91AC65520FA3441B00EEAE67 /* universe.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91AC61C50FA2729900EEAE67 /* universe.cpp */; };
|
||||
91AC65AD0FA34AC600EEAE67 /* universe.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91AC61C50FA2729900EEAE67 /* universe.cpp */; };
|
||||
91ACCE6418FFB61A00FAEF8B /* bladbase.exs in Copy Base Scenarios */ = {isa = PBXBuildFile; fileRef = 91B3EF250F969CE300BF5B67 /* bladbase.exs */; };
|
||||
91ACCE66190004F000FAEF8B /* dlogscroll.png in Copy Mac Graphics */ = {isa = PBXBuildFile; fileRef = 91ACCE65190004D300FAEF8B /* dlogscroll.png */; };
|
||||
91B3EF1F0F969C9C00BF5B67 /* BoECharEd.icns in Resources */ = {isa = PBXBuildFile; fileRef = 91B3EF110F969BD300BF5B67 /* BoECharEd.icns */; };
|
||||
91B3EF450F969F1700BF5B67 /* BoE Scenario Editor-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 91B3EED90F969BA700BF5B67 /* BoE Scenario Editor-Info.plist */; };
|
||||
91B3EF470F969F1700BF5B67 /* BoE Scenario Editor.icns in Resources */ = {isa = PBXBuildFile; fileRef = 91B3EEDB0F969BA700BF5B67 /* BoE Scenario Editor.icns */; };
|
||||
@@ -640,6 +641,7 @@
|
||||
912CF41D0FE44AAF0063B614 /* dlogbtnsm.png in Copy Mac Graphics */,
|
||||
912CF41E0FE44AAF0063B614 /* dlogbtntall.png in Copy Mac Graphics */,
|
||||
912CF41F0FE44AAF0063B614 /* dlogpics.png in Copy Mac Graphics */,
|
||||
91ACCE66190004F000FAEF8B /* dlogscroll.png in Copy Mac Graphics */,
|
||||
912CF4200FE44AAF0063B614 /* edbuttons.png in Copy Mac Graphics */,
|
||||
912CF4210FE44AAF0063B614 /* edsplash.png in Copy Mac Graphics */,
|
||||
912CF4220FE44AAF0063B614 /* fields.png in Copy Mac Graphics */,
|
||||
@@ -1461,6 +1463,7 @@
|
||||
91AC61C50FA2729900EEAE67 /* universe.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = universe.cpp; sourceTree = "<group>"; };
|
||||
91AC62090FA2853700EEAE67 /* creatlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = creatlist.h; sourceTree = "<group>"; };
|
||||
91AC620A0FA2853700EEAE67 /* creatlist.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = creatlist.cpp; sourceTree = "<group>"; };
|
||||
91ACCE65190004D300FAEF8B /* dlogscroll.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = dlogscroll.png; sourceTree = "<group>"; };
|
||||
91B3E8A50F938FFE00BF5B67 /* boe.consts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = boe.consts.h; sourceTree = "<group>"; };
|
||||
91B3EED90F969BA700BF5B67 /* BoE Scenario Editor-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "BoE Scenario Editor-Info.plist"; sourceTree = "<group>"; };
|
||||
91B3EEDA0F969BA700BF5B67 /* BOEScen.rsrc */ = {isa = PBXFileReference; lastKnownFileType = archive.rsrc; path = BOEScen.rsrc; sourceTree = "<group>"; };
|
||||
@@ -1720,6 +1723,7 @@
|
||||
912CF3A10FE44A9B0063B614 /* dlogbtnsm.png */,
|
||||
912CF3A20FE44A9B0063B614 /* dlogbtntall.png */,
|
||||
912CF3A30FE44A9B0063B614 /* dlogpics.png */,
|
||||
91ACCE65190004D300FAEF8B /* dlogscroll.png */,
|
||||
912CF3A40FE44A9B0063B614 /* edbuttons.png */,
|
||||
912CF3A50FE44A9B0063B614 /* edsplash.png */,
|
||||
912CF3A60FE44A9B0063B614 /* fields.png */,
|
||||
@@ -1730,8 +1734,6 @@
|
||||
912CF3AB0FE44A9B0063B614 /* mapOLD.png */,
|
||||
912CF3AC0FE44A9B0063B614 /* missiles.png */,
|
||||
912CF3AD0FE44A9B0063B614 /* monst1.png */,
|
||||
912CF3AE0FE44A9B0063B614 /* monst10.png */,
|
||||
912CF3AF0FE44A9B0063B614 /* monst11.png */,
|
||||
912CF3B00FE44A9B0063B614 /* monst2.png */,
|
||||
912CF3B10FE44A9B0063B614 /* monst3.png */,
|
||||
912CF3B20FE44A9B0063B614 /* monst4.png */,
|
||||
@@ -1740,6 +1742,8 @@
|
||||
912CF3B50FE44A9B0063B614 /* monst7.png */,
|
||||
912CF3B60FE44A9B0063B614 /* monst8.png */,
|
||||
912CF3B70FE44A9B0063B614 /* monst9.png */,
|
||||
912CF3AE0FE44A9B0063B614 /* monst10.png */,
|
||||
912CF3AF0FE44A9B0063B614 /* monst11.png */,
|
||||
912CF3B80FE44A9B0063B614 /* objects.png */,
|
||||
912CF3B90FE44A9B0063B614 /* outhelp.png */,
|
||||
912CF3BA0FE44A9B0063B614 /* pcedbuttons.png */,
|
||||
|
||||
@@ -622,9 +622,11 @@ void redraw_screen(int refresh) {
|
||||
draw_startup(0);
|
||||
break;
|
||||
case MODE_TALKING:
|
||||
if(refresh & REFRESH_DLOG); // TODO: Should call place_talk_str, but we don't have the strings
|
||||
refresh_talking();
|
||||
break;
|
||||
case MODE_SHOPPING:
|
||||
if(refresh & REFRESH_DLOG) draw_shop_graphics(0,{0,0,0,0});
|
||||
refresh_shopping();
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -8,8 +8,9 @@ enum {
|
||||
REFRESH_INVEN = 1 << 2,
|
||||
REFRESH_TRANS = 1 << 3,
|
||||
REFRESH_BAR = 1 << 4,
|
||||
REFRESH_DLOG = 1 << 5,
|
||||
REFRESH_TEXT = REFRESH_BAR | REFRESH_TRANS,
|
||||
REFRESH_ALL = 0x1f
|
||||
REFRESH_ALL = 0x3f
|
||||
};
|
||||
|
||||
void adjust_window_mode();
|
||||
|
||||
153
osx/boe.main.cpp
153
osx/boe.main.cpp
@@ -5,6 +5,7 @@
|
||||
#include "boe.global.h"
|
||||
#include "classes.h"
|
||||
|
||||
#include <thread>
|
||||
#include "boe.graphics.h"
|
||||
#include "boe.newgraph.h"
|
||||
#include "boe.fileio.h"
|
||||
@@ -267,12 +268,16 @@ void Initialize(void)
|
||||
text_sbar->setBounds(sbar_rect);
|
||||
text_sbar->setMaximum(58);
|
||||
text_sbar->setPosition(58);
|
||||
text_sbar->setPageSize(11);
|
||||
item_sbar.reset(new cScrollbar(mainPtr));
|
||||
item_sbar->setBounds(item_sbar_rect);
|
||||
item_sbar->setMaximum(16);
|
||||
item_sbar->setPageSize(8);
|
||||
shop_sbar.reset(new cScrollbar(mainPtr));
|
||||
shop_sbar->setBounds(shop_sbar_rect);
|
||||
shop_sbar->setMaximum(16);
|
||||
shop_sbar->setPageSize(8);
|
||||
shop_sbar->hide();
|
||||
adjust_window_mode();
|
||||
|
||||
}
|
||||
@@ -437,137 +442,45 @@ void Handle_Update()
|
||||
|
||||
}
|
||||
|
||||
// TODO: These three functions should probably be inside the cScrollbar class (the three are almost identical)
|
||||
void sbar_action(cScrollbar& bar, short part)
|
||||
{
|
||||
short old_setting,new_setting,max;
|
||||
|
||||
if (part == 0)
|
||||
return;
|
||||
|
||||
old_setting = bar.getPosition();
|
||||
new_setting = old_setting;
|
||||
max = bar.getMaximum();
|
||||
|
||||
switch (part) {
|
||||
case 0/*kControlUpButtonPart*/: new_setting--; break;
|
||||
case 1/*kControlDownButtonPart*/: new_setting++; break;
|
||||
case 2/*kControlPageUpPart*/: new_setting -= 11; break;
|
||||
case 3/*kControlPageDownPart*/: new_setting += 11; break;
|
||||
void handleUpdateWhileScrolling(volatile bool& doneScrolling, int refresh) {
|
||||
while(!doneScrolling) {
|
||||
sf::sleep(sf::milliseconds(10));
|
||||
redraw_screen(refresh);
|
||||
mainPtr.display();
|
||||
}
|
||||
new_setting = minmax(0,max,new_setting);
|
||||
bar.setPosition(new_setting);
|
||||
if (new_setting != old_setting)
|
||||
print_buf();
|
||||
}
|
||||
|
||||
void item_sbar_action(cScrollbar& bar, short part)
|
||||
{
|
||||
short old_setting,new_setting;
|
||||
short max;
|
||||
|
||||
if (part == 0)
|
||||
return;
|
||||
|
||||
old_setting = bar.getPosition();
|
||||
new_setting = old_setting;
|
||||
max = bar.getMaximum();
|
||||
|
||||
switch (part) {
|
||||
case 0/*kControlUpButtonPart*/: new_setting--; break;
|
||||
case 1/*kControlDownButtonPart*/: new_setting++; break;
|
||||
case 2/*kControlPageUpPart*/: new_setting -= (stat_window == 7) ? 2 : 8; break;
|
||||
case 3/*kControlPageDownPart*/: new_setting += (stat_window == 7) ? 2 : 8; break;
|
||||
}
|
||||
new_setting = minmax(0,max,new_setting);
|
||||
bar.setPosition(new_setting);
|
||||
if (new_setting != old_setting)
|
||||
put_item_screen(stat_window,1);
|
||||
}
|
||||
|
||||
void shop_sbar_action(cScrollbar bar, short part)
|
||||
{
|
||||
short old_setting,new_setting;
|
||||
short max;
|
||||
|
||||
if (part == 0)
|
||||
return;
|
||||
|
||||
old_setting = bar.getPosition();
|
||||
new_setting = old_setting;
|
||||
max = bar.getMaximum();
|
||||
|
||||
switch (part) {
|
||||
case 0/*kControlUpButtonPart*/: new_setting--; break;
|
||||
case 1/*kControlDownButtonPart*/: new_setting++; break;
|
||||
case 2/*kControlPageUpPart*/: new_setting -= 8; break;
|
||||
case 3/*kControlPageDownPart*/: new_setting += 8; break;
|
||||
}
|
||||
new_setting = minmax(0,max,new_setting);
|
||||
bar.setPosition(new_setting);
|
||||
if (new_setting != old_setting)
|
||||
draw_shop_graphics(0,shop_sbar_rect);
|
||||
}
|
||||
|
||||
// TODO: Pass the event object around instead of keeping a global one
|
||||
void Mouse_Pressed()
|
||||
{
|
||||
// TODO: What about other windows?
|
||||
// sf::Window& the_window = mainPtr;
|
||||
if (had_text_freeze > 0) {
|
||||
had_text_freeze--;
|
||||
return;
|
||||
}
|
||||
|
||||
//ding();
|
||||
// TODO: Most of this should be handled automatically by Cocoa, but make sure nothing important was missed (like the code under inGoAway, that looks important)
|
||||
#if 0
|
||||
// TODO: Honestly, I'm not quite sure how to track the scrollbars right now
|
||||
// if (the_window == mainPtr) {
|
||||
SetPortWindowPort(mainPtr);
|
||||
GlobalToLocal(&event.where);
|
||||
content_part = FindControl(event.where,the_window,&control_hit); // hit sbar?
|
||||
if (content_part != 0) {
|
||||
switch (content_part) {
|
||||
case kControlIndicatorPart:
|
||||
content_part = TrackControl(control_hit,event.where,NULL);
|
||||
if (control_hit == text_sbar)
|
||||
if (content_part == kControlIndicatorPart)
|
||||
print_buf();
|
||||
if (control_hit == item_sbar)
|
||||
if (content_part == kControlIndicatorPart)
|
||||
put_item_screen(stat_window,0);
|
||||
if (control_hit == shop_sbar)
|
||||
if (content_part == kControlIndicatorPart)
|
||||
draw_shop_graphics(0,shop_sbar_rect);
|
||||
break;
|
||||
case kControlUpButtonPart: case kControlPageUpPart: case kControlDownButtonPart: case kControlPageDownPart:
|
||||
#ifndef EXILE_BIG_GUNS
|
||||
if (control_hit == text_sbar)
|
||||
content_part = TrackControl(control_hit,event.where,(ControlActionUPP)sbar_action);
|
||||
if (control_hit == item_sbar)
|
||||
content_part = TrackControl(control_hit,event.where,(ControlActionUPP)item_sbar_action);
|
||||
if (control_hit == shop_sbar)
|
||||
content_part = TrackControl(control_hit,event.where,(ControlActionUPP)shop_sbar_action);
|
||||
#endif
|
||||
#ifdef EXILE_BIG_GUNS
|
||||
if (control_hit == text_sbar)
|
||||
content_part = TrackControl(control_hit,event.where,(ControlActionUPP)text_sbar_UPP);
|
||||
if (control_hit == item_sbar)
|
||||
content_part = TrackControl(control_hit,event.where,(ControlActionUPP)item_sbar_UPP);
|
||||
if (control_hit == shop_sbar)
|
||||
content_part = TrackControl(control_hit,event.where,(ControlActionUPP)shop_sbar_UPP);
|
||||
#endif
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
} // a control hit
|
||||
// else { // ordinary click
|
||||
#endif // end commented-out code section
|
||||
if(overall_mode != MODE_STARTUP)
|
||||
All_Done = handle_action(event);
|
||||
else All_Done = handle_startup_press({event.mouseButton.x, event.mouseButton.y});
|
||||
if(overall_mode != MODE_STARTUP) {
|
||||
location mousePos(event.mouseButton.x, event.mouseButton.y);
|
||||
volatile bool doneScrolling = false;
|
||||
if(mousePos.in(text_sbar->getBounds())) {
|
||||
std::thread updater(std::bind(handleUpdateWhileScrolling, std::ref(doneScrolling), REFRESH_TRANS));
|
||||
text_sbar->handleClick(mousePos);
|
||||
doneScrolling = true;
|
||||
updater.join();
|
||||
redraw_screen(REFRESH_TRANS);
|
||||
} else if(mousePos.in(item_sbar->getBounds())) {
|
||||
std::thread updater(std::bind(handleUpdateWhileScrolling, std::ref(doneScrolling), REFRESH_INVEN));
|
||||
item_sbar->handleClick(mousePos);
|
||||
doneScrolling = true;
|
||||
updater.join();
|
||||
redraw_screen(REFRESH_INVEN);
|
||||
} else if(overall_mode == MODE_SHOPPING && mousePos.in(shop_sbar->getBounds())) {
|
||||
std::thread updater(std::bind(handleUpdateWhileScrolling, std::ref(doneScrolling), REFRESH_DLOG));
|
||||
shop_sbar->handleClick(mousePos);
|
||||
doneScrolling = true;
|
||||
updater.join();
|
||||
redraw_screen(REFRESH_DLOG);
|
||||
} else All_Done = handle_action(event);
|
||||
} else All_Done = handle_startup_press({event.mouseButton.x, event.mouseButton.y});
|
||||
|
||||
menu_activate();
|
||||
|
||||
|
||||
@@ -549,6 +549,7 @@ void set_stat_window(short new_stat)
|
||||
stat_window = new_stat;
|
||||
if ((stat_window < 6) && (univ.party[stat_window].main_status != 1))
|
||||
stat_window = first_active_pc();
|
||||
item_sbar->setPageSize(8);
|
||||
switch (stat_window) {
|
||||
case 6:
|
||||
for (i = 0; i < 60; i++)
|
||||
@@ -563,6 +564,7 @@ void set_stat_window(short new_stat)
|
||||
break;
|
||||
case 7:
|
||||
item_sbar->setMaximum(2);
|
||||
item_sbar->setPageSize(2);
|
||||
break;
|
||||
default:
|
||||
item_sbar->setMaximum(16);
|
||||
|
||||
@@ -317,13 +317,12 @@ void cLedGroup::addChoice(cLed* ctrl, std::string key) {
|
||||
choices[key] = ctrl;
|
||||
}
|
||||
|
||||
bool cLedGroup::handleClick() {
|
||||
location where = sf::Mouse::getPosition(*inWindow);
|
||||
bool cLedGroup::handleClick(location where) {
|
||||
std::string which_clicked;
|
||||
ledIter iter = choices.begin();
|
||||
while(iter != choices.end()){
|
||||
if(iter->second->isVisible() && where.in(iter->second->getBounds())){
|
||||
if(iter->second->handleClick()) {
|
||||
if(iter->second->handleClick(where)) {
|
||||
which_clicked = iter->first;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ public:
|
||||
sf::Color getColour() throw(xUnsupportedProp);
|
||||
explicit cLedGroup(cDialog* parent);
|
||||
bool isClickable();
|
||||
bool handleClick();
|
||||
bool handleClick(location where);
|
||||
virtual ~cLedGroup();
|
||||
cLed& operator[](std::string id);
|
||||
void setSelected(std::string id);
|
||||
|
||||
@@ -178,18 +178,14 @@ void cControl::setActive(bool active) {
|
||||
depressed = active;
|
||||
}
|
||||
|
||||
bool cControl::handleClick(){
|
||||
bool cControl::handleClick(location where){
|
||||
sf::Event e;
|
||||
bool done = false, clicked = false;
|
||||
inWindow->setActive();
|
||||
depressed = true;
|
||||
while(!done){
|
||||
// If there's no parent dialog, we're not responsible for redrawing
|
||||
if(parent) parent->draw();
|
||||
else {
|
||||
// TODO: This only redraws this one control; should probably redraw the entire dialog? But what if there is no dialog?
|
||||
draw();
|
||||
inWindow->display();
|
||||
}
|
||||
if(!inWindow->pollEvent(e)) continue;
|
||||
if(e.type == sf::Event::MouseButtonReleased){
|
||||
done = true;
|
||||
@@ -207,11 +203,6 @@ bool cControl::handleClick(){
|
||||
}
|
||||
else sf::sleep(time_in_ticks(14));
|
||||
if(parent) parent->draw();
|
||||
else {
|
||||
// TODO: This only redraws this one control; should probably redraw the entire dialog? But what if there is no dialog?
|
||||
draw();
|
||||
inWindow->display();
|
||||
}
|
||||
return clicked;
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ public:
|
||||
virtual void setColour(sf::Color clr) throw(xUnsupportedProp) = 0;
|
||||
virtual sf::Color getColour() throw(xUnsupportedProp) = 0;
|
||||
virtual bool isClickable() = 0;
|
||||
virtual bool handleClick();
|
||||
virtual bool handleClick(location where);
|
||||
cControl(eControlType t, sf::RenderWindow& p);
|
||||
cControl(eControlType t, cDialog& p);
|
||||
virtual ~cControl();
|
||||
|
||||
@@ -18,6 +18,7 @@ using namespace ticpp;
|
||||
#include "button.h"
|
||||
#include "field.h"
|
||||
#include "message.h"
|
||||
#include "scrollbar.h"
|
||||
#include "winutil.h"
|
||||
#include "mathutil.h"
|
||||
|
||||
@@ -860,6 +861,7 @@ void cDialog::init(){
|
||||
cButton::init();
|
||||
cLed::init();
|
||||
cPict::init();
|
||||
cScrollbar::init();
|
||||
}
|
||||
|
||||
cDialog::~cDialog(){
|
||||
@@ -1188,7 +1190,7 @@ std::string cDialog::process_click(location where, eKeyMod mods){
|
||||
ctrlIter iter = controls.begin();
|
||||
while(iter != controls.end()){
|
||||
if(iter->second->isVisible() && iter->second->isClickable() && where.in(iter->second->getBounds())){
|
||||
if(iter->second->handleClick())
|
||||
if(iter->second->handleClick(where))
|
||||
return iter->first;
|
||||
else return "";
|
||||
}
|
||||
|
||||
@@ -61,6 +61,8 @@ short cTextMsg::getFormat(eFormat prop) throw(xUnsupportedProp){
|
||||
switch(prop){
|
||||
case TXT_FRAME:
|
||||
return drawFramed;
|
||||
case TXT_FRAMESTYLE:
|
||||
return frameStyle;
|
||||
case TXT_SIZE:
|
||||
return textSize;
|
||||
case TXT_FONT:
|
||||
|
||||
@@ -7,22 +7,34 @@
|
||||
//
|
||||
|
||||
#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) {}
|
||||
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) {
|
||||
if(newPos > max) pos = max;
|
||||
else pos = newPos;
|
||||
pos = minmax(0,max,pos);
|
||||
}
|
||||
|
||||
void cScrollbar::setMaximum(long newMax) {
|
||||
max = newMax;
|
||||
max = ::max(1,newMax);
|
||||
}
|
||||
|
||||
void cScrollbar::setPageSize(long newSize) {
|
||||
pgsz = newSize;
|
||||
}
|
||||
|
||||
long cScrollbar::getPosition() {
|
||||
@@ -33,6 +45,10 @@ long cScrollbar::getMaximum() {
|
||||
return max;
|
||||
}
|
||||
|
||||
long cScrollbar::getPageSize() {
|
||||
return pgsz;
|
||||
}
|
||||
|
||||
void cScrollbar::attachClickHandler(click_callback_t f) throw(xHandlerNotSupported) {
|
||||
onClick = f;
|
||||
}
|
||||
@@ -47,6 +63,74 @@ bool cScrollbar::triggerClickHandler(cDialog& me, std::string id, eKeyMod 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);
|
||||
}
|
||||
@@ -65,5 +149,41 @@ sf::Color cScrollbar::getColour() throw(xUnsupportedProp) {
|
||||
}
|
||||
|
||||
void cScrollbar::draw() {
|
||||
// TODO: Draw the scrollbar
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -12,14 +12,24 @@
|
||||
#include "control.h"
|
||||
|
||||
class cScrollbar : public cControl {
|
||||
int pos, max;
|
||||
int pos, max, pgsz;
|
||||
enum {
|
||||
PART_UP,
|
||||
PART_PGUP,
|
||||
PART_THUMB,
|
||||
PART_PGDN,
|
||||
PART_DOWN,
|
||||
} pressedPart;
|
||||
click_callback_t onClick;
|
||||
static sf::Texture scroll_gw;
|
||||
public:
|
||||
static void init();
|
||||
explicit cScrollbar(sf::RenderWindow& parent);
|
||||
explicit cScrollbar(cDialog& parent);
|
||||
void attachClickHandler(click_callback_t f) throw(xHandlerNotSupported);
|
||||
void attachFocusHandler(focus_callback_t f) throw(xHandlerNotSupported);
|
||||
bool triggerClickHandler(cDialog& me, std::string id, eKeyMod mods, location where);
|
||||
bool handleClick(location where);
|
||||
void setFormat(eFormat prop, short val) throw(xUnsupportedProp);
|
||||
short getFormat(eFormat prop) throw(xUnsupportedProp);
|
||||
void setColour(sf::Color clr) throw(xUnsupportedProp);
|
||||
@@ -27,8 +37,10 @@ public:
|
||||
bool isClickable();
|
||||
long getPosition();
|
||||
long getMaximum();
|
||||
long getPageSize();
|
||||
void setPosition(long to);
|
||||
void setMaximum(long to);
|
||||
void setPageSize(long to);
|
||||
void draw();
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user