Files
oboe/osx/dialogxml/button.cpp
Celtic Minstrel 6af129c277 - Nuked the storage_gworld and party_template_gworld. Monster, terrain, and PC graphics are now drawn directly from their sheets of origin. This is partly tested, and seems to work fine.
- Removed the terrain_pic and terrain_blockage arrays, which were redundant (though shorter).
- Cleaned out some of the commented code in boe.graphics.cpp and boe.graphutil.cpp
- Added a templated get function to cOutdoors::cWandering.
In the dialog engine:
- Important fields are now initialized to default values, as they should be.
- The absence of required attributes is now recognized as an error
- Added stack element to the DTD; no code support yet
- Added fore attribute to the dialog element to specify default text colour; DTD updated and code support added.
- Likewise with the def-key attribute on other clickable items besides buttons (which already had it)
- Updated stylesheet to fall back on the fore attribute when colour is unspecified
- When drawing default monster graphics, it uses m_start_pic instead of num as the index. This should be right, though it's untested.
Unfortunately, the dialog engine is still unstable.

git-svn-id: http://openexile.googlecode.com/svn/trunk@100 4ebdad44-0ea0-11de-aab3-ff745001d230
2009-06-28 17:18:24 +00:00

435 lines
11 KiB
C++

/*
* button.cpp
* BoE
*
* Created by Celtic Minstrel on 11/05/09.
*
*/
#include <Carbon/Carbon.h>
#include <vector>
#include <map>
#include <stdexcept>
#include "dialog.h"
#include "graphtool.h"
#include <cmath>
extern GWorldPtr bg_gworld;
void cButton::attachFocusHandler(focus_callback_t f __attribute__((unused))) throw(xHandlerNotSupported){
throw xHandlerNotSupported(true);
}
void cButton::attachClickHandler(click_callback_t f) throw(){
onClick = f;
}
bool cButton::triggerClickHandler(cDialog& me, std::string id, eKeyMod mods, Point where){
if(onClick != NULL) return onClick(me,id,mods);
return false;
}
cButton::cButton(cDialog* parent) :
cControl(parent,CTRL_BTN),
wrapLabel(false),
fromList("none") {}
cButton::cButton(cDialog* parent,eControlType t) :
cControl(parent,t),
fromList("none"),
wrapLabel("true") {/* This constructor is only called for LEDs. TODO: Should wrapLabel be true for LEDs? */}
bool cButton::isClickable(){
return true;
}
void cButton::draw(){
GrafPtr old_port;
Rect from_rect, to_rect;
GWorldPtr from_gw, to_gw;
GetPort(&old_port);
SetPortWindowPort(parent->win);
if(visible){
TextFont(font_nums[GENEVA]);
if(foundSilom())TextFace(normal);
else TextFace(bold);
if(type == BTN_TINY) TextSize(9);
else if(type == BTN_PUSH) TextSize(10);
else TextSize(12);
from_gw = buttons[btnGW[type]];
from_rect = btnRects[btnGW[type]][depressed];
to_rect = frame;
rect_draw_some_item(from_gw,from_rect,to_rect,(Point){0,0}); // TODO: This originally drew to dest 2 (dialog window); does it still?
RGBForeColor(&parent->defTextClr);
char_win_draw_string(parent->win,to_rect,lbl.c_str(),1,8);
// TODO: Adjust string location as appropriate
// Tiny button string location should be shifted right 20 pixels (or possibly 18)
// Push button string should be centred below the button
// Others may need adjustments too, not sure
ForeColor(blackColor);
if(key.spec && key.k == key_enter) drawFrame(2,0); // frame default button, to provide a visual cue that it's the default
}else{
tileImage(frame,bg_gworld,bg[parent->bg]);
}
SetPort(old_port);
}
void cButton::setFormat(eFormat prop, short val) throw(xUnsupportedProp){
if(prop == TXT_WRAP) wrapLabel = val;
else throw xUnsupportedProp(prop);
if(isVisible()) draw();
}
short cButton::getFormat(eFormat prop) throw(xUnsupportedProp){
if(prop == TXT_WRAP) return wrapLabel;
else throw xUnsupportedProp(prop);
}
// Indices within the buttons array.
size_t cButton::btnGW[14] = {
0, // BTN_SM
1, // BTN_REG
2, // BTN_LG
4, // BTN_HELP
1, // BTN_LEFT
1, // BTN_RIGHT
1, // BTN_UP
1, // BTN_DOWN
5, // BTN_TINY
1, // BTN_DONE
3, // BTN_TALL
3, // BTN_TRAIT
6, // BTN_PUSH
5, // BTN_LED
};
GWorldPtr cButton::buttons[7] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL};
Rect cButton::btnRects[13][2];
void cButton::init(){
static const char*const buttonFiles[7] = {
"dlogbtnsm.png",
"dlogbtnmed.png",
"dlogbtnlg.png",
"dlogbtntall.png",
"dlogbtnhelp.png",
"dlogbtnled.png",
"dlogbtnred.png"
};
for(int i = 0; i < 7; i++)
buttons[i] = load_pict(buttonFiles[i]);
SetRect(&btnRects[BTN_SM][0],0,0,23,23);
SetRect(&btnRects[BTN_REG][0],0,0,63,23);
SetRect(&btnRects[BTN_LEFT][0],0,23,63,46);
SetRect(&btnRects[BTN_RIGHT][0],0,46,63,69);
SetRect(&btnRects[BTN_UP][0],0,69,63,92);
SetRect(&btnRects[BTN_DOWN][0],0,92,63,115);
SetRect(&btnRects[BTN_DONE][0],0,115,63,138);
SetRect(&btnRects[BTN_LG][0],0,0,104,23);
SetRect(&btnRects[BTN_HELP][0],0,0,16,13);
SetRect(&btnRects[BTN_TINY][0],42,0,56,10);
SetRect(&btnRects[BTN_TALL][0],0,0,63,40);
SetRect(&btnRects[BTN_TRAIT][0],0,40,63,80);
SetRect(&btnRects[BTN_PUSH][0],0,0,30,30);
for(int j = 0; j < 12; j++)
btnRects[j][1] = btnRects[j][0];
OffsetRect(&btnRects[BTN_SM][1],23,0);
OffsetRect(&btnRects[BTN_REG][1],63,0);
OffsetRect(&btnRects[BTN_LEFT][1],63,0);
OffsetRect(&btnRects[BTN_RIGHT][1],63,0);
OffsetRect(&btnRects[BTN_UP][1],63,0);
OffsetRect(&btnRects[BTN_DOWN][1],63,0);
OffsetRect(&btnRects[BTN_DONE][1],63,0);
OffsetRect(&btnRects[BTN_LG][1],104,0);
OffsetRect(&btnRects[BTN_HELP][1],16,0);
OffsetRect(&btnRects[BTN_TINY][1],0,10);
OffsetRect(&btnRects[BTN_TALL][1],63,0);
OffsetRect(&btnRects[BTN_TRAIT][1],63,0);
OffsetRect(&btnRects[BTN_PUSH][1],30,0);
}
void cButton::finalize(){
for(int i = 0; i < 7; i++)
DisposeGWorld(buttons[i]);
}
Rect cLed::ledRects[3][2];
void cLed::init(){
Rect baseLed = {0,0,10,14};
for(int i = 0; i < 3; i++)
for(int j = 0; j < 2; j++){
ledRects[i][j] = baseLed;
OffsetRect(&ledRects[i][j],i * 14, j * 10);
}
}
cLed::cLed(cDialog* parent) :
cButton(parent,CTRL_LED),
state(led_off),
textFont(SILOM),
textSize(10),
color(parent->defTextClr) {}
void cLed::attachClickHandler(click_callback_t f) throw(){
onClick = f;
}
void cLed::attachFocusHandler(focus_callback_t f) throw(){
onFocus = f;
}
bool cLed::triggerFocusHandler(cDialog& me, std::string id, bool losing){
if(onFocus != NULL) return onFocus(me,id,losing);
return true;
}
bool cLed::triggerClickHandler(cDialog& me, std::string id, eKeyMod mods, Point where){
bool result;
eLedState oldState = state;
if(onClick != NULL) result = onClick(me,id,mods);
else{ // simple state toggle
switch(state){
case led_red:
case led_green:
state = led_off;
break;
case led_off:
state = led_red;
}
result = true;
}
if(!triggerFocusHandler(me,id, oldState != led_off)){
result = false;
state = oldState;
}
return result;
}
void cLed::setFormat(eFormat prop __attribute__((unused)), short val __attribute__((unused))) throw(xUnsupportedProp){
throw xUnsupportedProp(prop);
}
short cLed::getFormat(eFormat prop __attribute__((unused))) throw(xUnsupportedProp){
throw xUnsupportedProp(prop);
}
void cLed::draw(){
GrafPtr old_port;
Rect from_rect, to_rect;
GWorldPtr from_gw, to_gw;
GetPort(&old_port);
SetPortWindowPort(parent->win);
if(visible){
TextFont(font_nums[GENEVA]);
if(foundSilom())TextFace(normal);
else TextFace(bold);
TextSize(9);
from_gw = buttons[btnGW[BTN_LED]];
from_rect = ledRects[state][depressed];
to_rect = frame;
rect_draw_some_item(from_gw,from_rect,to_rect,(Point){0,0});
RGBForeColor(&parent->defTextClr);
char_win_draw_string(parent->win,to_rect,lbl.c_str(),1,8);
// TODO: Adjust string location as appropriate
// String location should be shifted right 20 pixels (or possibly 18)
ForeColor(blackColor);
}else{
tileImage(frame,bg_gworld,bg[parent->bg]);
}
SetPort(old_port);
}
cLedGroup::cLedGroup(cDialog* parent) :
cControl(parent,CTRL_GROUP),
fromList("none") {}
cButton::~cButton() {}
cLed::~cLed() {}
cLedGroup::~cLedGroup(){
ledIter iter = choices.begin();
while(iter != choices.end()){
delete iter->second;
iter++;
}
}
void cLedGroup::recalcRect(){
ledIter iter = choices.begin();
while(iter != choices.end()){
if(iter->second->frame.right > frame.right)
frame.right = iter->second->frame.right;
if(iter->second->frame.bottom > frame.bottom)
frame.bottom = iter->second->frame.bottom;
iter++;
}
frame.right += 6;
frame.bottom += 6;
}
/** A click handler is called whenever a click is received, even on the currently selected element. */
void cLedGroup::attachClickHandler(click_callback_t f) throw() {
onClick = f;
}
/** A focus handler is called when the currently selected element changes. */
void cLedGroup::attachFocusHandler(focus_callback_t f) throw() {
onFocus = f;
}
void cLed::setState(eLedState to){
state = to;
}
eLedState cLed::getState(){
return state;
}
bool cLedGroup::triggerClickHandler(cDialog& me, std::string id, eKeyMod mods, Point where){
std::string which_clicked;
ledIter iter = choices.begin();
while(iter != choices.end()){
if(iter->second->visible && PtInRect(where,&iter->second->frame)){
if(iter->second->handleClick())
which_clicked = iter->first;
}
iter++;
}
if(which_clicked == "") return false;
if(choices[which_clicked]->triggerClickHandler(me,which_clicked,mods,where)){
eLedState a, b;
a = choices[curSelect]->getState();
b = choices[which_clicked]->getState();
choices[curSelect]->setState(led_off);
choices[which_clicked]->setState(led_red);
if(!choices[curSelect]->triggerFocusHandler(me,curSelect,true)){
choices[curSelect]->setState(a);
choices[which_clicked]->setState(b);
return false;
}
if(!choices[which_clicked]->triggerFocusHandler(me,which_clicked,false)){
choices[curSelect]->setState(a);
choices[which_clicked]->setState(b);
return false;
}
curSelect = which_clicked;
}else return false;
return triggerFocusHandler(me,id,false);
}
bool cLedGroup::triggerFocusHandler(cDialog& me, std::string id, bool losingFocus){
if(onFocus != NULL) return onFocus(me,id,losingFocus);
return true;
}
void cLedGroup::disable(std::string id) {
// TODO: Implement this
}
void cLedGroup::enable(std::string id) {
// TODO: Implement this
}
void cLedGroup::show(std::string id){
choices[id]->show();
}
void cLedGroup::hide(std::string id){
choices[id]->hide();
}
void cLedGroup::setFormat(eFormat prop __attribute__((unused)), short val __attribute__((unused))) throw(xUnsupportedProp) {
throw xUnsupportedProp(prop);
}
short cLedGroup::getFormat(eFormat prop __attribute__((unused))) throw(xUnsupportedProp) {
throw xUnsupportedProp(prop);
}
bool cLedGroup::isClickable(){
return true;
}
cLed& cLedGroup::operator[](std::string id){
ledIter iter = choices.find(id);
if(iter == choices.end()) throw std::invalid_argument(id + " does not exist in the ledgroup.");
return *(iter->second);
}
void cLedGroup::setSelected(std::string id){
if(id == "") { // deselect all
eLedState was = choices[curSelect]->getState();
choices[curSelect]->setState(led_off);
if(choices[curSelect]->triggerFocusHandler(*parent,curSelect,true))
curSelect = "";
else
choices[curSelect]->setState(was);
return;
}
ledIter iter = choices.find(id);
if(iter == choices.end()) throw std::invalid_argument(id + " does not exist in the ledgroup.");
if(curSelect == ""){
if(iter->second->triggerFocusHandler(*parent,curSelect,false)){
iter->second->setState(led_red);
curSelect = iter->first;
}
}else{
eLedState a, b;
a = choices[curSelect]->getState();
b = iter->second->getState();
choices[curSelect]->setState(led_off);
iter->second->setState(led_red);
if(!choices[curSelect]->triggerFocusHandler(*parent,curSelect,true)){
choices[curSelect]->setState(a);
iter->second->setState(b);
return;
}
if(!iter->second->triggerFocusHandler(*parent,curSelect,false)){
choices[curSelect]->setState(a);
iter->second->setState(b);
return;
}
curSelect = iter->first;
}
}
std::string cLedGroup::getSelected(){
return curSelect;
}
std::string cLedGroup::getPrevSelection(){
return prevSelect;
}
void cLedGroup::draw(){
ledIter iter = choices.begin();
while(iter != choices.end()){
iter->second->draw();
iter++;
}
}
void cButton::setType(eBtnType newType){
if(type == BTN_LED) return; // can't change type
type = newType;
}
eBtnType cButton::getType(){
return type;
}