|
|
@ -1,5 +1,3 @@
|
|
|
|
// Dwarf Manipulator - a Therapist-style labor editor
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <modules/Screen.h>
|
|
|
|
#include <modules/Screen.h>
|
|
|
|
#include <modules/Translation.h>
|
|
|
|
#include <modules/Translation.h>
|
|
|
|
#include <modules/Units.h>
|
|
|
|
#include <modules/Units.h>
|
|
|
@ -7,7 +5,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
#include <VTableInterpose.h>
|
|
|
|
#include <VTableInterpose.h>
|
|
|
|
|
|
|
|
|
|
|
|
#include "df/viewscreen_petst.h"
|
|
|
|
//#include "df/viewscreen_petst.h"
|
|
|
|
#include "df/viewscreen_storesst.h"
|
|
|
|
#include "df/viewscreen_storesst.h"
|
|
|
|
#include "df/viewscreen_tradegoodsst.h"
|
|
|
|
#include "df/viewscreen_tradegoodsst.h"
|
|
|
|
#include "df/viewscreen_unitlistst.h"
|
|
|
|
#include "df/viewscreen_unitlistst.h"
|
|
|
@ -22,20 +20,35 @@ using namespace df::enums;
|
|
|
|
|
|
|
|
|
|
|
|
using df::global::gps;
|
|
|
|
using df::global::gps;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
Search Plugin
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
A plugin that adds a "Search" hotkey to some screens (Units, Trade and Stocks)
|
|
|
|
|
|
|
|
that allows filtering of the list items by a typed query.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Works by manipulating the vector(s) that the list based viewscreens use to store
|
|
|
|
|
|
|
|
their items. When a search is started the plugin saves the original vectors and
|
|
|
|
|
|
|
|
with each keystroke creates a new filtered vector off the saves for the screen
|
|
|
|
|
|
|
|
to use.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// START: Base Search functionality
|
|
|
|
// START: Base Search functionality
|
|
|
|
//
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Parent class that does most of the work
|
|
|
|
template <class S, class T, class V = void*>
|
|
|
|
template <class S, class T, class V = void*>
|
|
|
|
class search_parent
|
|
|
|
class search_parent
|
|
|
|
{
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
public:
|
|
|
|
|
|
|
|
// Called each time you enter or leave a searchable screen. Resets everything.
|
|
|
|
void reset_all()
|
|
|
|
void reset_all()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
reset_search();
|
|
|
|
reset_search();
|
|
|
@ -47,11 +60,15 @@ public:
|
|
|
|
track_secondary_values = false;
|
|
|
|
track_secondary_values = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// A new keystroke is received in a searchable screen
|
|
|
|
virtual bool process_input(set<df::interface_key> *input)
|
|
|
|
virtual bool process_input(set<df::interface_key> *input)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
// If the page has two search options (Trade screen), only allow one to operate
|
|
|
|
|
|
|
|
// at a time
|
|
|
|
if (lock != NULL && lock != this)
|
|
|
|
if (lock != NULL && lock != this)
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Allows custom preprocessing for each screen
|
|
|
|
if (!should_check_input(input))
|
|
|
|
if (!should_check_input(input))
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
@ -59,14 +76,18 @@ public:
|
|
|
|
|
|
|
|
|
|
|
|
if (entry_mode)
|
|
|
|
if (entry_mode)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
// Query typing mode
|
|
|
|
|
|
|
|
|
|
|
|
df::interface_key last_token = *input->rbegin();
|
|
|
|
df::interface_key last_token = *input->rbegin();
|
|
|
|
if (last_token >= interface_key::STRING_A032 && last_token <= interface_key::STRING_A126)
|
|
|
|
if (last_token >= interface_key::STRING_A032 && last_token <= interface_key::STRING_A126)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
// Standard character
|
|
|
|
search_string += last_token - ascii_to_enum_offset;
|
|
|
|
search_string += last_token - ascii_to_enum_offset;
|
|
|
|
do_search();
|
|
|
|
do_search();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (last_token == interface_key::STRING_A000)
|
|
|
|
else if (last_token == interface_key::STRING_A000)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
// Backspace
|
|
|
|
if (search_string.length() > 0)
|
|
|
|
if (search_string.length() > 0)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
search_string.erase(search_string.length()-1);
|
|
|
|
search_string.erase(search_string.length()-1);
|
|
|
@ -75,31 +96,40 @@ public:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (input->count(interface_key::SELECT) || input->count(interface_key::LEAVESCREEN))
|
|
|
|
else if (input->count(interface_key::SELECT) || input->count(interface_key::LEAVESCREEN))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
// ENTER or ESC: leave typing mode
|
|
|
|
end_entry_mode();
|
|
|
|
end_entry_mode();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (input->count(interface_key::CURSOR_UP) || input->count(interface_key::CURSOR_DOWN)
|
|
|
|
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))
|
|
|
|
|| input->count(interface_key::CURSOR_LEFT) || input->count(interface_key::CURSOR_RIGHT))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
// Arrow key pressed. Leave entry mode and allow screen to process key
|
|
|
|
end_entry_mode();
|
|
|
|
end_entry_mode();
|
|
|
|
key_processed = false;
|
|
|
|
key_processed = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Not in query typing mode
|
|
|
|
else if (input->count(select_token))
|
|
|
|
else if (input->count(select_token))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
// Hotkey pressed, enter typing mode
|
|
|
|
start_entry_mode();
|
|
|
|
start_entry_mode();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (input->count((df::interface_key) (select_token + shift_offset)))
|
|
|
|
else if (input->count((df::interface_key) (select_token + shift_offset)))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
// Shift + Hotkey pressed, clear query
|
|
|
|
clear_search();
|
|
|
|
clear_search();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
// Not a key for us, pass it on to the screen
|
|
|
|
key_processed = false;
|
|
|
|
key_processed = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return key_processed || entry_mode;
|
|
|
|
return key_processed || entry_mode; // Only pass unrecognized keys down if not in typing mode
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Called if the search should be redone after the screen processes the keystroke.
|
|
|
|
|
|
|
|
// Used by the stocks screen where changing categories should redo the search on
|
|
|
|
|
|
|
|
// the new category.
|
|
|
|
virtual void do_post_update_check()
|
|
|
|
virtual void do_post_update_check()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (redo_search)
|
|
|
|
if (redo_search)
|
|
|
@ -165,6 +195,10 @@ protected:
|
|
|
|
saved_indexes.clear();
|
|
|
|
saved_indexes.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// If the second vector is editable (i.e. Trade screen vector used for marking). then it may
|
|
|
|
|
|
|
|
// have been edited while the list was filtered. We have to update the original unfiltered
|
|
|
|
|
|
|
|
// list with these values. Uses a stored reference vector to determine if the list has been
|
|
|
|
|
|
|
|
// reordered after filtering, in which case indexes must be remapped.
|
|
|
|
void update_secondary_values()
|
|
|
|
void update_secondary_values()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (sort_list2 != NULL && track_secondary_values)
|
|
|
|
if (sort_list2 != NULL && track_secondary_values)
|
|
|
@ -193,13 +227,14 @@ protected:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Used to work out if filtered list has been sorted after filtering
|
|
|
|
// Store a copy of filtered list, used later to work out if filtered list has been sorted after filtering
|
|
|
|
void store_reference_values()
|
|
|
|
void store_reference_values()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (track_secondary_values)
|
|
|
|
if (track_secondary_values)
|
|
|
|
reference_list = *sort_list1;
|
|
|
|
reference_list = *sort_list1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Shortcut to clear the search immediately
|
|
|
|
void clear_search()
|
|
|
|
void clear_search()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (saved_list1.size() > 0)
|
|
|
|
if (saved_list1.size() > 0)
|
|
|
@ -215,6 +250,7 @@ protected:
|
|
|
|
search_string = "";
|
|
|
|
search_string = "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// The actual sort
|
|
|
|
void do_search()
|
|
|
|
void do_search()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (search_string.length() == 0)
|
|
|
|
if (search_string.length() == 0)
|
|
|
@ -225,13 +261,15 @@ protected:
|
|
|
|
|
|
|
|
|
|
|
|
if (saved_list1.size() == 0)
|
|
|
|
if (saved_list1.size() == 0)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
// On first run, save the original list
|
|
|
|
saved_list1 = *sort_list1;
|
|
|
|
saved_list1 = *sort_list1;
|
|
|
|
if (sort_list2 != NULL)
|
|
|
|
if (sort_list2 != NULL)
|
|
|
|
saved_list2 = *sort_list2;
|
|
|
|
saved_list2 = *sort_list2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
update_secondary_values();
|
|
|
|
update_secondary_values(); // Update original list with any modified values
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Clear viewscreen vectors
|
|
|
|
sort_list1->clear();
|
|
|
|
sort_list1->clear();
|
|
|
|
if (sort_list2 != NULL)
|
|
|
|
if (sort_list2 != NULL)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -251,12 +289,12 @@ protected:
|
|
|
|
{
|
|
|
|
{
|
|
|
|
sort_list2->push_back(saved_list2[i]);
|
|
|
|
sort_list2->push_back(saved_list2[i]);
|
|
|
|
if (track_secondary_values)
|
|
|
|
if (track_secondary_values)
|
|
|
|
saved_indexes.push_back(i);
|
|
|
|
saved_indexes.push_back(i); // Used to map filtered indexes back to original, if needed
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
store_reference_values();
|
|
|
|
store_reference_values(); //Keep a copy, in case user sorts new list
|
|
|
|
|
|
|
|
|
|
|
|
*cursor_pos = 0;
|
|
|
|
*cursor_pos = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -266,6 +304,7 @@ protected:
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Display hotkey message
|
|
|
|
void print_search_option(int x, int y = -1) const
|
|
|
|
void print_search_option(int x, int y = -1) const
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (y == -1)
|
|
|
|
if (y == -1)
|
|
|
@ -297,7 +336,7 @@ private:
|
|
|
|
};
|
|
|
|
};
|
|
|
|
template <class S, class T, class V> search_parent<S,T,V> *search_parent<S,T,V> ::lock = NULL;
|
|
|
|
template <class S, class T, class V> search_parent<S,T,V> *search_parent<S,T,V> ::lock = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Parent struct for the hooks
|
|
|
|
template <class T, class V, typename D = void>
|
|
|
|
template <class T, class V, typename D = void>
|
|
|
|
struct search_hook : T
|
|
|
|
struct search_hook : T
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -355,6 +394,7 @@ public:
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (viewscreen->in_group_mode)
|
|
|
|
if (viewscreen->in_group_mode)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
// Disable search if item lists are grouped
|
|
|
|
clear_search();
|
|
|
|
clear_search();
|
|
|
|
reset_search();
|
|
|
|
reset_search();
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -385,6 +425,7 @@ private:
|
|
|
|
|
|
|
|
|
|
|
|
if ((input->count(interface_key::CURSOR_UP) || input->count(interface_key::CURSOR_DOWN)) && !viewscreen->in_right_list)
|
|
|
|
if ((input->count(interface_key::CURSOR_UP) || input->count(interface_key::CURSOR_DOWN)) && !viewscreen->in_right_list)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
// Redo search if category changes
|
|
|
|
saved_list1.clear();
|
|
|
|
saved_list1.clear();
|
|
|
|
end_entry_mode();
|
|
|
|
end_entry_mode();
|
|
|
|
if (search_string.length() > 0)
|
|
|
|
if (search_string.length() > 0)
|
|
|
@ -434,7 +475,7 @@ private:
|
|
|
|
{
|
|
|
|
{
|
|
|
|
string desc = Translation::TranslateName(Units::getVisibleName(element), false);
|
|
|
|
string desc = Translation::TranslateName(Units::getVisibleName(element), false);
|
|
|
|
if (viewscreen->page == 1)
|
|
|
|
if (viewscreen->page == 1)
|
|
|
|
desc += Units::getProfessionName(element);
|
|
|
|
desc += Units::getProfessionName(element); // Check animal type too
|
|
|
|
|
|
|
|
|
|
|
|
return desc;
|
|
|
|
return desc;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -445,11 +486,12 @@ private:
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (!is_entry_mode())
|
|
|
|
if (!is_entry_mode())
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
// Changing screens, reset search
|
|
|
|
clear_search();
|
|
|
|
clear_search();
|
|
|
|
reset_all();
|
|
|
|
reset_all();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
input->clear();
|
|
|
|
input->clear(); // Ignore cursor keys when typing
|
|
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|