diff options
| author | Alexander Gavrilov | 2012-05-19 19:50:36 +0400 |
|---|---|---|
| committer | Alexander Gavrilov | 2012-05-19 19:50:36 +0400 |
| commit | 7774f5f2c1b1e16b9bd3eefe0fd8b4287d03fef7 (patch) | |
| tree | 26456ee2d47d78dde660842a4f317804a790b925 /plugins/sort.cpp | |
| parent | 4aa6dbdd005c8930f2ae972e780caa3fde97f854 (diff) | |
| download | dfhack-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.cpp | 553 |
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> ¶meters) -{ - Lua::StackUnwinder top(L); +typedef void (*SortHandler)(color_ostream *pout, lua_State *L, int top, + df::viewscreen *screen, vector<string> ¶meters); - 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> ¶meters); \ + 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> ¶meters) - 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> ¶meters) @@ -544,89 +461,75 @@ static command_result sort_units(color_ostream &out, vector <string> ¶meters 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> ¶meters) -{ - 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> ¶meters) @@ -637,8 +540,18 @@ static command_result sort_items(color_ostream &out, vector <string> ¶meters 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; } |
