Commit fe606b03 authored by twanvl's avatar twanvl

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)
parent b787142d
...@@ -35,6 +35,7 @@ class SimpleValueAction : public ValueAction { ...@@ -35,6 +35,7 @@ class SimpleValueAction : public ValueAction {
virtual void perform(bool to_undo) { virtual void perform(bool to_undo) {
swap(static_cast<T&>(*valueP).*member, new_value); swap(static_cast<T&>(*valueP).*member, new_value);
valueP->onAction(*this, to_undo); // notify value
} }
virtual bool merge(const Action& action) { virtual bool merge(const Action& action) {
...@@ -54,9 +55,9 @@ class SimpleValueAction : public ValueAction { ...@@ -54,9 +55,9 @@ class SimpleValueAction : public ValueAction {
typename T::ValueType T::*member; typename T::ValueType T::*member;
}; };
ValueAction* value_action(const ChoiceValueP& value, const Defaultable<String>& new_value) { return new SimpleValueAction<ChoiceValue, true> (value, new_value, &ChoiceValue::value); } ValueAction* value_action(const ChoiceValueP& value, const Defaultable<String>& new_value) { return new SimpleValueAction<ChoiceValue, true> (value, new_value, &ChoiceValue::value); }
ValueAction* value_action(const MultipleChoiceValueP& value, const Defaultable<String>& new_value) { return new SimpleValueAction<MultipleChoiceValue, false>(value, new_value, &MultipleChoiceValue::value); } ValueAction* value_action(const MultipleChoiceValueP& value, const Defaultable<String>& new_value) { return new SimpleValueAction<MultipleChoiceValue, false>(value, new_value, &MultipleChoiceValue::value); }
ValueAction* value_action(const ColorValueP& value, const Defaultable<Color>& new_value) { return new SimpleValueAction<ColorValue, true> (value, new_value, &ColorValue::value); } ValueAction* value_action(const ColorValueP& value, const Defaultable<Color>& new_value) { return new SimpleValueAction<ColorValue, true> (value, new_value, &ColorValue::value); }
ValueAction* value_action(const ImageValueP& value, const FileName& new_value) { return new SimpleValueAction<ImageValue, false>(value, new_value, &ImageValue::filename); } ValueAction* value_action(const ImageValueP& value, const FileName& new_value) { return new SimpleValueAction<ImageValue, false>(value, new_value, &ImageValue::filename); }
ValueAction* value_action(const SymbolValueP& value, const FileName& new_value) { return new SimpleValueAction<SymbolValue, false>(value, new_value, &SymbolValue::filename); } ValueAction* value_action(const SymbolValueP& value, const FileName& new_value) { return new SimpleValueAction<SymbolValue, false>(value, new_value, &SymbolValue::filename); }
...@@ -76,6 +77,7 @@ void TextValueAction::perform(bool to_undo) { ...@@ -76,6 +77,7 @@ void TextValueAction::perform(bool to_undo) {
swap(value().value, new_value); swap(value().value, new_value);
value().last_update.update(); value().last_update.update();
swap(selection_end, new_selection_end); swap(selection_end, new_selection_end);
valueP->onAction(*this, to_undo); // notify value
} }
bool TextValueAction::merge(const Action& action) { bool TextValueAction::merge(const Action& action) {
......
...@@ -127,10 +127,13 @@ Value::~Value() {} ...@@ -127,10 +127,13 @@ Value::~Value() {}
IMPLEMENT_REFLECTION_NAMELESS(Value) { IMPLEMENT_REFLECTION_NAMELESS(Value) {
} }
bool Value::equals(const Value* that) {
return this == that;
}
void init_object(const FieldP& field, ValueP& value) { void init_object(const FieldP& field, ValueP& value) {
if (!value) value = field->newValue(field); if (!value) value = field->newValue(field);
} }
template <> ValueP read_new<Value>(Reader&) { template <> ValueP read_new<Value>(Reader&) {
throw InternalError(_("IndexMap contains nullptr ValueP the application should have crashed already")); throw InternalError(_("IndexMap contains nullptr ValueP the application should have crashed already"));
} }
...@@ -21,6 +21,7 @@ DECLARE_POINTER_TYPE(Style); ...@@ -21,6 +21,7 @@ DECLARE_POINTER_TYPE(Style);
DECLARE_POINTER_TYPE(Value); DECLARE_POINTER_TYPE(Value);
class Context; class Context;
class Dependency; class Dependency;
class Action;
// for DataViewer/editor // for DataViewer/editor
class DataViewer; class DataEditor; class DataViewer; class DataEditor;
...@@ -134,6 +135,14 @@ class Value { ...@@ -134,6 +135,14 @@ class Value {
virtual String toString() const = 0; virtual String toString() const = 0;
/// Apply scripts to this value, return true if the value has changed /// Apply scripts to this value, return true if the value has changed
virtual bool update(Context&) { last_script_update.update(); return false; } 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: private:
DECLARE_REFLECTION_VIRTUAL(); DECLARE_REFLECTION_VIRTUAL();
......
...@@ -105,3 +105,18 @@ bool TextValue::update(Context& ctx) { ...@@ -105,3 +105,18 @@ bool TextValue::update(Context& ctx) {
IMPLEMENT_REFLECTION_NAMELESS(TextValue) { IMPLEMENT_REFLECTION_NAMELESS(TextValue) {
if (fieldP->save_value || tag.scripting()) REFLECT_NAMELESS(value); 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<const FakeTextValue*>(that);
if (!thatT || underlying != thatT->underlying) return false;
// update the value
value = *underlying;
return true;
}
...@@ -98,5 +98,22 @@ class TextValue : public Value { ...@@ -98,5 +98,22 @@ class TextValue : public Value {
DECLARE_REFLECTION(); 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 // ----------------------------------------------------------------------------- : EOF
#endif #endif
...@@ -34,21 +34,21 @@ class Game : public Packaged { ...@@ -34,21 +34,21 @@ class Game : public Packaged {
public: public:
Game(); Game();
OptionalScript init_script; ///< Script of variables available to other scripts in this game OptionalScript init_script; ///< Script of variables available to other scripts in this game
vector<FieldP> set_fields; ///< Fields for set information vector<FieldP> set_fields; ///< Fields for set information
IndexMap<FieldP,StyleP> default_set_style; ///< Default style for the set fields, because it is often the same IndexMap<FieldP,StyleP> default_set_style; ///< Default style for the set fields, because it is often the same
vector<FieldP> card_fields; ///< Fields on each card vector<FieldP> card_fields; ///< Fields on each card
vector<StatsDimensionP> statistics_dimensions; ///< (Additional) statistics dimensions vector<StatsDimensionP> statistics_dimensions; ///< (Additional) statistics dimensions
vector<StatsCategoryP> statistics_categories; ///< (Additional) statistics categories vector<StatsCategoryP> statistics_categories; ///< (Additional) statistics categories
bool has_keywords; ///< Does this game use keywords? bool has_keywords; ///< Does this game use keywords?
vector<KeywordParamP> keyword_parameter_types;///< Types of keyword parameters vector<KeywordParamP> keyword_parameter_types;///< Types of keyword parameters
vector<KeywordModeP> keyword_modes; ///< Modes of keywords vector<KeywordModeP> keyword_modes; ///< Modes of keywords
vector<KeywordP> keywords; ///< Keywords for use in text vector<KeywordP> keywords; ///< Keywords for use in text
Dependencies dependent_scripts_cards; ///< scripts that depend on the card list Dependencies dependent_scripts_cards; ///< scripts that depend on the card list
Dependencies dependent_scripts_keywords; ///< scripts that depend on the keywords Dependencies dependent_scripts_keywords; ///< scripts that depend on the keywords
bool dependencies_initialized; ///< are the script dependencies comming from this game all initialized? bool dependencies_initialized; ///< are the script dependencies comming from this game all initialized?
/// Loads the game with a particular name, for example "magic" /// Loads the game with a particular name, for example "magic"
static GameP byName(const String& name); static GameP byName(const String& name);
......
...@@ -59,6 +59,7 @@ class Keyword { ...@@ -59,6 +59,7 @@ class Keyword {
* captures 2,4,... capture the parameters * captures 2,4,... capture the parameters
*/ */
wxRegEx matchRe; 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. /// Prepare the expansion: (re)generate matchRe and the list of parameters.
/** Throws when there is an error in the input /** Throws when there is an error in the input
......
...@@ -119,7 +119,7 @@ Bitmap SymbolInFont::getBitmap(Context& ctx, Package& pkg, double size) { ...@@ -119,7 +119,7 @@ Bitmap SymbolInFont::getBitmap(Context& ctx, Package& pkg, double size) {
actual_size = wxSize(img.GetWidth(), img.GetHeight()); actual_size = wxSize(img.GetWidth(), img.GetHeight());
// scale to match expected size // scale to match expected size
Image resampled_image((int) (actual_size.GetWidth() * size / img_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); if (!resampled_image.Ok()) return Bitmap(1,1);
resample(img, resampled_image); resample(img, resampled_image);
// convert to bitmap, store for later use // convert to bitmap, store for later use
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include <data/set.hpp> #include <data/set.hpp>
#include <data/game.hpp> #include <data/game.hpp>
#include <data/keyword.hpp> #include <data/keyword.hpp>
#include <util/tagged_string.hpp>
#include <gfx/gfx.hpp>
DECLARE_TYPEOF_COLLECTION(KeywordP); DECLARE_TYPEOF_COLLECTION(KeywordP);
...@@ -23,7 +25,7 @@ KeywordList::KeywordList(Window* parent, int id, long additional_style) ...@@ -23,7 +25,7 @@ KeywordList::KeywordList(Window* parent, int id, long additional_style)
: ItemList(parent, id, additional_style) : ItemList(parent, id, additional_style)
{ {
// Add columns // 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(1, _LABEL_("match"), wxLIST_FORMAT_LEFT, 200);
InsertColumn(2, _LABEL_("mode"), wxLIST_FORMAT_LEFT, 100); InsertColumn(2, _LABEL_("mode"), wxLIST_FORMAT_LEFT, 100);
InsertColumn(3, _LABEL_("uses"), wxLIST_FORMAT_RIGHT, 80); InsertColumn(3, _LABEL_("uses"), wxLIST_FORMAT_RIGHT, 80);
...@@ -51,11 +53,21 @@ void KeywordList::onAction(const Action& action, bool undone) { ...@@ -51,11 +53,21 @@ void KeywordList::onAction(const Action& action, bool undone) {
// ----------------------------------------------------------------------------- : KeywordListBase : for ItemList // ----------------------------------------------------------------------------- : KeywordListBase : for ItemList
String match_string(const Keyword& a) {
return untag(replace_all(replace_all(
a.match,
_("<param>"), _("")),
_("</param>"), _(""))
);
}
void KeywordList::getItems(vector<VoidP>& out) const { void KeywordList::getItems(vector<VoidP>& out) const {
FOR_EACH(k, set->keywords) { FOR_EACH(k, set->keywords) {
k->fixed = false;
out.push_back(k); out.push_back(k);
} }
FOR_EACH(k, set->game->keywords) { FOR_EACH(k, set->game->keywords) {
k->fixed = true;
out.push_back(k); out.push_back(k);
} }
} }
...@@ -83,7 +95,7 @@ String KeywordList::OnGetItemText (long pos, long col) const { ...@@ -83,7 +95,7 @@ String KeywordList::OnGetItemText (long pos, long col) const {
const Keyword& kw = *getKeyword(pos); const Keyword& kw = *getKeyword(pos);
switch(col) { switch(col) {
case 0: return kw.keyword; case 0: return kw.keyword;
case 1: return kw.match; case 1: return match_string(kw);
case 2: return kw.mode; case 2: return kw.mode;
case 3: return _("TODO"); case 3: return _("TODO");
case 4: return _("TODO"); case 4: return _("TODO");
...@@ -93,3 +105,11 @@ String KeywordList::OnGetItemText (long pos, long col) const { ...@@ -93,3 +105,11 @@ String KeywordList::OnGetItemText (long pos, long col) const {
int KeywordList::OnGetItemImage(long pos) const { int KeywordList::OnGetItemImage(long pos) const {
return -1; 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;
}
...@@ -68,9 +68,13 @@ class KeywordList : public ItemList, public SetView { ...@@ -68,9 +68,13 @@ class KeywordList : public ItemList, public SetView {
/// Get the image of an item, by default no image is used /// Get the image of an item, by default no image is used
/** Overrides a function from wxListCtrl */ /** Overrides a function from wxListCtrl */
virtual int OnGetItemImage(long pos) const; virtual int OnGetItemImage(long pos) const;
/// Get the color for an item
virtual wxListItemAttr* OnGetItemAttr(long pos) const;
private: private:
void storeColumns(); void storeColumns();
mutable wxListItemAttr item_attr; // for OnGetItemAttr
}; };
// ----------------------------------------------------------------------------- : EOF // ----------------------------------------------------------------------------- : EOF
......
...@@ -37,7 +37,7 @@ void TextCtrl::setValue(String* value) { ...@@ -37,7 +37,7 @@ void TextCtrl::setValue(String* value) {
// create a field, style and value // create a field, style and value
TextFieldP field(new TextField); TextFieldP field(new TextField);
TextStyleP style(new TextStyle(field)); TextStyleP style(new TextStyle(field));
TextValueP value(new TextValue(field)); TextValueP value(new FakeTextValue(field, this->value));
// set stuff // set stuff
field->index = 0; field->index = 0;
field->multi_line = true; field->multi_line = true;
...@@ -57,6 +57,11 @@ void TextCtrl::setValue(String* value) { ...@@ -57,6 +57,11 @@ void TextCtrl::setValue(String* value) {
viewers.front()->getEditor()->determineSize(true); viewers.front()->getEditor()->determineSize(true);
// We don't wan to change the window size // We don't wan to change the window size
//SetMinSize(RealSize(style->width + 6, style->height + 6)); //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<TextField>(viewer.getField()), this->value));
viewer.setValue(new_value);
} }
valueChanged(); valueChanged();
} }
...@@ -70,13 +75,15 @@ void TextCtrl::valueChanged() { ...@@ -70,13 +75,15 @@ void TextCtrl::valueChanged() {
} }
void TextCtrl::onAction(const Action& action, bool undone) { void TextCtrl::onAction(const Action& action, bool undone) {
DataEditor::onAction(action, undone); DataEditor::onAction(action, undone);
/*
TYPE_CASE(action, TextValueAction) { TYPE_CASE(action, TextValueAction) {
TextValue& tv = static_cast<TextValue&>(*viewers.front()->getValue()); FakeTextValue& tv = static_cast<FakeTextValue&>(*viewers.front()->getValue());
if (&tv == action.valueP.get()) { if (tv.equals(action.valueP.get())) {
// the value has changed // the value has changed
if (value) *value = tv.value(); if (value) *value = tv.value();
} }
} }
*/
} }
void TextCtrl::onChangeSet() { void TextCtrl::onChangeSet() {
DataEditor::onChangeSet(); DataEditor::onChangeSet();
......
...@@ -8,8 +8,10 @@ ...@@ -8,8 +8,10 @@
#include <gui/set/keywords_panel.hpp> #include <gui/set/keywords_panel.hpp>
#include <gui/control/keyword_list.hpp> #include <gui/control/keyword_list.hpp>
#include <gui/control/text_ctrl.hpp>
#include <data/keyword.hpp> #include <data/keyword.hpp>
#include <wx/listctrl.h> #include <wx/listctrl.h>
#include <wx/splitter.h>
// ----------------------------------------------------------------------------- : KeywordsPanel // ----------------------------------------------------------------------------- : KeywordsPanel
...@@ -17,18 +19,44 @@ KeywordsPanel::KeywordsPanel(Window* parent, int id) ...@@ -17,18 +19,44 @@ KeywordsPanel::KeywordsPanel(Window* parent, int id)
: SetWindowPanel(parent, id) : SetWindowPanel(parent, id)
{ {
// init controls // 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 // init sizer
wxSizer* s = new wxBoxSizer(wxHORIZONTAL); 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 //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); /* wxSizer* s2 = new wxBoxSizer(wxVERTICAL);
s2->Add(list_active, 1, wxEXPAND); s2->Add(list_active, 1, wxEXPAND);
s2->Add(list_inactive, 1, wxEXPAND);*/ s2->Add(list_inactive, 1, wxEXPAND);*/
s->SetSizeHints(this);
SetSizer(s);
} }
void KeywordsPanel::onChangeSet() { void KeywordsPanel::onChangeSet() {
list->setSet(set); list->setSet(set);
} }
\ No newline at end of file
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <util/prec.hpp> #include <util/prec.hpp>
#include <gui/set/panel.hpp> #include <gui/set/panel.hpp>
class wxSplitterWindow;
class KeywordList; class KeywordList;
class TextCtrl; class TextCtrl;
...@@ -25,8 +26,13 @@ class KeywordsPanel : public SetWindowPanel { ...@@ -25,8 +26,13 @@ class KeywordsPanel : public SetWindowPanel {
virtual void onChangeSet(); virtual void onChangeSet();
private: private:
KeywordList* list; // --------------------------------------------------- : Controls
TextCtrl* keyword; wxSplitterWindow* splitter;
KeywordList* list;
TextCtrl* keyword;
TextCtrl* match;
TextCtrl* reminder;
TextCtrl* rules;
}; };
// ----------------------------------------------------------------------------- : EOF // ----------------------------------------------------------------------------- : EOF
......
...@@ -125,7 +125,7 @@ void DataViewer::onAction(const Action& action, bool undone) { ...@@ -125,7 +125,7 @@ void DataViewer::onAction(const Action& action, bool undone) {
} }
TYPE_CASE(action, ValueAction) { TYPE_CASE(action, ValueAction) {
FOR_EACH(v, viewers) { FOR_EACH(v, viewers) {
if (v->getValue() == action.valueP) { if (v->getValue()->equals( action.valueP.get() )) {
// refresh the viewer // refresh the viewer
v->onAction(action, undone); v->onAction(action, undone);
onChange(); onChange();
......
...@@ -79,16 +79,16 @@ class ValueViewer { ...@@ -79,16 +79,16 @@ class ValueViewer {
// ----------------------------------------------------------------------------- : Utility // ----------------------------------------------------------------------------- : Utility
#define DECLARE_VALUE_VIEWER(Type) \ #define DECLARE_VALUE_VIEWER(Type) \
protected: \ protected: \
inline Type##Style& style() const { return static_cast< Type##Style&>(*ValueViewer::styleP); } \ inline Type##Style& style() const { return static_cast< Type##Style&>(*ValueViewer::styleP); } \
inline const Type##Value& value() const { return static_cast<const Type##Value&>(*ValueViewer::valueP); } \ inline const Type##Value& value() const { return static_cast<const Type##Value&>(*ValueViewer::valueP); } \
inline const Type##Field& field() const { return style().field(); } \ inline const Type##Field& field() const { return style().field(); } \
inline Type##StyleP styleP() const { return static_pointer_cast<Type##Style>(ValueViewer::styleP); } \ inline Type##StyleP styleP() const { return static_pointer_cast<Type##Style>(ValueViewer::styleP); } \
inline Type##ValueP valueP() const { return static_pointer_cast<Type##Value>(ValueViewer::valueP); } \ inline Type##ValueP valueP() const { return static_pointer_cast<Type##Value>(ValueViewer::valueP); } \
inline Type##FieldP fieldP() const { return static_pointer_cast<Type##Field>(style().fieldP); } \ inline Type##FieldP fieldP() const { return static_pointer_cast<Type##Field>(style().fieldP); } \
public: \ public: \
Type##ValueViewer(DataViewer& parent, const Type ## StyleP& style) Type##ValueViewer(DataViewer& parent, const Type ## StyleP& style)
// ----------------------------------------------------------------------------- : EOF // ----------------------------------------------------------------------------- : EOF
......
...@@ -51,42 +51,42 @@ ...@@ -51,42 +51,42 @@
#define TYPEOF_REF(Value) TypeOf<typeid(Value)>::reference #define TYPEOF_REF(Value) TypeOf<typeid(Value)>::reference
/// The type of a const reference /// The type of a const reference
#define TYPEOF_CREF(Value) TypeOf<typeid(Value)>::const_reference #define TYPEOF_CREF(Value) TypeOf<typeid(Value)>::const_reference
/// Declare typeof magic for a specific type /// Declare typeof magic for a specific type
#define DECLARE_TYPEOF(T) \ #define DECLARE_TYPEOF(T) \
template<> struct TypeOf<typeid(T)> { \ template<> struct TypeOf<typeid(T)> { \
typedef T type; \ typedef T type; \
typedef T::iterator iterator; \ typedef T::iterator iterator; \
typedef T::const_iterator const_iterator; \ typedef T::const_iterator const_iterator; \
typedef T::reverse_iterator reverse_iterator; \ typedef T::reverse_iterator reverse_iterator; \
typedef T::const_reverse_iterator const_reverse_iterator; \ typedef T::const_reverse_iterator const_reverse_iterator; \
typedef T::reference reference; \ typedef T::reference reference; \
typedef T::const_reference const_reference; \ typedef T::const_reference const_reference; \
} }
/// Declare typeof magic for a specific type that doesn't support reverse iterators /// Declare typeof magic for a specific type that doesn't support reverse iterators
#define DECLARE_TYPEOF_NO_REV(T) \ #define DECLARE_TYPEOF_NO_REV(T) \
template<> struct TypeOf<typeid(T)> { \ template<> struct TypeOf<typeid(T)> { \
typedef T type; \ typedef T type; \
typedef T::iterator iterator; \ typedef T::iterator iterator; \
typedef T::const_iterator const_iterator; \ typedef T::const_iterator const_iterator; \
typedef T::reference reference; \ typedef T::reference reference; \
typedef T::const_reference const_reference; \ typedef T::const_reference const_reference; \
} }
/// Declare typeof magic for a specific type, using const iterators /// Declare typeof magic for a specific type, using const iterators
#define DECLARE_TYPEOF_CONST(T) \ #define DECLARE_TYPEOF_CONST(T) \
template<> struct TypeOf<typeid(T)> { \ template<> struct TypeOf<typeid(T)> { \
typedef T type; \ typedef T type; \
typedef T::const_iterator iterator; \ typedef T::const_iterator iterator; \
typedef T::const_iterator const_iterator; \ typedef T::const_iterator const_iterator; \
typedef T::const_reverse_iterator reverse_iterator; \ typedef T::const_reverse_iterator reverse_iterator; \
typedef T::const_reverse_iterator const_reverse_iterator; \ typedef T::const_reverse_iterator const_reverse_iterator; \
typedef T::const_reference reference; \ typedef T::const_reference reference; \
typedef T::const_reference const_reference; \ typedef T::const_reference const_reference; \
} }
/// Declare typeof magic for a specific std::vector type /// Declare typeof magic for a specific std::vector type
#define DECLARE_TYPEOF_COLLECTION(T) DECLARE_TYPEOF(vector< T >); \ #define DECLARE_TYPEOF_COLLECTION(T) DECLARE_TYPEOF(vector< T >); \
DECLARE_TYPEOF_CONST(set< T >) DECLARE_TYPEOF_CONST(set< T >)
#endif #endif
...@@ -103,33 +103,33 @@ ...@@ -103,33 +103,33 @@
/// Iterate over a collection, using an iterator it of type Type /// Iterate over a collection, using an iterator it of type Type
/** Usage: FOR_EACH_IT_T(Type,it,collect) { body-of-loop } /** Usage: FOR_EACH_IT_T(Type,it,collect) { body-of-loop }
*/ */
#define FOR_EACH_IT_T(Type,Iterator,Collection) \ #define FOR_EACH_IT_T(Type,Iterator,Collection) \
for(Type Iterator = Collection.begin() ; \ for(Type Iterator = Collection.begin() ; \
Iterator != Collection.end() ; \ Iterator != Collection.end() ; \
++Iterator) ++Iterator)
/// Iterate over a collection whos type must be declared with DECLARE_TYPEOF /// Iterate over a collection whos type must be declared with DECLARE_TYPEOF
/** Usage: FOR_EACH_IT(it,collect) { body-of-loop } /** Usage: FOR_EACH_IT(it,collect) { body-of-loop }
*/ */
#define FOR_EACH_IT(Iterator,Collection) \ #define FOR_EACH_IT(Iterator,Collection) \
FOR_EACH_IT_T(TYPEOF_IT(Collection), Iterator, Collection) FOR_EACH_IT_T(TYPEOF_IT(Collection), Iterator, Collection)
/// Iterate over a collection whos type must be declared with DECLARE_TYPEOF /// Iterate over a collection whos type must be declared with DECLARE_TYPEOF
/** Uses a const_iterator /** Uses a const_iterator
* Usage: FOR_EACH_IT(it,collect) { body-of-loop } * Usage: FOR_EACH_IT(it,collect) { body-of-loop }
*/ */
#define FOR_EACH_CONST_IT(Iterator,Collection) \ #define FOR_EACH_CONST_IT(Iterator,Collection) \
FOR_EACH_IT_T(TYPEOF_CIT(Collection), Iterator, Collection) FOR_EACH_IT_T(TYPEOF_CIT(Collection), Iterator, Collection)
/// Iterate over a collection in whos type must be declared with DECLARE_TYPEOF /// Iterate over a collection in whos type must be declared with DECLARE_TYPEOF
/** Iterates using a reverse_iterator /** Iterates using a reverse_iterator
* Usage: FOR_EACH_REVERSE_IT(it,collect) { body-of-loop } * Usage: FOR_EACH_REVERSE_IT(it,collect) { body-of-loop }
*/ */
#define FOR_EACH_REVERSE_IT(Iterator,Collection) \ #define FOR_EACH_REVERSE_IT(Iterator,Collection) \
for(TYPEOF_RIT(Collection) \ for(TYPEOF_RIT(Collection) \
Iterator = Collection.rbegin() ; \ Iterator = Collection.rbegin() ; \
Iterator != Collection.rend() ; \ Iterator != Collection.rend() ; \
++Iterator) ++Iterator)
// ----------------------------------------------------------------------------- : Looping macros // ----------------------------------------------------------------------------- : Looping macros
...@@ -140,40 +140,40 @@ ...@@ -140,40 +140,40 @@
* To do this we use a nested for loop that is only executed once, and which is optimized away. * 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. * 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) \ #define FOR_EACH_T(TypeIt,TypeElem,Elem,Collection, begin, end) \
for(std::pair<TypeIt,bool> Elem##_IT(Collection.begin(), true) ; \ for(std::pair<TypeIt,bool> Elem##_IT(Collection.begin(), true) ; \
Elem##_IT.second && Elem##_IT.first != Collection.end() ; \ Elem##_IT.second && Elem##_IT.first != Collection.end() ; \
++Elem##_IT.first, Elem##_IT.second = !Elem##_IT.second) \ ++Elem##_IT.first, Elem##_IT.second = !Elem##_IT.second) \
for(TypeElem Elem = *Elem##_IT.first ; \ for(TypeElem Elem = *Elem##_IT.first ; \
Elem##_IT.second ; \ Elem##_IT.second ; \
Elem##_IT.second = false) Elem##_IT.second = false)
/// Iterate over a collection whos type must be declared with DECLARE_TYPEOF /// Iterate over a collection whos type must be declared with DECLARE_TYPEOF
/** Usage: FOR_EACH(e,collect) { body-of-loop } /** Usage: FOR_EACH(e,collect) { body-of-loop }
*/ */
#define FOR_EACH(Elem,Collection) \ #define FOR_EACH(Elem,Collection) \
FOR_EACH_T(TYPEOF_IT(Collection), TYPEOF_REF(Collection), Elem, Collection, begin, end) 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 /// Iterate over a collection whos type must be declared with DECLARE_TYPEOF
/** Uses a const iterator /** Uses a const iterator
* Usage: FOR_EACH_CONST(e,collect) { body-of-loop } * Usage: FOR_EACH_CONST(e,collect) { body-of-loop }
*/ */
#define FOR_EACH_CONST(Elem,Collection) \ #define FOR_EACH_CONST(Elem,Collection) \
FOR_EACH_T(TYPEOF_CIT(Collection), TYPEOF_CREF(Collection), Elem, Collection, begin, end) 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 /// Iterate over a collection whos type must be declared with DECLARE_TYPEOF
/** Iterates using a reverse_iterator /** Iterates using a reverse_iterator
* Usage: FOR_EACH_REVERSE(e,collect) { body-of-loop } * Usage: FOR_EACH_REVERSE(e,collect) { body-of-loop }
*/ */
#define FOR_EACH_REVERSE(Elem,Collection) \ #define FOR_EACH_REVERSE(Elem,Collection) \
FOR_EACH_T(TYPEOF_RIT(Collection), TYPEOF_REF(Collection), Elem, Collection, rbegin, rend) 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 /// Iterate over a collection whos type must be declared with DECLARE_TYPEOF
/** Iterates using a const_reverse_iterator /** Iterates using a const_reverse_iterator
* Usage: FOR_EACH_CONST_REVERSE(e,collect) { body-of-loop } * Usage: FOR_EACH_CONST_REVERSE(e,collect) { body-of-loop }
*/ */
#define FOR_EACH_CONST_REVERSE(Elem,Collection) \ #define FOR_EACH_CONST_REVERSE(Elem,Collection) \
FOR_EACH_T(TYPEOF_CRIT(Collection), TYPEOF_CREF(Collection), Elem, Collection, rbegin, rend) FOR_EACH_T(TYPEOF_CRIT(Collection), TYPEOF_CREF(Collection), Elem, Collection, rbegin, rend)
/// Iterate over two collection in parallel /// Iterate over two collection in parallel
/** Usage: FOR_EACH_2_T(TypeIt1,TypeElem1,e1,collect1,TypeIt2,TypeElem2,e2,collect2) { body-of-loop } /** Usage: FOR_EACH_2_T(TypeIt1,TypeElem1,e1,collect1,TypeIt2,TypeElem2,e2,collect2) { body-of-loop }
...@@ -181,33 +181,33 @@ ...@@ -181,33 +181,33 @@
* Note: This has got to be one of the craziest pieces of code I have ever written :) * 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. * 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) \ #define FOR_EACH_2_T(TypeIt1,TypeElem1,Elem1,Coll1,TypeIt2,TypeElem2,Elem2,Coll2) \
for(std::pair<std::pair<TypeIt1,TypeIt2>, bool> \ for(std::pair<std::pair<TypeIt1,TypeIt2>, bool> \
Elem1##_IT(make_pair(Coll1.begin(), Coll2.begin()), true) ; \ Elem1##_IT(make_pair(Coll1.begin(), Coll2.begin()), true) ; \
Elem1##_IT.first.first != Coll1.end() && \ Elem1##_IT.first.first != Coll1.end() && \
Elem1##_IT.first.second != Coll2.end() ; \ Elem1##_IT.first.second != Coll2.end() ; \
++Elem1##_IT.first.first, ++Elem1##_IT.first.second, \ ++Elem1##_IT.first.first, ++Elem1##_IT.first.second, \
Elem1##_IT.second = true) \ Elem1##_IT.second = true) \
for(TypeElem1 Elem1 = *Elem1##_IT.first.first ; \ for(TypeElem1 Elem1 = *Elem1##_IT.first.first ; \
Elem1##_IT.second ; \ Elem1##_IT.second ; \
Elem1##_IT.second = false) \ Elem1##_IT.second = false) \
for(TypeElem2 Elem2 = *Elem1##_IT.first.second ; \ for(TypeElem2 Elem2 = *Elem1##_IT.first.second ; \
Elem1##_IT.second ; \ Elem1##_IT.second ; \
Elem1##_IT.second = false) Elem1##_IT.second = false)
/// Iterate over two collections in parallel, their type must be declared with DECLARE_TYPEOF. /// 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 } /** Usage: FOR_EACH_2(e1,collect1, e2,collect2) { body-of-loop }
*/ */
#define FOR_EACH_2(Elem1,Collection1, Elem2,Collection2) \ #define FOR_EACH_2(Elem1,Collection1, Elem2,Collection2) \
FOR_EACH_2_T(TYPEOF_IT(Collection1), TYPEOF_REF(Collection1), Elem1, Collection1, \ FOR_EACH_2_T(TYPEOF_IT(Collection1), TYPEOF_REF(Collection1), Elem1, Collection1, \
TYPEOF_IT(Collection2), TYPEOF_REF(Collection2), Elem2, Collection2) TYPEOF_IT(Collection2), TYPEOF_REF(Collection2), Elem2, Collection2)
/// Iterate over two constants collections in parallel, their type must be declared with DECLARE_TYPEOF. /// 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 } /** Usage: FOR_EACH_2_CONST(e1,collect1, e2,collect2) { body-of-loop }
*/ */
#define FOR_EACH_2_CONST(Elem1,Collection1, Elem2,Collection2) \ #define FOR_EACH_2_CONST(Elem1,Collection1, Elem2,Collection2) \
FOR_EACH_2_T(TYPEOF_CIT(Collection1), TYPEOF_CREF(Collection1), Elem1, Collection1, \ FOR_EACH_2_T(TYPEOF_CIT(Collection1), TYPEOF_CREF(Collection1), Elem1, Collection1, \
TYPEOF_CIT(Collection2), TYPEOF_CREF(Collection2), Elem2, Collection2) TYPEOF_CIT(Collection2), TYPEOF_CREF(Collection2), Elem2, Collection2)
// ----------------------------------------------------------------------------- : EOF // ----------------------------------------------------------------------------- : EOF
......
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