From 825d46af51694fa45120a04532a2fd84313a898a Mon Sep 17 00:00:00 2001 From: lethosor Date: Tue, 28 Jul 2015 21:48:00 -0400 Subject: [PATCH] Move ListColumn class to a separate header --- plugins/autochop.cpp | 1 + plugins/autodump.cpp | 4 +- plugins/automelt.cpp | 4 +- plugins/autotrade.cpp | 4 +- plugins/buildingplan-lib.h | 3 +- plugins/dwarfmonitor.cpp | 1 + plugins/hotkeys.cpp | 1 + plugins/listcolumn.h | 469 +++++++++++++++++++++++++++++ plugins/manipulator.cpp | 1 + plugins/mousequery.cpp | 5 +- plugins/remotefortressreader.cpp | 2 +- plugins/stockflow.cpp | 5 +- plugins/stockpiles/stockpiles.cpp | 1 + plugins/stocks.cpp | 1 + plugins/uicommon.h | 472 ------------------------------ 15 files changed, 484 insertions(+), 490 deletions(-) create mode 100644 plugins/listcolumn.h diff --git a/plugins/autochop.cpp b/plugins/autochop.cpp index 3009877f1..f7ba3d300 100644 --- a/plugins/autochop.cpp +++ b/plugins/autochop.cpp @@ -1,6 +1,7 @@ // automatically chop trees #include "uicommon.h" +#include "listcolumn.h" #include "Core.h" #include "Console.h" diff --git a/plugins/autodump.cpp b/plugins/autodump.cpp index 944288001..3fbe1ae77 100644 --- a/plugins/autodump.cpp +++ b/plugins/autodump.cpp @@ -37,6 +37,7 @@ using MapExtras::MapCache; using df::building_stockpilest; DFHACK_PLUGIN("autodump"); +REQUIRE_GLOBAL(gps); REQUIRE_GLOBAL(world); // Stockpile interface START @@ -254,9 +255,6 @@ DFHACK_PLUGIN_IS_ENABLED(is_enabled); DFhackCExport command_result plugin_enable(color_ostream &out, bool enable) { - if (!gps) - return CR_FAILURE; - if (enable != is_enabled) { if (!INTERPOSE_HOOK(dump_hook, feed).apply(enable) || diff --git a/plugins/automelt.cpp b/plugins/automelt.cpp index 620ed622e..0aacce233 100644 --- a/plugins/automelt.cpp +++ b/plugins/automelt.cpp @@ -18,6 +18,7 @@ using df::building_stockpilest; DFHACK_PLUGIN("automelt"); #define PLUGIN_VERSION 0.3 +REQUIRE_GLOBAL(gps); REQUIRE_GLOBAL(world); REQUIRE_GLOBAL(cursor); REQUIRE_GLOBAL(ui); @@ -282,9 +283,6 @@ DFHACK_PLUGIN_IS_ENABLED(is_enabled); DFhackCExport command_result plugin_enable(color_ostream &out, bool enable) { - if (!gps) - return CR_FAILURE; - if (enable != is_enabled) { if (!INTERPOSE_HOOK(melt_hook, feed).apply(enable) || diff --git a/plugins/autotrade.cpp b/plugins/autotrade.cpp index aa7a35494..a645d579e 100644 --- a/plugins/autotrade.cpp +++ b/plugins/autotrade.cpp @@ -22,6 +22,7 @@ using df::building_stockpilest; DFHACK_PLUGIN("autotrade"); +REQUIRE_GLOBAL(gps); REQUIRE_GLOBAL(world); REQUIRE_GLOBAL(cursor); REQUIRE_GLOBAL(ui); @@ -465,9 +466,6 @@ DFHACK_PLUGIN_IS_ENABLED(is_enabled); DFhackCExport command_result plugin_enable(color_ostream &out, bool enable) { - if (!gps) - return CR_FAILURE; - if (enable != is_enabled) { depot_info.reset(); diff --git a/plugins/buildingplan-lib.h b/plugins/buildingplan-lib.h index 7b2be66cb..7ec0c41d4 100644 --- a/plugins/buildingplan-lib.h +++ b/plugins/buildingplan-lib.h @@ -2,6 +2,7 @@ #define BUILDINGPLAN_H #include "uicommon.h" +#include "listcolumn.h" #include @@ -492,4 +493,4 @@ static Planner planner; static RoomMonitor roomMonitor; -#endif \ No newline at end of file +#endif diff --git a/plugins/dwarfmonitor.cpp b/plugins/dwarfmonitor.cpp index 798d4e36d..e70bb8399 100644 --- a/plugins/dwarfmonitor.cpp +++ b/plugins/dwarfmonitor.cpp @@ -1,4 +1,5 @@ #include "uicommon.h" +#include "listcolumn.h" #include "DataDefs.h" diff --git a/plugins/hotkeys.cpp b/plugins/hotkeys.cpp index 7709c0719..45ca07cbd 100644 --- a/plugins/hotkeys.cpp +++ b/plugins/hotkeys.cpp @@ -1,4 +1,5 @@ #include "uicommon.h" +#include "listcolumn.h" #include "df/viewscreen_dwarfmodest.h" #include "df/ui.h" diff --git a/plugins/listcolumn.h b/plugins/listcolumn.h new file mode 100644 index 000000000..e90f2f5fb --- /dev/null +++ b/plugins/listcolumn.h @@ -0,0 +1,469 @@ +#include "uicommon.h" + +using df::global::enabler; +using df::global::gps; + +/* + * List classes + */ +template +class ListEntry +{ +public: + T elem; + string text, keywords; + bool selected; + UIColor color; + + ListEntry(const string text, const T elem, const string keywords = "", const UIColor color = COLOR_UNSELECTED) : + elem(elem), text(text), selected(false), keywords(keywords), color(color) + { + } +}; + +template +class ListColumn +{ +public: + int highlighted_index; + int display_start_offset; + unsigned short text_clip_at; + int32_t bottom_margin, search_margin, left_margin; + bool multiselect; + bool allow_null; + bool auto_select; + bool allow_search; + bool feed_mouse_set_highlight; + bool feed_changed_highlight; + + ListColumn() + { + bottom_margin = 3; + clear(); + left_margin = 2; + search_margin = 63; + highlighted_index = 0; + text_clip_at = 0; + multiselect = false; + allow_null = true; + auto_select = false; + allow_search = true; + feed_mouse_set_highlight = false; + feed_changed_highlight = false; + } + + void clear() + { + list.clear(); + display_list.clear(); + display_start_offset = 0; + if (highlighted_index != -1) + highlighted_index = 0; + max_item_width = title.length(); + resize(); + } + + void resize() + { + display_max_rows = gps->dimy - 4 - bottom_margin; + } + + void add(ListEntry &entry) + { + list.push_back(entry); + if (entry.text.length() > max_item_width) + max_item_width = entry.text.length(); + } + + void add(const string &text, const T &elem) + { + list.push_back(ListEntry(text, elem)); + if (text.length() > max_item_width) + max_item_width = text.length(); + } + + int fixWidth() + { + if (text_clip_at > 0 && max_item_width > text_clip_at) + max_item_width = text_clip_at; + + for (auto it = list.begin(); it != list.end(); it++) + { + it->text = pad_string(it->text, max_item_width, false); + } + + return getMaxItemWidth(); + } + + int getMaxItemWidth() + { + return left_margin + max_item_width; + } + + virtual void display_extras(const T &elem, int32_t &x, int32_t &y) const {} + + void display(const bool is_selected_column) const + { + int32_t y = 2; + paint_text(COLOR_TITLE, left_margin, y, title); + + int last_index_able_to_display = display_start_offset + display_max_rows; + for (int i = display_start_offset; i < display_list.size() && i < last_index_able_to_display; i++) + { + ++y; + UIColor fg_color = (display_list[i]->selected) ? COLOR_SELECTED : display_list[i]->color; + UIColor bg_color = (is_selected_column && i == highlighted_index) ? COLOR_HIGHLIGHTED : COLOR_BLACK; + + string item_label = display_list[i]->text; + if (text_clip_at > 0 && item_label.length() > text_clip_at) + item_label.resize(text_clip_at); + + paint_text(fg_color, left_margin, y, item_label, bg_color); + int x = left_margin + display_list[i]->text.length() + 1; + display_extras(display_list[i]->elem, x, y); + } + + if (is_selected_column && allow_search) + { + y = gps->dimy - 3; + int32_t x = search_margin; + OutputHotkeyString(x, y, "Search" ,"S"); + OutputString(COLOR_WHITE, x, y, ": "); + OutputString(COLOR_WHITE, x, y, search_string); + OutputString(COLOR_LIGHTGREEN, x, y, "_"); + } + } + + void filterDisplay() + { + ListEntry *prev_selected = (getDisplayListSize() > 0) ? display_list[highlighted_index] : NULL; + display_list.clear(); + + search_string = toLower(search_string); + vector search_tokens; + if (!search_string.empty()) + split_string(&search_tokens, search_string, " "); + + for (size_t i = 0; i < list.size(); i++) + { + ListEntry *entry = &list[i]; + + bool include_item = true; + if (!search_string.empty()) + { + string item_string = toLower(list[i].text); + for (auto si = search_tokens.begin(); si != search_tokens.end(); si++) + { + if (!si->empty() && item_string.find(*si) == string::npos && + list[i].keywords.find(*si) == string::npos) + { + include_item = false; + break; + } + } + } + + if (include_item) + { + display_list.push_back(entry); + if (entry == prev_selected) + highlighted_index = display_list.size() - 1; + } + else if (auto_select) + { + entry->selected = false; + } + } + changeHighlight(0); + feed_changed_highlight = true; + } + + void selectDefaultEntry() + { + for (size_t i = 0; i < display_list.size(); i++) + { + if (display_list[i]->selected) + { + highlighted_index = i; + break; + } + } + } + + void centerSelection() + { + if (display_list.size() == 0) + return; + display_start_offset = highlighted_index - (display_max_rows / 2); + validateDisplayOffset(); + validateHighlight(); + } + + void validateHighlight() + { + set_to_limit(highlighted_index, display_list.size() - 1); + + if (highlighted_index < display_start_offset) + display_start_offset = highlighted_index; + else if (highlighted_index >= display_start_offset + display_max_rows) + display_start_offset = highlighted_index - display_max_rows + 1; + + if (auto_select || (!allow_null && list.size() == 1)) + display_list[highlighted_index]->selected = true; + + feed_changed_highlight = true; + } + + void changeHighlight(const int highlight_change, const int offset_shift = 0) + { + if (!initHighlightChange()) + return; + + highlighted_index += highlight_change + offset_shift * display_max_rows; + + display_start_offset += offset_shift * display_max_rows; + validateDisplayOffset(); + validateHighlight(); + } + + void validateDisplayOffset() + { + set_to_limit(display_start_offset, max(0, (int)(display_list.size())-display_max_rows)); + } + + void setHighlight(const int index) + { + if (!initHighlightChange()) + return; + + highlighted_index = index; + validateHighlight(); + } + + bool initHighlightChange() + { + if (display_list.size() == 0) + return false; + + if (auto_select && !multiselect) + { + for (auto it = list.begin(); it != list.end(); it++) + { + it->selected = false; + } + } + + return true; + } + + void toggleHighlighted() + { + if (display_list.size() == 0) + return; + + if (auto_select) + return; + + ListEntry *entry = display_list[highlighted_index]; + if (!multiselect || !allow_null) + { + int selected_count = 0; + for (size_t i = 0; i < list.size(); i++) + { + if (!multiselect && !entry->selected) + list[i].selected = false; + if (!allow_null && list[i].selected) + selected_count++; + } + + if (!allow_null && entry->selected && selected_count == 1) + return; + } + + entry->selected = !entry->selected; + } + + vector getSelectedElems(bool only_one = false) + { + vector results; + for (auto it = list.begin(); it != list.end(); it++) + { + if ((*it).selected) + { + results.push_back(it->elem); + if (only_one) + break; + } + } + + return results; + } + + T getFirstSelectedElem() + { + vector results = getSelectedElems(true); + if (results.size() == 0) + return (T)nullptr; + else + return results[0]; + } + + void clearSelection() + { + for_each_(list, clear_fn); + } + + void selectItem(const T elem) + { + int i = 0; + for (; i < display_list.size(); i++) + { + if (display_list[i]->elem == elem) + { + setHighlight(i); + break; + } + } + } + + void clearSearch() + { + search_string.clear(); + filterDisplay(); + } + + size_t getDisplayListSize() + { + return display_list.size(); + } + + vector*> &getDisplayList() + { + return display_list; + } + + size_t getBaseListSize() + { + return list.size(); + } + + bool feed(set *input) + { + feed_mouse_set_highlight = feed_changed_highlight = false; + if (input->count(interface_key::CURSOR_UP)) + { + changeHighlight(-1); + } + else if (input->count(interface_key::CURSOR_DOWN)) + { + changeHighlight(1); + } + else if (input->count(interface_key::STANDARDSCROLL_PAGEUP)) + { + changeHighlight(0, -1); + } + else if (input->count(interface_key::STANDARDSCROLL_PAGEDOWN)) + { + changeHighlight(0, 1); + } + else if (input->count(interface_key::SELECT) && !auto_select) + { + toggleHighlighted(); + } + else if (input->count(interface_key::CUSTOM_SHIFT_S)) + { + clearSearch(); + } + else if (enabler->tracking_on && gps->mouse_x != -1 && gps->mouse_y != -1 && enabler->mouse_lbut) + { + return setHighlightByMouse(); + } + else if (allow_search) + { + // Search query typing mode always on + df::interface_key last_token = get_string_key(input); + int charcode = Screen::keyToChar(last_token); + if ((charcode >= 96 && charcode <= 123) || charcode == 32) + { + // Standard character + search_string += char(charcode); + filterDisplay(); + centerSelection(); + } + else if (last_token == interface_key::STRING_A000) + { + // Backspace + if (search_string.length() > 0) + { + search_string.erase(search_string.length()-1); + filterDisplay(); + centerSelection(); + } + } + else + { + return false; + } + + return true; + } + else + { + return false; + } + + return true; + } + + bool setHighlightByMouse() + { + if (gps->mouse_y >= 3 && gps->mouse_y < display_max_rows + 3 && + gps->mouse_x >= left_margin && gps->mouse_x < left_margin + max_item_width) + { + int new_index = display_start_offset + gps->mouse_y - 3; + if (new_index < display_list.size()) + { + setHighlight(new_index); + feed_mouse_set_highlight = true; + } + + enabler->mouse_lbut = enabler->mouse_rbut = 0; + + return true; + } + + return false; + } + + void sort(bool force_sort = false) + { + if (force_sort || list.size() < 100) + std::sort(list.begin(), list.end(), sort_fn); + + filterDisplay(); + } + + void setTitle(const string t) + { + title = t; + if (title.length() > max_item_width) + max_item_width = title.length(); + } + + size_t getDisplayedListSize() + { + return display_list.size(); + } + +protected: + static void clear_fn(ListEntry &e) { e.selected = false; } + static bool sort_fn(ListEntry const& a, ListEntry const& b) { return a.text.compare(b.text) < 0; } + + vector> list; + vector*> display_list; + string search_string; + string title; + int display_max_rows; + int max_item_width; +}; + diff --git a/plugins/manipulator.cpp b/plugins/manipulator.cpp index f675793df..6a69d7996 100644 --- a/plugins/manipulator.cpp +++ b/plugins/manipulator.cpp @@ -33,6 +33,7 @@ #include "df/entity_raw.h" #include "uicommon.h" +#include "listcolumn.h" using std::stringstream; using std::set; diff --git a/plugins/mousequery.cpp b/plugins/mousequery.cpp index 4547a62d0..b0835832f 100644 --- a/plugins/mousequery.cpp +++ b/plugins/mousequery.cpp @@ -22,6 +22,8 @@ #include "DataFuncs.h" DFHACK_PLUGIN("mousequery"); +REQUIRE_GLOBAL(enabler); +REQUIRE_GLOBAL(gps); REQUIRE_GLOBAL(world); REQUIRE_GLOBAL(ui); REQUIRE_GLOBAL(ui_build_selector); @@ -815,9 +817,6 @@ DFHACK_PLUGIN_IS_ENABLED(is_enabled); DFhackCExport command_result plugin_enable ( color_ostream &out, bool enable) { - if (!gps) - return CR_FAILURE; - if (is_enabled != enable) { last_clicked_x = last_clicked_y = last_clicked_z = -1; diff --git a/plugins/remotefortressreader.cpp b/plugins/remotefortressreader.cpp index 6629e7893..bc9bdbb08 100644 --- a/plugins/remotefortressreader.cpp +++ b/plugins/remotefortressreader.cpp @@ -1159,4 +1159,4 @@ static command_result GetBuildingDefList(color_ostream &stream, const EmptyMessa } } return CR_OK; -} \ No newline at end of file +} diff --git a/plugins/stockflow.cpp b/plugins/stockflow.cpp index 34dfc1bd7..75d09e1e8 100644 --- a/plugins/stockflow.cpp +++ b/plugins/stockflow.cpp @@ -22,12 +22,9 @@ using df::building_stockpilest; DFHACK_PLUGIN("stockflow"); #define AUTOENABLE false -#ifdef DFHACK_PLUGIN_IS_ENABLED DFHACK_PLUGIN_IS_ENABLED(enabled); -#else -bool enabled = false; -#endif +REQUIRE_GLOBAL(gps); REQUIRE_GLOBAL(world); REQUIRE_GLOBAL(ui); diff --git a/plugins/stockpiles/stockpiles.cpp b/plugins/stockpiles/stockpiles.cpp index 936052a15..f02d19e45 100644 --- a/plugins/stockpiles/stockpiles.cpp +++ b/plugins/stockpiles/stockpiles.cpp @@ -40,6 +40,7 @@ using namespace google::protobuf; using namespace dfstockpiles; DFHACK_PLUGIN ( "stockpiles" ); +REQUIRE_GLOBAL(gps); REQUIRE_GLOBAL(world); REQUIRE_GLOBAL(ui); REQUIRE_GLOBAL(selection_rect); diff --git a/plugins/stocks.cpp b/plugins/stocks.cpp index bf7969f6c..0f6039bfc 100644 --- a/plugins/stocks.cpp +++ b/plugins/stocks.cpp @@ -1,4 +1,5 @@ #include "uicommon.h" +#include "listcolumn.h" #include diff --git a/plugins/uicommon.h b/plugins/uicommon.h index 5f5414b72..a54b3aa04 100644 --- a/plugins/uicommon.h +++ b/plugins/uicommon.h @@ -37,10 +37,6 @@ using std::set; using namespace DFHack; using namespace df::enums; -using df::global::enabler; -using df::global::gps; - - #ifndef HAVE_NULLPTR #define nullptr 0L #endif @@ -432,471 +428,3 @@ protected: PersistentDataItem config; string persistence_key; }; - - - -/* - * List classes - */ -template -class ListEntry -{ -public: - T elem; - string text, keywords; - bool selected; - UIColor color; - - ListEntry(const string text, const T elem, const string keywords = "", const UIColor color = COLOR_UNSELECTED) : - elem(elem), text(text), selected(false), keywords(keywords), color(color) - { - } -}; - -template -class ListColumn -{ -public: - int highlighted_index; - int display_start_offset; - unsigned short text_clip_at; - int32_t bottom_margin, search_margin, left_margin; - bool multiselect; - bool allow_null; - bool auto_select; - bool allow_search; - bool feed_mouse_set_highlight; - bool feed_changed_highlight; - - ListColumn() - { - bottom_margin = 3; - clear(); - left_margin = 2; - search_margin = 63; - highlighted_index = 0; - text_clip_at = 0; - multiselect = false; - allow_null = true; - auto_select = false; - allow_search = true; - feed_mouse_set_highlight = false; - feed_changed_highlight = false; - } - - void clear() - { - list.clear(); - display_list.clear(); - display_start_offset = 0; - if (highlighted_index != -1) - highlighted_index = 0; - max_item_width = title.length(); - resize(); - } - - void resize() - { - display_max_rows = gps->dimy - 4 - bottom_margin; - } - - void add(ListEntry &entry) - { - list.push_back(entry); - if (entry.text.length() > max_item_width) - max_item_width = entry.text.length(); - } - - void add(const string &text, const T &elem) - { - list.push_back(ListEntry(text, elem)); - if (text.length() > max_item_width) - max_item_width = text.length(); - } - - int fixWidth() - { - if (text_clip_at > 0 && max_item_width > text_clip_at) - max_item_width = text_clip_at; - - for (auto it = list.begin(); it != list.end(); it++) - { - it->text = pad_string(it->text, max_item_width, false); - } - - return getMaxItemWidth(); - } - - int getMaxItemWidth() - { - return left_margin + max_item_width; - } - - virtual void display_extras(const T &elem, int32_t &x, int32_t &y) const {} - - void display(const bool is_selected_column) const - { - int32_t y = 2; - paint_text(COLOR_TITLE, left_margin, y, title); - - int last_index_able_to_display = display_start_offset + display_max_rows; - for (int i = display_start_offset; i < display_list.size() && i < last_index_able_to_display; i++) - { - ++y; - UIColor fg_color = (display_list[i]->selected) ? COLOR_SELECTED : display_list[i]->color; - UIColor bg_color = (is_selected_column && i == highlighted_index) ? COLOR_HIGHLIGHTED : COLOR_BLACK; - - string item_label = display_list[i]->text; - if (text_clip_at > 0 && item_label.length() > text_clip_at) - item_label.resize(text_clip_at); - - paint_text(fg_color, left_margin, y, item_label, bg_color); - int x = left_margin + display_list[i]->text.length() + 1; - display_extras(display_list[i]->elem, x, y); - } - - if (is_selected_column && allow_search) - { - y = gps->dimy - 3; - int32_t x = search_margin; - OutputHotkeyString(x, y, "Search" ,"S"); - OutputString(COLOR_WHITE, x, y, ": "); - OutputString(COLOR_WHITE, x, y, search_string); - OutputString(COLOR_LIGHTGREEN, x, y, "_"); - } - } - - void filterDisplay() - { - ListEntry *prev_selected = (getDisplayListSize() > 0) ? display_list[highlighted_index] : NULL; - display_list.clear(); - - search_string = toLower(search_string); - vector search_tokens; - if (!search_string.empty()) - split_string(&search_tokens, search_string, " "); - - for (size_t i = 0; i < list.size(); i++) - { - ListEntry *entry = &list[i]; - - bool include_item = true; - if (!search_string.empty()) - { - string item_string = toLower(list[i].text); - for (auto si = search_tokens.begin(); si != search_tokens.end(); si++) - { - if (!si->empty() && item_string.find(*si) == string::npos && - list[i].keywords.find(*si) == string::npos) - { - include_item = false; - break; - } - } - } - - if (include_item) - { - display_list.push_back(entry); - if (entry == prev_selected) - highlighted_index = display_list.size() - 1; - } - else if (auto_select) - { - entry->selected = false; - } - } - changeHighlight(0); - feed_changed_highlight = true; - } - - void selectDefaultEntry() - { - for (size_t i = 0; i < display_list.size(); i++) - { - if (display_list[i]->selected) - { - highlighted_index = i; - break; - } - } - } - - void centerSelection() - { - if (display_list.size() == 0) - return; - display_start_offset = highlighted_index - (display_max_rows / 2); - validateDisplayOffset(); - validateHighlight(); - } - - void validateHighlight() - { - set_to_limit(highlighted_index, display_list.size() - 1); - - if (highlighted_index < display_start_offset) - display_start_offset = highlighted_index; - else if (highlighted_index >= display_start_offset + display_max_rows) - display_start_offset = highlighted_index - display_max_rows + 1; - - if (auto_select || (!allow_null && list.size() == 1)) - display_list[highlighted_index]->selected = true; - - feed_changed_highlight = true; - } - - void changeHighlight(const int highlight_change, const int offset_shift = 0) - { - if (!initHighlightChange()) - return; - - highlighted_index += highlight_change + offset_shift * display_max_rows; - - display_start_offset += offset_shift * display_max_rows; - validateDisplayOffset(); - validateHighlight(); - } - - void validateDisplayOffset() - { - set_to_limit(display_start_offset, max(0, (int)(display_list.size())-display_max_rows)); - } - - void setHighlight(const int index) - { - if (!initHighlightChange()) - return; - - highlighted_index = index; - validateHighlight(); - } - - bool initHighlightChange() - { - if (display_list.size() == 0) - return false; - - if (auto_select && !multiselect) - { - for (auto it = list.begin(); it != list.end(); it++) - { - it->selected = false; - } - } - - return true; - } - - void toggleHighlighted() - { - if (display_list.size() == 0) - return; - - if (auto_select) - return; - - ListEntry *entry = display_list[highlighted_index]; - if (!multiselect || !allow_null) - { - int selected_count = 0; - for (size_t i = 0; i < list.size(); i++) - { - if (!multiselect && !entry->selected) - list[i].selected = false; - if (!allow_null && list[i].selected) - selected_count++; - } - - if (!allow_null && entry->selected && selected_count == 1) - return; - } - - entry->selected = !entry->selected; - } - - vector getSelectedElems(bool only_one = false) - { - vector results; - for (auto it = list.begin(); it != list.end(); it++) - { - if ((*it).selected) - { - results.push_back(it->elem); - if (only_one) - break; - } - } - - return results; - } - - T getFirstSelectedElem() - { - vector results = getSelectedElems(true); - if (results.size() == 0) - return (T)nullptr; - else - return results[0]; - } - - void clearSelection() - { - for_each_(list, clear_fn); - } - - void selectItem(const T elem) - { - int i = 0; - for (; i < display_list.size(); i++) - { - if (display_list[i]->elem == elem) - { - setHighlight(i); - break; - } - } - } - - void clearSearch() - { - search_string.clear(); - filterDisplay(); - } - - size_t getDisplayListSize() - { - return display_list.size(); - } - - vector*> &getDisplayList() - { - return display_list; - } - - size_t getBaseListSize() - { - return list.size(); - } - - bool feed(set *input) - { - feed_mouse_set_highlight = feed_changed_highlight = false; - if (input->count(interface_key::CURSOR_UP)) - { - changeHighlight(-1); - } - else if (input->count(interface_key::CURSOR_DOWN)) - { - changeHighlight(1); - } - else if (input->count(interface_key::STANDARDSCROLL_PAGEUP)) - { - changeHighlight(0, -1); - } - else if (input->count(interface_key::STANDARDSCROLL_PAGEDOWN)) - { - changeHighlight(0, 1); - } - else if (input->count(interface_key::SELECT) && !auto_select) - { - toggleHighlighted(); - } - else if (input->count(interface_key::CUSTOM_SHIFT_S)) - { - clearSearch(); - } - else if (enabler->tracking_on && gps->mouse_x != -1 && gps->mouse_y != -1 && enabler->mouse_lbut) - { - return setHighlightByMouse(); - } - else if (allow_search) - { - // Search query typing mode always on - df::interface_key last_token = get_string_key(input); - int charcode = Screen::keyToChar(last_token); - if ((charcode >= 96 && charcode <= 123) || charcode == 32) - { - // Standard character - search_string += char(charcode); - filterDisplay(); - centerSelection(); - } - else if (last_token == interface_key::STRING_A000) - { - // Backspace - if (search_string.length() > 0) - { - search_string.erase(search_string.length()-1); - filterDisplay(); - centerSelection(); - } - } - else - { - return false; - } - - return true; - } - else - { - return false; - } - - return true; - } - - bool setHighlightByMouse() - { - if (gps->mouse_y >= 3 && gps->mouse_y < display_max_rows + 3 && - gps->mouse_x >= left_margin && gps->mouse_x < left_margin + max_item_width) - { - int new_index = display_start_offset + gps->mouse_y - 3; - if (new_index < display_list.size()) - { - setHighlight(new_index); - feed_mouse_set_highlight = true; - } - - enabler->mouse_lbut = enabler->mouse_rbut = 0; - - return true; - } - - return false; - } - - void sort(bool force_sort = false) - { - if (force_sort || list.size() < 100) - std::sort(list.begin(), list.end(), sort_fn); - - filterDisplay(); - } - - void setTitle(const string t) - { - title = t; - if (title.length() > max_item_width) - max_item_width = title.length(); - } - - size_t getDisplayedListSize() - { - return display_list.size(); - } - -protected: - static void clear_fn(ListEntry &e) { e.selected = false; } - static bool sort_fn(ListEntry const& a, ListEntry const& b) { return a.text.compare(b.text) < 0; } - - vector> list; - vector*> display_list; - string search_string; - string title; - int display_max_rows; - int max_item_width; -}; - -