mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 04:57:00 -04:00
Added filter box for keywords
git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@1615 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
@@ -413,9 +413,10 @@ tooltip:
|
||||
label:
|
||||
# Cards tab
|
||||
card notes: Card notes:
|
||||
search cards: Search for cards
|
||||
search cards: Search for cards...
|
||||
|
||||
# Keywords tab
|
||||
search keywords: Search for keywords...
|
||||
keyword: Keyword
|
||||
match: Matches
|
||||
mode: Mode
|
||||
|
||||
@@ -55,41 +55,6 @@ String Card::identification() const {
|
||||
}
|
||||
}
|
||||
|
||||
/// Does the given object match the quick search query?
|
||||
template <typename T>
|
||||
bool match_quicksearch_query(String const& query, T const& object) {
|
||||
bool need_match = true;
|
||||
// iterate over the components of the query
|
||||
for (size_t i = 0 ; i < query.size() ; ) {
|
||||
if (query.GetChar(i) == _(' ')) {
|
||||
// skip spaces
|
||||
i++;
|
||||
} else if (query.GetChar(i) == _('-')) {
|
||||
// negate the next query, i.e. match only if it is not on the card
|
||||
need_match = !need_match;
|
||||
i++;
|
||||
} else {
|
||||
size_t end, next;
|
||||
if (query.GetChar(i) == _('"')) {
|
||||
// quoted string, match exactly
|
||||
i++;
|
||||
end =query.find_first_of(_('"'),i);
|
||||
next = min(end,query.size()) + 1;
|
||||
} else {
|
||||
// single word
|
||||
next = end = query.find_first_of(_(' '),i);
|
||||
}
|
||||
bool match = object.contains(query.substr(i,end-i));
|
||||
if (match != need_match) {
|
||||
return false;
|
||||
}
|
||||
need_match = true; // next word is no longer negated
|
||||
i = next;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Card::contains(String const& query) const {
|
||||
FOR_EACH_CONST(v, data) {
|
||||
if (find_i(v->toString(),query) != String::npos) return true;
|
||||
@@ -97,9 +62,6 @@ bool Card::contains(String const& query) const {
|
||||
if (find_i(notes,query) != String::npos) return true;
|
||||
return false;
|
||||
}
|
||||
bool Card::contains_words(String const& query) const {
|
||||
return match_quicksearch_query(query,*this);
|
||||
}
|
||||
|
||||
IndexMap<FieldP, ValueP>& Card::extraDataFor(const StyleSheet& stylesheet) {
|
||||
return extra_data.get(stylesheet.name(), stylesheet.extra_card_fields);
|
||||
|
||||
@@ -80,6 +80,14 @@ void read_compat(Reader& tag, Keyword* k) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Keyword::contains(String const& query) const {
|
||||
if (find_i(keyword,query) != String::npos) return true;
|
||||
if (find_i(rules,query) != String::npos) return true;
|
||||
if (find_i(match,query) != String::npos) return true;
|
||||
if (find_i(reminder.get(),query) != String::npos) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
IMPLEMENT_REFLECTION(Keyword) {
|
||||
REFLECT(keyword);
|
||||
read_compat(tag, this);
|
||||
|
||||
@@ -116,6 +116,9 @@ class Keyword : public IntrusivePtrVirtualBase {
|
||||
*/
|
||||
void prepare(const vector<KeywordParamP>& param_types, bool force = false);
|
||||
|
||||
/// Does the keyword contain the given query word?
|
||||
bool contains(String const& word) const;
|
||||
|
||||
DECLARE_REFLECTION();
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
//+----------------------------------------------------------------------------+
|
||||
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
|
||||
//| Copyright: (C) 2001 - 2010 Twan van Laarhoven and Sean Hunt |
|
||||
//| License: GNU General Public License 2 or later (see file COPYING) |
|
||||
//+----------------------------------------------------------------------------+
|
||||
|
||||
// ----------------------------------------------------------------------------- : Includes
|
||||
|
||||
#include <util/prec.hpp>
|
||||
#include <gui/control/filter_ctrl.hpp>
|
||||
#include <gui/about_window.hpp> // for HoverButton
|
||||
#include <gui/drop_down_list.hpp>
|
||||
|
||||
// ----------------------------------------------------------------------------- : DropDownMRUList
|
||||
|
||||
/// A drop down list of recent choices, for autocomplete
|
||||
class DropDownMRUList : public DropDownList {
|
||||
public:
|
||||
DropDownMRUList(Window* parent, vector<String> const& choices)
|
||||
: DropDownList(parent)
|
||||
, choices(choices)
|
||||
{}
|
||||
|
||||
vector<String> choices;
|
||||
|
||||
protected:
|
||||
virtual size_t selection() const { return NO_SELECTION; }
|
||||
virtual size_t itemCount() const { return choices.size(); }
|
||||
virtual String itemText(size_t item) const { return choices.at(item); }
|
||||
virtual void select(size_t item);
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : FilterControl
|
||||
|
||||
/// Text control that forwards focus events to the parent
|
||||
class TextCtrlWithFocus : public wxTextCtrl {
|
||||
public:
|
||||
DECLARE_EVENT_TABLE();
|
||||
void forwardFocusEvent(wxFocusEvent&);
|
||||
void forwardKeyEvent(wxKeyEvent&);
|
||||
};
|
||||
|
||||
FilterCtrl::FilterCtrl(wxWindow* parent, int id, String const& placeholder)
|
||||
: wxControl(parent, id, wxDefaultPosition, wxSize(160,41), wxSTATIC_BORDER)
|
||||
, changing(false)
|
||||
, placeholder(placeholder)
|
||||
{
|
||||
wxColour bg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
|
||||
SetBackgroundColour(bg);
|
||||
SetCursor(wxCURSOR_IBEAM);
|
||||
filter_ctrl = new TextCtrlWithFocus();
|
||||
filter_ctrl->Create(this, wxID_ANY, _(""), wxDefaultPosition, wxSize(130,-1), wxNO_BORDER);
|
||||
clear_button = new HoverButton(this, wxID_ANY, _("btn_clear_filter"), bg, false);
|
||||
clear_button->SetCursor(*wxSTANDARD_CURSOR);
|
||||
onSize();
|
||||
update();
|
||||
}
|
||||
|
||||
void FilterCtrl::setFilter(const String& new_value, bool event) {
|
||||
if (this->value == new_value) return;
|
||||
// update ui
|
||||
this->value = new_value;
|
||||
update();
|
||||
// send event
|
||||
if (event) {
|
||||
wxCommandEvent ev(wxEVT_COMMAND_TEXT_UPDATED, GetId());
|
||||
GetParent()->HandleWindowEvent(ev);
|
||||
}
|
||||
}
|
||||
|
||||
void FilterCtrl::update() {
|
||||
changing = true;
|
||||
if (!value.empty() || hasFocus()) {
|
||||
filter_ctrl->SetValue(value);
|
||||
wxColour fg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
|
||||
filter_ctrl->SetDefaultStyle(wxTextAttr(fg));
|
||||
filter_ctrl->SetForegroundColour(fg);
|
||||
wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
|
||||
filter_ctrl->SetFont(font);
|
||||
} else {
|
||||
filter_ctrl->SetValue(placeholder);
|
||||
wxColour fg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
|
||||
wxColour bg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
|
||||
filter_ctrl->SetDefaultStyle(wxTextAttr(lerp(fg,bg,0.5)));
|
||||
filter_ctrl->SetForegroundColour(lerp(fg,bg,0.5));
|
||||
wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
|
||||
font.SetStyle(wxFONTSTYLE_ITALIC);
|
||||
filter_ctrl->SetFont(font);
|
||||
}
|
||||
clear_button->Show(!value.empty());
|
||||
changing = false;
|
||||
}
|
||||
|
||||
void FilterCtrl::onChangeEvent(wxCommandEvent&) {
|
||||
if (!changing) {
|
||||
setFilter(filter_ctrl->GetValue(),true);
|
||||
}
|
||||
}
|
||||
void FilterCtrl::onChar(wxKeyEvent& ev) {
|
||||
if (ev.GetKeyCode() == WXK_ESCAPE) {
|
||||
// escape clears the filter box
|
||||
clearFilter(true);
|
||||
} else {
|
||||
ev.Skip();
|
||||
}
|
||||
}
|
||||
|
||||
void FilterCtrl::onClear(wxCommandEvent&) {
|
||||
clearFilter(true);
|
||||
}
|
||||
|
||||
void FilterCtrl::onSizeEvent(wxSizeEvent&) {
|
||||
onSize();
|
||||
}
|
||||
void FilterCtrl::onSize() {
|
||||
wxSize s = GetClientSize();
|
||||
wxSize fs = filter_ctrl->GetBestSize();
|
||||
wxSize cs = clear_button->GetBestSize();
|
||||
int margin = 2;
|
||||
filter_ctrl ->SetSize(margin, max(margin,(s.y-fs.y)/2), s.x - cs.x - 3*margin, fs.y);
|
||||
clear_button->SetSize(s.x - cs.x - margin, (s.y-cs.y)/2, cs.x, cs.y);
|
||||
}
|
||||
|
||||
void FilterCtrl::onSetFocus(wxFocusEvent&) {
|
||||
filter_ctrl->SetFocus();
|
||||
update();
|
||||
}
|
||||
void FilterCtrl::onKillFocus(wxFocusEvent&) {
|
||||
update();
|
||||
}
|
||||
|
||||
bool FilterCtrl::hasFocus() {
|
||||
wxWindow* focus = wxWindow::FindFocus();
|
||||
return focus == this || focus == filter_ctrl || focus == clear_button;
|
||||
}
|
||||
|
||||
BEGIN_EVENT_TABLE(FilterCtrl, wxControl)
|
||||
EVT_BUTTON (wxID_ANY, FilterCtrl::onClear)
|
||||
EVT_TEXT (wxID_ANY, FilterCtrl::onChangeEvent)
|
||||
EVT_SIZE (FilterCtrl::onSizeEvent)
|
||||
EVT_SET_FOCUS (FilterCtrl::onSetFocus)
|
||||
EVT_KILL_FOCUS(FilterCtrl::onKillFocus)
|
||||
EVT_CHAR (FilterCtrl::onChar)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
// ----------------------------------------------------------------------------- : TextCtrlWithFocus
|
||||
|
||||
void TextCtrlWithFocus::forwardFocusEvent(wxFocusEvent& ev) {
|
||||
GetParent()->HandleWindowEvent(ev);
|
||||
}
|
||||
void TextCtrlWithFocus::forwardKeyEvent(wxKeyEvent& ev) {
|
||||
GetParent()->HandleWindowEvent(ev);
|
||||
}
|
||||
|
||||
BEGIN_EVENT_TABLE(TextCtrlWithFocus, wxTextCtrl)
|
||||
EVT_SET_FOCUS (TextCtrlWithFocus::forwardFocusEvent)
|
||||
EVT_KILL_FOCUS(TextCtrlWithFocus::forwardFocusEvent)
|
||||
EVT_CHAR (TextCtrlWithFocus::forwardKeyEvent)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
//+----------------------------------------------------------------------------+
|
||||
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
|
||||
//| Copyright: (C) 2001 - 2010 Twan van Laarhoven and Sean Hunt |
|
||||
//| License: GNU General Public License 2 or later (see file COPYING) |
|
||||
//+----------------------------------------------------------------------------+
|
||||
|
||||
#ifndef HEADER_GUI_CONTROL_FILTER_CTRL
|
||||
#define HEADER_GUI_CONTROL_FILTER_CTRL
|
||||
|
||||
// ----------------------------------------------------------------------------- : Includes
|
||||
|
||||
#include <util/prec.hpp>
|
||||
#include <data/filter.hpp>
|
||||
|
||||
class HoverButton;
|
||||
class TextCtrlWithFocus;
|
||||
|
||||
// ----------------------------------------------------------------------------- : FilterCtrl
|
||||
|
||||
/// A search/filter textbox
|
||||
class FilterCtrl : public wxControl {
|
||||
public:
|
||||
FilterCtrl(wxWindow* parent, int id, String const& placeholder);
|
||||
|
||||
/// Set the filter text
|
||||
void setFilter(const String& filter, bool send_event = false);
|
||||
void clearFilter(bool send_event = false) { setFilter(String(),send_event); }
|
||||
bool hasFilter() const { return !value.empty(); }
|
||||
String const& getFilterString() const { return value; }
|
||||
|
||||
template <typename T>
|
||||
intrusive_ptr<Filter<T> > getFilter() const {
|
||||
if (hasFilter()) {
|
||||
return intrusive(new QuickFilter<T>(getFilterString()));
|
||||
} else {
|
||||
return intrusive_ptr<Filter<T> >();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
DECLARE_EVENT_TABLE();
|
||||
bool changing;
|
||||
String value;
|
||||
String placeholder;
|
||||
TextCtrlWithFocus* filter_ctrl;
|
||||
HoverButton* clear_button;
|
||||
|
||||
void update();
|
||||
bool hasFocus();
|
||||
// wxWidgets appears to have developed an overload allergy
|
||||
void onChangeEvent(wxCommandEvent&);
|
||||
void onClear(wxCommandEvent&);
|
||||
void onSizeEvent(wxSizeEvent&);
|
||||
void onChar(wxKeyEvent&);
|
||||
void onSize();
|
||||
void onSetFocus(wxFocusEvent&);
|
||||
void onKillFocus(wxFocusEvent&);
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
#endif
|
||||
@@ -33,18 +33,3 @@ void FilteredCardList::getItems(vector<VoidP>& out) const {
|
||||
filter->getItems(set->cards,out);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : CardListFilter
|
||||
|
||||
void CardListFilter::getItems(const vector<CardP>& cards, vector<VoidP>& out) const {
|
||||
FOR_EACH_CONST(c, cards) {
|
||||
if (keep(c)) {
|
||||
out.push_back(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool QueryCardListFilter::keep(const CardP& card) const {
|
||||
return card->contains_words(query);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,29 +11,9 @@
|
||||
|
||||
#include <util/prec.hpp>
|
||||
#include <gui/control/card_list.hpp>
|
||||
#include <data/filter.hpp>
|
||||
|
||||
DECLARE_POINTER_TYPE(CardListFilter);
|
||||
|
||||
// ----------------------------------------------------------------------------- : CardListFilter
|
||||
|
||||
/// A filter function to determine which items are shown in a card list
|
||||
class CardListFilter : public IntrusivePtrVirtualBase {
|
||||
public:
|
||||
virtual ~CardListFilter() {}
|
||||
/// Should a card be shown in the list?
|
||||
virtual bool keep(const CardP& card) const { return false; }
|
||||
/// Select cards from a card list
|
||||
virtual void getItems(const vector<CardP>& cards, vector<VoidP>& out) const;
|
||||
};
|
||||
|
||||
/// A filter function that searches for cards containing a string
|
||||
class QueryCardListFilter : public CardListFilter {
|
||||
public:
|
||||
QueryCardListFilter(String const& query) : query(query) {}
|
||||
virtual bool keep(const CardP& card) const;
|
||||
private:
|
||||
String query;
|
||||
};
|
||||
typedef intrusive_ptr<Filter<Card> > CardListFilterP;
|
||||
|
||||
// ----------------------------------------------------------------------------- : FilteredCardList
|
||||
|
||||
|
||||
@@ -56,6 +56,11 @@ void KeywordList::onChangeSet() {
|
||||
refreshList();
|
||||
}
|
||||
|
||||
void KeywordList::setFilter(const KeywordListFilterP& filter) {
|
||||
this->filter = filter;
|
||||
refreshList();
|
||||
}
|
||||
|
||||
void KeywordList::onAction(const Action& action, bool undone) {
|
||||
TYPE_CASE(action, AddKeywordAction) {
|
||||
if (action.action.adding != undone) {
|
||||
@@ -151,11 +156,15 @@ String match_string(const Keyword& a) {
|
||||
void KeywordList::getItems(vector<VoidP>& out) const {
|
||||
FOR_EACH(k, set->keywords) {
|
||||
k->fixed = false;
|
||||
out.push_back(k);
|
||||
if (!filter || filter->keep(*k)) {
|
||||
out.push_back(k);
|
||||
}
|
||||
}
|
||||
FOR_EACH(k, set->game->keywords) {
|
||||
k->fixed = true;
|
||||
out.push_back(k);
|
||||
if (!filter || filter->keep(*k)) {
|
||||
out.push_back(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
void KeywordList::sendEvent() {
|
||||
|
||||
@@ -12,8 +12,11 @@
|
||||
#include <util/prec.hpp>
|
||||
#include <gui/control/item_list.hpp>
|
||||
#include <data/keyword.hpp>
|
||||
#include <data/filter.hpp>
|
||||
#include <data/set.hpp>
|
||||
|
||||
typedef intrusive_ptr<Filter<Keyword> > KeywordListFilterP;
|
||||
|
||||
// ----------------------------------------------------------------------------- : Events
|
||||
|
||||
DECLARE_EVENT_TYPE(EVENT_KEYWORD_SELECT, <not used>)
|
||||
@@ -51,6 +54,9 @@ class KeywordList : public ItemList, public SetView {
|
||||
inline KeywordP getKeyword() const { return static_pointer_cast<Keyword>(selected_item); }
|
||||
inline void setKeyword(const KeywordP& kw) { selectItem(kw, true, false); }
|
||||
|
||||
/// Change the filter to use, can be null
|
||||
void setFilter(const KeywordListFilterP& filter);
|
||||
|
||||
// --------------------------------------------------- : Clipboard
|
||||
|
||||
bool canDelete() const;
|
||||
@@ -87,6 +93,7 @@ class KeywordList : public ItemList, public SetView {
|
||||
void storeColumns();
|
||||
|
||||
mutable wxListItemAttr item_attr; // for OnGetItemAttr
|
||||
KeywordListFilterP filter; ///< Which keywords to show?
|
||||
|
||||
/// How often is a keyword used in the set?
|
||||
int usage(const Keyword&) const;
|
||||
|
||||
+3
-178
@@ -11,10 +11,10 @@
|
||||
#include <gui/control/image_card_list.hpp>
|
||||
#include <gui/control/card_editor.hpp>
|
||||
#include <gui/control/text_ctrl.hpp>
|
||||
#include <gui/control/filter_ctrl.hpp>
|
||||
#include <gui/about_window.hpp> // for HoverButton
|
||||
#include <gui/update_checker.hpp>
|
||||
#include <gui/icon_menu.hpp>
|
||||
#include <gui/drop_down_list.hpp>
|
||||
#include <gui/util.hpp>
|
||||
#include <data/set.hpp>
|
||||
#include <data/game.hpp>
|
||||
@@ -35,177 +35,6 @@ DECLARE_TYPEOF_COLLECTION(AddCardsScriptP);
|
||||
#define HAVE_TOOLBAR_DROPDOWN_MENU 1
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------- : DropDownMRUList
|
||||
|
||||
/// A drop down list of recent choices, for autocomplete
|
||||
class DropDownMRUList : public DropDownList {
|
||||
public:
|
||||
DropDownMRUList(Window* parent, vector<String> const& choices)
|
||||
: DropDownList(parent)
|
||||
, choices(choices)
|
||||
{}
|
||||
|
||||
vector<String> choices;
|
||||
|
||||
protected:
|
||||
virtual size_t selection() const { return NO_SELECTION; }
|
||||
virtual size_t itemCount() const { return choices.size(); }
|
||||
virtual String itemText(size_t item) const { return choices.at(item); }
|
||||
virtual void select(size_t item);
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : FilterControl
|
||||
|
||||
/// Text control that forwards focus events to the parent
|
||||
class TextCtrlWithFocus : public wxTextCtrl {
|
||||
public:
|
||||
DECLARE_EVENT_TABLE();
|
||||
void forwardFocusEvent(wxFocusEvent&);
|
||||
void forwardKeyEvent(wxKeyEvent&);
|
||||
};
|
||||
|
||||
/// A search/filter textbox
|
||||
class FilterCtrl : public wxControl {
|
||||
public:
|
||||
FilterCtrl(wxWindow* parent, int id);
|
||||
/// Set the filter text
|
||||
void setFilter(const String& filter, bool event = false);
|
||||
void clearFilter(bool event = false) { setFilter(String(),event); }
|
||||
bool hasFilter() const { return !value.empty(); }
|
||||
String const& getFilter() const { return value; }
|
||||
|
||||
//bool AcceptsFocus() const { return false; }
|
||||
private:
|
||||
DECLARE_EVENT_TABLE();
|
||||
bool changing;
|
||||
wxString value;
|
||||
TextCtrlWithFocus* filter_ctrl;
|
||||
HoverButton* clear_button;
|
||||
|
||||
void update();
|
||||
bool hasFocus();
|
||||
// wxWidgets appears to have developed an overload allergy
|
||||
void onChange();
|
||||
void onChangeEvent(wxCommandEvent&);
|
||||
void onClear(wxCommandEvent&);
|
||||
void onSizeEvent(wxSizeEvent&);
|
||||
void onChar(wxKeyEvent&);
|
||||
void onSize();
|
||||
public:
|
||||
void onSetFocus(wxFocusEvent&);
|
||||
void onKillFocus(wxFocusEvent&);
|
||||
};
|
||||
|
||||
FilterCtrl::FilterCtrl(wxWindow* parent, int id)
|
||||
: wxControl(parent, id, wxDefaultPosition, wxSize(160,41), wxSTATIC_BORDER)
|
||||
, changing(false)
|
||||
{
|
||||
wxColour bg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
|
||||
SetBackgroundColour(bg);
|
||||
SetCursor(wxCURSOR_IBEAM);
|
||||
filter_ctrl = new TextCtrlWithFocus();
|
||||
filter_ctrl->Create(this, wxID_ANY, _(""), wxDefaultPosition, wxSize(130,-1), wxNO_BORDER);
|
||||
clear_button = new HoverButton(this, wxID_ANY, _("btn_clear_filter"), bg, false);
|
||||
clear_button->SetCursor(*wxSTANDARD_CURSOR);
|
||||
onSize();
|
||||
update();
|
||||
}
|
||||
|
||||
void FilterCtrl::setFilter(const String& new_value, bool event) {
|
||||
if (this->value == new_value) return;
|
||||
// update ui
|
||||
this->value = new_value;
|
||||
update();
|
||||
// send event
|
||||
if (event) {
|
||||
wxCommandEvent ev(wxEVT_COMMAND_TEXT_UPDATED, GetId());
|
||||
GetParent()->HandleWindowEvent(ev);
|
||||
}
|
||||
}
|
||||
|
||||
void FilterCtrl::update() {
|
||||
changing = true;
|
||||
if (!value.empty() || hasFocus()) {
|
||||
filter_ctrl->SetValue(value);
|
||||
wxColour fg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
|
||||
filter_ctrl->SetDefaultStyle(wxTextAttr(fg));
|
||||
filter_ctrl->SetForegroundColour(fg);
|
||||
} else {
|
||||
filter_ctrl->SetValue(_LABEL_("search cards"));
|
||||
wxColour fg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
|
||||
wxColour bg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
|
||||
filter_ctrl->SetDefaultStyle(wxTextAttr(lerp(fg,bg,0.5)));
|
||||
filter_ctrl->SetForegroundColour(lerp(fg,bg,0.5));
|
||||
}
|
||||
clear_button->Show(!value.empty());
|
||||
changing = false;
|
||||
}
|
||||
|
||||
void FilterCtrl::onChangeEvent(wxCommandEvent&) {
|
||||
if (!changing) {
|
||||
setFilter(filter_ctrl->GetValue(),true);
|
||||
}
|
||||
}
|
||||
void FilterCtrl::onChar(wxKeyEvent& ev) {
|
||||
if (ev.GetKeyCode() == WXK_ESCAPE) {
|
||||
// escape clears the filter box
|
||||
clearFilter(true);
|
||||
} else {
|
||||
ev.Skip();
|
||||
}
|
||||
}
|
||||
|
||||
void FilterCtrl::onClear(wxCommandEvent&) {
|
||||
clearFilter(true);
|
||||
}
|
||||
|
||||
void FilterCtrl::onSizeEvent(wxSizeEvent&) {
|
||||
onSize();
|
||||
}
|
||||
void FilterCtrl::onSize() {
|
||||
wxSize s = GetClientSize();
|
||||
wxSize fs = filter_ctrl->GetBestSize();
|
||||
wxSize cs = clear_button->GetBestSize();
|
||||
int margin = 2;
|
||||
filter_ctrl ->SetSize(margin, max(margin,(s.y-fs.y)/2), s.x - cs.x - 3*margin, fs.y);
|
||||
clear_button->SetSize(s.x - cs.x - margin, (s.y-cs.y)/2, cs.x, cs.y);
|
||||
}
|
||||
|
||||
void FilterCtrl::onSetFocus(wxFocusEvent&) {
|
||||
filter_ctrl->SetFocus();
|
||||
update();
|
||||
}
|
||||
void FilterCtrl::onKillFocus(wxFocusEvent&) {
|
||||
update();
|
||||
}
|
||||
|
||||
bool FilterCtrl::hasFocus() {
|
||||
wxWindow* focus = wxWindow::FindFocus();
|
||||
return focus == this || focus == filter_ctrl || focus == clear_button;
|
||||
}
|
||||
|
||||
BEGIN_EVENT_TABLE(FilterCtrl, wxControl)
|
||||
EVT_BUTTON (wxID_ANY, FilterCtrl::onClear)
|
||||
EVT_TEXT (wxID_ANY, FilterCtrl::onChangeEvent)
|
||||
EVT_SIZE (FilterCtrl::onSizeEvent)
|
||||
EVT_SET_FOCUS (FilterCtrl::onSetFocus)
|
||||
EVT_KILL_FOCUS(FilterCtrl::onKillFocus)
|
||||
EVT_CHAR (FilterCtrl::onChar)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
void TextCtrlWithFocus::forwardFocusEvent(wxFocusEvent& ev) {
|
||||
GetParent()->HandleWindowEvent(ev);
|
||||
}
|
||||
void TextCtrlWithFocus::forwardKeyEvent(wxKeyEvent& ev) {
|
||||
GetParent()->HandleWindowEvent(ev);
|
||||
}
|
||||
|
||||
BEGIN_EVENT_TABLE(TextCtrlWithFocus, wxTextCtrl)
|
||||
EVT_SET_FOCUS (TextCtrlWithFocus::forwardFocusEvent)
|
||||
EVT_KILL_FOCUS(TextCtrlWithFocus::forwardFocusEvent)
|
||||
EVT_CHAR (TextCtrlWithFocus::forwardKeyEvent)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
// ----------------------------------------------------------------------------- : CardsPanel
|
||||
|
||||
CardsPanel::CardsPanel(Window* parent, int id)
|
||||
@@ -387,7 +216,7 @@ void CardsPanel::initUI(wxToolBar* tb, wxMenuBar* mb) {
|
||||
#endif
|
||||
// Filter/search textbox
|
||||
tb->AddSeparator();
|
||||
if (!filter) filter = new FilterCtrl(tb, ID_CARD_FILTER);
|
||||
if (!filter) filter = new FilterCtrl(tb, ID_CARD_FILTER, _LABEL_("search cards"));
|
||||
tb->AddControl(filter);
|
||||
tb->Realize();
|
||||
// Menus
|
||||
@@ -518,11 +347,7 @@ void CardsPanel::onCommand(int id) {
|
||||
}
|
||||
case ID_CARD_FILTER: {
|
||||
// card filter has changed, update the card list
|
||||
if (filter->hasFilter()) {
|
||||
card_list->setFilter(intrusive(new QueryCardListFilter(filter->getFilter())));
|
||||
} else {
|
||||
card_list->setFilter(CardListFilterP());
|
||||
}
|
||||
card_list->setFilter(filter->getFilter<Card>());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
||||
@@ -49,6 +49,7 @@ void KeywordsPanel::initControls() {
|
||||
ref_param = new wxButton(panel, ID_KEYWORD_REF_PARAM, _BUTTON_("refer parameter"));
|
||||
rules = new TextCtrl(panel, ID_RULES, true);
|
||||
errors = new wxStaticText(panel, wxID_ANY, _(""));
|
||||
filter = nullptr;
|
||||
errors->SetForegroundColour(*wxRED);
|
||||
// warning about fixed keywords
|
||||
fixedL = new wxStaticText(panel, wxID_ANY, _(""));
|
||||
@@ -132,6 +133,10 @@ void KeywordsPanel::initUI(wxToolBar* tb, wxMenuBar* mb) {
|
||||
// Toolbar
|
||||
tb->AddTool(ID_KEYWORD_ADD, _(""), load_resource_tool_image(_("keyword_add")), wxNullBitmap, wxITEM_NORMAL,_TOOLTIP_("add keyword"), _HELP_("add keyword"));
|
||||
tb->AddTool(ID_KEYWORD_REMOVE, _(""), load_resource_tool_image(_("keyword_del")), wxNullBitmap, wxITEM_NORMAL,_TOOLTIP_("remove keyword"),_HELP_("remove keyword"));
|
||||
// Filter/search textbox
|
||||
tb->AddSeparator();
|
||||
if (!filter) filter = new FilterCtrl(tb, ID_KEYWORD_FILTER, _LABEL_("search keywords"));
|
||||
tb->AddControl(filter);
|
||||
tb->Realize();
|
||||
// Menus
|
||||
mb->Insert(2, menuKeyword, _MENU_("keywords"));
|
||||
@@ -141,6 +146,9 @@ void KeywordsPanel::destroyUI(wxToolBar* tb, wxMenuBar* mb) {
|
||||
// Toolbar
|
||||
tb->DeleteTool(ID_KEYWORD_ADD);
|
||||
tb->DeleteTool(ID_KEYWORD_REMOVE);
|
||||
tb->DeleteTool(filter->GetId()); filter = nullptr;
|
||||
// HACK: hardcoded size of rest of toolbar
|
||||
tb->DeleteToolByPos(12); // delete separator
|
||||
// Menus
|
||||
mb->Remove(2);
|
||||
|
||||
@@ -203,6 +211,11 @@ void KeywordsPanel::onCommand(int id) {
|
||||
ref_param->PopupMenu(&ref_menu, 0, ref_param->GetSize().y);
|
||||
break;
|
||||
}
|
||||
case ID_KEYWORD_FILTER: {
|
||||
// keyword filter has changed, update the list
|
||||
list->setFilter(filter->getFilter<Keyword>());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (id >= ID_PARAM_TYPE_MIN && id < ID_PARAM_TYPE_MAX) {
|
||||
// add parameter
|
||||
|
||||
@@ -11,12 +11,14 @@
|
||||
|
||||
#include <util/prec.hpp>
|
||||
#include <gui/set/panel.hpp>
|
||||
#include <gui/control/filter_ctrl.hpp>
|
||||
|
||||
class wxSplitterWindow;
|
||||
class KeywordList;
|
||||
class TextCtrl;
|
||||
class IconMenu;
|
||||
struct KeywordSelectEvent;
|
||||
class FilterCtrl;
|
||||
|
||||
// ----------------------------------------------------------------------------- : KeywordsPanel
|
||||
|
||||
@@ -69,6 +71,7 @@ class KeywordsPanel : public SetWindowPanel {
|
||||
wxChoice* mode;
|
||||
wxButton* add_param;
|
||||
wxButton* ref_param;
|
||||
FilterCtrl* filter;
|
||||
|
||||
// --------------------------------------------------- : Events
|
||||
void onKeywordSelect(KeywordSelectEvent& ev);
|
||||
|
||||
@@ -530,7 +530,7 @@ void StatsPanel::onGraphSelect(wxCommandEvent&) {
|
||||
|
||||
// ----------------------------------------------------------------------------- : Filtering card list
|
||||
|
||||
class StatsFilter : public CardListFilter {
|
||||
class StatsFilter : public Filter<Card> {
|
||||
public:
|
||||
StatsFilter(GraphData& data, const vector<int> match) {
|
||||
data.indices(match, indices);
|
||||
|
||||
@@ -622,6 +622,12 @@
|
||||
<Filter
|
||||
Name="control"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\gui\control\filter_ctrl.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\gui\control\filter_ctrl.hpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\gui\control\gallery_list.cpp">
|
||||
</File>
|
||||
@@ -1884,6 +1890,9 @@
|
||||
<File
|
||||
RelativePath=".\data\export_template.hpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\data\filter.hpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\data\font.cpp">
|
||||
<FileConfiguration
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -105,7 +105,6 @@ enum ChildMenuID {
|
||||
, ID_CARD_ROTATE_90
|
||||
, ID_CARD_ROTATE_180
|
||||
, ID_CARD_ROTATE_270
|
||||
, ID_CARD_FILTER
|
||||
// CardList
|
||||
, ID_SELECT_COLUMNS
|
||||
|
||||
@@ -181,6 +180,7 @@ enum ChildMenuID {
|
||||
|
||||
// On cards panel
|
||||
, ID_COLLAPSE_NOTES = 8001
|
||||
, ID_CARD_FILTER
|
||||
|
||||
// Style panel
|
||||
, ID_STYLE_USE_FOR_ALL = 8011
|
||||
@@ -190,6 +190,7 @@ enum ChildMenuID {
|
||||
, ID_KEYWORD_ADD_PARAM = 8021
|
||||
, ID_KEYWORD_REF_PARAM
|
||||
, ID_KEYWORD_MODE
|
||||
, ID_KEYWORD_FILTER
|
||||
, ID_PARAM_TYPE_MIN = 8101
|
||||
, ID_PARAM_TYPE_MAX = 8200
|
||||
, ID_PARAM_REF_MIN = 8201
|
||||
|
||||
Reference in New Issue
Block a user