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:
2015-10-02 17:03:25 -04:00
parent 22e63d898f
commit a455941d92
16 changed files with 419 additions and 23 deletions

View File

@@ -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;
};

View File

@@ -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);
}

View File

@@ -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 {

View File

@@ -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);

View File

@@ -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.

View File

@@ -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

View File

@@ -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++;

View File

@@ -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;
}

View File

@@ -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.

View 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;
}

View 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

View File

@@ -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
------------------

View File

@@ -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) {