New scroll pane control in the dialog engine
Also: - Use a scroll pane for the credits in the about dialog, so that new credits can be added without altering other elements - Use a scroll pane for the list of sections to be deleted in the resize outdoors dialog - New cContainer superclass for controls that contain other controls - Scrollbars consider their maximum as part of their state
This commit is contained in:
@@ -141,6 +141,9 @@
|
||||
919B13A21BBCDF14009905A4 /* monst_legacy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 919B13A11BBCDE18009905A4 /* monst_legacy.cpp */; };
|
||||
919B13A41BBD8854009905A4 /* item_legacy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 919B13A31BBD8849009905A4 /* item_legacy.cpp */; };
|
||||
919B13A61BBDE986009905A4 /* spec_legacy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 919B13A51BBDE985009905A4 /* spec_legacy.cpp */; };
|
||||
919B13AA1BBE2B71009905A4 /* scrollpane.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 919B13A81BBE2B54009905A4 /* scrollpane.cpp */; };
|
||||
919B13AB1BBE2B71009905A4 /* scrollpane.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 919B13A81BBE2B54009905A4 /* scrollpane.cpp */; };
|
||||
919B13AC1BBE2B71009905A4 /* scrollpane.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 919B13A81BBE2B54009905A4 /* scrollpane.cpp */; };
|
||||
919CC2481B3772F300273FDA /* creatlist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91AC620A0FA2853700EEAE67 /* creatlist.cpp */; };
|
||||
919CC2491B3772FB00273FDA /* creature.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 914698FE1A747C4500F20F5E /* creature.cpp */; };
|
||||
919CC24B1B37730300273FDA /* item.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91279D3D0F9D1D6A007B0D52 /* item.cpp */; };
|
||||
@@ -665,6 +668,8 @@
|
||||
919B13A11BBCDE18009905A4 /* monst_legacy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = monst_legacy.cpp; sourceTree = "<group>"; };
|
||||
919B13A31BBD8849009905A4 /* item_legacy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = item_legacy.cpp; sourceTree = "<group>"; };
|
||||
919B13A51BBDE985009905A4 /* spec_legacy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = spec_legacy.cpp; sourceTree = "<group>"; };
|
||||
919B13A71BBE297B009905A4 /* scrollpane.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = scrollpane.hpp; sourceTree = "<group>"; };
|
||||
919B13A81BBE2B54009905A4 /* scrollpane.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scrollpane.cpp; sourceTree = "<group>"; };
|
||||
919DDBFA19006CC9003E7FED /* libboost_filesystem.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libboost_filesystem.dylib; path = /usr/local/lib/libboost_filesystem.dylib; sourceTree = "<absolute>"; };
|
||||
919DDBFB19006CC9003E7FED /* libboost_system.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libboost_system.dylib; path = /usr/local/lib/libboost_system.dylib; sourceTree = "<absolute>"; };
|
||||
919DDC091900750D003E7FED /* freetype.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = freetype.framework; path = ../../../../../../Library/Frameworks/freetype.framework; sourceTree = "<group>"; };
|
||||
@@ -939,6 +944,7 @@
|
||||
910BBAA80FB8F733001E34EA /* pict.hpp */,
|
||||
913FB40A1A5C90840067B9D2 /* pictypes.hpp */,
|
||||
919145FD18E3C750005CF3A4 /* scrollbar.hpp */,
|
||||
919B13A71BBE297B009905A4 /* scrollpane.hpp */,
|
||||
9179A4631A4867E200FEF872 /* stack.hpp */,
|
||||
);
|
||||
name = headers;
|
||||
@@ -955,6 +961,7 @@
|
||||
910BBAB90FB91ADB001E34EA /* message.cpp */,
|
||||
910BBAA90FB8F733001E34EA /* pict.cpp */,
|
||||
9191460018E63D8E005CF3A4 /* scrollbar.cpp */,
|
||||
919B13A81BBE2B54009905A4 /* scrollpane.cpp */,
|
||||
9179A4641A48681800FEF872 /* stack.cpp */,
|
||||
);
|
||||
name = src;
|
||||
@@ -1733,6 +1740,7 @@
|
||||
912DFE8F18E2872400B00D75 /* boe.menus.mac.mm in Sources */,
|
||||
919145FC18E3AB1B005CF3A4 /* boe.appleevents.mm in Sources */,
|
||||
915325171A2E1DF0000A9A1C /* oldstructs.cpp in Sources */,
|
||||
919B13AC1BBE2B71009905A4 /* scrollpane.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -1814,6 +1822,7 @@
|
||||
91C6864A0FD5EEFD000F6D01 /* pc.graphics.cpp in Sources */,
|
||||
91FCC8DC18FE2CE8007026CE /* pc.menus.mac.mm in Sources */,
|
||||
91FCC8F418FF0866007026CE /* pc.appleevents.mm in Sources */,
|
||||
919B13AB1BBE2B71009905A4 /* scrollpane.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -1831,6 +1840,7 @@
|
||||
91B3F1850F97894A00BF5B67 /* scen.graphics.cpp in Sources */,
|
||||
914CA45819074E0100B6ADD1 /* scen.menus.mac.mm in Sources */,
|
||||
91034D211B225E4A008F01C1 /* scen.appleevents.mm in Sources */,
|
||||
919B13AA1BBE2B71009905A4 /* scrollpane.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@@ -96,7 +96,7 @@ bool rectangle::contains(int x, int y) {
|
||||
rectangle_size_delegate::rectangle_size_delegate(rectangle& rect, int rectangle::* first, int rectangle::* last) :
|
||||
forRect(rect), b1(first), b2(last) {}
|
||||
|
||||
rectangle_size_delegate::operator int() {
|
||||
rectangle_size_delegate::operator int() const {
|
||||
return forRect.*b2 - forRect.*b1;
|
||||
}
|
||||
|
||||
@@ -125,6 +125,26 @@ rectangle_size_delegate& rectangle_size_delegate::operator/=(int val) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
rectangle_size_delegate& rectangle_size_delegate::operator=(const rectangle_size_delegate& val) {
|
||||
return operator=(int(val));
|
||||
}
|
||||
|
||||
rectangle_size_delegate& rectangle_size_delegate::operator+=(const rectangle_size_delegate& val) {
|
||||
return operator+=(int(val));
|
||||
}
|
||||
|
||||
rectangle_size_delegate& rectangle_size_delegate::operator-=(const rectangle_size_delegate& val) {
|
||||
return operator-=(int(val));
|
||||
}
|
||||
|
||||
rectangle_size_delegate& rectangle_size_delegate::operator*=(const rectangle_size_delegate& val) {
|
||||
return operator*=(int(val));
|
||||
}
|
||||
|
||||
rectangle_size_delegate& rectangle_size_delegate::operator/=(const rectangle_size_delegate& val) {
|
||||
return operator/=(int(val));
|
||||
}
|
||||
|
||||
rectangle_size_delegate rectangle::width() {
|
||||
return rectangle_size_delegate(*this, &rectangle::left, &rectangle::right);
|
||||
}
|
||||
|
@@ -40,12 +40,17 @@ class rectangle_size_delegate {
|
||||
int rectangle::* b2;
|
||||
rectangle_size_delegate(rectangle& rect, int rectangle::* first, int rectangle::* last);
|
||||
public:
|
||||
operator int();
|
||||
operator int() const;
|
||||
rectangle_size_delegate& operator=(int val);
|
||||
rectangle_size_delegate& operator+=(int val);
|
||||
rectangle_size_delegate& operator-=(int val);
|
||||
rectangle_size_delegate& operator*=(int val);
|
||||
rectangle_size_delegate& operator/=(int val);
|
||||
rectangle_size_delegate& operator=(const rectangle_size_delegate& val);
|
||||
rectangle_size_delegate& operator+=(const rectangle_size_delegate& val);
|
||||
rectangle_size_delegate& operator-=(const rectangle_size_delegate& val);
|
||||
rectangle_size_delegate& operator*=(const rectangle_size_delegate& val);
|
||||
rectangle_size_delegate& operator/=(const rectangle_size_delegate& val);
|
||||
};
|
||||
|
||||
struct rectangle {
|
||||
|
@@ -439,7 +439,7 @@ void cLed::restore(storage_t to) {
|
||||
}
|
||||
|
||||
cLedGroup::cLedGroup(cDialog& parent) :
|
||||
cControl(CTRL_GROUP,parent),
|
||||
cContainer(CTRL_GROUP,parent),
|
||||
fromList("none") {}
|
||||
|
||||
cButton::~cButton() {}
|
||||
@@ -691,7 +691,7 @@ bool cLedGroup::isClickable(){
|
||||
return true;
|
||||
}
|
||||
|
||||
cLed& cLedGroup::operator[](std::string id){
|
||||
cLed& cLedGroup::getChild(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);
|
||||
|
@@ -160,8 +160,7 @@ private:
|
||||
/// so calling the LED group's getSelected() method will still return the previous selection.
|
||||
/// However, when the focus handler of the LED group is called, the selection _has_ been updated.,
|
||||
/// so getSelected() will return the new selection. (This is the reason for the getPreviousSelection() method.)
|
||||
class cLedGroup : public cControl {
|
||||
std::vector<cLed> btns;
|
||||
class cLedGroup : public cContainer {
|
||||
click_callback_t onClick;
|
||||
focus_callback_t onFocus;
|
||||
std::map<std::string,cLed*> choices;
|
||||
@@ -220,7 +219,7 @@ public:
|
||||
/// @param id The unique key of the choice.
|
||||
/// @return A reference to the LED object.
|
||||
/// @throw std::invalid_argument if the choice does not exist in the group.
|
||||
cLed& operator[](std::string id);
|
||||
cLed& getChild(std::string id);
|
||||
/// Set the currently selected LED in this group.
|
||||
/// @param id The unique key of the choice.
|
||||
/// @throw std::invalid_argument if the choice does not exist in the group.
|
||||
|
@@ -47,6 +47,7 @@ enum eControlType {
|
||||
CTRL_GROUP, ///< A LED radiobutton-like group
|
||||
CTRL_STACK, ///< A group of controls that represents one element in an array
|
||||
CTRL_SCROLL,///< A scrollbar
|
||||
CTRL_PANE, ///< A scroll pane
|
||||
};
|
||||
|
||||
/// The signature of a click handler.
|
||||
@@ -146,6 +147,9 @@ public:
|
||||
/// Check if this control is visible.
|
||||
/// @return true if it's visible
|
||||
bool isVisible(); // cd_get_active
|
||||
/// Check if this control is a container which contains other controls.
|
||||
/// @return true if it's a container
|
||||
virtual bool isContainer() {return false;}
|
||||
/// Set if this control is active. A control is normally active when the mouse button is held down within its bounding rect.
|
||||
/// @param active true if it should be active, false if not
|
||||
void setActive(bool active); // "active" here means "selected", so if it's a button, draw it pressed
|
||||
@@ -272,4 +276,24 @@ private:
|
||||
eControlType type;
|
||||
};
|
||||
|
||||
class cContainer : public cControl {
|
||||
public:
|
||||
/// Create a new container control attached to an arbitrary window, rather than a dialog.
|
||||
/// @param t The type of the control.
|
||||
/// @param p The parent window.
|
||||
cContainer(eControlType t, sf::RenderWindow& p) : cControl(t, p) {}
|
||||
/// Create a new container control attached to a dialog.
|
||||
/// @param t The type of the control.
|
||||
/// @param p The parent dialog.
|
||||
cContainer(eControlType t, cDialog& p) : cControl(t, p) {}
|
||||
/// Get a reference to a child control.
|
||||
/// @param id The unique key of the control.
|
||||
/// @throw std::invalid_argument if the control does not exist.
|
||||
/// @return a reference to the requested control.
|
||||
virtual cControl& getChild(std::string id) = 0;
|
||||
/// @copydoc getChild()
|
||||
cControl& operator[](std::string id) {return getChild(id);}
|
||||
bool isContainer() {return true;}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -18,6 +18,7 @@ using namespace ticpp;
|
||||
#include "field.hpp"
|
||||
#include "message.hpp"
|
||||
#include "scrollbar.hpp"
|
||||
#include "scrollpane.hpp"
|
||||
#include "stack.hpp"
|
||||
#include "winutil.hpp"
|
||||
#include "mathutil.hpp"
|
||||
@@ -241,6 +242,11 @@ void cDialog::loadFromFile(std::string path){
|
||||
controls.insert(parsed);
|
||||
// Now, if it contains any fields, their tab order must be accounted for
|
||||
parsed.second->fillTabOrder(specificTabs, reverseTabs);
|
||||
} else if(type == "pane") {
|
||||
auto parsed = parse<cScrollPane>(*node);
|
||||
controls.insert(parsed);
|
||||
// TODO: Now, if it contains any fields, their tab order must be accounted for
|
||||
//parsed.second->fillTabOrder(specificTabs, reverseTabs);
|
||||
} else throw xBadNode(type,node->Row(),node->Column(),fname);
|
||||
}
|
||||
// Sort by tab order
|
||||
@@ -903,10 +909,10 @@ cControl& cDialog::getControl(std::string id) {
|
||||
|
||||
iter = controls.begin();
|
||||
while(iter != controls.end()){
|
||||
if(iter->second->getType() == CTRL_GROUP){
|
||||
if(iter->second->isContainer()){
|
||||
try{
|
||||
cLedGroup* tmp = (cLedGroup*) (iter->second);
|
||||
return tmp->operator[](id);
|
||||
cContainer* tmp = (cContainer*) (iter->second);
|
||||
return tmp->getChild(id);
|
||||
}catch(std::invalid_argument) {}
|
||||
}
|
||||
iter++;
|
||||
|
@@ -13,7 +13,7 @@
|
||||
|
||||
sf::Texture cScrollbar::scroll_gw;
|
||||
|
||||
cScrollbar::cScrollbar(cDialog& parent) : cControl(CTRL_SCROLL, parent) {}
|
||||
cScrollbar::cScrollbar(cDialog& parent) : cControl(CTRL_SCROLL, parent), pos(0), max(0), pgsz(10) {}
|
||||
|
||||
cScrollbar::cScrollbar(sf::RenderWindow& parent) : cControl(CTRL_SCROLL, parent), pos(0), max(0), pgsz(10) {}
|
||||
|
||||
@@ -210,6 +210,7 @@ std::string cScrollbar::parse(ticpp::Element& who, std::string fname) {
|
||||
cControl::storage_t cScrollbar::store() {
|
||||
storage_t storage = cControl::store();
|
||||
storage["scroll-pos"] = pos;
|
||||
storage["scroll-max"] = max;
|
||||
return storage;
|
||||
}
|
||||
|
||||
@@ -217,5 +218,7 @@ void cScrollbar::restore(storage_t to) {
|
||||
cControl::restore(to);
|
||||
if(to.find("scroll-pos") != to.end())
|
||||
pos = boost::any_cast<int>(to["scroll-pos"]);
|
||||
if(to.find("scroll-max") != to.end())
|
||||
pos = boost::any_cast<int>(to["scroll-max"]);
|
||||
else pos = 0;
|
||||
}
|
||||
|
@@ -63,7 +63,7 @@ public:
|
||||
/// in the area between the arrow buttons and the scrollbar thumb.
|
||||
long getPageSize();
|
||||
/// Set the scrollbar thumb's current position.
|
||||
/// @param to The current position.
|
||||
/// @param to The new position.
|
||||
void setPosition(long to);
|
||||
/// Set the scrollbar thumb's maximum value.
|
||||
/// @param to The maximum value.
|
||||
|
228
src/dialogxml/scrollpane.cpp
Normal file
228
src/dialogxml/scrollpane.cpp
Normal file
@@ -0,0 +1,228 @@
|
||||
//
|
||||
// scrollpane.cpp
|
||||
// BoE
|
||||
//
|
||||
// Created by Celtic Minstrel on 15-10-01.
|
||||
//
|
||||
//
|
||||
|
||||
#include "scrollpane.hpp"
|
||||
#include "message.hpp"
|
||||
#include "field.hpp"
|
||||
#include "button.hpp"
|
||||
#include "pict.hpp"
|
||||
#include "stack.hpp"
|
||||
|
||||
cScrollPane::cScrollPane(cDialog& parent) : cContainer(CTRL_PANE, parent), scroll(parent) {
|
||||
recalcRect();
|
||||
}
|
||||
|
||||
void cScrollPane::attachClickHandler(click_callback_t) throw(xHandlerNotSupported) {
|
||||
throw xHandlerNotSupported(false);
|
||||
}
|
||||
|
||||
void cScrollPane::attachFocusHandler(focus_callback_t) throw(xHandlerNotSupported) {
|
||||
throw xHandlerNotSupported(true);
|
||||
}
|
||||
|
||||
bool cScrollPane::triggerClickHandler(cDialog&, std::string, eKeyMod) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cScrollPane::handleClick(location where) {
|
||||
if(scroll.getBounds().contains(where))
|
||||
return scroll.handleClick(where);
|
||||
where.y += scroll.getPosition();
|
||||
for(auto& ctrl : contents) {
|
||||
if(ctrl.second->isClickable() && ctrl.second->getBounds().contains(where))
|
||||
return ctrl.second->handleClick(where);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void cScrollPane::recalcRect() {
|
||||
auto iter = contents.begin();
|
||||
globalFrame = {INT_MAX, INT_MAX, 0, 0};
|
||||
while(iter != contents.end()){
|
||||
cControl& ctrl = *iter->second;
|
||||
rectangle otherFrame = ctrl.getBounds();
|
||||
if(otherFrame.right > globalFrame.right)
|
||||
globalFrame.right = otherFrame.right;
|
||||
if(otherFrame.bottom > globalFrame.bottom)
|
||||
globalFrame.bottom = otherFrame.bottom;
|
||||
if(otherFrame.left < globalFrame.left)
|
||||
globalFrame.left = otherFrame.left;
|
||||
if(otherFrame.top < globalFrame.top)
|
||||
globalFrame.top = otherFrame.top;
|
||||
iter++;
|
||||
}
|
||||
globalFrame.inset(-4,-4);
|
||||
frame.left = globalFrame.left;
|
||||
frame.right = globalFrame.right;
|
||||
scroll.setMaximum(globalFrame.height() - frame.height());
|
||||
scroll.setPageSize(100);
|
||||
rectangle scrollFrame;
|
||||
scrollFrame.left = frame.right;
|
||||
scrollFrame.top = frame.top;
|
||||
scrollFrame.width() = 16;
|
||||
scrollFrame.height() = frame.height();
|
||||
scroll.setBounds(scrollFrame);
|
||||
frame.right += scrollFrame.width();
|
||||
}
|
||||
|
||||
void cScrollPane::setFormat(eFormat prop, short val) throw(xUnsupportedProp) {
|
||||
if(prop == TXT_FRAME) framed = val;
|
||||
else if(prop == TXT_FRAMESTYLE) frameStyle = val;
|
||||
else throw xUnsupportedProp(prop);
|
||||
}
|
||||
|
||||
short cScrollPane::getFormat(eFormat prop) throw(xUnsupportedProp) {
|
||||
if(prop == TXT_FRAME) return framed;
|
||||
else if(prop == TXT_FRAMESTYLE) return frameStyle;
|
||||
else throw xUnsupportedProp(prop);
|
||||
}
|
||||
|
||||
void cScrollPane::setColour(sf::Color) throw(xUnsupportedProp) {
|
||||
// TODO: Colour is not supported
|
||||
}
|
||||
|
||||
sf::Color cScrollPane::getColour() throw(xUnsupportedProp) {
|
||||
// TODO: Colour is not supported
|
||||
return sf::Color();
|
||||
}
|
||||
|
||||
cControl::storage_t cScrollPane::store() {
|
||||
// We don't call the superclass store() here like other controls do
|
||||
storage_t storage;
|
||||
storage[""] = scroll.store();
|
||||
for(auto& ctrl : contents)
|
||||
storage[ctrl.first] = ctrl.second->store();
|
||||
return storage;
|
||||
}
|
||||
|
||||
void cScrollPane::restore(storage_t to) {
|
||||
// We don't call the superclass restore() here like the other controls do
|
||||
if(to.find("") != to.end())
|
||||
scroll.restore(boost::any_cast<storage_t>(to[""]));
|
||||
for(auto& ctrl : contents) {
|
||||
if(to.find(ctrl.first) != to.end())
|
||||
ctrl.second->restore(boost::any_cast<storage_t>(to[ctrl.first]));
|
||||
}
|
||||
}
|
||||
|
||||
bool cScrollPane::isClickable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
long cScrollPane::getPosition() {
|
||||
return scroll.getPosition();
|
||||
}
|
||||
|
||||
long cScrollPane::getMaximum() {
|
||||
return scroll.getMaximum();
|
||||
}
|
||||
|
||||
void cScrollPane::setPosition(long to) {
|
||||
scroll.setPosition(to);
|
||||
}
|
||||
|
||||
cControl& cScrollPane::getChild(std::string id) {
|
||||
auto iter = contents.find(id);
|
||||
if(iter == contents.end()) throw std::invalid_argument(id + " does not exist in the scroll pane.");
|
||||
return *(iter->second);
|
||||
}
|
||||
|
||||
void cScrollPane::addChild(cControl* ctrl, std::string key) {
|
||||
contents[key] = ctrl;
|
||||
}
|
||||
|
||||
void cScrollPane::draw() {
|
||||
if(!visible) return;
|
||||
inWindow->setActive();
|
||||
clip_rect(*inWindow, getBounds());
|
||||
for(auto& ctrl : contents) {
|
||||
rectangle localBounds = ctrl.second->getBounds();
|
||||
rectangle globalBounds = localBounds;
|
||||
globalBounds.offset(0, -scroll.getPosition());
|
||||
ctrl.second->setBounds(globalBounds);
|
||||
ctrl.second->draw();
|
||||
ctrl.second->setBounds(localBounds);
|
||||
}
|
||||
undo_clip(*inWindow);
|
||||
scroll.draw();
|
||||
if(framed)
|
||||
drawFrame(4, getFormat(TXT_FRAMESTYLE));
|
||||
}
|
||||
|
||||
std::string cScrollPane::parse(ticpp::Element& who, std::string fname) {
|
||||
using namespace ticpp;
|
||||
Iterator<Attribute> attr;
|
||||
Iterator<Element> node;
|
||||
std::string name, id;
|
||||
rectangle frame;
|
||||
int width = 0, height = 0;
|
||||
bool foundTop = false, foundLeft = false;
|
||||
for(attr = attr.begin(&who); attr != attr.end(); attr++) {
|
||||
attr->GetName(&name);
|
||||
if(name == "name")
|
||||
attr->GetValue(&id);
|
||||
else if(name == "top")
|
||||
attr->GetValue(&frame.top), foundTop = true;
|
||||
else if(name == "left")
|
||||
attr->GetValue(&frame.left), foundLeft = true;
|
||||
else if(name == "width")
|
||||
attr->GetValue(&width);
|
||||
else if(name == "height")
|
||||
attr->GetValue(&height);
|
||||
else if(name == "framed") {
|
||||
std::string val;
|
||||
attr->GetValue(&val);
|
||||
if(val == "true") setFormat(TXT_FRAME, true);
|
||||
else setFormat(TXT_FRAME, false);
|
||||
} else throw xBadAttr("pane",name,attr->Row(),attr->Column(),fname);
|
||||
}
|
||||
if(!foundTop) throw xMissingAttr("pane","top",who.Row(),who.Column(),fname);
|
||||
if(!foundLeft) throw xMissingAttr("pane","left",who.Row(),who.Column(),fname);
|
||||
if(width > 0) {
|
||||
frame.right = frame.left + width;
|
||||
}else{
|
||||
throw xMissingAttr("pane","width",who.Row(),who.Column(),fname);
|
||||
}
|
||||
if(height > 0) {
|
||||
frame.bottom = frame.top + height;
|
||||
}else{
|
||||
frame.bottom = frame.top + 10;
|
||||
}
|
||||
setBounds(frame);
|
||||
for(node = node.begin(&who); node != node.end(); node++) {
|
||||
std::string val;
|
||||
int type = node->Type();
|
||||
node->GetValue(&val);
|
||||
if(type == TiXmlNode::ELEMENT) {
|
||||
if(val == "field") {
|
||||
auto field = parent->parse<cTextField>(*node);
|
||||
contents.insert(field);
|
||||
// TODO: Add field to tab order
|
||||
//tabOrder.push_back(field);
|
||||
} else if(val == "text") {
|
||||
auto text = parent->parse<cTextMsg>(*node);
|
||||
contents.insert(text);
|
||||
} else if(val == "pict") {
|
||||
auto pict = parent->parse<cPict>(*node);
|
||||
contents.insert(pict);
|
||||
} else if(val == "button") {
|
||||
auto button = parent->parse<cButton>(*node);
|
||||
contents.insert(button);
|
||||
} else if(val == "led") {
|
||||
auto led = parent->parse<cLed>(*node);
|
||||
contents.insert(led);
|
||||
} else if(val == "group") {
|
||||
auto group = parent->parse<cLedGroup>(*node);
|
||||
contents.insert(group);
|
||||
} else throw xBadNode(val,node->Row(),node->Column(),fname);
|
||||
} else if(type != TiXmlNode::COMMENT)
|
||||
throw xBadVal("pane",xBadVal::CONTENT,val,node->Row(),node->Column(),fname);
|
||||
}
|
||||
recalcRect();
|
||||
return id;
|
||||
}
|
61
src/dialogxml/scrollpane.hpp
Normal file
61
src/dialogxml/scrollpane.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// scrollpane.hpp
|
||||
// BoE
|
||||
//
|
||||
// Created by Celtic Minstrel on 15-10-01.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef BoE_scrollpane_hpp
|
||||
#define BoE_scrollpane_hpp
|
||||
|
||||
/// @file
|
||||
/// Scroll-pane-related classes and types
|
||||
|
||||
#include "scrollbar.hpp"
|
||||
|
||||
/// A container element that has a fixed viewport and a vertical scrollbar.
|
||||
class cScrollPane : public cContainer {
|
||||
cScrollbar scroll;
|
||||
std::map<std::string, cControl*> contents;
|
||||
rectangle globalFrame;
|
||||
bool frameStyle;
|
||||
bool framed = false;
|
||||
public:
|
||||
/// Create a new scroll pane
|
||||
explicit cScrollPane(cDialog& parent);
|
||||
std::string parse(ticpp::Element& who, std::string fname);
|
||||
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);
|
||||
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);
|
||||
sf::Color getColour() throw(xUnsupportedProp);
|
||||
cControl& getChild(std::string id);
|
||||
storage_t store();
|
||||
void restore(storage_t to);
|
||||
bool isClickable();
|
||||
/// Add a new control to this pane.
|
||||
/// @param ctrl A pointer to the control, which should already be constructed.
|
||||
/// @param key A key to be used to look up the control later.
|
||||
/// @note This function is intended for internal use, which is why it takes a control pointer instead of a unique key.
|
||||
void addChild(cControl* ctrl, std::string key);
|
||||
/// Recalculate the pane's bounding rect based on its contained controls.
|
||||
void recalcRect();
|
||||
/// Get the pane's current scroll position.
|
||||
/// @return The current position.
|
||||
long getPosition();
|
||||
/// Get the pane's maximum scroll position.
|
||||
/// @return The maximum value.
|
||||
long getMaximum();
|
||||
/// Set the pane's current scroll position.
|
||||
/// @param to The new position.
|
||||
void setPosition(long to);
|
||||
void draw();
|
||||
cScrollPane& operator=(cScrollPane& other) = delete;
|
||||
cScrollPane(cScrollPane& other) = delete;
|
||||
};
|
||||
|
||||
#endif
|
@@ -209,13 +209,24 @@ The `<stack>` tag
|
||||
-----------------
|
||||
|
||||
The `<stack>` tag groups elements that represent a single entry in an array.
|
||||
It can contain any elements except for nested `<stack>` elements.
|
||||
It can contain any elements except for nested `<stack>` or `<pane>` elements.
|
||||
|
||||
The `<stack>` tag accepts the following attributes:
|
||||
|
||||
* `pages` - The initial number of pages in the stack. This can also be
|
||||
set programmatically.
|
||||
|
||||
The `<pane>` tag
|
||||
----------------
|
||||
|
||||
The `<pane>` tag groups elements into a scrollable subpane.
|
||||
It can contain any elements except for nested `<stack>` or `<pane>` elements.
|
||||
|
||||
The `<pane>` tag accepts the following attributes:
|
||||
|
||||
* `framed` - Specifies whether a frame is drawn around the pane. Can
|
||||
be either `true` or `false`; defaults to `true`.
|
||||
|
||||
Keyboard Shortcuts
|
||||
------------------
|
||||
|
||||
|
@@ -17,6 +17,7 @@
|
||||
#include "dlogutil.hpp"
|
||||
#include "winutil.hpp"
|
||||
#include "stack.hpp"
|
||||
#include "scrollpane.hpp"
|
||||
#include "fileio.hpp"
|
||||
|
||||
extern short cen_x, cen_y, overall_mode;
|
||||
@@ -1260,9 +1261,12 @@ static void fill_resize_outdoors(cDialog& me, int top, int left, int right, int
|
||||
|
||||
me["w-new"].setTextToNum(scenario.outdoors.width() + left + right);
|
||||
me["h-new"].setTextToNum(scenario.outdoors.height() + top + bottom);
|
||||
if(left >= 0 && right >= 0 && top >= 0 && bottom >= 0)
|
||||
|
||||
rectangle txtBounds = me["delete"].getBounds();
|
||||
if(left >= 0 && right >= 0 && top >= 0 && bottom >= 0) {
|
||||
me["delete"].setText("(none)");
|
||||
else {
|
||||
txtBounds.height() = 10;
|
||||
} else {
|
||||
del.clear();
|
||||
while(left < 0) {
|
||||
for(int y = 0; y < scenario.outdoors.height(); y++)
|
||||
@@ -1285,11 +1289,16 @@ static void fill_resize_outdoors(cDialog& me, int top, int left, int right, int
|
||||
bottom++;
|
||||
}
|
||||
std::ostringstream list;
|
||||
auto txtHeight = txtBounds.height();
|
||||
txtHeight = 0;
|
||||
for(location l : del) {
|
||||
list << '(' << l.x << ", " << l.y << ") " << scenario.outdoors[l.x][l.y]->out_name << '|';
|
||||
txtHeight += 10;
|
||||
}
|
||||
me["delete"].setText(list.str());
|
||||
}
|
||||
me["delete"].setBounds(txtBounds);
|
||||
dynamic_cast<cScrollPane&>(me["scroll"]).recalcRect();
|
||||
}
|
||||
|
||||
static bool resize_outdoors_filter(cDialog& me, std::string btn, rectangle& mod, loc_set& del) {
|
||||
|
Reference in New Issue
Block a user