Misc. confirm plugin cleanup

This avoids the need to list newly-added classes in multiple places
(which could be extended to the search plugin) and gets rid of a few
ugly macros, along with a few other minor changes.
develop
lethosor 2015-11-11 23:00:20 -05:00
parent 9c62ff1d7f
commit e7c3b03ada
1 changed files with 81 additions and 70 deletions

@ -33,48 +33,61 @@ struct conf_wrapper;
static std::map<std::string, conf_wrapper*> confirmations; static std::map<std::string, conf_wrapper*> confirmations;
template <typename VT, typename FT> template <typename VT, typename FT>
bool in_vector (std::vector<VT> &vec, FT item) inline bool in_vector (std::vector<VT> &vec, FT item)
{ {
return std::find(vec.begin(), vec.end(), item) != vec.end(); return std::find(vec.begin(), vec.end(), item) != vec.end();
} }
#define goods_selected_func(list) \ namespace trade {
static bool list##_goods_selected(df::viewscreen_tradegoodsst *screen) \ static bool goods_selected (const std::vector<char> &selected)
{ \ {
for (auto it = screen->list##_selected.begin(); it != screen->list##_selected.end(); ++it) \ for (auto it = selected.begin(); it != selected.end(); ++it)
if (*it) return true; \ if (*it)
return false; \ return true;
return false;
}
inline bool trader_goods_selected (df::viewscreen_tradegoodsst *screen)
{
return goods_selected(screen->trader_selected);
}
inline bool broker_goods_selected (df::viewscreen_tradegoodsst *screen)
{
return goods_selected(screen->broker_selected);
} }
goods_selected_func(trader);
goods_selected_func(broker);
#undef goods_selected_func
#define goods_all_selected_func(list) \ static bool goods_all_selected(const std::vector<char> &selected, const std::vector<df::item*> &items) \
static bool list##_goods_all_selected(df::viewscreen_tradegoodsst *screen) \ {
{ \ for (size_t i = 0; i < selected.size(); ++i)
for (size_t i = 0; i < screen->list##_selected.size(); ++i) \ {
{ \ if (!selected[i])
if (!screen->list##_selected[i]) \ {
{ \ // check to see if item is in a container
std::vector<df::general_ref*> *refs = &screen->list##_items[i]->general_refs; \ // (if the container is not selected, it will be detected separately)
bool in_container = false; \ std::vector<df::general_ref*> &refs = items[i]->general_refs;
for (auto it = refs->begin(); it != refs->end(); ++it) \ bool in_container = false;
{ \ for (auto it = refs.begin(); it != refs.end(); ++it)
if (virtual_cast<df::general_ref_contained_in_itemst>(*it)) \ {
{ \ if (virtual_cast<df::general_ref_contained_in_itemst>(*it))
in_container = true; \ {
break; \ in_container = true;
} \ break;
} \ }
if (!in_container) \ }
return false; \ if (!in_container)
} \ return false;
} \ }
return true; \ }
return true;
}
inline bool trader_goods_all_selected(df::viewscreen_tradegoodsst *screen)
{
return goods_all_selected(screen->trader_selected, screen->trader_items);
}
inline bool broker_goods_all_selected(df::viewscreen_tradegoodsst *screen)
{
return goods_all_selected(screen->broker_selected, screen->broker_items);
}
} }
goods_all_selected_func(trader);
goods_all_selected_func(broker);
#undef goods_all_selected_func
template <class T> template <class T>
class confirmation { class confirmation {
@ -172,6 +185,7 @@ public:
} }
} }
virtual bool intercept_key (df::interface_key key) = 0; virtual bool intercept_key (df::interface_key key) = 0;
virtual string get_id() = 0;
virtual string get_title() { return "Confirm"; } virtual string get_title() { return "Confirm"; }
virtual string get_message() = 0; virtual string get_message() = 0;
virtual UIColor get_color() { return COLOR_YELLOW; } virtual UIColor get_color() { return COLOR_YELLOW; }
@ -181,9 +195,10 @@ protected:
}; };
struct conf_wrapper { struct conf_wrapper {
private:
bool enabled; bool enabled;
std::set<VMethodInterposeLinkBase*> hooks; std::set<VMethodInterposeLinkBase*> hooks;
public:
conf_wrapper() conf_wrapper()
:enabled(false) :enabled(false)
{} {}
@ -203,8 +218,22 @@ struct conf_wrapper {
enabled = state; enabled = state;
return true; return true;
} }
inline bool is_enabled() { return enabled; }
}; };
template<typename T>
int conf_register(confirmation<T> *c, ...)
{
conf_wrapper *w = new conf_wrapper;
confirmations[c->get_id()] = w;
va_list args;
va_start(args, c);
while (VMethodInterposeLinkBase *hook = va_arg(args, VMethodInterposeLinkBase*))
w->add_hook(hook);
va_end(args);
return 0;
}
#define IMPLEMENT_CONFIRMATION_HOOKS(cls) IMPLEMENT_CONFIRMATION_HOOKS_PRIO(cls, 0) #define IMPLEMENT_CONFIRMATION_HOOKS(cls) IMPLEMENT_CONFIRMATION_HOOKS_PRIO(cls, 0)
#define IMPLEMENT_CONFIRMATION_HOOKS_PRIO(cls, prio) \ #define IMPLEMENT_CONFIRMATION_HOOKS_PRIO(cls, prio) \
static cls cls##_instance; \ static cls cls##_instance; \
@ -229,7 +258,12 @@ struct cls##_hooks : cls::screen_type { \
}; \ }; \
IMPLEMENT_VMETHOD_INTERPOSE_PRIO(cls##_hooks, feed, prio); \ IMPLEMENT_VMETHOD_INTERPOSE_PRIO(cls##_hooks, feed, prio); \
IMPLEMENT_VMETHOD_INTERPOSE_PRIO(cls##_hooks, render, prio); \ IMPLEMENT_VMETHOD_INTERPOSE_PRIO(cls##_hooks, render, prio); \
IMPLEMENT_VMETHOD_INTERPOSE_PRIO(cls##_hooks, key_conflict, prio); IMPLEMENT_VMETHOD_INTERPOSE_PRIO(cls##_hooks, key_conflict, prio); \
static int conf_register_##cls = conf_register(&cls##_instance, \
&INTERPOSE_HOOK(cls##_hooks, feed), \
&INTERPOSE_HOOK(cls##_hooks, render), \
&INTERPOSE_HOOK(cls##_hooks, key_conflict), \
NULL);
class trade_confirmation : public confirmation<df::viewscreen_tradegoodsst> { class trade_confirmation : public confirmation<df::viewscreen_tradegoodsst> {
public: public:
@ -241,13 +275,13 @@ public:
virtual string get_title() { return "Confirm trade"; } virtual string get_title() { return "Confirm trade"; }
virtual string get_message() virtual string get_message()
{ {
if (trader_goods_selected(screen) && broker_goods_selected(screen)) if (trade::trader_goods_selected(screen) && trade::broker_goods_selected(screen))
return "Are you sure you want to trade the selected goods?"; return "Are you sure you want to trade the selected goods?";
else if (trader_goods_selected(screen)) else if (trade::trader_goods_selected(screen))
return "You are not giving any items. This is likely\n" return "You are not giving any items. This is likely\n"
"to irritate the merchants.\n" "to irritate the merchants.\n"
"Attempt to trade anyway?"; "Attempt to trade anyway?";
else if (broker_goods_selected(screen)) else if (trade::broker_goods_selected(screen))
return "You are not receiving any items. You may want to\n" return "You are not receiving any items. You may want to\n"
"offer these items instead or choose items to receive.\n" "offer these items instead or choose items to receive.\n"
"Attempt to trade anyway?"; "Attempt to trade anyway?";
@ -264,7 +298,7 @@ public:
virtual bool intercept_key (df::interface_key key) virtual bool intercept_key (df::interface_key key)
{ {
return key == df::interface_key::LEAVESCREEN && return key == df::interface_key::LEAVESCREEN &&
(trader_goods_selected(screen) || broker_goods_selected(screen)); (trade::trader_goods_selected(screen) || trade::broker_goods_selected(screen));
} }
virtual string get_id() { return "trade-cancel"; } virtual string get_id() { return "trade-cancel"; }
virtual string get_title() { return "Cancel trade"; } virtual string get_title() { return "Cancel trade"; }
@ -276,7 +310,7 @@ class trade_seize_confirmation : public confirmation<df::viewscreen_tradegoodsst
public: public:
virtual bool intercept_key (df::interface_key key) virtual bool intercept_key (df::interface_key key)
{ {
return trader_goods_selected(screen) && key == df::interface_key::TRADE_SEIZE; return trade::trader_goods_selected(screen) && key == df::interface_key::TRADE_SEIZE;
} }
virtual string get_id() { return "trade-seize"; } virtual string get_id() { return "trade-seize"; }
virtual string get_title() { return "Confirm seize"; } virtual string get_title() { return "Confirm seize"; }
@ -288,7 +322,7 @@ class trade_offer_confirmation : public confirmation<df::viewscreen_tradegoodsst
public: public:
virtual bool intercept_key (df::interface_key key) virtual bool intercept_key (df::interface_key key)
{ {
return broker_goods_selected(screen) && key == df::interface_key::TRADE_OFFER; return trade::broker_goods_selected(screen) && key == df::interface_key::TRADE_OFFER;
} }
virtual string get_id() { return "trade-offer"; } virtual string get_id() { return "trade-offer"; }
virtual string get_title() { return "Confirm offer"; } virtual string get_title() { return "Confirm offer"; }
@ -302,9 +336,9 @@ public:
{ {
if (key == df::interface_key::SEC_SELECT) if (key == df::interface_key::SEC_SELECT)
{ {
if (screen->in_right_pane && broker_goods_selected(screen) && !broker_goods_all_selected(screen)) if (screen->in_right_pane && trade::broker_goods_selected(screen) && !trade::broker_goods_all_selected(screen))
return true; return true;
else if (!screen->in_right_pane && trader_goods_selected(screen) && !trader_goods_all_selected(screen)) else if (!screen->in_right_pane && trade::trader_goods_selected(screen) && !trade::trader_goods_all_selected(screen))
return true; return true;
} }
return false; return false;
@ -403,31 +437,8 @@ public:
}; };
IMPLEMENT_CONFIRMATION_HOOKS(route_delete_confirmation); IMPLEMENT_CONFIRMATION_HOOKS(route_delete_confirmation);
#define CHOOK(cls) \
HOOK_ACTION(cls, render) \
HOOK_ACTION(cls, feed) \
HOOK_ACTION(cls, key_conflict)
#define CHOOKS \
CHOOK(trade_confirmation) \
CHOOK(trade_cancel_confirmation) \
CHOOK(trade_seize_confirmation) \
CHOOK(trade_offer_confirmation) \
CHOOK(trade_select_all_confirmation) \
CHOOK(hauling_route_delete_confirmation) \
CHOOK(depot_remove_confirmation) \
CHOOK(squad_disband_confirmation) \
CHOOK(note_delete_confirmation) \
CHOOK(route_delete_confirmation)
DFhackCExport command_result plugin_init (color_ostream &out, vector <PluginCommand> &commands) DFhackCExport command_result plugin_init (color_ostream &out, vector <PluginCommand> &commands)
{ {
#define HOOK_ACTION(cls, method) \
if (confirmations.find(cls##_instance.get_id()) == confirmations.end()) \
confirmations[cls##_instance.get_id()] = new conf_wrapper; \
confirmations[cls##_instance.get_id()]->add_hook(&INTERPOSE_HOOK(cls##_hooks, method));
CHOOKS
#undef HOOK_ACTION
commands.push_back(PluginCommand( commands.push_back(PluginCommand(
"confirm", "confirm",
"Confirmation dialogs", "Confirmation dialogs",
@ -485,7 +496,7 @@ command_result df_confirm (color_ostream &out, vector <string> & parameters)
out << "Available options: \n"; out << "Available options: \n";
for (auto it = confirmations.begin(); it != confirmations.end(); ++it) for (auto it = confirmations.begin(); it != confirmations.end(); ++it)
{ {
out << " " << it->first << ": " << (it->second->enabled ? "enabled" : "disabled") << std::endl; out << " " << it->first << ": " << (it->second->is_enabled() ? "enabled" : "disabled") << std::endl;
} }
return CR_OK; return CR_OK;
} }