Refactoring to use templates

develop
Anuradha Dissanayake 2012-10-21 14:18:29 +13:00
parent fd60db44ab
commit c5b38a24eb
1 changed files with 316 additions and 260 deletions

@ -20,292 +20,347 @@ using namespace df::enums;
using df::global::gps; using df::global::gps;
void OutputString(int8_t color, int &x, int y, const std::string &text) void OutputString(int8_t color, int &x, int y, const std::string &text)
{ {
Screen::paintString(Screen::Pen(' ', color, 0), x, y, text); Screen::paintString(Screen::Pen(' ', color, 0), x, y, text);
x += text.length(); x += text.length();
} }
struct search_struct
//
// START: Base Search functionality
//
template <class S, class T, class V = void>
struct search_parent
{ {
static string search_string; vector <T*> *sort_list1;
static bool entry_mode; vector <V*> *sort_list2;
int *cursor_pos;
void print_search_option(int &x) char select_key;
{ const S *viewscreen;
OutputString(12, x, gps->dimy - 2, "s");
OutputString(15, x, gps->dimy - 2, ": Search"); bool valid;
if (search_string.length() > 0 || entry_mode) bool entry_mode;
OutputString(15, x, gps->dimy - 2, ": " + search_string); bool redo_search;
if (entry_mode) string search_string;
OutputString(12, x, gps->dimy - 2, "_"); vector <T*> saved_list1;
} vector <V*> saved_list2;
bool process_input(df::interface_key select_key, set<df::interface_key> *input, bool &string_changed) df::interface_key select_token;
{ const int ascii_to_enum_offset;
bool key_processed = true;
string_changed = false; search_parent() : ascii_to_enum_offset(interface_key::STRING_A048 - '0')
{
if (entry_mode) reset_all();
{ }
df::interface_key last_token = *input->rbegin();
if (last_token >= interface_key::STRING_A032 && last_token <= interface_key::STRING_A126) virtual void init(int *cursor_pos, vector <T*> *sort_list1, vector <V*> *sort_list2 = NULL, char select_key = 's')
{ {
search_string += 32 + last_token - interface_key::STRING_A032; this->cursor_pos = cursor_pos;
string_changed = true; this->sort_list1 = sort_list1;
} this->sort_list2 = sort_list2;
else if (last_token == interface_key::STRING_A000) this->select_key = select_key;
{ select_token = (df::interface_key) (ascii_to_enum_offset + select_key);
if (search_string.length() > 0) valid = true;
{ }
search_string.erase(search_string.length()-1);
string_changed = true; void reset_search()
} {
} entry_mode = false;
else if (input->count(interface_key::SELECT) || input->count(interface_key::LEAVESCREEN)) search_string = "";
{ saved_list1.clear();
entry_mode = false; saved_list2.clear();
} }
else if (input->count(interface_key::CURSOR_UP) || input->count(interface_key::CURSOR_DOWN))
{ void reset_all()
entry_mode = false; {
key_processed = false; reset_search();
} valid = false;
} sort_list1 = NULL;
else if (input->count(select_key)) sort_list2 = NULL;
{ viewscreen = NULL;
entry_mode = true; select_key = 's';
} }
else
{ void clear_search()
key_processed = false; {
} if (saved_list1.size() > 0)
{
return key_processed; *sort_list1 = saved_list1;
} if (sort_list2 != NULL)
*sort_list2 = saved_list2;
}
}
void do_search()
{
if (search_string.length() == 0)
{
clear_search();
return;
}
if (saved_list1.size() == 0)
{
saved_list1 = *sort_list1;
if (sort_list2 != NULL)
saved_list2 = *sort_list2;
}
sort_list1->clear();
if (sort_list2 != NULL)
sort_list2->clear();
string search_string_l = toLower(search_string);
for (int i = 0; i < saved_list1.size(); i++ )
{
T *element = saved_list1[i];
string desc = toLower(get_element_description(element));
if (desc.find(search_string_l) != string::npos)
{
sort_list1->push_back(element);
if (sort_list2 != NULL)
sort_list2->push_back(saved_list2[i]);
}
}
*cursor_pos = 0;
}
virtual bool process_input(const set<df::interface_key> *input)
{
bool key_processed = true;
if (entry_mode)
{
df::interface_key last_token = *input->rbegin();
if (last_token >= interface_key::STRING_A032 && last_token <= interface_key::STRING_A126)
{
search_string += last_token - ascii_to_enum_offset;
do_search();
}
else if (last_token == interface_key::STRING_A000)
{
if (search_string.length() > 0)
{
search_string.erase(search_string.length()-1);
do_search();
}
}
else if (input->count(interface_key::SELECT) || input->count(interface_key::LEAVESCREEN))
{
entry_mode = false;
}
else if (input->count(interface_key::CURSOR_UP) || input->count(interface_key::CURSOR_DOWN)
|| input->count(interface_key::CURSOR_LEFT) || input->count(interface_key::CURSOR_RIGHT))
{
entry_mode = false;
key_processed = false;
}
}
else if (input->count(select_token))
{
entry_mode = true;
}
else
{
key_processed = false;
}
return key_processed;
}
virtual string get_element_description(T *element) const = 0;
virtual void render () const = 0;
virtual void do_post_update_check()
{
if (redo_search)
{
do_search();
redo_search = false;
}
}
void print_search_option(int x) const
{
OutputString((entry_mode) ? 4 : 12, x, gps->dimy - 2, string(1, select_key));
OutputString((entry_mode) ? 10 : 15, x, gps->dimy - 2, ": Search");
if (search_string.length() > 0 || entry_mode)
OutputString(15, x, gps->dimy - 2, ": " + search_string);
if (entry_mode)
OutputString(10, x, gps->dimy - 2, "_");
}
}; };
string search_struct::search_string = "";
bool search_struct::entry_mode = false;
struct stocks_search : df::viewscreen_storesst, search_struct template <class T, class V>
struct search_hook : T
{ {
typedef df::viewscreen_storesst interpose_base; typedef T interpose_base;
static vector<df::item* > saved_items; static V module;
static void reset_search() DEFINE_VMETHOD_INTERPOSE(void, feed, (set<df::interface_key> *input))
{ {
entry_mode = false; module.init(this);
search_string = ""; if (!module.process_input(input))
saved_items.clear(); {
} INTERPOSE_NEXT(feed)(input);
module.do_post_update_check();
void clear_search() }
{
if (saved_items.size() > 0) }
{
items = saved_items; DEFINE_VMETHOD_INTERPOSE(void, render, ())
} {
} module.init(this);
INTERPOSE_NEXT(render)();
module.render();
}
DEFINE_VMETHOD_INTERPOSE(void, render, ())
{
INTERPOSE_NEXT(render)();
int x = 1;
print_search_option(x);
}
DEFINE_VMETHOD_INTERPOSE(void, feed, (set<df::interface_key> *input))
{
if (in_group_mode)
{
INTERPOSE_NEXT(feed)(input);
return;
}
bool string_changed = false;
if ((input->count(interface_key::CURSOR_UP) || input->count(interface_key::CURSOR_DOWN)) && !in_right_list)
{
saved_items.clear();
entry_mode = false;
if (search_string.length() > 0)
string_changed = true;
INTERPOSE_NEXT(feed)(input);
}
else
{
if (!process_input(interface_key::CUSTOM_S, input, string_changed) && !entry_mode)
{
INTERPOSE_NEXT(feed)(input);
if (in_group_mode)
{
clear_search();
reset_search();
}
}
}
if (string_changed)
{
if (search_string.length() == 0)
{
clear_search();
return;
}
if (saved_items.size() == 0 && items.size() > 0)
{
saved_items = items;
}
items.clear();
for (int i = 0; i < saved_items.size(); i++ )
{
string search_string_l = toLower(search_string);
string desc = Items::getDescription(saved_items[i], 0, true);
if (desc.find(search_string_l) != string::npos)
{
items.push_back(saved_items[i]);
}
}
item_cursor = 0;
}
}
}; };
vector<df::item* > stocks_search::saved_items; template <class T, class V> V search_hook<T, V> ::module;
IMPLEMENT_VMETHOD_INTERPOSE(stocks_search, feed);
IMPLEMENT_VMETHOD_INTERPOSE(stocks_search, render);
//
// END: Base Search functionality
//
struct unitlist_search : df::viewscreen_unitlistst, search_struct //
// START: Stocks screen search
//
struct stocks_search : search_parent<df::viewscreen_storesst, df::item>
{ {
typedef df::viewscreen_unitlistst interpose_base; virtual void render() const
{
static vector<df::unit*> saved_units; if (!viewscreen->in_group_mode)
static vector<df::job*> saved_jobs; print_search_option(1);
else
{
static void reset_search() int x = 1;
{ OutputString(15, x, gps->dimy - 2, "Tab to enable Search");
entry_mode = false; }
search_string = ""; }
saved_units.clear();
saved_jobs.clear(); virtual string get_element_description(df::item *element) const
} {
return Items::getDescription(element, 0, true);
void clear_search() }
{
if (saved_units.size() > 0) virtual bool process_input(const set<df::interface_key> *input)
{ {
units[page] = saved_units; if (viewscreen->in_group_mode)
jobs[page] = saved_jobs; return false;
}
} if ((input->count(interface_key::CURSOR_UP) || input->count(interface_key::CURSOR_DOWN)) && !viewscreen->in_right_list)
{
void do_search() saved_list1.clear();
{ entry_mode = false;
if (search_string.length() == 0) if (search_string.length() > 0)
{ redo_search = true;
clear_search();
return; return false;
} }
else
while(1) return search_parent::process_input(input) || entry_mode;
{
if (saved_units.size() == 0) return true;
{ }
saved_units = units[page];
saved_jobs = jobs[page]; virtual void do_post_update_check()
} {
units[page].clear(); if (viewscreen->in_group_mode)
jobs[page].clear(); {
clear_search();
for (int i = 0; i < saved_units.size(); i++ ) reset_search();
{ }
df::unit *unit = saved_units[i]; else
string search_string_l = toLower(search_string); search_parent::do_post_update_check();
string name = toLower(Translation::TranslateName(Units::getVisibleName(unit), false)); }
if (name.find(search_string_l) != string::npos)
{ virtual void init(df::viewscreen_storesst *screen)
units[page].push_back(unit); {
jobs[page].push_back(saved_jobs[i]); if (!valid)
} {
} viewscreen = screen;
search_parent::init(&screen->item_cursor, &screen->items);
if (units[page].size() > 0) }
{ }
cursor_pos[page] = 0;
break;
}
search_string.erase(search_string.length()-1);
}
}
DEFINE_VMETHOD_INTERPOSE(void, feed, (set<df::interface_key> *input))
{
bool string_changed = false;
if (!process_input(interface_key::CUSTOM_S, input, string_changed))
{
if (!entry_mode)
{
if (input->count(interface_key::CURSOR_LEFT) || input->count(interface_key::CURSOR_RIGHT))
{
clear_search();
reset_search();
}
INTERPOSE_NEXT(feed)(input);
}
}
else if (string_changed)
do_search();
}
DEFINE_VMETHOD_INTERPOSE(void, render, ())
{
INTERPOSE_NEXT(render)();
if (units[page].size())
{
int x = 28;
print_search_option(x);
}
}
}; };
vector<df::unit*> unitlist_search::saved_units;
vector<df::job*> unitlist_search::saved_jobs;
typedef search_hook<df::viewscreen_storesst, stocks_search> stocks_search_hook;
IMPLEMENT_VMETHOD_INTERPOSE(stocks_search_hook, feed);
IMPLEMENT_VMETHOD_INTERPOSE(stocks_search_hook, render);
IMPLEMENT_VMETHOD_INTERPOSE(unitlist_search, feed); //
IMPLEMENT_VMETHOD_INTERPOSE(unitlist_search, render); // END: Stocks screen search
//
//
// START: Unit screen search
//
struct unitlist_search : search_parent<df::viewscreen_unitlistst, df::unit, df::job>
{
virtual void render() const
{
print_search_option(28);
}
virtual string get_element_description(df::unit *element) const
{
return Translation::TranslateName(Units::getVisibleName(element), false);
}
virtual bool process_input(const set<df::interface_key> *input)
{
if (input->count(interface_key::CURSOR_LEFT) || input->count(interface_key::CURSOR_RIGHT))
{
if (!entry_mode)
{
clear_search();
reset_search();
return false;
}
}
else
return search_parent::process_input(input) || entry_mode;
return true;
}
virtual void init(df::viewscreen_unitlistst *screen)
{
if (!valid)
{
viewscreen = screen;
search_parent::init(&screen->cursor_pos[viewscreen->page], &screen->units[viewscreen->page], &screen->jobs[viewscreen->page]);
}
}
};
typedef search_hook<df::viewscreen_unitlistst, unitlist_search> unitlist_search_hook;
IMPLEMENT_VMETHOD_INTERPOSE(unitlist_search_hook, feed);
IMPLEMENT_VMETHOD_INTERPOSE(unitlist_search_hook, render);
//
// END: Unit screen search
//
DFHACK_PLUGIN("search"); DFHACK_PLUGIN("search");
DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCommand> &commands) DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCommand> &commands)
{ {
if (!gps || !INTERPOSE_HOOK(unitlist_search, feed).apply() || !INTERPOSE_HOOK(unitlist_search, render).apply() if (!gps || !INTERPOSE_HOOK(unitlist_search_hook, feed).apply() || !INTERPOSE_HOOK(unitlist_search_hook, render).apply()
|| !INTERPOSE_HOOK(stocks_search, feed).apply() || !INTERPOSE_HOOK(stocks_search, render).apply()) || !INTERPOSE_HOOK(stocks_search_hook, feed).apply() || !INTERPOSE_HOOK(stocks_search_hook, render).apply())
out.printerr("Could not insert Search hooks!\n"); out.printerr("Could not insert Search hooks!\n");
return CR_OK; return CR_OK;
@ -313,15 +368,16 @@ DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCom
DFhackCExport command_result plugin_shutdown ( color_ostream &out ) DFhackCExport command_result plugin_shutdown ( color_ostream &out )
{ {
INTERPOSE_HOOK(unitlist_search, feed).remove(); INTERPOSE_HOOK(unitlist_search_hook, feed).remove();
INTERPOSE_HOOK(unitlist_search, render).remove(); INTERPOSE_HOOK(unitlist_search_hook, render).remove();
INTERPOSE_HOOK(stocks_search, feed).remove(); INTERPOSE_HOOK(stocks_search_hook, feed).remove();
INTERPOSE_HOOK(stocks_search, render).remove(); INTERPOSE_HOOK(stocks_search_hook, render).remove();
return CR_OK; return CR_OK;
} }
DFhackCExport command_result plugin_onstatechange ( color_ostream &out, state_change_event event ) DFhackCExport command_result plugin_onstatechange ( color_ostream &out, state_change_event event )
{ {
unitlist_search::reset_search(); unitlist_search_hook::module.reset_all();
return CR_OK; stocks_search_hook::module.reset_all();
return CR_OK;
} }