summaryrefslogtreecommitdiff
path: root/plugins/sort.cpp
diff options
context:
space:
mode:
authorAlexander Gavrilov2012-05-19 19:50:36 +0400
committerAlexander Gavrilov2012-05-19 19:50:36 +0400
commit7774f5f2c1b1e16b9bd3eefe0fd8b4287d03fef7 (patch)
tree26456ee2d47d78dde660842a4f317804a790b925 /plugins/sort.cpp
parent4aa6dbdd005c8930f2ae972e780caa3fde97f854 (diff)
downloaddfhack-7774f5f2c1b1e16b9bd3eefe0fd8b4287d03fef7.tar.gz
dfhack-7774f5f2c1b1e16b9bd3eefe0fd8b4287d03fef7.tar.bz2
dfhack-7774f5f2c1b1e16b9bd3eefe0fd8b4287d03fef7.tar.xz
Add a mechanism converting ui focus to a string representation.
The idea is to make ui handling more modular, dispensing with huge functions that switch or if/else on lots of variables. For now, used to split up functions in the sort plugin.
Diffstat (limited to 'plugins/sort.cpp')
-rw-r--r--plugins/sort.cpp553
1 files changed, 233 insertions, 320 deletions
diff --git a/plugins/sort.cpp b/plugins/sort.cpp
index 430fb719..9274a4cf 100644
--- a/plugins/sort.cpp
+++ b/plugins/sort.cpp
@@ -204,7 +204,8 @@ static bool ParseSpec(color_ostream &out, lua_State *L, const char *type, vector
}
#define PARSE_SPEC(type, params) \
- if (!ParseSpec(*pout, L, type, params)) return false;
+ std::vector<unsigned> order; \
+ if (!ParseSpec(*pout, L, type, params)) return;
static bool prepare_sort(color_ostream *pout, lua_State *L)
{
@@ -230,310 +231,226 @@ static df::layer_object_listst *getLayerList(df::viewscreen_layerst *layer, int
return virtual_cast<df::layer_object_listst>(vector_get(layer->layer_objects,idx));
}
-static bool maybe_sort_units(color_ostream *pout, lua_State *L,
- df::viewscreen *screen, vector<string> &parameters)
-{
- Lua::StackUnwinder top(L);
+typedef void (*SortHandler)(color_ostream *pout, lua_State *L, int top,
+ df::viewscreen *screen, vector<string> &parameters);
- if (!prepare_sort(pout, L))
- return false;
+#define VIEWSCREEN(name) df::viewscreen_##name##st
+#define DEFINE_SORT_HANDLER(map, screen_type, tail, screen) \
+ static void CONCAT_TOKENS(SortHandler_##screen_type,__LINE__)\
+ (color_ostream *pout, lua_State *L, int top, \
+ VIEWSCREEN(screen_type) *screen, vector<string> &parameters); \
+ DFHACK_STATIC_ADD_TO_MAP(&map, #screen_type tail, \
+ (SortHandler)CONCAT_TOKENS(SortHandler_##screen_type,__LINE__) ); \
+ static void CONCAT_TOKENS(SortHandler_##screen_type,__LINE__)\
+ (color_ostream *pout, lua_State *L, int top, \
+ VIEWSCREEN(screen_type) *screen, vector<string> &parameters)
- std::vector<unsigned> order;
+static std::map<std::string, SortHandler> unit_sorters;
- if (auto units = strict_virtual_cast<df::viewscreen_unitlistst>(screen))
- {
- if (!L) return true;
+/*
+ * Sort units in the 'u'nit list screen.
+ */
- /*
- * Sort units in the 'u'nit list screen.
- */
+DEFINE_SORT_HANDLER(unit_sorters, unitlist, "", units)
+{
+ PARSE_SPEC("units", parameters);
- PARSE_SPEC("units", parameters);
+ int page = units->page;
- int page = units->page;
+ if (compute_order(*pout, L, top, &order, units->units[page]))
+ {
+ reorder_cursor(&units->cursor_pos[page], order);
+ reorder_vector(&units->units[page], order);
+ reorder_vector(&units->jobs[page], order);
+ }
+}
- if (compute_order(*pout, L, top, &order, units->units[page]))
- {
- reorder_cursor(&units->cursor_pos[page], order);
- reorder_vector(&units->units[page], order);
- reorder_vector(&units->jobs[page], order);
- }
+/*
+ * Sort units in the 'j'ob list screen.
+ */
- return true;
- }
- else if (auto jobs = strict_virtual_cast<df::viewscreen_joblistst>(screen))
+DEFINE_SORT_HANDLER(unit_sorters, joblist, "", jobs)
+{
+ PARSE_SPEC("units", parameters);
+
+ if (compute_order(*pout, L, top, &order, jobs->units))
{
- if (!L) return true;
+ reorder_cursor(&jobs->cursor_pos, order);
+ reorder_vector(&jobs->units, order);
+ reorder_vector(&jobs->jobs, order);
+ }
+}
- /*
- * Sort units in the 'j'ob list screen.
- */
+/*
+ * Sort candidate units in the 'p'osition page of the 'm'ilitary screen.
+ */
- PARSE_SPEC("units", parameters);
+DEFINE_SORT_HANDLER(unit_sorters, layer_military, "/Positions/Candidates", military)
+{
+ auto &candidates = military->positions.candidates;
+ auto list3 = getLayerList(military, 2);
- if (compute_order(*pout, L, top, &order, jobs->units))
- {
- reorder_cursor(&jobs->cursor_pos, order);
- reorder_vector(&jobs->units, order);
- reorder_vector(&jobs->jobs, order);
- }
+ PARSE_SPEC("units", parameters);
- return true;
- }
- else if (auto military = strict_virtual_cast<df::viewscreen_layer_militaryst>(screen))
+ if (compute_order(*pout, L, top, &order, candidates))
{
- switch (military->page)
- {
- case df::viewscreen_layer_militaryst::Positions:
- {
- auto &candidates = military->positions.candidates;
- auto list3 = getLayerList(military, 2);
+ reorder_cursor(&list3->cursor, order);
+ reorder_vector(&candidates, order);
+ }
+}
- /*
- * Sort candidate units in the 'p'osition page of the 'm'ilitary screen.
- */
- if (list3 && !candidates.empty() && list3->bright)
- {
- if (!L) return true;
+/*
+ * Sort units in the workshop 'q'uery 'P'rofile modification screen.
+ */
- PARSE_SPEC("units", parameters);
+DEFINE_SORT_HANDLER(unit_sorters, layer_workshop_profile, "/Unit", profile)
+{
+ auto list1 = getLayerList(profile, 0);
- if (compute_order(*pout, L, top, &order, candidates))
- {
- reorder_cursor(&list3->cursor, order);
- reorder_vector(&candidates, order);
- }
+ PARSE_SPEC("units", parameters);
- return true;
- }
+ if (compute_order(*pout, L, top, &order, profile->workers))
+ {
+ reorder_cursor(&list1->cursor, order);
+ reorder_vector(&profile->workers, order);
+ }
+}
- return false;
- }
+DEFINE_SORT_HANDLER(unit_sorters, layer_noblelist, "/Appoint", nobles)
+{
+ auto list2 = getLayerList(nobles, 1);
- default:
- return false;
- }
- }
- else if (auto profile = strict_virtual_cast<df::viewscreen_layer_workshop_profilest>(screen))
- {
- auto list1 = getLayerList(profile, 0);
+ sort_null_first(parameters);
+ PARSE_SPEC("units", parameters);
- if (!list1) return false;
- if (!L) return true;
+ std::vector<df::unit*> units;
+ for (size_t i = 0; i < nobles->candidates.size(); i++)
+ units.push_back(nobles->candidates[i]->unit);
- /*
- * Sort units in the workshop 'q'uery 'P'rofile modification screen.
- */
+ if (compute_order(*pout, L, top, &order, units))
+ {
+ reorder_cursor(&list2->cursor, order);
+ reorder_vector(&nobles->candidates, order);
+ }
+}
- PARSE_SPEC("units", parameters);
+/*
+ * Sort animal units in the Animal page of the 'z' status screen.
+ */
- if (compute_order(*pout, L, top, &order, profile->workers))
- {
- reorder_cursor(&list1->cursor, order);
- reorder_vector(&profile->workers, order);
- }
+DEFINE_SORT_HANDLER(unit_sorters, pet, "/List", animals)
+{
+ PARSE_SPEC("units", parameters);
- return true;
- }
- else if (auto nobles = strict_virtual_cast<df::viewscreen_layer_noblelistst>(screen))
- {
- switch (nobles->mode)
- {
- case df::viewscreen_layer_noblelistst::Appoint:
- {
- auto list2 = getLayerList(nobles, 1);
+ std::vector<df::unit*> units;
+ for (size_t i = 0; i < animals->animal.size(); i++)
+ units.push_back(animals->is_vermin[i] ? NULL : (df::unit*)animals->animal[i]);
- /*
- * Sort units in the appointment candidate list of the 'n'obles screen.
- */
+ if (compute_order(*pout, L, top, &order, units))
+ {
+ reorder_cursor(&animals->cursor, order);
+ reorder_vector(&animals->animal, order);
+ reorder_vector(&animals->is_vermin, order);
+ reorder_vector(&animals->pet_info, order);
+ reorder_vector(&animals->is_tame, order);
+ reorder_vector(&animals->is_adopting, order);
+ }
+}
- if (list2)
- {
- if (!L) return true;
+/*
+ * Sort candidate trainers in the Animal page of the 'z' status screen.
+ */
- sort_null_first(parameters);
- PARSE_SPEC("units", parameters);
+DEFINE_SORT_HANDLER(unit_sorters, pet, "/SelectTrainer", animals)
+{
+ sort_null_first(parameters);
+ PARSE_SPEC("units", parameters);
- std::vector<df::unit*> units;
- for (size_t i = 0; i < nobles->candidates.size(); i++)
- units.push_back(nobles->candidates[i]->unit);
+ if (compute_order(*pout, L, top, &order, animals->trainer_unit))
+ {
+ reorder_cursor(&animals->trainer_cursor, order);
+ reorder_vector(&animals->trainer_unit, order);
+ reorder_vector(&animals->trainer_mode, order);
+ }
+}
- if (compute_order(*pout, L, top, &order, units))
- {
- reorder_cursor(&list2->cursor, order);
- reorder_vector(&nobles->candidates, order);
- }
+/*
+ * Sort units in the Health page of the 'z' status screen.
+ */
- return true;
- }
+DEFINE_SORT_HANDLER(unit_sorters, layer_overall_health, "/Units", health)
+{
+ auto list1 = getLayerList(health, 0);
- return false;
- }
+ PARSE_SPEC("units", parameters);
- default:
- return false;
- }
- }
- else if (auto animals = strict_virtual_cast<df::viewscreen_petst>(screen))
+ if (compute_order(*pout, L, top, &order, health->unit))
{
- switch (animals->mode)
- {
- case df::viewscreen_petst::List:
- {
- if (!L) return true;
-
- /*
- * Sort animal units in the Animal page of the 'z' status screen.
- */
-
- PARSE_SPEC("units", parameters);
-
- std::vector<df::unit*> units;
- for (size_t i = 0; i < animals->animal.size(); i++)
- units.push_back(animals->is_vermin[i] ? NULL : (df::unit*)animals->animal[i]);
-
- if (compute_order(*pout, L, top, &order, units))
- {
- reorder_cursor(&animals->cursor, order);
- reorder_vector(&animals->animal, order);
- reorder_vector(&animals->is_vermin, order);
- reorder_vector(&animals->pet_info, order);
- reorder_vector(&animals->is_tame, order);
- reorder_vector(&animals->is_adopting, order);
- }
-
- return true;
- }
-
- case df::viewscreen_petst::SelectTrainer:
- {
- if (!L) return true;
-
- /*
- * Sort candidate trainers in the Animal page of the 'z' status screen.
- */
-
- sort_null_first(parameters);
- PARSE_SPEC("units", parameters);
-
- if (compute_order(*pout, L, top, &order, animals->trainer_unit))
- {
- reorder_cursor(&animals->trainer_cursor, order);
- reorder_vector(&animals->trainer_unit, order);
- reorder_vector(&animals->trainer_mode, order);
- }
-
- return true;
- }
-
- default:
- return false;
- }
+ reorder_cursor(&list1->cursor, order);
+ reorder_vector(&health->unit, order);
+ reorder_vector(&health->bits1, order);
+ reorder_vector(&health->bits2, order);
+ reorder_vector(&health->bits3, order);
}
- else if (auto health = strict_virtual_cast<df::viewscreen_layer_overall_healthst>(screen))
- {
- auto list1 = getLayerList(health, 0);
+}
+
+/*
+ * Sort burrow member candidate units in the 'w' sidebar mode.
+ */
+
+DEFINE_SORT_HANDLER(unit_sorters, dwarfmode, "/Burrows/AddUnits", screen)
+{
+ PARSE_SPEC("units", parameters);
- if (!list1) return false;
- if (!L) return true;
+ if (compute_order(*pout, L, top, &order, ui->burrows.list_units))
+ {
+ reorder_cursor(&ui->burrows.unit_cursor_pos, order);
+ reorder_vector(&ui->burrows.list_units, order);
+ reorder_vector(&ui->burrows.sel_units, order);
+ }
+}
- /*
- * Sort units in the Health page of the 'z' status screen.
- */
+/*
+ * Sort building owner candidate units in the 'q' sidebar mode, or cage assignment.
+ */
- PARSE_SPEC("units", parameters);
+DEFINE_SORT_HANDLER(unit_sorters, dwarfmode, "/QueryBuilding/Some/Assign", screen)
+{
+ sort_null_first(parameters);
- if (compute_order(*pout, L, top, &order, health->unit))
- {
- reorder_cursor(&list1->cursor, order);
- reorder_vector(&health->unit, order);
- reorder_vector(&health->bits1, order);
- reorder_vector(&health->bits2, order);
- reorder_vector(&health->bits3, order);
- }
+ PARSE_SPEC("units", parameters);
- return true;
- }
- else if (strict_virtual_cast<df::viewscreen_dwarfmodest>(screen))
+ if (compute_order(*pout, L, top, &order, *ui_building_assign_units))
{
- switch (ui->main.mode)
- {
- case ui_sidebar_mode::Burrows:
- if (!L) return true;
-
- /*
- * Sort burrow member candidate units in the 'w' sidebar mode.
- */
-
- PARSE_SPEC("units", parameters);
-
- if (compute_order(*pout, L, top, &order, ui->burrows.list_units))
- {
- reorder_cursor(&ui->burrows.unit_cursor_pos, order);
- reorder_vector(&ui->burrows.list_units, order);
- reorder_vector(&ui->burrows.sel_units, order);
- }
-
- return true;
-
- case ui_sidebar_mode::QueryBuilding:
- if (!ui_building_in_assign || !*ui_building_in_assign)
- return false;
- // fall through for building owner / chain assign animal
-
- case ui_sidebar_mode::ZonesPenInfo:
- if (ui_building_item_cursor &&
- ui_building_assign_type &&
- ui_building_assign_is_marked &&
- ui_building_assign_units &&
- ui_building_assign_items &&
- ui_building_assign_type->size() == ui_building_assign_units->size() &&
- !ui_building_assign_type->empty())
- {
- if (!L) return true;
-
- /*
- * Sort building owner candidate units in the 'q' sidebar mode,
- * or pen assignment candidate units in 'z'->'N', or cage assignment.
- */
-
- // TODO: better way
- bool is_assign_owner = ((*ui_building_assign_type)[0] == -1);
-
- if (is_assign_owner)
- sort_null_first(parameters);
-
- PARSE_SPEC("units", parameters);
-
- if (compute_order(*pout, L, top, &order, *ui_building_assign_units))
- {
- reorder_cursor(ui_building_item_cursor, order);
- reorder_vector(ui_building_assign_type, order);
- reorder_vector(ui_building_assign_units, order);
-
- if (ui_building_assign_units->size() == ui_building_assign_items->size())
- reorder_vector(ui_building_assign_items, order);
- if (ui_building_assign_units->size() == ui_building_assign_is_marked->size())
- reorder_vector(ui_building_assign_is_marked, order);
- }
-
- return true;
- }
- return false;
+ reorder_cursor(ui_building_item_cursor, order);
+ reorder_vector(ui_building_assign_type, order);
+ reorder_vector(ui_building_assign_units, order);
+ }
+}
- default:
- return false;
- }
+/*
+ * Sort pen assignment candidate units in 'z'->'N'.
+ */
+
+DEFINE_SORT_HANDLER(unit_sorters, dwarfmode, "/ZonesPenInfo/Assign", screen)
+{
+ PARSE_SPEC("units", parameters);
+
+ if (compute_order(*pout, L, top, &order, *ui_building_assign_units))
+ {
+ reorder_cursor(ui_building_item_cursor, order);
+ reorder_vector(ui_building_assign_type, order);
+ reorder_vector(ui_building_assign_units, order);
+ reorder_vector(ui_building_assign_items, order);
+ reorder_vector(ui_building_assign_is_marked, order);
}
- else
- return false;
}
static bool unit_list_hotkey(df::viewscreen *screen)
{
- vector<string> dummy;
- return maybe_sort_units(NULL, NULL, screen, dummy);
+ auto focus = Gui::getFocusString(screen);
+ return findPrefixInMap(unit_sorters, focus) != NULL;
}
static command_result sort_units(color_ostream &out, vector <string> &parameters)
@@ -544,89 +461,75 @@ static command_result sort_units(color_ostream &out, vector <string> &parameters
auto L = Lua::Core::State;
auto screen = Core::getInstance().getTopViewscreen();
- if (!maybe_sort_units(&out, L, screen, parameters))
+ Lua::StackUnwinder top(L);
+
+ if (!prepare_sort(&out, L))
return CR_WRONG_USAGE;
+ auto focus = Gui::getFocusString(screen);
+ auto handler = findPrefixInMap(unit_sorters, focus);
+
+ if (!handler)
+ return CR_WRONG_USAGE;
+ else
+ handler(&out, L, top, screen, parameters);
+
return CR_OK;
}
-static bool maybe_sort_items(color_ostream *pout, lua_State *L,
- df::viewscreen *screen, vector<string> &parameters)
-{
- Lua::StackUnwinder top(L);
-
- if (!prepare_sort(pout, L))
- return false;
+static std::map<std::string, SortHandler> item_sorters;
- std::vector<unsigned> order;
+DEFINE_SORT_HANDLER(item_sorters, tradegoods, "/Items/Broker", trade)
+{
+ PARSE_SPEC("items", parameters);
- if (auto trade = strict_virtual_cast<df::viewscreen_tradegoodsst>(screen))
+ if (compute_order(*pout, L, top, &order, trade->broker_items))
{
- if (!L) return true;
-
- PARSE_SPEC("items", parameters);
-
- if (trade->in_right_pane)
- {
- if (compute_order(*pout, L, top, &order, trade->broker_items))
- {
- reorder_cursor(&trade->broker_cursor, order);
- reorder_vector(&trade->broker_items, order);
- reorder_vector(&trade->broker_selected, order);
- reorder_vector(&trade->broker_count, order);
- }
- }
- else
- {
- if (compute_order(*pout, L, top, &order, trade->trader_items))
- {
- reorder_cursor(&trade->trader_cursor, order);
- reorder_vector(&trade->trader_items, order);
- reorder_vector(&trade->trader_selected, order);
- reorder_vector(&trade->trader_count, order);
- }
- }
-
- return true;
+ reorder_cursor(&trade->broker_cursor, order);
+ reorder_vector(&trade->broker_items, order);
+ reorder_vector(&trade->broker_selected, order);
+ reorder_vector(&trade->broker_count, order);
}
- else if (auto bring = strict_virtual_cast<df::viewscreen_layer_assigntradest>(screen))
- {
- auto list1 = getLayerList(bring, 0);
- auto list2 = getLayerList(bring, 1);
- if (!list1 || !list2 || !list2->bright)
- return false;
+}
- int list_idx = vector_get(bring->visible_lists, list1->cursor, (int16_t)-1);
- unsigned num_lists = sizeof(bring->lists)/sizeof(std::vector<int32_t>);
- if (unsigned(list_idx) >= num_lists)
- return false;
+DEFINE_SORT_HANDLER(item_sorters, tradegoods, "/Items/Trader", trade)
+{
+ PARSE_SPEC("items", parameters);
- if (!L) return true;
+ if (compute_order(*pout, L, top, &order, trade->trader_items))
+ {
+ reorder_cursor(&trade->trader_cursor, order);
+ reorder_vector(&trade->trader_items, order);
+ reorder_vector(&trade->trader_selected, order);
+ reorder_vector(&trade->trader_count, order);
+ }
+}
- PARSE_SPEC("items", parameters);
+DEFINE_SORT_HANDLER(item_sorters, layer_assigntrade, "/Items", bring)
+{
+ auto list1 = getLayerList(bring, 0);
+ auto list2 = getLayerList(bring, 1);
+ int list_idx = vector_get(bring->visible_lists, list1->cursor, (int16_t)-1);
- auto &vec = bring->lists[list_idx];
+ PARSE_SPEC("items", parameters);
- std::vector<df::item*> items;
- for (size_t i = 0; i < vec.size(); i++)
- items.push_back(bring->info[vec[i]]->item);
+ auto &vec = bring->lists[list_idx];
- if (compute_order(*pout, L, top, &order, items))
- {
- reorder_cursor(&list2->cursor, order);
- reorder_vector(&vec, order);
- }
+ std::vector<df::item*> items;
+ for (size_t i = 0; i < vec.size(); i++)
+ items.push_back(bring->info[vec[i]]->item);
- return true;
+ if (compute_order(*pout, L, top, &order, items))
+ {
+ reorder_cursor(&list2->cursor, order);
+ reorder_vector(&vec, order);
}
- else
- return false;
}
static bool item_list_hotkey(df::viewscreen *screen)
{
- vector<string> dummy;
- return maybe_sort_items(NULL, NULL, screen, dummy);
+ auto focus = Gui::getFocusString(screen);
+ return findPrefixInMap(item_sorters, focus) != NULL;
}
static command_result sort_items(color_ostream &out, vector <string> &parameters)
@@ -637,8 +540,18 @@ static command_result sort_items(color_ostream &out, vector <string> &parameters
auto L = Lua::Core::State;
auto screen = Core::getInstance().getTopViewscreen();
- if (!maybe_sort_items(&out, L, screen, parameters))
+ Lua::StackUnwinder top(L);
+
+ if (!prepare_sort(&out, L))
return CR_WRONG_USAGE;
+ auto focus = Gui::getFocusString(screen);
+ auto handler = findPrefixInMap(item_sorters, focus);
+
+ if (!handler)
+ return CR_WRONG_USAGE;
+ else
+ handler(&out, L, top, screen, parameters);
+
return CR_OK;
}