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:
2014-04-17 11:32:43 -04:00
parent b960139d6b
commit 369c7f9f93
13 changed files with 194 additions and 146 deletions

View File

@@ -454,6 +454,7 @@
91AC65520FA3441B00EEAE67 /* universe.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91AC61C50FA2729900EEAE67 /* universe.cpp */; }; 91AC65520FA3441B00EEAE67 /* universe.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91AC61C50FA2729900EEAE67 /* universe.cpp */; };
91AC65AD0FA34AC600EEAE67 /* 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 */; }; 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 */; }; 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 */; }; 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 */; }; 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 */, 912CF41D0FE44AAF0063B614 /* dlogbtnsm.png in Copy Mac Graphics */,
912CF41E0FE44AAF0063B614 /* dlogbtntall.png in Copy Mac Graphics */, 912CF41E0FE44AAF0063B614 /* dlogbtntall.png in Copy Mac Graphics */,
912CF41F0FE44AAF0063B614 /* dlogpics.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 */, 912CF4200FE44AAF0063B614 /* edbuttons.png in Copy Mac Graphics */,
912CF4210FE44AAF0063B614 /* edsplash.png in Copy Mac Graphics */, 912CF4210FE44AAF0063B614 /* edsplash.png in Copy Mac Graphics */,
912CF4220FE44AAF0063B614 /* fields.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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 91B3EEDA0F969BA700BF5B67 /* BOEScen.rsrc */ = {isa = PBXFileReference; lastKnownFileType = archive.rsrc; path = BOEScen.rsrc; sourceTree = "<group>"; };
@@ -1720,6 +1723,7 @@
912CF3A10FE44A9B0063B614 /* dlogbtnsm.png */, 912CF3A10FE44A9B0063B614 /* dlogbtnsm.png */,
912CF3A20FE44A9B0063B614 /* dlogbtntall.png */, 912CF3A20FE44A9B0063B614 /* dlogbtntall.png */,
912CF3A30FE44A9B0063B614 /* dlogpics.png */, 912CF3A30FE44A9B0063B614 /* dlogpics.png */,
91ACCE65190004D300FAEF8B /* dlogscroll.png */,
912CF3A40FE44A9B0063B614 /* edbuttons.png */, 912CF3A40FE44A9B0063B614 /* edbuttons.png */,
912CF3A50FE44A9B0063B614 /* edsplash.png */, 912CF3A50FE44A9B0063B614 /* edsplash.png */,
912CF3A60FE44A9B0063B614 /* fields.png */, 912CF3A60FE44A9B0063B614 /* fields.png */,
@@ -1730,8 +1734,6 @@
912CF3AB0FE44A9B0063B614 /* mapOLD.png */, 912CF3AB0FE44A9B0063B614 /* mapOLD.png */,
912CF3AC0FE44A9B0063B614 /* missiles.png */, 912CF3AC0FE44A9B0063B614 /* missiles.png */,
912CF3AD0FE44A9B0063B614 /* monst1.png */, 912CF3AD0FE44A9B0063B614 /* monst1.png */,
912CF3AE0FE44A9B0063B614 /* monst10.png */,
912CF3AF0FE44A9B0063B614 /* monst11.png */,
912CF3B00FE44A9B0063B614 /* monst2.png */, 912CF3B00FE44A9B0063B614 /* monst2.png */,
912CF3B10FE44A9B0063B614 /* monst3.png */, 912CF3B10FE44A9B0063B614 /* monst3.png */,
912CF3B20FE44A9B0063B614 /* monst4.png */, 912CF3B20FE44A9B0063B614 /* monst4.png */,
@@ -1740,6 +1742,8 @@
912CF3B50FE44A9B0063B614 /* monst7.png */, 912CF3B50FE44A9B0063B614 /* monst7.png */,
912CF3B60FE44A9B0063B614 /* monst8.png */, 912CF3B60FE44A9B0063B614 /* monst8.png */,
912CF3B70FE44A9B0063B614 /* monst9.png */, 912CF3B70FE44A9B0063B614 /* monst9.png */,
912CF3AE0FE44A9B0063B614 /* monst10.png */,
912CF3AF0FE44A9B0063B614 /* monst11.png */,
912CF3B80FE44A9B0063B614 /* objects.png */, 912CF3B80FE44A9B0063B614 /* objects.png */,
912CF3B90FE44A9B0063B614 /* outhelp.png */, 912CF3B90FE44A9B0063B614 /* outhelp.png */,
912CF3BA0FE44A9B0063B614 /* pcedbuttons.png */, 912CF3BA0FE44A9B0063B614 /* pcedbuttons.png */,

View File

@@ -622,9 +622,11 @@ void redraw_screen(int refresh) {
draw_startup(0); draw_startup(0);
break; break;
case MODE_TALKING: case MODE_TALKING:
if(refresh & REFRESH_DLOG); // TODO: Should call place_talk_str, but we don't have the strings
refresh_talking(); refresh_talking();
break; break;
case MODE_SHOPPING: case MODE_SHOPPING:
if(refresh & REFRESH_DLOG) draw_shop_graphics(0,{0,0,0,0});
refresh_shopping(); refresh_shopping();
break; break;
default: default:

View File

@@ -8,8 +8,9 @@ enum {
REFRESH_INVEN = 1 << 2, REFRESH_INVEN = 1 << 2,
REFRESH_TRANS = 1 << 3, REFRESH_TRANS = 1 << 3,
REFRESH_BAR = 1 << 4, REFRESH_BAR = 1 << 4,
REFRESH_DLOG = 1 << 5,
REFRESH_TEXT = REFRESH_BAR | REFRESH_TRANS, REFRESH_TEXT = REFRESH_BAR | REFRESH_TRANS,
REFRESH_ALL = 0x1f REFRESH_ALL = 0x3f
}; };
void adjust_window_mode(); void adjust_window_mode();

View File

@@ -5,6 +5,7 @@
#include "boe.global.h" #include "boe.global.h"
#include "classes.h" #include "classes.h"
#include <thread>
#include "boe.graphics.h" #include "boe.graphics.h"
#include "boe.newgraph.h" #include "boe.newgraph.h"
#include "boe.fileio.h" #include "boe.fileio.h"
@@ -267,12 +268,16 @@ void Initialize(void)
text_sbar->setBounds(sbar_rect); text_sbar->setBounds(sbar_rect);
text_sbar->setMaximum(58); text_sbar->setMaximum(58);
text_sbar->setPosition(58); text_sbar->setPosition(58);
text_sbar->setPageSize(11);
item_sbar.reset(new cScrollbar(mainPtr)); item_sbar.reset(new cScrollbar(mainPtr));
item_sbar->setBounds(item_sbar_rect); item_sbar->setBounds(item_sbar_rect);
item_sbar->setMaximum(16); item_sbar->setMaximum(16);
item_sbar->setPageSize(8);
shop_sbar.reset(new cScrollbar(mainPtr)); shop_sbar.reset(new cScrollbar(mainPtr));
shop_sbar->setBounds(shop_sbar_rect); shop_sbar->setBounds(shop_sbar_rect);
shop_sbar->setMaximum(16); shop_sbar->setMaximum(16);
shop_sbar->setPageSize(8);
shop_sbar->hide();
adjust_window_mode(); 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 handleUpdateWhileScrolling(volatile bool& doneScrolling, int refresh) {
void sbar_action(cScrollbar& bar, short part) while(!doneScrolling) {
{ sf::sleep(sf::milliseconds(10));
short old_setting,new_setting,max; redraw_screen(refresh);
mainPtr.display();
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;
} }
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 // TODO: Pass the event object around instead of keeping a global one
void Mouse_Pressed() void Mouse_Pressed()
{ {
// TODO: What about other windows?
// sf::Window& the_window = mainPtr;
if (had_text_freeze > 0) { if (had_text_freeze > 0) {
had_text_freeze--; had_text_freeze--;
return; return;
} }
//ding(); if(overall_mode != MODE_STARTUP) {
// 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) location mousePos(event.mouseButton.x, event.mouseButton.y);
#if 0 volatile bool doneScrolling = false;
// TODO: Honestly, I'm not quite sure how to track the scrollbars right now if(mousePos.in(text_sbar->getBounds())) {
// if (the_window == mainPtr) { std::thread updater(std::bind(handleUpdateWhileScrolling, std::ref(doneScrolling), REFRESH_TRANS));
SetPortWindowPort(mainPtr); text_sbar->handleClick(mousePos);
GlobalToLocal(&event.where); doneScrolling = true;
content_part = FindControl(event.where,the_window,&control_hit); // hit sbar? updater.join();
if (content_part != 0) { redraw_screen(REFRESH_TRANS);
switch (content_part) { } else if(mousePos.in(item_sbar->getBounds())) {
case kControlIndicatorPart: std::thread updater(std::bind(handleUpdateWhileScrolling, std::ref(doneScrolling), REFRESH_INVEN));
content_part = TrackControl(control_hit,event.where,NULL); item_sbar->handleClick(mousePos);
if (control_hit == text_sbar) doneScrolling = true;
if (content_part == kControlIndicatorPart) updater.join();
print_buf(); redraw_screen(REFRESH_INVEN);
if (control_hit == item_sbar) } else if(overall_mode == MODE_SHOPPING && mousePos.in(shop_sbar->getBounds())) {
if (content_part == kControlIndicatorPart) std::thread updater(std::bind(handleUpdateWhileScrolling, std::ref(doneScrolling), REFRESH_DLOG));
put_item_screen(stat_window,0); shop_sbar->handleClick(mousePos);
if (control_hit == shop_sbar) doneScrolling = true;
if (content_part == kControlIndicatorPart) updater.join();
draw_shop_graphics(0,shop_sbar_rect); redraw_screen(REFRESH_DLOG);
break; } else All_Done = handle_action(event);
case kControlUpButtonPart: case kControlPageUpPart: case kControlDownButtonPart: case kControlPageDownPart: } else All_Done = handle_startup_press({event.mouseButton.x, event.mouseButton.y});
#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});
menu_activate(); menu_activate();

View File

@@ -549,6 +549,7 @@ void set_stat_window(short new_stat)
stat_window = new_stat; stat_window = new_stat;
if ((stat_window < 6) && (univ.party[stat_window].main_status != 1)) if ((stat_window < 6) && (univ.party[stat_window].main_status != 1))
stat_window = first_active_pc(); stat_window = first_active_pc();
item_sbar->setPageSize(8);
switch (stat_window) { switch (stat_window) {
case 6: case 6:
for (i = 0; i < 60; i++) for (i = 0; i < 60; i++)
@@ -563,6 +564,7 @@ void set_stat_window(short new_stat)
break; break;
case 7: case 7:
item_sbar->setMaximum(2); item_sbar->setMaximum(2);
item_sbar->setPageSize(2);
break; break;
default: default:
item_sbar->setMaximum(16); item_sbar->setMaximum(16);

View File

@@ -317,13 +317,12 @@ void cLedGroup::addChoice(cLed* ctrl, std::string key) {
choices[key] = ctrl; choices[key] = ctrl;
} }
bool cLedGroup::handleClick() { bool cLedGroup::handleClick(location where) {
location where = sf::Mouse::getPosition(*inWindow);
std::string which_clicked; std::string which_clicked;
ledIter iter = choices.begin(); ledIter iter = choices.begin();
while(iter != choices.end()){ while(iter != choices.end()){
if(iter->second->isVisible() && where.in(iter->second->getBounds())){ if(iter->second->isVisible() && where.in(iter->second->getBounds())){
if(iter->second->handleClick()) { if(iter->second->handleClick(where)) {
which_clicked = iter->first; which_clicked = iter->first;
break; break;
} }

View File

@@ -117,7 +117,7 @@ public:
sf::Color getColour() throw(xUnsupportedProp); sf::Color getColour() throw(xUnsupportedProp);
explicit cLedGroup(cDialog* parent); explicit cLedGroup(cDialog* parent);
bool isClickable(); bool isClickable();
bool handleClick(); bool handleClick(location where);
virtual ~cLedGroup(); virtual ~cLedGroup();
cLed& operator[](std::string id); cLed& operator[](std::string id);
void setSelected(std::string id); void setSelected(std::string id);

View File

@@ -178,18 +178,14 @@ void cControl::setActive(bool active) {
depressed = active; depressed = active;
} }
bool cControl::handleClick(){ bool cControl::handleClick(location where){
sf::Event e; sf::Event e;
bool done = false, clicked = false; bool done = false, clicked = false;
inWindow->setActive(); inWindow->setActive();
depressed = true; depressed = true;
while(!done){ while(!done){
// If there's no parent dialog, we're not responsible for redrawing
if(parent) parent->draw(); 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(!inWindow->pollEvent(e)) continue;
if(e.type == sf::Event::MouseButtonReleased){ if(e.type == sf::Event::MouseButtonReleased){
done = true; done = true;
@@ -207,11 +203,6 @@ bool cControl::handleClick(){
} }
else sf::sleep(time_in_ticks(14)); else sf::sleep(time_in_ticks(14));
if(parent) parent->draw(); 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; return clicked;
} }

View File

@@ -98,7 +98,7 @@ public:
virtual void setColour(sf::Color clr) throw(xUnsupportedProp) = 0; virtual void setColour(sf::Color clr) throw(xUnsupportedProp) = 0;
virtual sf::Color getColour() throw(xUnsupportedProp) = 0; virtual sf::Color getColour() throw(xUnsupportedProp) = 0;
virtual bool isClickable() = 0; virtual bool isClickable() = 0;
virtual bool handleClick(); virtual bool handleClick(location where);
cControl(eControlType t, sf::RenderWindow& p); cControl(eControlType t, sf::RenderWindow& p);
cControl(eControlType t, cDialog& p); cControl(eControlType t, cDialog& p);
virtual ~cControl(); virtual ~cControl();

View File

@@ -18,6 +18,7 @@ using namespace ticpp;
#include "button.h" #include "button.h"
#include "field.h" #include "field.h"
#include "message.h" #include "message.h"
#include "scrollbar.h"
#include "winutil.h" #include "winutil.h"
#include "mathutil.h" #include "mathutil.h"
@@ -860,6 +861,7 @@ void cDialog::init(){
cButton::init(); cButton::init();
cLed::init(); cLed::init();
cPict::init(); cPict::init();
cScrollbar::init();
} }
cDialog::~cDialog(){ cDialog::~cDialog(){
@@ -1188,7 +1190,7 @@ std::string cDialog::process_click(location where, eKeyMod mods){
ctrlIter iter = controls.begin(); ctrlIter iter = controls.begin();
while(iter != controls.end()){ while(iter != controls.end()){
if(iter->second->isVisible() && iter->second->isClickable() && where.in(iter->second->getBounds())){ if(iter->second->isVisible() && iter->second->isClickable() && where.in(iter->second->getBounds())){
if(iter->second->handleClick()) if(iter->second->handleClick(where))
return iter->first; return iter->first;
else return ""; else return "";
} }

View File

@@ -61,6 +61,8 @@ short cTextMsg::getFormat(eFormat prop) throw(xUnsupportedProp){
switch(prop){ switch(prop){
case TXT_FRAME: case TXT_FRAME:
return drawFramed; return drawFramed;
case TXT_FRAMESTYLE:
return frameStyle;
case TXT_SIZE: case TXT_SIZE:
return textSize; return textSize;
case TXT_FONT: case TXT_FONT:

View File

@@ -7,22 +7,34 @@
// //
#include "scrollbar.h" #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(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(){ bool cScrollbar::isClickable(){
return true; return true;
} }
void cScrollbar::setPosition(long newPos) { void cScrollbar::setPosition(long newPos) {
if(newPos > max) pos = max; pos = minmax(0,max,pos);
else pos = newPos;
} }
void cScrollbar::setMaximum(long newMax) { void cScrollbar::setMaximum(long newMax) {
max = newMax; max = ::max(1,newMax);
}
void cScrollbar::setPageSize(long newSize) {
pgsz = newSize;
} }
long cScrollbar::getPosition() { long cScrollbar::getPosition() {
@@ -33,6 +45,10 @@ long cScrollbar::getMaximum() {
return max; return max;
} }
long cScrollbar::getPageSize() {
return pgsz;
}
void cScrollbar::attachClickHandler(click_callback_t f) throw(xHandlerNotSupported) { void cScrollbar::attachClickHandler(click_callback_t f) throw(xHandlerNotSupported) {
onClick = f; onClick = f;
} }
@@ -47,6 +63,74 @@ bool cScrollbar::triggerClickHandler(cDialog& me, std::string id, eKeyMod mods,
return false; 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) { void cScrollbar::setFormat(eFormat prop, short val) throw(xUnsupportedProp) {
throw xUnsupportedProp(prop); throw xUnsupportedProp(prop);
} }
@@ -65,5 +149,41 @@ sf::Color cScrollbar::getColour() throw(xUnsupportedProp) {
} }
void cScrollbar::draw() { 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);
} }

View File

@@ -12,14 +12,24 @@
#include "control.h" #include "control.h"
class cScrollbar : public cControl { 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; click_callback_t onClick;
static sf::Texture scroll_gw;
public: public:
static void init();
explicit cScrollbar(sf::RenderWindow& parent); explicit cScrollbar(sf::RenderWindow& parent);
explicit cScrollbar(cDialog& parent); explicit cScrollbar(cDialog& parent);
void attachClickHandler(click_callback_t f) throw(xHandlerNotSupported); void attachClickHandler(click_callback_t f) throw(xHandlerNotSupported);
void attachFocusHandler(focus_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 triggerClickHandler(cDialog& me, std::string id, eKeyMod mods, location where);
bool handleClick(location where);
void setFormat(eFormat prop, short val) throw(xUnsupportedProp); void setFormat(eFormat prop, short val) throw(xUnsupportedProp);
short getFormat(eFormat prop) throw(xUnsupportedProp); short getFormat(eFormat prop) throw(xUnsupportedProp);
void setColour(sf::Color clr) throw(xUnsupportedProp); void setColour(sf::Color clr) throw(xUnsupportedProp);
@@ -27,8 +37,10 @@ public:
bool isClickable(); bool isClickable();
long getPosition(); long getPosition();
long getMaximum(); long getMaximum();
long getPageSize();
void setPosition(long to); void setPosition(long to);
void setMaximum(long to); void setMaximum(long to);
void setPageSize(long to);
void draw(); void draw();
}; };