Commit 3604888a authored by twanvl's avatar twanvl

Fixed undo issue for combined editor;

Added keyword usage statistics
parent ea2ae3b4
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
class Game; class Game;
class Dependency; class Dependency;
class Keyword;
DECLARE_POINTER_TYPE(Card); DECLARE_POINTER_TYPE(Card);
DECLARE_POINTER_TYPE(Field); DECLARE_POINTER_TYPE(Field);
DECLARE_POINTER_TYPE(Value); DECLARE_POINTER_TYPE(Value);
...@@ -50,6 +51,9 @@ class Card : public IntrusivePtrVirtualBase { ...@@ -50,6 +51,9 @@ class Card : public IntrusivePtrVirtualBase {
/// Styling information for a particular stylesheet /// Styling information for a particular stylesheet
IndexMap<FieldP, ValueP>& extraDataFor(const StyleSheet& stylesheet) ; IndexMap<FieldP, ValueP>& extraDataFor(const StyleSheet& stylesheet) ;
/// Keyword usage statistics
vector<pair<Value*,const Keyword*> > keyword_usage;
/// Get the identification of this card, an identification is something like a name, title, etc. /// Get the identification of this card, an identification is something like a name, title, etc.
/** May return "" */ /** May return "" */
String identification() const; String identification() const;
......
...@@ -199,6 +199,8 @@ StyleListener::~StyleListener() { ...@@ -199,6 +199,8 @@ StyleListener::~StyleListener() {
// ----------------------------------------------------------------------------- : Value // ----------------------------------------------------------------------------- : Value
IMPLEMENT_DYNAMIC_ARG(Value*, value_being_updated, nullptr);
Value::~Value() {} Value::~Value() {}
IMPLEMENT_REFLECTION_NAMELESS(Value) { IMPLEMENT_REFLECTION_NAMELESS(Value) {
......
...@@ -29,6 +29,9 @@ class DataViewer; class DataEditor; ...@@ -29,6 +29,9 @@ class DataViewer; class DataEditor;
DECLARE_POINTER_TYPE(ValueViewer); DECLARE_POINTER_TYPE(ValueViewer);
DECLARE_POINTER_TYPE(ValueEditor); DECLARE_POINTER_TYPE(ValueEditor);
// Value for which script updates are being run
DECLARE_DYNAMIC_ARG(Value*, value_being_updated);
// ----------------------------------------------------------------------------- : Field // ----------------------------------------------------------------------------- : Field
/// Information on how to store a value /// Information on how to store a value
......
...@@ -119,7 +119,8 @@ String TextValue::toString() const { ...@@ -119,7 +119,8 @@ String TextValue::toString() const {
} }
bool TextValue::update(Context& ctx) { bool TextValue::update(Context& ctx) {
Value::update(ctx); Value::update(ctx);
WITH_DYNAMIC_ARG(last_update_age, value.isDefault() ? 0 : last_update.get()); WITH_DYNAMIC_ARG(last_update_age, last_update.get());
WITH_DYNAMIC_ARG(value_being_updated, this);
bool change = field().default_script.invokeOnDefault(ctx, value) bool change = field().default_script.invokeOnDefault(ctx, value)
| field(). script.invokeOn(ctx, value); | field(). script.invokeOn(ctx, value);
if (change) last_update.update(); if (change) last_update.update();
......
...@@ -92,7 +92,7 @@ class TextStyle : public Style { ...@@ -92,7 +92,7 @@ class TextStyle : public Style {
/// The Value in a TextField /// The Value in a TextField
class TextValue : public Value { class TextValue : public Value {
public: public:
inline TextValue(const TextFieldP& field) : Value(field) {} inline TextValue(const TextFieldP& field) : Value(field), last_update(1) {}
DECLARE_HAS_FIELD(Text) DECLARE_HAS_FIELD(Text)
typedef Defaultable<String> ValueType; typedef Defaultable<String> ValueType;
......
...@@ -17,6 +17,8 @@ DECLARE_TYPEOF_COLLECTION(KeywordModeP); ...@@ -17,6 +17,8 @@ DECLARE_TYPEOF_COLLECTION(KeywordModeP);
DECLARE_TYPEOF_COLLECTION(KeywordParamP); DECLARE_TYPEOF_COLLECTION(KeywordParamP);
DECLARE_TYPEOF_COLLECTION(const Keyword*); DECLARE_TYPEOF_COLLECTION(const Keyword*);
DECLARE_POINTER_TYPE(KeywordParamValue); DECLARE_POINTER_TYPE(KeywordParamValue);
class Value;
DECLARE_DYNAMIC_ARG(Value*, value_being_updated);
// ----------------------------------------------------------------------------- : Reflection // ----------------------------------------------------------------------------- : Reflection
...@@ -329,6 +331,8 @@ KeywordTrie* KeywordTrie::insertAnyStar() { ...@@ -329,6 +331,8 @@ KeywordTrie* KeywordTrie::insertAnyStar() {
// ----------------------------------------------------------------------------- : KeywordDatabase // ----------------------------------------------------------------------------- : KeywordDatabase
IMPLEMENT_DYNAMIC_ARG(KeywordUsageStatistics*, keyword_usage_statistics, nullptr);
KeywordDatabase::KeywordDatabase() KeywordDatabase::KeywordDatabase()
: root(nullptr) : root(nullptr)
{} {}
...@@ -440,6 +444,17 @@ String KeywordDatabase::expand(const String& text, ...@@ -440,6 +444,17 @@ String KeywordDatabase::expand(const String& text,
Context& ctx) const { Context& ctx) const {
assert(combine_script); assert(combine_script);
// Clean up usage statistics
KeywordUsageStatistics* stat = keyword_usage_statistics();
Value* stat_key = value_being_updated();
if (stat && stat_key) {
for (size_t i = stat->size() - 1 ; i + 1 > 0 ; --i) { // loop backwards
if ((*stat)[i].first == stat_key) {
stat->erase(stat->begin() + i);
}
}
}
// Remove all old reminder texts // Remove all old reminder texts
String s = remove_tag_contents(text, _("<atom-reminder")); String s = remove_tag_contents(text, _("<atom-reminder"));
s = remove_tag_contents(s, _("<atom-keyword")); // OLD, TODO: REMOVEME s = remove_tag_contents(s, _("<atom-keyword")); // OLD, TODO: REMOVEME
...@@ -614,6 +629,11 @@ String KeywordDatabase::expand(const String& text, ...@@ -614,6 +629,11 @@ String KeywordDatabase::expand(const String& text,
result += _("</kw-"); result += expand_type; result += _(">"); result += _("</kw-"); result += expand_type; result += _(">");
} }
// Add to usage statistics
if (stat && stat_key) {
stat->push_back(make_pair(stat_key, kw));
}
// After keyword // After keyword
s = s.substr(end); s = s.substr(end);
untagged = untagged.substr(start_u + len_u); untagged = untagged.substr(start_u + len_u);
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <util/prec.hpp> #include <util/prec.hpp>
#include <script/scriptable.hpp> #include <script/scriptable.hpp>
#include <util/dynamic_arg.hpp>
#include <wx/regex.h> #include <wx/regex.h>
DECLARE_POINTER_TYPE(KeywordParam); DECLARE_POINTER_TYPE(KeywordParam);
...@@ -18,6 +19,7 @@ DECLARE_POINTER_TYPE(KeywordMode); ...@@ -18,6 +19,7 @@ DECLARE_POINTER_TYPE(KeywordMode);
DECLARE_POINTER_TYPE(Keyword); DECLARE_POINTER_TYPE(Keyword);
DECLARE_POINTER_TYPE(ParamReferenceType); DECLARE_POINTER_TYPE(ParamReferenceType);
class KeywordTrie; class KeywordTrie;
class Value;
// ----------------------------------------------------------------------------- : Keyword parameters // ----------------------------------------------------------------------------- : Keyword parameters
...@@ -115,6 +117,10 @@ class Keyword : public IntrusivePtrVirtualBase { ...@@ -115,6 +117,10 @@ class Keyword : public IntrusivePtrVirtualBase {
// ----------------------------------------------------------------------------- : Using keywords // ----------------------------------------------------------------------------- : Using keywords
/// Store keyword usage statistics here, using value_being_updated as the key
typedef vector<pair<Value*, const Keyword*> > KeywordUsageStatistics;
DECLARE_DYNAMIC_ARG(KeywordUsageStatistics*, keyword_usage_statistics);
/// A database of keywords to allow for fast matching /// A database of keywords to allow for fast matching
/** NOTE: keywords may not be altered after they are added to the database, /** NOTE: keywords may not be altered after they are added to the database,
* The database should be rebuild. * The database should be rebuild.
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <gui/icon_menu.hpp> #include <gui/icon_menu.hpp>
#include <data/set.hpp> #include <data/set.hpp>
#include <data/game.hpp> #include <data/game.hpp>
#include <data/card.hpp>
#include <data/keyword.hpp> #include <data/keyword.hpp>
#include <data/action/value.hpp> #include <data/action/value.hpp>
#include <data/action/keyword.hpp> #include <data/action/keyword.hpp>
...@@ -20,6 +21,7 @@ ...@@ -20,6 +21,7 @@
#include <wx/clipbrd.h> #include <wx/clipbrd.h>
DECLARE_TYPEOF_COLLECTION(KeywordP); DECLARE_TYPEOF_COLLECTION(KeywordP);
DECLARE_TYPEOF_COLLECTION(CardP);
// ----------------------------------------------------------------------------- : Events // ----------------------------------------------------------------------------- : Events
...@@ -49,6 +51,7 @@ void KeywordList::onBeforeChangeSet() { ...@@ -49,6 +51,7 @@ void KeywordList::onBeforeChangeSet() {
storeColumns(); storeColumns();
} }
void KeywordList::onChangeSet() { void KeywordList::onChangeSet() {
updateUsageStatistics();
refreshList(); refreshList();
} }
...@@ -83,6 +86,15 @@ void KeywordList::onAction(const Action& action, bool undone) { ...@@ -83,6 +86,15 @@ void KeywordList::onAction(const Action& action, bool undone) {
} }
} }
void KeywordList::updateUsageStatistics() {
usage_statistics.clear();
FOR_EACH_CONST(card, set->cards) {
for (KeywordUsageStatistics::const_iterator it = card->keyword_usage.begin() ; it != card->keyword_usage.end() ; ++it) {
usage_statistics[it->second]++;
}
}
}
// ----------------------------------------------------------------------------- : Clipboard // ----------------------------------------------------------------------------- : Clipboard
bool KeywordList::canCopy() const { return !!selected_item; } bool KeywordList::canCopy() const { return !!selected_item; }
...@@ -154,13 +166,19 @@ bool KeywordList::compareItems(void* a, void* b) const { ...@@ -154,13 +166,19 @@ bool KeywordList::compareItems(void* a, void* b) const {
case 0: return ka.keyword < kb.keyword; case 0: return ka.keyword < kb.keyword;
case 1: return ka.match < kb.match; case 1: return ka.match < kb.match;
case 2: return ka.mode < kb.mode; case 2: return ka.mode < kb.mode;
//case 3: case 3: return usage(ka) < usage(kb);
case 4: return ka.reminder.getUnparsed() < kb.reminder.getUnparsed(); case 4: return ka.reminder.getUnparsed() < kb.reminder.getUnparsed();
default: // TODO: 3 default: // TODO: 3
return ka.keyword < kb.keyword; return ka.keyword < kb.keyword;
} }
} }
int KeywordList::usage(const Keyword& kw) const {
map<const Keyword*,int>::const_iterator it = usage_statistics.find(&kw);
if (it == usage_statistics.end()) return 0;
else return it->second;
}
// ----------------------------------------------------------------------------- : KeywordList : Item text // ----------------------------------------------------------------------------- : KeywordList : Item text
String KeywordList::OnGetItemText (long pos, long col) const { String KeywordList::OnGetItemText (long pos, long col) const {
...@@ -169,7 +187,7 @@ String KeywordList::OnGetItemText (long pos, long col) const { ...@@ -169,7 +187,7 @@ String KeywordList::OnGetItemText (long pos, long col) const {
case 0: return kw.keyword; case 0: return kw.keyword;
case 1: return match_string(kw); case 1: return match_string(kw);
case 2: return kw.mode; case 2: return kw.mode;
case 3: return _("?"); case 3: return String::Format(_("%d"), usage(kw));
case 4: { case 4: {
// convert all whitespace to ' ' // convert all whitespace to ' '
String formatted; String formatted;
......
...@@ -44,6 +44,7 @@ class KeywordList : public ItemList, public SetView { ...@@ -44,6 +44,7 @@ class KeywordList : public ItemList, public SetView {
virtual void onBeforeChangeSet(); virtual void onBeforeChangeSet();
virtual void onChangeSet(); virtual void onChangeSet();
virtual void onAction(const Action&, bool); virtual void onAction(const Action&, bool);
void updateUsageStatistics();
// --------------------------------------------------- : Selection // --------------------------------------------------- : Selection
...@@ -86,6 +87,10 @@ class KeywordList : public ItemList, public SetView { ...@@ -86,6 +87,10 @@ class KeywordList : public ItemList, public SetView {
mutable wxListItemAttr item_attr; // for OnGetItemAttr mutable wxListItemAttr item_attr; // for OnGetItemAttr
/// How often is a keyword used in the set?
int usage(const Keyword&) const;
map<const Keyword*,int> usage_statistics;
// --------------------------------------------------- : Window events // --------------------------------------------------- : Window events
DECLARE_EVENT_TABLE(); DECLARE_EVENT_TABLE();
......
...@@ -285,6 +285,8 @@ SCRIPT_RULE_2_N_DEP(expand_keywords, ScriptValueP, _("default expand"), default_ ...@@ -285,6 +285,8 @@ SCRIPT_RULE_2_N_DEP(expand_keywords, ScriptValueP, _("default expand"), default_
db.add(set->game->keywords); db.add(set->game->keywords);
db.add(set->keywords); db.add(set->keywords);
} }
SCRIPT_OPTIONAL_PARAM_(CardP, card);
WITH_DYNAMIC_ARG(keyword_usage_statistics, card ? &card->keyword_usage : nullptr);
SCRIPT_RETURN(db.expand(input, default_expand, combine, ctx)); SCRIPT_RETURN(db.expand(input, default_expand, combine, ctx));
} }
SCRIPT_RULE_2_DEPENDENCIES(expand_keywords) { SCRIPT_RULE_2_DEPENDENCIES(expand_keywords) {
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
/** Age is counted using a global variable */ /** Age is counted using a global variable */
class Age { class Age {
public: public:
/// Construct a new age value, /// Construct a new age value
Age() { Age() {
update(); update();
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment