From 4a6e10ad93c082d5497bd1af32f313d3dec3dac3 Mon Sep 17 00:00:00 2001 From: twanvl Date: Fri, 18 May 2007 21:26:21 +0000 Subject: [PATCH] Support for extra card fields in stylesheets; Fixed some bugs: - Missing choice images can crash mse. - The wrong style is used for making preview choice images on style panel. FOR_EACH(x, *y.z) should now work without parentheses on linux as well. git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@389 0fc631ac-6414-0410-93d0-97cfa31319b6 --- src/data/card.hpp | 3 ++ src/data/set.cpp | 2 +- src/data/set.hpp | 4 +-- src/data/stylesheet.cpp | 24 +++++++++++--- src/data/stylesheet.hpp | 5 ++- src/gui/control/graph.cpp | 2 +- src/gui/control/native_look_editor.cpp | 2 +- src/gui/image_slice_window.hpp | 2 +- src/gui/thumbnail_thread.cpp | 9 +++++- src/gui/value/text.cpp | 7 ++++- src/mse.vcproj | 6 ++-- src/render/card/viewer.cpp | 43 +++++++++++++++++++------- src/render/card/viewer.hpp | 7 +++-- src/script/dependency.hpp | 1 + src/script/script_manager.cpp | 28 +++++++++++++++-- src/script/script_manager.hpp | 4 +++ src/util/error.cpp | 4 ++- src/util/for_each.hpp | 12 +++---- src/util/index_map.hpp | 13 ++++++-- 19 files changed, 136 insertions(+), 42 deletions(-) diff --git a/src/data/card.hpp b/src/data/card.hpp index 6076cbc9..fe50bf34 100644 --- a/src/data/card.hpp +++ b/src/data/card.hpp @@ -34,6 +34,9 @@ class Card : public IntrusivePtrVirtualBase { /// The values on the fields of the card. /** The indices should correspond to the card_fields in the Game */ IndexMap data; + /// The values on the extra fields of the card. + /** The indices should correspond to the extra_card_fields in the StyleSheet */ + IndexMap extra_data; /// Notes for this card String notes; /// Alternative style to use for this card diff --git a/src/data/set.cpp b/src/data/set.cpp index f7549d7f..9e63c653 100644 --- a/src/data/set.cpp +++ b/src/data/set.cpp @@ -53,7 +53,7 @@ Context& Set::getContext(const CardP& card) { assert(wxThread::IsMain()); return script_manager->getContext(card); } -void Set::updateFor(const CardP& card) { +void Set::updateStyles(const CardP& card) { script_manager->updateStyles(card); } void Set::updateDelayed() { diff --git a/src/data/set.hpp b/src/data/set.hpp index bf6836fe..ac4b89b3 100644 --- a/src/data/set.hpp +++ b/src/data/set.hpp @@ -66,8 +66,8 @@ class Set : public Packaged { /// A context for performing scripts on a particular card /** Should only be used from the main thread! */ Context& getContext(const CardP& card); - /// Update styles for a card - void updateFor(const CardP& card); + /// Update styles and extra_card_fields for a card + void updateStyles(const CardP& card); /// Update scripts that were delayed void updateDelayed(); /// A context for performing scripts diff --git a/src/data/stylesheet.cpp b/src/data/stylesheet.cpp index f561ea99..3dbd78f4 100644 --- a/src/data/stylesheet.cpp +++ b/src/data/stylesheet.cpp @@ -12,6 +12,7 @@ #include DECLARE_TYPEOF_COLLECTION(StyleSheet*); +DECLARE_TYPEOF_COLLECTION(FieldP); // ----------------------------------------------------------------------------- : StyleSheet @@ -62,22 +63,35 @@ IMPLEMENT_REFLECTION(StyleSheet) { REFLECT(game); REFLECT_BASE(Packaged); - REFLECT(init_script); REFLECT(card_width); REFLECT(card_height); REFLECT(card_dpi); REFLECT(card_background); + REFLECT(init_script); + // styling + REFLECT(styling_fields); + REFLECT_IF_READING styling_style.init(styling_fields); + REFLECT(styling_style); + // style of game fields if (game) { REFLECT_IF_READING { card_style.init(game->card_fields); set_info_style.cloneFrom(game->default_set_style); } - REFLECT(card_style); REFLECT(set_info_style); + REFLECT(card_style); } - REFLECT(styling_fields); - REFLECT_IF_READING styling_style.init(styling_fields); - REFLECT(styling_style); + // extra card fields + REFLECT(extra_card_fields); + REFLECT_IF_READING { + if (extra_card_style.init(extra_card_fields)) { + // make sure the extra_card_fields are not editable and savable + FOR_EACH(f, extra_card_fields) { + f->editable = f->save_value = false; + } + } + } + REFLECT(extra_card_style); } diff --git a/src/data/stylesheet.hpp b/src/data/stylesheet.hpp index e1f08727..b2b1f90c 100644 --- a/src/data/stylesheet.hpp +++ b/src/data/stylesheet.hpp @@ -38,7 +38,10 @@ class StyleSheet : public Packaged { /// The styling for set info fields /** The indices should correspond to the set_fields in the Game */ IndexMap set_info_style; - /// Extra fields for styling + /// Extra card fields for boxes and borders + vector extra_card_fields; + IndexMap extra_card_style; + /// Extra fields for styling options vector styling_fields; /// The styling for the extra set fields /** The indices should correspond to the styling_fields */ diff --git a/src/gui/control/graph.cpp b/src/gui/control/graph.cpp index 5209dd56..128c732b 100644 --- a/src/gui/control/graph.cpp +++ b/src/gui/control/graph.cpp @@ -79,7 +79,7 @@ GraphData::GraphData(const GraphDataPre& d) } } else if (a->order) { // specific group order - FOR_EACH_CONST(gn, (*(a->order))) { + FOR_EACH_CONST(gn, *a->order) { UInt count = counts[gn]; a->groups.push_back(GraphGroup(gn, count)); a->max = max(a->max, count); diff --git a/src/gui/control/native_look_editor.cpp b/src/gui/control/native_look_editor.cpp index aa9c3621..cd0af335 100644 --- a/src/gui/control/native_look_editor.cpp +++ b/src/gui/control/native_look_editor.cpp @@ -192,7 +192,7 @@ StylingEditor::StylingEditor(Window* parent, int id, long style) {} void StylingEditor::showStylesheet(const StyleSheetP& stylesheet) { - setStyles(set->stylesheet, stylesheet->styling_style); + setStyles(stylesheet, stylesheet->styling_style); setData(set->stylingDataFor(*stylesheet)); } diff --git a/src/gui/image_slice_window.hpp b/src/gui/image_slice_window.hpp index 8a41cd3a..3625403e 100644 --- a/src/gui/image_slice_window.hpp +++ b/src/gui/image_slice_window.hpp @@ -10,11 +10,11 @@ // ----------------------------------------------------------------------------- : Includes #include -#include class ImageSlicePreview; class ImageSliceSelector; class wxSpinEvent; +class wxSpinCtrl; DECLARE_POINTER_TYPE(AlphaMask); // ----------------------------------------------------------------------------- : ImageSlice diff --git a/src/gui/thumbnail_thread.cpp b/src/gui/thumbnail_thread.cpp index 4e0d64b9..c7bdb98f 100644 --- a/src/gui/thumbnail_thread.cpp +++ b/src/gui/thumbnail_thread.cpp @@ -8,6 +8,7 @@ #include #include +#include #include typedef pair pair_ThumbnailRequestP_Image; @@ -71,7 +72,13 @@ wxThread::ExitCode ThumbnailThreadWorker::Entry() { parent->open_requests.pop_front(); } // perform request - Image img = current->generate(); + Image img; + try { + img = current->generate(); + } catch (const Error& e) { + handle_error(e, false, false); + } catch (...) { + } // store in cache if (img.Ok()) { String filename = image_cache_dir() + safe_filename(current->cache_name) + _(".png"); diff --git a/src/gui/value/text.cpp b/src/gui/value/text.cpp index 24ef9cd6..d8d7ddb3 100644 --- a/src/gui/value/text.cpp +++ b/src/gui/value/text.cpp @@ -196,8 +196,13 @@ bool TextValueEditor::onChar(wxKeyEvent& ev) { } break; default: + #ifdef __WXMSW__ + if (ev.GetKeyCode() >= _(' ') && ev.GetKeyCode() == (int)ev.GetRawKeyCode()) { + // This check is need, otherwise pressing a key, say "0" on the numpad produces "a0" + // (don't ask me why) + #else if (ev.GetKeyCode() >= _(' ') /*&& ev.GetKeyCode() == (int)ev.GetRawKeyCode()*/) { -// if (ev.GetKeyCode() >= _(' ') && ev.GetKeyCode() == (int)ev.GetRawKeyCode()) { + #endif // TODO: Find a more correct way to determine normal characters, // this might not work for internationalized input. // It might also not be portable! diff --git a/src/mse.vcproj b/src/mse.vcproj index 81d03814..2b8317b8 100644 --- a/src/mse.vcproj +++ b/src/mse.vcproj @@ -2506,6 +2506,9 @@ + + @@ -2534,9 +2537,6 @@ - - diff --git a/src/render/card/viewer.cpp b/src/render/card/viewer.cpp index 648b530e..fbc50412 100644 --- a/src/render/card/viewer.cpp +++ b/src/render/card/viewer.cpp @@ -41,10 +41,14 @@ void DataViewer::draw(RotatedDC& dc, const Color& background) { clearDC(dc.getDC(), background); // update style scripts try { - Context& ctx = getContext(); - FOR_EACH(v, viewers) { - if (v->getStyle()->update(ctx)) { - v->getStyle()->tellListeners(); + if (card) { + set->updateStyles(card); + } else { + Context& ctx = getContext(); + FOR_EACH(v, viewers) { + if (v->getStyle()->update(ctx)) { + v->getStyle()->tellListeners(); + } } } } catch (const Error& e) { @@ -91,8 +95,9 @@ void DataViewer::setCard(const CardP& card, bool refresh) { assert(set); this->card = card; stylesheet = new_stylesheet; - setStyles(stylesheet, stylesheet->card_style); - setData(card->data); + setStyles(stylesheet, stylesheet->card_style, &stylesheet->extra_card_style); + card->extra_data.init(stylesheet->extra_card_fields); // make sure extra_data is initialized + setData(card->data, &card->extra_data); onChangeSize(); } @@ -111,7 +116,7 @@ struct CompareViewer { } }; -void DataViewer::setStyles(const StyleSheetP& stylesheet, IndexMap& styles) { +void DataViewer::setStyles(const StyleSheetP& stylesheet, IndexMap& styles, IndexMap* extra_styles) { if (!viewers.empty() && styles.contains(viewers.front()->getStyle())) { // already using these styles return; @@ -119,6 +124,13 @@ void DataViewer::setStyles(const StyleSheetP& stylesheet, IndexMapstylesheet = stylesheet; // create viewers viewers.clear(); + addStyles(styles); + if (extra_styles) addStyles(*extra_styles); + // sort viewers by z-index of style + stable_sort(viewers.begin(), viewers.end(), CompareViewer()); + onInit(); +} +void DataViewer::addStyles(IndexMap& styles) { FOR_EACH(s, styles) { if ((s->visible || s->visible.isScripted()) && nativeLook() || ( @@ -129,14 +141,21 @@ void DataViewer::setStyles(const StyleSheetP& stylesheet, IndexMap& values) { +void DataViewer::setData(IndexMap& values, IndexMap* extra_values) { FOR_EACH(v, viewers) { - v->setValue(values[v->getField()]); + // is this field contained in values? + ValueP val = values.tryGet(v->getField()); + if (val) { + v->setValue(val); + } else { + // if it is not in values it should be in extra values + assert(extra_values); + val = extra_values->tryGet(v->getField()); + assert(val); + v->setValue(val); + } } onChange(); } diff --git a/src/render/card/viewer.hpp b/src/render/card/viewer.hpp index 0e7bd921..7c36f0a3 100644 --- a/src/render/card/viewer.hpp +++ b/src/render/card/viewer.hpp @@ -72,11 +72,14 @@ class DataViewer : public SetView { virtual void onChangeSet(); // --------------------------------------------------- : The viewers + private: + /// Create some viewers for the given styles + void addStyles(IndexMap& styles); protected: /// Set the styles for the data to be shown, recreating the viewers - void setStyles(const StyleSheetP& stylesheet, IndexMap& styles); + void setStyles(const StyleSheetP& stylesheet, IndexMap& styles, IndexMap* extra_styles = nullptr); /// Set the data to be shown in the viewers, refresh them - void setData(IndexMap& values); + void setData(IndexMap& values, IndexMap* extra_values = nullptr); /// Create a viewer for the given style. /** Can be overloaded to create a ValueEditor instead */ diff --git a/src/script/dependency.hpp b/src/script/dependency.hpp index 3e50b33e..b3c5f3b4 100644 --- a/src/script/dependency.hpp +++ b/src/script/dependency.hpp @@ -19,6 +19,7 @@ enum DependencyType , DEP_CARDS_FIELD ///< dependency of a script in a "card" field for all cards , DEP_SET_FIELD ///< dependency of a script in a "set" field , DEP_STYLE ///< dependency of a script in a "style" property, data gives the stylesheet +, DEP_EXTRA_CARD_FIELD ///< dependency of a script in an extra stylesheet specific card field , DEP_CARD_COPY_DEP ///< copy the dependencies from a card field , DEP_SET_COPY_DEP ///< copy the dependencies from a set field }; diff --git a/src/script/script_manager.cpp b/src/script/script_manager.cpp index 3416bbd7..1d802b62 100644 --- a/src/script/script_manager.cpp +++ b/src/script/script_manager.cpp @@ -123,6 +123,10 @@ void SetScriptManager::initDependencies(Context& ctx, Game& game) { void SetScriptManager::initDependencies(Context& ctx, StyleSheet& stylesheet) { if (stylesheet.dependencies_initialized) return; stylesheet.dependencies_initialized = true; + // find dependencies of extra card fields + /*FOR_EACH(f, stylesheet.extra_card_fields) { + f->initDependencies(ctx, Dependency(DEP_EXTRA_CARD_FIELD, f->index, &stylesheet)); + }*/ // find dependencies of choice images and other style stuff FOR_EACH(s, stylesheet.card_style) { s->initDependencies(ctx, Dependency(DEP_STYLE, s->fieldP->index, &stylesheet)); @@ -188,11 +192,20 @@ void SetScriptManager::onAction(const Action& action, bool undone) { } void SetScriptManager::updateStyles(const CardP& card) { -// lastUpdatedCard = card; + assert(card); const StyleSheet& stylesheet = set.stylesheetFor(card); Context& ctx = getContext(card); + // update extra card fields + card->extra_data.init(stylesheet.extra_card_fields); + FOR_EACH(v, card->extra_data) { + v->update(ctx); + } // update all styles - FOR_EACH_CONST(s, stylesheet.card_style) { + updateStyles(ctx, stylesheet.card_style); + updateStyles(ctx, stylesheet.extra_card_style); +} +void SetScriptManager::updateStyles(Context& ctx, const IndexMap& styles) { + FOR_EACH_CONST(s, styles) { if (s->update(ctx)) { // style has changed, tell listeners s->tellListeners(); @@ -313,6 +326,17 @@ void SetScriptManager::alsoUpdate(deque& to_update, const vector(d.data); + StyleSheet* stylesheet_card = &set.stylesheetFor(card); + if (stylesheet == stylesheet_card) { + ValueP value = card->extra_data.at(d.index); + to_update.push_back(ToUpdate(value.get(), card)); + } + } + break;*/ } case DEP_CARD_COPY_DEP: { // propagate dependencies from another field FieldP f = set.game->card_fields[d.index]; diff --git a/src/script/script_manager.hpp b/src/script/script_manager.hpp index 05426798..4825215f 100644 --- a/src/script/script_manager.hpp +++ b/src/script/script_manager.hpp @@ -21,6 +21,8 @@ class Value; DECLARE_POINTER_TYPE(Game); DECLARE_POINTER_TYPE(StyleSheet); DECLARE_POINTER_TYPE(Card); +DECLARE_POINTER_TYPE(Field); +DECLARE_POINTER_TYPE(Style); // ----------------------------------------------------------------------------- : SetScriptContext @@ -76,6 +78,8 @@ class SetScriptManager : public SetScriptContext, public ActionListener { void initDependencies(Context&, Game&); void initDependencies(Context&, StyleSheet&); + /// Update a map of styles + void updateStyles(Context& ctx, const IndexMap& styles); /// Updates scripts, starting at some value /** if the value changes any dependend values are updated as well */ void updateValue(Value& value, const CardP& card); diff --git a/src/util/error.cpp b/src/util/error.cpp index 5fd8d2db..59a798d9 100644 --- a/src/util/error.cpp +++ b/src/util/error.cpp @@ -55,10 +55,12 @@ vector previous_errors; String pending_errors; String pending_warnings; DECLARE_TYPEOF_COLLECTION(String); +wxCriticalSection crit_error_handling; void handle_error(const String& e, bool allow_duplicate = true, bool now = true) { + // Thread safety + wxCriticalSectionLocker lock(crit_error_handling); // Check duplicates - // TODO: thread safety if (!allow_duplicate) { FOR_EACH(pe, previous_errors) { if (e == pe) return; diff --git a/src/util/for_each.hpp b/src/util/for_each.hpp index 6aa6173c..0a62524b 100644 --- a/src/util/for_each.hpp +++ b/src/util/for_each.hpp @@ -26,12 +26,12 @@ #define DECLARE_TYPEOF_COLLECTION(T) #define TYPEOF(Value) __typeof(Value) - #define TYPEOF_IT(Value) __typeof(Value.begin()) - #define TYPEOF_CIT(Value) __typeof(Value.begin()) - #define TYPEOF_RIT(Value) __typeof(Value.rbegin()) - #define TYPEOF_CRIT(Value) __typeof(Value.rbegin()) - #define TYPEOF_REF(Value) __typeof(*Value.begin())& - #define TYPEOF_CREF(Value) __typeof(*Value.begin())& + #define TYPEOF_IT(Value) __typeof((Value).begin()) + #define TYPEOF_CIT(Value) __typeof((Value).begin()) + #define TYPEOF_RIT(Value) __typeof((Value).rbegin()) + #define TYPEOF_CRIT(Value) __typeof((Value).rbegin()) + #define TYPEOF_REF(Value) __typeof(*(Value).begin())& + #define TYPEOF_CREF(Value) __typeof(*(Value).begin())& #else /// Helper for typeof tricks diff --git a/src/util/index_map.hpp b/src/util/index_map.hpp index cf07085c..03504d6b 100644 --- a/src/util/index_map.hpp +++ b/src/util/index_map.hpp @@ -43,8 +43,8 @@ class IndexMap : private vector { /// Initialize this map with default values given a list of keys /** has no effect if already initialized with the given keys */ - void init(const vector& keys) { - if (this->size() == keys.size()) return; + bool init(const vector& keys) { + if (this->size() == keys.size() && (this->empty() || get_key(this->front()) == keys.front())) return false; this->reserve(keys.size()); for(typename vector::const_iterator it = keys.begin() ; it != keys.end() ; ++it) { const Key& key = *it; @@ -52,6 +52,7 @@ class IndexMap : private vector { if (key->index >= this->size()) this->resize(key->index + 1); init_object(key, (*this)[key->index]); } + return true; } /// Initialize this map with cloned values from another list void cloneFrom(const IndexMap& values) { @@ -75,6 +76,14 @@ class IndexMap : private vector { assert(this->size() > key->index); return at(key->index); } + /// Retrieve a value given its key, if it matches + inline Value tryGet (const Key& key) { + assert(key); + if (this->size() <= key->index) return Value(); + Value v = at(key->index); + if (get_key(v) != key) return Value(); + return v; + } /// Is a value contained in this index map? inline bool contains(const Value& value) const {