undo/redo for edit/clear shop
This commit is contained in:
12
rsrc/dialogs/confirm-edit-shop.xml
Normal file
12
rsrc/dialogs/confirm-edit-shop.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
|
||||
<!-- NOTE: This file should be updated to use relative positioning the next time it changes. -->
|
||||
<?xml-stylesheet href="dialog.xsl" type="text/xsl"?>
|
||||
<dialog defbtn='keep' escbtn='cancel'>
|
||||
<pict type='dlog' num='7' top='6' left='6'/>
|
||||
<text name='keep-msg' top='6' left='49' width='256' height='32'>
|
||||
Keep changes to {{shop}} before editing another shop?
|
||||
</text>
|
||||
<button name='cancel' type='regular' top='43' left='109'>Cancel</button>
|
||||
<button name='revert' type='regular' top='43' left='175'>Discard</button>
|
||||
<button name='keep' type='regular' top='43' left='240'>Keep</button>
|
||||
</dialog>
|
@@ -328,3 +328,24 @@ int cShopItem::getCost(int adj) const {
|
||||
cost /= 10;
|
||||
return cost;
|
||||
}
|
||||
|
||||
bool cShopItem::operator==(const cShopItem& other) {
|
||||
CHECK_EQ(other, type);
|
||||
CHECK_EQ(other, quantity);
|
||||
CHECK_EQ(other, index);
|
||||
CHECK_EQ(other, item);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cShop::operator==(const cShop& other) {
|
||||
CHECK_EQ(other, items.size());
|
||||
for(size_t i = 0; i < items.size(); ++i){
|
||||
if(items[i] != other.items[i]) return false;
|
||||
}
|
||||
CHECK_EQ(other, cost_adj);
|
||||
CHECK_EQ(other, name);
|
||||
CHECK_EQ(other, type);
|
||||
CHECK_EQ(other, prompt);
|
||||
CHECK_EQ(other, face);
|
||||
return true;
|
||||
}
|
@@ -49,6 +49,10 @@ struct cShopItem {
|
||||
size_t quantity, index;
|
||||
cItem item{ITEM_SHOP};
|
||||
int getCost(int adj) const;
|
||||
|
||||
// For detecting actual changes to shops in the scenario editor
|
||||
bool operator==(const cShopItem& other);
|
||||
bool operator!=(const cShopItem& other) { return !(*this == other); }
|
||||
};
|
||||
|
||||
enum eShopPreset {SHOP_HEALING, SHOP_JUNK};
|
||||
@@ -92,6 +96,10 @@ public:
|
||||
void takeOne(size_t i);
|
||||
void clearItem(size_t i);
|
||||
void clear();
|
||||
|
||||
// For detecting actual changes to shops in the scenario editor
|
||||
bool operator==(const cShop& other);
|
||||
bool operator!=(const cShop& other) { return !(*this == other); }
|
||||
};
|
||||
|
||||
std::istream& operator>>(std::istream& in, eShopType& type);
|
||||
|
@@ -666,19 +666,17 @@ static bool handle_rb_action(location the_point, bool option_hit) {
|
||||
scenario.shops.pop_back();
|
||||
}
|
||||
// Clear shop (it can't be fully deleted)
|
||||
else scenario.shops[j] = cShop("Unused Shop");
|
||||
else{
|
||||
cShop cleared("Unused Shop");
|
||||
undo_list.add(action_ptr(new aEditClearShop("Clear Shop", j, scenario.shops[j], cleared)));
|
||||
update_edit_menu();
|
||||
scenario.shops[j] = cleared;
|
||||
}
|
||||
} else {
|
||||
bool is_new = (j == scenario.shops.size());
|
||||
if(edit_shop(j)){
|
||||
// Create new confirmed
|
||||
if(is_new){
|
||||
undo_list.add(action_ptr(new aCreateDeleteShop(true, scenario.shops.back())));
|
||||
update_edit_menu();
|
||||
}
|
||||
// Shop edited
|
||||
else{
|
||||
// TODO undo action
|
||||
}
|
||||
// Shop create/edit undo action is added in save_shop_from_dlog() because shop editor
|
||||
// has left/right buttons and can be launched with create/edit buttons elsewhere.
|
||||
}
|
||||
// Create new canceled
|
||||
else if(is_new){
|
||||
|
@@ -2472,7 +2472,7 @@ static void put_shop_in_dlog(cDialog& me, const cShop& shop, size_t which_shop)
|
||||
}
|
||||
}
|
||||
|
||||
static bool save_shop_from_dlog(cDialog& me, cShop& shop, size_t which_shop, bool close) {
|
||||
static bool save_shop_from_dlog(cDialog& me, cShop& shop, size_t which_shop, bool& is_new, bool need_confirm, bool close) {
|
||||
if(!me.toast(true)) return false;
|
||||
|
||||
shop.setName(me["name"].getText());
|
||||
@@ -2481,13 +2481,38 @@ static bool save_shop_from_dlog(cDialog& me, cShop& shop, size_t which_shop, boo
|
||||
shop.setFace(dynamic_cast<cPict&>(me["face"]).getPicNum());
|
||||
// Items are filled in as they're added by the dialog, so that's all we need to do here
|
||||
|
||||
scenario.shops[which_shop] = shop;
|
||||
if(shop != scenario.shops[which_shop] || is_new){
|
||||
if(need_confirm){
|
||||
// Confirm keeping changes
|
||||
cChoiceDlog dlog("confirm-edit-shop", {"keep","revert","cancel"}, &me);
|
||||
dlog->getControl("keep-msg").replaceText("{{shop}}", shop.getName());
|
||||
std::string choice = dlog.show();
|
||||
if(choice == "revert"){
|
||||
put_shop_in_dlog(me, scenario.shops[which_shop], which_shop);
|
||||
return false;
|
||||
}else if(choice == "cancel"){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Create new confirmed
|
||||
if(is_new){
|
||||
undo_list.add(action_ptr(new aCreateDeleteShop(true, shop)));
|
||||
update_edit_menu();
|
||||
}
|
||||
// Shop edited
|
||||
else{
|
||||
undo_list.add(action_ptr(new aEditClearShop("Edit Shop", which_shop, scenario.shops[which_shop], shop)));
|
||||
update_edit_menu();
|
||||
}
|
||||
|
||||
scenario.shops[which_shop] = shop;
|
||||
}
|
||||
if(!close) me.untoast();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool change_shop_dlog_page(cDialog& me, std::string dir, cShop& shop, size_t& which_shop) {
|
||||
if(!save_shop_from_dlog(me, shop, which_shop, false))
|
||||
static bool change_shop_dlog_page(cDialog& me, std::string dir, cShop& shop, size_t& which_shop, bool& is_new) {
|
||||
if(!save_shop_from_dlog(me, shop, which_shop, is_new, true, false))
|
||||
return true;
|
||||
|
||||
if(dir == "left") {
|
||||
@@ -2728,7 +2753,12 @@ static bool add_shop_entry(cDialog& me, std::string type, cShop& shop, size_t wh
|
||||
|
||||
bool edit_shop(size_t which_shop, cDialog* parent) {
|
||||
using namespace std::placeholders;
|
||||
if(which_shop == scenario.shops.size()) scenario.shops.emplace_back("New Shop");
|
||||
bool is_new = false;
|
||||
if(which_shop == scenario.shops.size()){
|
||||
is_new = true;
|
||||
scenario.shops.emplace_back("New Shop");
|
||||
}
|
||||
bool was_new = is_new;
|
||||
cShop shop = scenario.shops[which_shop];
|
||||
if(shop.size() == 0 && (shop.getName() == "New Shop" || shop.getName() == "Unused Shop")) {
|
||||
cChoiceDlog new_shop_dlg("new-shop", {"magic", "heal", "custom", "cancel"});
|
||||
@@ -2744,7 +2774,7 @@ bool edit_shop(size_t which_shop, cDialog* parent) {
|
||||
|
||||
cDialog shop_dlg(*ResMgr::dialogs.get("edit-shop"), parent);
|
||||
shop_dlg["cancel"].attachClickHandler(std::bind(&cDialog::toast, _1, false));
|
||||
shop_dlg["okay"].attachClickHandler(std::bind(save_shop_from_dlog, _1, std::ref(shop), std::ref(which_shop), true));
|
||||
shop_dlg["okay"].attachClickHandler(std::bind(save_shop_from_dlog, _1, std::ref(shop), std::ref(which_shop), std::ref(is_new), false, true));
|
||||
shop_dlg["pickface"].attachClickHandler(std::bind(pick_picture, PIC_TALK, _1, "", "face"));
|
||||
shop_dlg.attachClickHandlers(std::bind(change_shop_dlog_items_page, _1, _2, std::ref(shop)), {"up", "down"});
|
||||
shop_dlg.attachClickHandlers(std::bind(delete_shop_entry, _1, _2, std::ref(shop), std::ref(which_shop)), {"del1", "del2", "del3", "del4", "del5"});
|
||||
@@ -2755,12 +2785,12 @@ bool edit_shop(size_t which_shop, cDialog* parent) {
|
||||
shop_dlg["left"].hide();
|
||||
shop_dlg["right"].hide();
|
||||
} else {
|
||||
shop_dlg.attachClickHandlers(std::bind(change_shop_dlog_page, _1, _2, std::ref(shop), std::ref(which_shop)), {"left", "right"});
|
||||
shop_dlg.attachClickHandlers(std::bind(change_shop_dlog_page, _1, _2, std::ref(shop), std::ref(which_shop), std::ref(is_new)), {"left", "right"});
|
||||
}
|
||||
|
||||
put_shop_in_dlog(shop_dlg, shop, which_shop);
|
||||
shop_dlg.run();
|
||||
return shop_dlg.accepted();
|
||||
return shop_dlg.accepted() || was_new != is_new;
|
||||
}
|
||||
|
||||
static void put_vehicle_area(cDialog& me, const cVehicle& what) {
|
||||
|
@@ -479,4 +479,24 @@ bool aEditClearQuest::redo_me() {
|
||||
}
|
||||
scenario.quests[which] = after;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool aEditClearShop::undo_me() {
|
||||
// If not editing shops, show it
|
||||
if(overall_mode != MODE_EDIT_SHOPS){
|
||||
start_shops_editing();
|
||||
// TODO scroll to show the shop
|
||||
}
|
||||
scenario.shops[which] = before;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool aEditClearShop::redo_me() {
|
||||
// If not editing shops, show it
|
||||
if(overall_mode != MODE_EDIT_SHOPS){
|
||||
start_shops_editing();
|
||||
// TODO scroll to show the shop
|
||||
}
|
||||
scenario.shops[which] = after;
|
||||
return true;
|
||||
}
|
@@ -328,4 +328,16 @@ public:
|
||||
cAction(name), which(which), before(before), after(after) {}
|
||||
};
|
||||
|
||||
/// Action which edits or clears a shop
|
||||
class aEditClearShop : public cAction {
|
||||
size_t which;
|
||||
cShop before;
|
||||
cShop after;
|
||||
bool undo_me() override;
|
||||
bool redo_me() override;
|
||||
public:
|
||||
aEditClearShop(std::string name, size_t which, cShop before, cShop after) :
|
||||
cAction(name), which(which), before(before), after(after) {}
|
||||
};
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user