Added 'filter' support to position function; Made sure sort script can depend on the value of the field itself.

Cleaned up some things, why is a blank image not thread safe?

git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@548 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
twanvl
2007-07-10 18:57:41 +00:00
parent 7676c0b6b6
commit 8833d07c4a
20 changed files with 229 additions and 142 deletions
+16
View File
@@ -37,6 +37,10 @@ Field::Field()
Field::~Field() {}
void Field::initDependencies(Context& ctx, const Dependency& dep) const {
sort_script.initDependencies(ctx, dep);
}
IMPLEMENT_REFLECTION(Field) {
REFLECT_IF_NOT_READING {
String type = typeName();
@@ -215,6 +219,18 @@ bool Value::equals(const Value* that) {
return this == that;
}
bool Value::update(Context& ctx) {
updateAge();
updateSortValue(ctx);
return false;
}
void Value::updateAge() {
last_script_update.update();
}
void Value::updateSortValue(Context& ctx) {
sort_value = fieldP->sort_script.invoke(ctx)->toString();
}
void init_object(const FieldP& field, ValueP& value) {
if (!value)
value = field->newValue(field);
+12 -12
View File
@@ -68,9 +68,7 @@ class Field : public IntrusivePtrVirtualBase {
virtual String typeName() const = 0;
/// Add the given dependency to the dependet_scripts list for the variables this field depends on
inline virtual void initDependencies(Context& ctx, const Dependency& dep) const {
sort_script.initDependencies(ctx, dep);
}
virtual void initDependencies(Context& ctx, const Dependency& dep) const;
private:
DECLARE_REFLECTION_VIRTUAL();
@@ -186,7 +184,7 @@ class Value : public IntrusivePtrVirtualBase {
const FieldP fieldP; ///< Field this value is for, should have the right type!
Age last_script_update; ///< When where the scripts last updated? (by calling update)
ScriptValueP sortValue; ///< How this should be sorted.
String sort_value; ///< How this should be sorted.
/// Get a copy of this value
virtual ValueP clone() const = 0;
@@ -194,11 +192,7 @@ class Value : public IntrusivePtrVirtualBase {
/// Convert this value to a string for use in tables
virtual String toString() const = 0;
/// Apply scripts to this value, return true if the value has changed
inline virtual bool update(Context& ctx) {
sortValue = fieldP->sort_script.invoke(ctx);
last_script_update.update();
return false;
}
virtual bool update(Context& ctx);
/// This value has been updated by an action
/** Does nothing for most Values, only FakeValues can update underlying data */
virtual void onAction(Action& a, bool undone) {}
@@ -208,11 +202,17 @@ class Value : public IntrusivePtrVirtualBase {
*/
virtual bool equals(const Value* that);
/// Get the sort key for this value.
inline String getSortKey () const {
return sortValue == script_nil ? *sortValue : toString();
/// Get the key to use for sorting this value
inline String getSortKey() const {
return fieldP->sort_script ? sort_value : toString();
}
protected:
/// update() split into two functions;.
/** Derived classes should put their stuff in between if they need the age in scripts */
void updateAge();
void updateSortValue(Context& ctx);
private:
DECLARE_REFLECTION_VIRTUAL();
};
+3 -3
View File
@@ -8,7 +8,6 @@
#include <data/field/choice.hpp>
#include <util/io/package.hpp>
#include <wx/spinctrl.h>
#include <wx/imaglist.h>
DECLARE_TYPEOF_COLLECTION(ChoiceField::ChoiceP);
@@ -312,9 +311,10 @@ String ChoiceValue::toString() const {
return value();
}
bool ChoiceValue::update(Context& ctx) {
bool change = field().default_script.invokeOnDefault(ctx, value)
| field(). script.invokeOn(ctx, value);
Value::update(ctx);
return field().default_script.invokeOnDefault(ctx, value)
| field(). script.invokeOn(ctx, value);
return change;
}
IMPLEMENT_REFLECTION_NAMELESS(ChoiceValue) {
+3 -2
View File
@@ -91,9 +91,10 @@ String ColorValue::toString() const {
return _("<color>");
}
bool ColorValue::update(Context& ctx) {
bool change = field().default_script.invokeOnDefault(ctx, value)
| field(). script.invokeOn(ctx, value);
Value::update(ctx);
return field().default_script.invokeOnDefault(ctx, value)
| field(). script.invokeOn(ctx, value);
return change;
}
IMPLEMENT_REFLECTION_NAMELESS(ColorValue) {
+3 -2
View File
@@ -66,9 +66,10 @@ String InfoValue::toString() const {
return value;
}
bool InfoValue::update(Context& ctx) {
Value::update(ctx);
if (value.empty()) value = field().name;
return field().script.invokeOn(ctx, value);
bool change = field().script.invokeOn(ctx, value);
Value::update(ctx);
return change;
}
IMPLEMENT_REFLECTION_NAMELESS(InfoValue) {
+2 -1
View File
@@ -127,12 +127,13 @@ String TextValue::toString() const {
return untag_hide_sep(value());
}
bool TextValue::update(Context& ctx) {
Value::update(ctx);
updateAge();
WITH_DYNAMIC_ARG(last_update_age, last_update.get());
WITH_DYNAMIC_ARG(value_being_updated, this);
bool change = field().default_script.invokeOnDefault(ctx, value)
| field(). script.invokeOn(ctx, value);
if (change) last_update.update();
updateSortValue(ctx);
return change;
}
+25 -5
View File
@@ -208,23 +208,43 @@ void reflect_set_info_get_member(GetMember& tag, const IndexMap<FieldP, ValueP>&
REFLECT_NAMELESS(data);
}
int Set::positionOfCard(const CardP& card, const ScriptValueP& order_by) {
int Set::positionOfCard(const CardP& card, const ScriptValueP& order_by, const ScriptValueP& filter) {
// TODO : Lock the map?
assert(order_by);
OrderCacheP& order = order_cache[order_by];
OrderCacheP& order = order_cache[make_pair(order_by,filter)];
if (!order) {
// 1. make a list of the order value for each card
vector<String> values; values.reserve(cards.size());
vector<int> keep; if(filter) keep.reserve(cards.size());
FOR_EACH_CONST(c, cards) {
values.push_back(*order_by->eval(getContext(c)));
Context& ctx = getContext(c);
values.push_back(*order_by->eval(ctx));
if (filter) {
keep.push_back(*filter->eval(ctx));
}
}
// 2. initialize order cache
order = new_intrusive2<OrderCache<CardP> >(cards, values);
// 3. initialize order cache
order = new_intrusive3<OrderCache<CardP> >(cards, values, filter ? &keep : nullptr);
}
return order->find(card);
}
int Set::numberOfCards(const ScriptValueP& filter) {
if (!filter) return (int)cards.size();
map<ScriptValueP,int>::const_iterator it = filter_cache.find(filter);
if (it !=filter_cache.end()) {
return it->second;
} else {
int n = 0;
FOR_EACH_CONST(c, cards) {
if (*filter->eval(getContext(c))) ++n;
}
filter_cache.insert(make_pair(filter,n));
return n;
}
}
void Set::clearOrderCache() {
order_cache.clear();
filter_cache.clear();
}
// ----------------------------------------------------------------------------- : SetView
+5 -2
View File
@@ -106,7 +106,9 @@ class Set : public Packaged {
}
/// Find the position of a card in this set, when the card list is sorted using the given cirterium
int positionOfCard(const CardP& card, const ScriptValueP& order_by);
int positionOfCard(const CardP& card, const ScriptValueP& order_by, const ScriptValueP& filter);
/// Find the number of cards that match the given filter
int numberOfCards(const ScriptValueP& filter);
/// Clear the order_cache used by positionOfCard
void clearOrderCache();
@@ -122,7 +124,8 @@ class Set : public Packaged {
/// Object for executing scripts from the thumbnail thread
scoped_ptr<SetScriptContext> thumbnail_script_context;
/// Cache of cards ordered by some criterion
map<ScriptValueP,OrderCacheP> order_cache;
map<pair<ScriptValueP,ScriptValueP>,OrderCacheP> order_cache;
map<ScriptValueP,int> filter_cache;
};
inline String type_name(const Set&) {