From f1c5a8b974d7bcc88a10112846bdf939a0444445 Mon Sep 17 00:00:00 2001 From: twanvl Date: Sat, 24 Mar 2007 20:27:38 +0000 Subject: [PATCH] Fixed Actions for TextCtrl, actions used to apply to the wrong value. Changed some TABs to spaces in macros, that should end the conflicts because we use different tab sizes (4 vs 8) git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@234 0fc631ac-6414-0410-93d0-97cfa31319b6 --- src/data/action/value.cpp | 6 +- src/data/field.cpp | 5 +- src/data/field.hpp | 9 ++ src/data/field/text.cpp | 15 +++ src/data/field/text.hpp | 17 ++++ src/data/game.hpp | 24 ++--- src/data/keyword.hpp | 1 + src/data/symbol_font.cpp | 2 +- src/gui/control/keyword_list.cpp | 24 ++++- src/gui/control/keyword_list.hpp | 4 + src/gui/control/text_ctrl.cpp | 13 ++- src/gui/set/keywords_panel.cpp | 38 +++++++- src/gui/set/keywords_panel.hpp | 10 +- src/render/card/viewer.cpp | 2 +- src/render/value/viewer.hpp | 20 ++-- src/util/for_each.hpp | 156 +++++++++++++++---------------- 16 files changed, 229 insertions(+), 117 deletions(-) diff --git a/src/data/action/value.cpp b/src/data/action/value.cpp index 3c2b4628..d28e6d2e 100644 --- a/src/data/action/value.cpp +++ b/src/data/action/value.cpp @@ -35,6 +35,7 @@ class SimpleValueAction : public ValueAction { virtual void perform(bool to_undo) { swap(static_cast(*valueP).*member, new_value); + valueP->onAction(*this, to_undo); // notify value } virtual bool merge(const Action& action) { @@ -54,9 +55,9 @@ class SimpleValueAction : public ValueAction { typename T::ValueType T::*member; }; -ValueAction* value_action(const ChoiceValueP& value, const Defaultable& new_value) { return new SimpleValueAction (value, new_value, &ChoiceValue::value); } +ValueAction* value_action(const ChoiceValueP& value, const Defaultable& new_value) { return new SimpleValueAction (value, new_value, &ChoiceValue::value); } ValueAction* value_action(const MultipleChoiceValueP& value, const Defaultable& new_value) { return new SimpleValueAction(value, new_value, &MultipleChoiceValue::value); } -ValueAction* value_action(const ColorValueP& value, const Defaultable& new_value) { return new SimpleValueAction (value, new_value, &ColorValue::value); } +ValueAction* value_action(const ColorValueP& value, const Defaultable& new_value) { return new SimpleValueAction (value, new_value, &ColorValue::value); } ValueAction* value_action(const ImageValueP& value, const FileName& new_value) { return new SimpleValueAction(value, new_value, &ImageValue::filename); } ValueAction* value_action(const SymbolValueP& value, const FileName& new_value) { return new SimpleValueAction(value, new_value, &SymbolValue::filename); } @@ -76,6 +77,7 @@ void TextValueAction::perform(bool to_undo) { swap(value().value, new_value); value().last_update.update(); swap(selection_end, new_selection_end); + valueP->onAction(*this, to_undo); // notify value } bool TextValueAction::merge(const Action& action) { diff --git a/src/data/field.cpp b/src/data/field.cpp index 7f9ed3e5..df85e8cb 100644 --- a/src/data/field.cpp +++ b/src/data/field.cpp @@ -127,10 +127,13 @@ Value::~Value() {} IMPLEMENT_REFLECTION_NAMELESS(Value) { } +bool Value::equals(const Value* that) { + return this == that; +} + void init_object(const FieldP& field, ValueP& value) { if (!value) value = field->newValue(field); } template <> ValueP read_new(Reader&) { throw InternalError(_("IndexMap contains nullptr ValueP the application should have crashed already")); } - diff --git a/src/data/field.hpp b/src/data/field.hpp index 809b0218..2071b465 100644 --- a/src/data/field.hpp +++ b/src/data/field.hpp @@ -21,6 +21,7 @@ DECLARE_POINTER_TYPE(Style); DECLARE_POINTER_TYPE(Value); class Context; class Dependency; +class Action; // for DataViewer/editor class DataViewer; class DataEditor; @@ -134,6 +135,14 @@ class Value { virtual String toString() const = 0; /// Apply scripts to this value, return true if the value has changed virtual bool update(Context&) { last_script_update.update(); return false; } + /// 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) {} + /// Is this value the same as some other value (for the same field&card) + /** Has behaviour other than == for FakeTextValue. + * In that case, afterwards this becomes equal to that if they use the same underlying object. + */ + virtual bool equals(const Value* that); private: DECLARE_REFLECTION_VIRTUAL(); diff --git a/src/data/field/text.cpp b/src/data/field/text.cpp index e0b9e2f8..b5a10c56 100644 --- a/src/data/field/text.cpp +++ b/src/data/field/text.cpp @@ -105,3 +105,18 @@ bool TextValue::update(Context& ctx) { IMPLEMENT_REFLECTION_NAMELESS(TextValue) { if (fieldP->save_value || tag.scripting()) REFLECT_NAMELESS(value); } + +// ----------------------------------------------------------------------------- : FakeTextValue + +void FakeTextValue::onAction(Action& a, bool undone) { + *underlying = value; +} + +bool FakeTextValue::equals(const Value* that) { + if (this == that) return true; + const FakeTextValue* thatT = dynamic_cast(that); + if (!thatT || underlying != thatT->underlying) return false; + // update the value + value = *underlying; + return true; +} diff --git a/src/data/field/text.hpp b/src/data/field/text.hpp index 49047bbe..df1f585a 100644 --- a/src/data/field/text.hpp +++ b/src/data/field/text.hpp @@ -98,5 +98,22 @@ class TextValue : public Value { DECLARE_REFLECTION(); }; +// ----------------------------------------------------------------------------- : TextValue + +/// A 'fake' TextValue that is used to edit some other string +/** Used by TextCtrl */ +class FakeTextValue : public TextValue { + public: + inline FakeTextValue(const TextFieldP& field, String* underlying) + : TextValue(field), underlying(underlying) {} + + String* const underlying; ///< The underlying actual value + + /// Update underlying data + virtual void onAction(Action& a, bool undone); + /// Editing the same underlying value? + virtual bool equals(const Value* that); +}; + // ----------------------------------------------------------------------------- : EOF #endif diff --git a/src/data/game.hpp b/src/data/game.hpp index 4282846b..04f61e19 100644 --- a/src/data/game.hpp +++ b/src/data/game.hpp @@ -34,21 +34,21 @@ class Game : public Packaged { public: Game(); - OptionalScript init_script; ///< Script of variables available to other scripts in this game - vector set_fields; ///< Fields for set information - IndexMap default_set_style; ///< Default style for the set fields, because it is often the same - vector card_fields; ///< Fields on each card - vector statistics_dimensions; ///< (Additional) statistics dimensions - vector statistics_categories; ///< (Additional) statistics categories - + OptionalScript init_script; ///< Script of variables available to other scripts in this game + vector set_fields; ///< Fields for set information + IndexMap default_set_style; ///< Default style for the set fields, because it is often the same + vector card_fields; ///< Fields on each card + vector statistics_dimensions; ///< (Additional) statistics dimensions + vector statistics_categories; ///< (Additional) statistics categories + bool has_keywords; ///< Does this game use keywords? vector keyword_parameter_types;///< Types of keyword parameters vector keyword_modes; ///< Modes of keywords - vector keywords; ///< Keywords for use in text - - Dependencies dependent_scripts_cards; ///< scripts that depend on the card list - Dependencies dependent_scripts_keywords; ///< scripts that depend on the keywords - bool dependencies_initialized; ///< are the script dependencies comming from this game all initialized? + vector keywords; ///< Keywords for use in text + + Dependencies dependent_scripts_cards; ///< scripts that depend on the card list + Dependencies dependent_scripts_keywords; ///< scripts that depend on the keywords + bool dependencies_initialized; ///< are the script dependencies comming from this game all initialized? /// Loads the game with a particular name, for example "magic" static GameP byName(const String& name); diff --git a/src/data/keyword.hpp b/src/data/keyword.hpp index 1d2cba4e..f95f281c 100644 --- a/src/data/keyword.hpp +++ b/src/data/keyword.hpp @@ -59,6 +59,7 @@ class Keyword { * captures 2,4,... capture the parameters */ wxRegEx matchRe; + bool fixed; ///< Is this keyword uneditable? (true for game keywods, false for set keywords) /// Prepare the expansion: (re)generate matchRe and the list of parameters. /** Throws when there is an error in the input diff --git a/src/data/symbol_font.cpp b/src/data/symbol_font.cpp index ccb7f09c..ab3871ce 100644 --- a/src/data/symbol_font.cpp +++ b/src/data/symbol_font.cpp @@ -119,7 +119,7 @@ Bitmap SymbolInFont::getBitmap(Context& ctx, Package& pkg, double size) { actual_size = wxSize(img.GetWidth(), img.GetHeight()); // scale to match expected size Image resampled_image((int) (actual_size.GetWidth() * size / img_size), - (int) (actual_size.GetHeight() * size / img_size), false); + (int) (actual_size.GetHeight() * size / img_size), false); if (!resampled_image.Ok()) return Bitmap(1,1); resample(img, resampled_image); // convert to bitmap, store for later use diff --git a/src/gui/control/keyword_list.cpp b/src/gui/control/keyword_list.cpp index ea86c50f..28bceded 100644 --- a/src/gui/control/keyword_list.cpp +++ b/src/gui/control/keyword_list.cpp @@ -10,6 +10,8 @@ #include #include #include +#include +#include DECLARE_TYPEOF_COLLECTION(KeywordP); @@ -23,7 +25,7 @@ KeywordList::KeywordList(Window* parent, int id, long additional_style) : ItemList(parent, id, additional_style) { // Add columns - InsertColumn(0, _LABEL_("keyword"), wxLIST_FORMAT_LEFT, 100); + InsertColumn(0, _LABEL_("keyword"), wxLIST_FORMAT_LEFT, 0); InsertColumn(1, _LABEL_("match"), wxLIST_FORMAT_LEFT, 200); InsertColumn(2, _LABEL_("mode"), wxLIST_FORMAT_LEFT, 100); InsertColumn(3, _LABEL_("uses"), wxLIST_FORMAT_RIGHT, 80); @@ -51,11 +53,21 @@ void KeywordList::onAction(const Action& action, bool undone) { // ----------------------------------------------------------------------------- : KeywordListBase : for ItemList +String match_string(const Keyword& a) { + return untag(replace_all(replace_all( + a.match, + _(""), _("‹")), + _(""), _("›")) + ); +} + void KeywordList::getItems(vector& out) const { FOR_EACH(k, set->keywords) { + k->fixed = false; out.push_back(k); } FOR_EACH(k, set->game->keywords) { + k->fixed = true; out.push_back(k); } } @@ -83,7 +95,7 @@ String KeywordList::OnGetItemText (long pos, long col) const { const Keyword& kw = *getKeyword(pos); switch(col) { case 0: return kw.keyword; - case 1: return kw.match; + case 1: return match_string(kw); case 2: return kw.mode; case 3: return _("TODO"); case 4: return _("TODO"); @@ -93,3 +105,11 @@ String KeywordList::OnGetItemText (long pos, long col) const { int KeywordList::OnGetItemImage(long pos) const { return -1; } + +wxListItemAttr* KeywordList::OnGetItemAttr(long pos) const { + // black for set keywords, grey for game keywords (uneditable) + const Keyword& kw = *getKeyword(pos); + if (!kw.fixed) return nullptr; + item_attr.SetTextColour(lerp(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW),wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT),0.5)); + return &item_attr; +} diff --git a/src/gui/control/keyword_list.hpp b/src/gui/control/keyword_list.hpp index 096b1d58..09168d86 100644 --- a/src/gui/control/keyword_list.hpp +++ b/src/gui/control/keyword_list.hpp @@ -68,9 +68,13 @@ class KeywordList : public ItemList, public SetView { /// Get the image of an item, by default no image is used /** Overrides a function from wxListCtrl */ virtual int OnGetItemImage(long pos) const; + /// Get the color for an item + virtual wxListItemAttr* OnGetItemAttr(long pos) const; private: void storeColumns(); + + mutable wxListItemAttr item_attr; // for OnGetItemAttr }; // ----------------------------------------------------------------------------- : EOF diff --git a/src/gui/control/text_ctrl.cpp b/src/gui/control/text_ctrl.cpp index 9f8f63f5..92677599 100644 --- a/src/gui/control/text_ctrl.cpp +++ b/src/gui/control/text_ctrl.cpp @@ -37,7 +37,7 @@ void TextCtrl::setValue(String* value) { // create a field, style and value TextFieldP field(new TextField); TextStyleP style(new TextStyle(field)); - TextValueP value(new TextValue(field)); + TextValueP value(new FakeTextValue(field, this->value)); // set stuff field->index = 0; field->multi_line = true; @@ -57,6 +57,11 @@ void TextCtrl::setValue(String* value) { viewers.front()->getEditor()->determineSize(true); // We don't wan to change the window size //SetMinSize(RealSize(style->width + 6, style->height + 6)); + } else if (value) { + // create a new value, for a different underlying actual value + ValueViewer& viewer = *viewers.front(); + TextValueP new_value(new FakeTextValue(static_pointer_cast(viewer.getField()), this->value)); + viewer.setValue(new_value); } valueChanged(); } @@ -70,13 +75,15 @@ void TextCtrl::valueChanged() { } void TextCtrl::onAction(const Action& action, bool undone) { DataEditor::onAction(action, undone); + /* TYPE_CASE(action, TextValueAction) { - TextValue& tv = static_cast(*viewers.front()->getValue()); - if (&tv == action.valueP.get()) { + FakeTextValue& tv = static_cast(*viewers.front()->getValue()); + if (tv.equals(action.valueP.get())) { // the value has changed if (value) *value = tv.value(); } } + */ } void TextCtrl::onChangeSet() { DataEditor::onChangeSet(); diff --git a/src/gui/set/keywords_panel.cpp b/src/gui/set/keywords_panel.cpp index 5657c820..4b488fc3 100644 --- a/src/gui/set/keywords_panel.cpp +++ b/src/gui/set/keywords_panel.cpp @@ -8,8 +8,10 @@ #include #include +#include #include #include +#include // ----------------------------------------------------------------------------- : KeywordsPanel @@ -17,18 +19,44 @@ KeywordsPanel::KeywordsPanel(Window* parent, int id) : SetWindowPanel(parent, id) { // init controls - list = new KeywordList(this, wxID_ANY); + Panel* panel; + splitter = new wxSplitterWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0); + list = new KeywordList(splitter, wxID_ANY); + panel = new Panel(splitter, wxID_ANY); + keyword = new TextCtrl(panel, wxID_ANY); + match = new TextCtrl(panel, wxID_ANY); + reminder = new TextCtrl(panel, wxID_ANY); + rules = new TextCtrl(panel, wxID_ANY); + // init sizer for panel + wxSizer* sp = new wxBoxSizer(wxVERTICAL); + sp->Add(new wxStaticText(panel, wxID_ANY, _("Keyword:")), 0, wxALL, 6); + sp->Add(keyword, 0, wxEXPAND | wxALL & ~wxTOP, 6); + wxSizer* s2 = new wxStaticBoxSizer(wxVERTICAL, panel, _("Match")); + s2->Add(new wxStaticText(panel, wxID_ANY, _("Keyword format:")), 0, wxALL, 6); + s2->Add(match, 0, wxEXPAND | wxALL & ~wxTOP, 6); + s2->Add(new wxStaticText(panel, wxID_ANY, _("Parameters:")), 0, wxALL, 6); + sp->Add(s2, 0, wxEXPAND | wxALL, 6); + sp->Add(new wxStaticText(panel, wxID_ANY, _("Reminder:")), 0, wxALL, 6); + sp->Add(reminder, 0, wxEXPAND | wxALL & ~wxTOP, 6); + sp->Add(new wxStaticText(panel, wxID_ANY, _("Rules:")), 0, wxALL, 6); + sp->Add(rules, 0, wxEXPAND | wxALL & ~wxTOP, 6); + panel->SetSizer(sp); + // init splitter + splitter->SetMinimumPaneSize(100); + splitter->SetSashGravity(0.5); + splitter->SplitVertically(list, panel, -200); // init sizer wxSizer* s = new wxBoxSizer(wxHORIZONTAL); - s->Add(list, 1, wxEXPAND); + s->Add(splitter, 1, wxEXPAND); + s->SetSizeHints(this); + SetSizer(s); + //s->Add(new wxStaticText(this, wxID_ANY, _("Sorry, no keywords for now"),wxDefaultPosition,wxDefaultSize,wxALIGN_CENTER), 1, wxALIGN_CENTER); // TODO: Remove /* wxSizer* s2 = new wxBoxSizer(wxVERTICAL); s2->Add(list_active, 1, wxEXPAND); s2->Add(list_inactive, 1, wxEXPAND);*/ - s->SetSizeHints(this); - SetSizer(s); } void KeywordsPanel::onChangeSet() { list->setSet(set); -} \ No newline at end of file +} diff --git a/src/gui/set/keywords_panel.hpp b/src/gui/set/keywords_panel.hpp index df43ff27..79145f9b 100644 --- a/src/gui/set/keywords_panel.hpp +++ b/src/gui/set/keywords_panel.hpp @@ -12,6 +12,7 @@ #include #include +class wxSplitterWindow; class KeywordList; class TextCtrl; @@ -25,8 +26,13 @@ class KeywordsPanel : public SetWindowPanel { virtual void onChangeSet(); private: - KeywordList* list; - TextCtrl* keyword; + // --------------------------------------------------- : Controls + wxSplitterWindow* splitter; + KeywordList* list; + TextCtrl* keyword; + TextCtrl* match; + TextCtrl* reminder; + TextCtrl* rules; }; // ----------------------------------------------------------------------------- : EOF diff --git a/src/render/card/viewer.cpp b/src/render/card/viewer.cpp index 5743da36..200cbf7f 100644 --- a/src/render/card/viewer.cpp +++ b/src/render/card/viewer.cpp @@ -125,7 +125,7 @@ void DataViewer::onAction(const Action& action, bool undone) { } TYPE_CASE(action, ValueAction) { FOR_EACH(v, viewers) { - if (v->getValue() == action.valueP) { + if (v->getValue()->equals( action.valueP.get() )) { // refresh the viewer v->onAction(action, undone); onChange(); diff --git a/src/render/value/viewer.hpp b/src/render/value/viewer.hpp index a418389d..b9c20962 100644 --- a/src/render/value/viewer.hpp +++ b/src/render/value/viewer.hpp @@ -79,16 +79,16 @@ class ValueViewer { // ----------------------------------------------------------------------------- : Utility -#define DECLARE_VALUE_VIEWER(Type) \ - protected: \ - inline Type##Style& style() const { return static_cast< Type##Style&>(*ValueViewer::styleP); } \ - inline const Type##Value& value() const { return static_cast(*ValueViewer::valueP); } \ - inline const Type##Field& field() const { return style().field(); } \ - inline Type##StyleP styleP() const { return static_pointer_cast(ValueViewer::styleP); } \ - inline Type##ValueP valueP() const { return static_pointer_cast(ValueViewer::valueP); } \ - inline Type##FieldP fieldP() const { return static_pointer_cast(style().fieldP); } \ - public: \ - Type##ValueViewer(DataViewer& parent, const Type ## StyleP& style) +#define DECLARE_VALUE_VIEWER(Type) \ + protected: \ + inline Type##Style& style() const { return static_cast< Type##Style&>(*ValueViewer::styleP); } \ + inline const Type##Value& value() const { return static_cast(*ValueViewer::valueP); } \ + inline const Type##Field& field() const { return style().field(); } \ + inline Type##StyleP styleP() const { return static_pointer_cast(ValueViewer::styleP); } \ + inline Type##ValueP valueP() const { return static_pointer_cast(ValueViewer::valueP); } \ + inline Type##FieldP fieldP() const { return static_pointer_cast(style().fieldP); } \ + public: \ + Type##ValueViewer(DataViewer& parent, const Type ## StyleP& style) // ----------------------------------------------------------------------------- : EOF diff --git a/src/util/for_each.hpp b/src/util/for_each.hpp index 9aba9d5a..ec235db0 100644 --- a/src/util/for_each.hpp +++ b/src/util/for_each.hpp @@ -51,42 +51,42 @@ #define TYPEOF_REF(Value) TypeOf::reference /// The type of a const reference #define TYPEOF_CREF(Value) TypeOf::const_reference - + /// Declare typeof magic for a specific type - #define DECLARE_TYPEOF(T) \ - template<> struct TypeOf { \ - typedef T type; \ - typedef T::iterator iterator; \ - typedef T::const_iterator const_iterator; \ - typedef T::reverse_iterator reverse_iterator; \ - typedef T::const_reverse_iterator const_reverse_iterator; \ - typedef T::reference reference; \ - typedef T::const_reference const_reference; \ - } + #define DECLARE_TYPEOF(T) \ + template<> struct TypeOf { \ + typedef T type; \ + typedef T::iterator iterator; \ + typedef T::const_iterator const_iterator; \ + typedef T::reverse_iterator reverse_iterator; \ + typedef T::const_reverse_iterator const_reverse_iterator; \ + typedef T::reference reference; \ + typedef T::const_reference const_reference; \ + } /// Declare typeof magic for a specific type that doesn't support reverse iterators - #define DECLARE_TYPEOF_NO_REV(T) \ - template<> struct TypeOf { \ - typedef T type; \ - typedef T::iterator iterator; \ - typedef T::const_iterator const_iterator; \ - typedef T::reference reference; \ - typedef T::const_reference const_reference; \ - } + #define DECLARE_TYPEOF_NO_REV(T) \ + template<> struct TypeOf { \ + typedef T type; \ + typedef T::iterator iterator; \ + typedef T::const_iterator const_iterator; \ + typedef T::reference reference; \ + typedef T::const_reference const_reference; \ + } /// Declare typeof magic for a specific type, using const iterators - #define DECLARE_TYPEOF_CONST(T) \ - template<> struct TypeOf { \ - typedef T type; \ - typedef T::const_iterator iterator; \ - typedef T::const_iterator const_iterator; \ - typedef T::const_reverse_iterator reverse_iterator; \ - typedef T::const_reverse_iterator const_reverse_iterator; \ - typedef T::const_reference reference; \ - typedef T::const_reference const_reference; \ - } + #define DECLARE_TYPEOF_CONST(T) \ + template<> struct TypeOf { \ + typedef T type; \ + typedef T::const_iterator iterator; \ + typedef T::const_iterator const_iterator; \ + typedef T::const_reverse_iterator reverse_iterator; \ + typedef T::const_reverse_iterator const_reverse_iterator; \ + typedef T::const_reference reference; \ + typedef T::const_reference const_reference; \ + } /// Declare typeof magic for a specific std::vector type - #define DECLARE_TYPEOF_COLLECTION(T) DECLARE_TYPEOF(vector< T >); \ - DECLARE_TYPEOF_CONST(set< T >) + #define DECLARE_TYPEOF_COLLECTION(T) DECLARE_TYPEOF(vector< T >); \ + DECLARE_TYPEOF_CONST(set< T >) #endif @@ -103,33 +103,33 @@ /// Iterate over a collection, using an iterator it of type Type /** Usage: FOR_EACH_IT_T(Type,it,collect) { body-of-loop } */ -#define FOR_EACH_IT_T(Type,Iterator,Collection) \ - for(Type Iterator = Collection.begin() ; \ - Iterator != Collection.end() ; \ - ++Iterator) +#define FOR_EACH_IT_T(Type,Iterator,Collection) \ + for(Type Iterator = Collection.begin() ; \ + Iterator != Collection.end() ; \ + ++Iterator) /// Iterate over a collection whos type must be declared with DECLARE_TYPEOF /** Usage: FOR_EACH_IT(it,collect) { body-of-loop } */ -#define FOR_EACH_IT(Iterator,Collection) \ - FOR_EACH_IT_T(TYPEOF_IT(Collection), Iterator, Collection) +#define FOR_EACH_IT(Iterator,Collection) \ + FOR_EACH_IT_T(TYPEOF_IT(Collection), Iterator, Collection) /// Iterate over a collection whos type must be declared with DECLARE_TYPEOF /** Uses a const_iterator * Usage: FOR_EACH_IT(it,collect) { body-of-loop } */ -#define FOR_EACH_CONST_IT(Iterator,Collection) \ - FOR_EACH_IT_T(TYPEOF_CIT(Collection), Iterator, Collection) +#define FOR_EACH_CONST_IT(Iterator,Collection) \ + FOR_EACH_IT_T(TYPEOF_CIT(Collection), Iterator, Collection) /// Iterate over a collection in whos type must be declared with DECLARE_TYPEOF /** Iterates using a reverse_iterator * Usage: FOR_EACH_REVERSE_IT(it,collect) { body-of-loop } */ -#define FOR_EACH_REVERSE_IT(Iterator,Collection) \ - for(TYPEOF_RIT(Collection) \ - Iterator = Collection.rbegin() ; \ - Iterator != Collection.rend() ; \ - ++Iterator) +#define FOR_EACH_REVERSE_IT(Iterator,Collection) \ + for(TYPEOF_RIT(Collection) \ + Iterator = Collection.rbegin() ; \ + Iterator != Collection.rend() ; \ + ++Iterator) // ----------------------------------------------------------------------------- : Looping macros @@ -140,40 +140,40 @@ * To do this we use a nested for loop that is only executed once, and which is optimized away. * To terminate this loop we need an extra bool, which we set to false after the first iteration. */ -#define FOR_EACH_T(TypeIt,TypeElem,Elem,Collection, begin, end) \ - for(std::pair Elem##_IT(Collection.begin(), true) ; \ - Elem##_IT.second && Elem##_IT.first != Collection.end() ; \ - ++Elem##_IT.first, Elem##_IT.second = !Elem##_IT.second) \ - for(TypeElem Elem = *Elem##_IT.first ; \ - Elem##_IT.second ; \ - Elem##_IT.second = false) +#define FOR_EACH_T(TypeIt,TypeElem,Elem,Collection, begin, end) \ + for(std::pair Elem##_IT(Collection.begin(), true) ; \ + Elem##_IT.second && Elem##_IT.first != Collection.end() ; \ + ++Elem##_IT.first, Elem##_IT.second = !Elem##_IT.second) \ + for(TypeElem Elem = *Elem##_IT.first ; \ + Elem##_IT.second ; \ + Elem##_IT.second = false) /// Iterate over a collection whos type must be declared with DECLARE_TYPEOF /** Usage: FOR_EACH(e,collect) { body-of-loop } */ -#define FOR_EACH(Elem,Collection) \ - FOR_EACH_T(TYPEOF_IT(Collection), TYPEOF_REF(Collection), Elem, Collection, begin, end) +#define FOR_EACH(Elem,Collection) \ + FOR_EACH_T(TYPEOF_IT(Collection), TYPEOF_REF(Collection), Elem, Collection, begin, end) /// Iterate over a collection whos type must be declared with DECLARE_TYPEOF /** Uses a const iterator * Usage: FOR_EACH_CONST(e,collect) { body-of-loop } */ -#define FOR_EACH_CONST(Elem,Collection) \ - FOR_EACH_T(TYPEOF_CIT(Collection), TYPEOF_CREF(Collection), Elem, Collection, begin, end) +#define FOR_EACH_CONST(Elem,Collection) \ + FOR_EACH_T(TYPEOF_CIT(Collection), TYPEOF_CREF(Collection), Elem, Collection, begin, end) /// Iterate over a collection whos type must be declared with DECLARE_TYPEOF /** Iterates using a reverse_iterator * Usage: FOR_EACH_REVERSE(e,collect) { body-of-loop } */ -#define FOR_EACH_REVERSE(Elem,Collection) \ - FOR_EACH_T(TYPEOF_RIT(Collection), TYPEOF_REF(Collection), Elem, Collection, rbegin, rend) +#define FOR_EACH_REVERSE(Elem,Collection) \ + FOR_EACH_T(TYPEOF_RIT(Collection), TYPEOF_REF(Collection), Elem, Collection, rbegin, rend) /// Iterate over a collection whos type must be declared with DECLARE_TYPEOF /** Iterates using a const_reverse_iterator * Usage: FOR_EACH_CONST_REVERSE(e,collect) { body-of-loop } */ -#define FOR_EACH_CONST_REVERSE(Elem,Collection) \ - FOR_EACH_T(TYPEOF_CRIT(Collection), TYPEOF_CREF(Collection), Elem, Collection, rbegin, rend) +#define FOR_EACH_CONST_REVERSE(Elem,Collection) \ + FOR_EACH_T(TYPEOF_CRIT(Collection), TYPEOF_CREF(Collection), Elem, Collection, rbegin, rend) /// Iterate over two collection in parallel /** Usage: FOR_EACH_2_T(TypeIt1,TypeElem1,e1,collect1,TypeIt2,TypeElem2,e2,collect2) { body-of-loop } @@ -181,33 +181,33 @@ * Note: This has got to be one of the craziest pieces of code I have ever written :) * It is just an extension of the idea of FOR_EACH_T. */ -#define FOR_EACH_2_T(TypeIt1,TypeElem1,Elem1,Coll1,TypeIt2,TypeElem2,Elem2,Coll2) \ - for(std::pair, bool> \ - Elem1##_IT(make_pair(Coll1.begin(), Coll2.begin()), true) ; \ - Elem1##_IT.first.first != Coll1.end() && \ - Elem1##_IT.first.second != Coll2.end() ; \ - ++Elem1##_IT.first.first, ++Elem1##_IT.first.second, \ - Elem1##_IT.second = true) \ - for(TypeElem1 Elem1 = *Elem1##_IT.first.first ; \ - Elem1##_IT.second ; \ - Elem1##_IT.second = false) \ - for(TypeElem2 Elem2 = *Elem1##_IT.first.second ; \ - Elem1##_IT.second ; \ - Elem1##_IT.second = false) +#define FOR_EACH_2_T(TypeIt1,TypeElem1,Elem1,Coll1,TypeIt2,TypeElem2,Elem2,Coll2) \ + for(std::pair, bool> \ + Elem1##_IT(make_pair(Coll1.begin(), Coll2.begin()), true) ; \ + Elem1##_IT.first.first != Coll1.end() && \ + Elem1##_IT.first.second != Coll2.end() ; \ + ++Elem1##_IT.first.first, ++Elem1##_IT.first.second, \ + Elem1##_IT.second = true) \ + for(TypeElem1 Elem1 = *Elem1##_IT.first.first ; \ + Elem1##_IT.second ; \ + Elem1##_IT.second = false) \ + for(TypeElem2 Elem2 = *Elem1##_IT.first.second ; \ + Elem1##_IT.second ; \ + Elem1##_IT.second = false) /// Iterate over two collections in parallel, their type must be declared with DECLARE_TYPEOF. /** Usage: FOR_EACH_2(e1,collect1, e2,collect2) { body-of-loop } */ -#define FOR_EACH_2(Elem1,Collection1, Elem2,Collection2) \ - FOR_EACH_2_T(TYPEOF_IT(Collection1), TYPEOF_REF(Collection1), Elem1, Collection1, \ - TYPEOF_IT(Collection2), TYPEOF_REF(Collection2), Elem2, Collection2) +#define FOR_EACH_2(Elem1,Collection1, Elem2,Collection2) \ + FOR_EACH_2_T(TYPEOF_IT(Collection1), TYPEOF_REF(Collection1), Elem1, Collection1, \ + TYPEOF_IT(Collection2), TYPEOF_REF(Collection2), Elem2, Collection2) /// Iterate over two constants collections in parallel, their type must be declared with DECLARE_TYPEOF. /** Usage: FOR_EACH_2_CONST(e1,collect1, e2,collect2) { body-of-loop } */ -#define FOR_EACH_2_CONST(Elem1,Collection1, Elem2,Collection2) \ - FOR_EACH_2_T(TYPEOF_CIT(Collection1), TYPEOF_CREF(Collection1), Elem1, Collection1, \ - TYPEOF_CIT(Collection2), TYPEOF_CREF(Collection2), Elem2, Collection2) +#define FOR_EACH_2_CONST(Elem1,Collection1, Elem2,Collection2) \ + FOR_EACH_2_T(TYPEOF_CIT(Collection1), TYPEOF_CREF(Collection1), Elem1, Collection1, \ + TYPEOF_CIT(Collection2), TYPEOF_CREF(Collection2), Elem2, Collection2) // ----------------------------------------------------------------------------- : EOF