Commit 974399c7 authored by twanvl's avatar twanvl

Cleaned up Set::Styling/Card::Styling by spliting that functionality into a...

Cleaned up Set::Styling/Card::Styling by spliting that functionality into a 'DelayedIndexMaps' class;
Added 'right' and 'bottom' properties to style as an alternative way of specifying width/height;
Added content_width, content_height and content_lines properties that give feedback on text rendering;
Always show warnings when showing errors and vice-versa, this prevents script errors from appearing before the reader/parse error that caused them;
Finally some preliminairy work on export templates
parent 33b6aec9
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include <data/field.hpp> #include <data/field.hpp>
#include <util/error.hpp> #include <util/error.hpp>
#include <util/reflect.hpp> #include <util/reflect.hpp>
#include <wx/sstream.h> #include <util/delayed_index_maps.hpp>
DECLARE_TYPEOF_COLLECTION(FieldP); DECLARE_TYPEOF_COLLECTION(FieldP);
DECLARE_TYPEOF_NO_REV(IndexMap<FieldP COMMA ValueP>); DECLARE_TYPEOF_NO_REV(IndexMap<FieldP COMMA ValueP>);
...@@ -45,6 +45,10 @@ String Card::identification() const { ...@@ -45,6 +45,10 @@ String Card::identification() const {
} }
} }
IndexMap<FieldP, ValueP>& Card::extraDataFor(const StyleSheet& stylesheet) {
return extra_data.get(stylesheet.name(), stylesheet.extra_card_fields);
}
void mark_dependency_member(const Card& card, const String& name, const Dependency& dep) { void mark_dependency_member(const Card& card, const String& name, const Dependency& dep) {
mark_dependency_member(card.data, name, dep); mark_dependency_member(card.data, name, dep);
} }
...@@ -52,48 +56,6 @@ void mark_dependency_member(const Card& card, const String& name, const Dependen ...@@ -52,48 +56,6 @@ void mark_dependency_member(const Card& card, const String& name, const Dependen
IMPLEMENT_REFLECTION(Card) { IMPLEMENT_REFLECTION(Card) {
REFLECT(stylesheet); REFLECT(stylesheet);
REFLECT(notes); REFLECT(notes);
REFLECT_NO_SCRIPT(extra_data); REFLECT_NO_SCRIPT(extra_data); // don't allow scripts to depend on style specific data
REFLECT_NAMELESS(data); REFLECT_NAMELESS(data);
} }
// ----------------------------------------------------------------------------- : Styling
// TODO : this is practically the same as Set::Styling, maybe somehow abstract it
// Extra card data, for a specific stylesheet
/* The data is not read immediatly, because we do not know the stylesheet */
class Card::Styling : public IntrusivePtrBase<Card::Styling> {
public:
/// The values on the extra card fields of the card.
/** The indices should correspond to the extra_card_fields in the StyleSheet */
IndexMap<FieldP, ValueP> extra_data;
/// Unparsed extra_data
String unread_data;
DECLARE_REFLECTION();
};
IndexMap<FieldP, ValueP>& Card::extraDataFor(const StyleSheet& stylesheet) {
StylingP& styling = extra_data[stylesheet.name()];
if (!styling) {
styling = new_intrusive<Styling>();
styling->extra_data.init(stylesheet.extra_card_fields);
} else if (!styling->unread_data.empty() || (styling->extra_data.empty()) && !stylesheet.extra_card_fields.empty()) {
// we delayed the reading of the data, read it now
styling->extra_data.init(stylesheet.extra_card_fields);
Reader reader(new_shared1<wxStringInputStream>(styling->unread_data), _("extra card values for ") + stylesheet.stylesheetName());
reader.handle_greedy(styling->extra_data);
styling->unread_data.clear();
}
return styling->extra_data;
}
// custom reflection : read into unread_data
template <> void Reader::handle(Card::Styling& s) {
handle(s.unread_data);
}
template <> void Writer::handle(const Card::Styling& s) {
handle(s.extra_data);
}
// for the love of god, don't depend on styling
template <> void GetMember::handle(const Card::Styling& s) {}
template <> void GetDefaultMember::handle(const Card::Styling& s) {}
...@@ -41,8 +41,7 @@ class Card : public IntrusivePtrVirtualBase { ...@@ -41,8 +41,7 @@ class Card : public IntrusivePtrVirtualBase {
StyleSheetP stylesheet; StyleSheetP stylesheet;
/// Extra values for specitic stylesheets, indexed by stylesheet name /// Extra values for specitic stylesheets, indexed by stylesheet name
DECLARE_POINTER_TYPE(Styling); DelayedIndexMaps<FieldP,ValueP> extra_data;
map<String, StylingP> extra_data;
/// 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) ;
......
...@@ -7,9 +7,13 @@ ...@@ -7,9 +7,13 @@
// ----------------------------------------------------------------------------- : Includes // ----------------------------------------------------------------------------- : Includes
#include <data/export_template.hpp> #include <data/export_template.hpp>
#include <data/game.hpp>
#include <data/field.hpp>
// ----------------------------------------------------------------------------- : Export template, basics // ----------------------------------------------------------------------------- : Export template, basics
ExportTemplate::ExportTemplate() {}
String ExportTemplate::typeNameStatic() { return _("export-template"); } String ExportTemplate::typeNameStatic() { return _("export-template"); }
String ExportTemplate::typeName() const { return _("export-template"); } String ExportTemplate::typeName() const { return _("export-template"); }
......
...@@ -13,16 +13,23 @@ ...@@ -13,16 +13,23 @@
#include <util/io/package.hpp> #include <util/io/package.hpp>
#include <script/scriptable.hpp> #include <script/scriptable.hpp>
DECLARE_POINTER_TYPE(Game);
DECLARE_POINTER_TYPE(Field);
DECLARE_POINTER_TYPE(Style);
// ----------------------------------------------------------------------------- : ExportTemplate // ----------------------------------------------------------------------------- : ExportTemplate
/// A template for exporting sets to HTML or text format /// A template for exporting sets to HTML or text format
class ExportTemplate : public Packaged { class ExportTemplate : public Packaged {
public: public:
ExportTemplate();
OptionalScript script; ///< Export script GameP game; ///< Game this template is for
String file_type; ///< Type of the created file, in "name|*.ext" format OptionalScript script; ///< Export script
bool create_directory; ///< The export creates an entire directory String file_type; ///< Type of the created file, in "name|*.ext" format
bool create_directory; ///< The export creates an entire directory
vector<FieldP> option_fields; ///< Options for exporting
IndexMap<FieldP,StyleP> option_style; ///< Style of the options
static String typeNameStatic(); static String typeNameStatic();
virtual String typeName() const; virtual String typeName() const;
......
...@@ -85,7 +85,10 @@ Style::Style(const FieldP& field) ...@@ -85,7 +85,10 @@ Style::Style(const FieldP& field)
, z_index(0) , z_index(0)
, left(0), top(0) , left(0), top(0)
, width(0), height(0) , width(0), height(0)
, right(0), bottom(0)
, visible(true) , visible(true)
, automatic_side(AUTO_UNKNOWN)
, content_dependent(false)
{} {}
Style::~Style() {} Style::~Style() {}
...@@ -93,9 +96,11 @@ Style::~Style() {} ...@@ -93,9 +96,11 @@ Style::~Style() {}
IMPLEMENT_REFLECTION(Style) { IMPLEMENT_REFLECTION(Style) {
REFLECT(z_index); REFLECT(z_index);
REFLECT(left); REFLECT(left);
REFLECT(top);
REFLECT(width); REFLECT(width);
REFLECT(right);
REFLECT(top);
REFLECT(height); REFLECT(height);
REFLECT(bottom);
REFLECT(visible); REFLECT(visible);
} }
...@@ -107,11 +112,35 @@ template <> StyleP read_new<Style>(Reader&) { ...@@ -107,11 +112,35 @@ template <> StyleP read_new<Style>(Reader&) {
} }
bool Style::update(Context& ctx) { bool Style::update(Context& ctx) {
return left .update(ctx) bool changed =
| top .update(ctx) left .update(ctx)
| width .update(ctx) | width .update(ctx)
| right .update(ctx)
| top .update(ctx)
| height .update(ctx) | height .update(ctx)
| bottom .update(ctx)
| visible.update(ctx); | visible.update(ctx);
// determine automatic_side
if (automatic_side == AUTO_UNKNOWN) {
if (right == 0) automatic_side = (AutomaticSide)(automatic_side | AUTO_RIGHT);
else if (width == 0) automatic_side = (AutomaticSide)(automatic_side | AUTO_WIDTH);
else automatic_side = (AutomaticSide)(automatic_side | AUTO_LEFT);
if (bottom == 0) automatic_side = (AutomaticSide)(automatic_side | AUTO_BOTTOM);
else if (height == 0) automatic_side = (AutomaticSide)(automatic_side | AUTO_HEIGHT);
else automatic_side = (AutomaticSide)(automatic_side | AUTO_TOP);
}
if (automatic_side & AUTO_WIDTH){
changed=changed;//BREAKPOINT
}
// update the automatic_side
if (automatic_side & AUTO_LEFT) left = right - width;
else if (automatic_side & AUTO_WIDTH) width = right - left;
else right = left + width;
if (automatic_side & AUTO_TOP) top = bottom - height;
else if (automatic_side & AUTO_HEIGHT) height = bottom - top;
else bottom = top + height;
// are there changes?
return changed;
} }
void Style::initDependencies(Context& ctx, const Dependency& dep) const { void Style::initDependencies(Context& ctx, const Dependency& dep) const {
...@@ -121,6 +150,23 @@ void Style::initDependencies(Context& ctx, const Dependency& dep) const { ...@@ -121,6 +150,23 @@ void Style::initDependencies(Context& ctx, const Dependency& dep) const {
// height .initDependencies(ctx,dep); // height .initDependencies(ctx,dep);
// visible.initDependencies(ctx,dep); // visible.initDependencies(ctx,dep);
} }
void Style::checkContentDependencies(Context& ctx, const Dependency& dep) const {
left .initDependencies(ctx,dep);
top .initDependencies(ctx,dep);
width .initDependencies(ctx,dep);
height .initDependencies(ctx,dep);
right .initDependencies(ctx,dep);
bottom .initDependencies(ctx,dep);
visible.initDependencies(ctx,dep);
}
void Style::markDependencyMember(const String& name, const Dependency& dep) const {
// no content specific properties here
}
void mark_dependency_member(const Style& style, const String& name, const Dependency& dep) {
style.markDependencyMember(name,dep);
}
// ----------------------------------------------------------------------------- : StyleListener // ----------------------------------------------------------------------------- : StyleListener
......
...@@ -88,7 +88,14 @@ class Style : public IntrusivePtrVirtualBase { ...@@ -88,7 +88,14 @@ class Style : public IntrusivePtrVirtualBase {
int z_index; ///< Stacking of values of this field, higher = on top int z_index; ///< Stacking of values of this field, higher = on top
Scriptable<double> left, top; ///< Position of this field Scriptable<double> left, top; ///< Position of this field
Scriptable<double> width, height; ///< Position of this field Scriptable<double> width, height; ///< Position of this field
Scriptable<double> right, bottom; ///< Position of this field
Scriptable<bool> visible; ///< Is this field visible? Scriptable<bool> visible; ///< Is this field visible?
enum AutomaticSide {
AUTO_UNKNOWN = 0x00,
AUTO_LEFT = 0x01, AUTO_WIDTH = 0x02, AUTO_RIGHT = 0x04,
AUTO_TOP = 0x10, AUTO_HEIGHT = 0x20, AUTO_BOTTOM = 0x40,
} automatic_side : 8; ///< Which of (left, width, right) and (top, height, bottom) is determined automatically?
bool content_dependent; ///< Does this style depend on content properties?
inline RealPoint getPos() const { return RealPoint(left, top ); } inline RealPoint getPos() const { return RealPoint(left, top ); }
inline RealSize getSize() const { return RealSize ( width, height); } inline RealSize getSize() const { return RealSize ( width, height); }
...@@ -110,6 +117,13 @@ class Style : public IntrusivePtrVirtualBase { ...@@ -110,6 +117,13 @@ class Style : public IntrusivePtrVirtualBase {
/// Add the given dependency to the dependent_scripts list for the variables this style depends on /// Add the given dependency to the dependent_scripts list for the variables this style depends on
/** Only use for things that need invalidate() */ /** Only use for things that need invalidate() */
virtual void initDependencies(Context&, const Dependency&) const; virtual void initDependencies(Context&, const Dependency&) const;
/// Check if the style depends on content properties
/** If there is such a dependency, set dep.index to true.
* This is done by mark_dependency_member for those properies */
virtual void checkContentDependencies(Context&, const Dependency&) const;
/// Dependencies on properies?
/** In particular, if dep == DEP_DUMMY and name is a content property, set dep.index=true */
virtual void markDependencyMember(const String& name, const Dependency&) const;
/// Invalidate scripted images for this style /// Invalidate scripted images for this style
virtual void invalidate(Context&) {} virtual void invalidate(Context&) {}
...@@ -131,6 +145,8 @@ inline const FieldP& get_key (const StyleP& s) { return s->fieldP; } ...@@ -131,6 +145,8 @@ inline const FieldP& get_key (const StyleP& s) { return s->fieldP; }
inline const String& get_key_name(const StyleP& s) { return s->fieldP->name; } inline const String& get_key_name(const StyleP& s) { return s->fieldP->name; }
template <> StyleP read_new<Style>(Reader&); template <> StyleP read_new<Style>(Reader&);
void mark_dependency_member(const Style& style, const String& name, const Dependency& dep);
// ----------------------------------------------------------------------------- : StyleListener // ----------------------------------------------------------------------------- : StyleListener
/// An object that can respond when a style changes; /// An object that can respond when a style changes;
......
...@@ -68,6 +68,18 @@ void TextStyle::initDependencies(Context& ctx, const Dependency& dep) const { ...@@ -68,6 +68,18 @@ void TextStyle::initDependencies(Context& ctx, const Dependency& dep) const {
// font .initDependencies(ctx, dep); // font .initDependencies(ctx, dep);
// symbol_font.initDependencies(ctx, dep); // symbol_font.initDependencies(ctx, dep);
} }
void TextStyle::checkContentDependencies(Context& ctx, const Dependency& dep) const {
Style ::checkContentDependencies(ctx, dep);
alignment.initDependencies(ctx, dep);
}
void TextStyle::markDependencyMember(const String& name, const Dependency& dep) const {
Style::markDependencyMember(name, dep);
// mark dependencies on content
if (dep.type == DEP_DUMMY && dep.index == false &&
(name == _("content width") || name == _("content height") || name == _("content lines"))) {
const_cast<Dependency&>(dep).index = true;
}
}
IMPLEMENT_REFLECTION(TextBackground) { IMPLEMENT_REFLECTION(TextBackground) {
REFLECT(image); REFLECT(image);
...@@ -75,6 +87,13 @@ IMPLEMENT_REFLECTION(TextBackground) { ...@@ -75,6 +87,13 @@ IMPLEMENT_REFLECTION(TextBackground) {
REFLECT_N("displacement_y", displacement.height); REFLECT_N("displacement_y", displacement.height);
} }
template <typename T> void reflect_content(T& tag, const TextStyle& ts) {}
template <> void reflect_content(GetMember& tag, const TextStyle& ts) {
REFLECT_N("content_width", ts.content_width);
REFLECT_N("content_height", ts.content_height);
REFLECT_N("content_lines", ts.content_lines);
}
IMPLEMENT_REFLECTION(TextStyle) { IMPLEMENT_REFLECTION(TextStyle) {
REFLECT_BASE(Style); REFLECT_BASE(Style);
REFLECT(font); REFLECT(font);
...@@ -99,6 +118,7 @@ IMPLEMENT_REFLECTION(TextStyle) { ...@@ -99,6 +118,7 @@ IMPLEMENT_REFLECTION(TextStyle) {
REFLECT(text_background); REFLECT(text_background);
REFLECT(text_background_left); REFLECT(text_background_left);
REFLECT(text_background_right); REFLECT(text_background_right);
reflect_content(tag, *this);
} }
// ----------------------------------------------------------------------------- : TextValue // ----------------------------------------------------------------------------- : TextValue
......
...@@ -80,9 +80,14 @@ class TextStyle : public Style { ...@@ -80,9 +80,14 @@ class TextStyle : public Style {
Direction direction; ///< In what direction is text layed out? Direction direction; ///< In what direction is text layed out?
TextBackgroundP text_background; ///< Image behind the text TextBackgroundP text_background; ///< Image behind the text
TextBackgroundP text_background_left, text_background_right; TextBackgroundP text_background_left, text_background_right;
// information from text rendering
double content_width, content_height; ///< Size of the rendered text
int content_lines; ///< Number of rendered lines
virtual bool update(Context&); virtual bool update(Context&);
virtual void initDependencies(Context&, const Dependency&) const; virtual void initDependencies(Context&, const Dependency&) const;
virtual void checkContentDependencies(Context&, const Dependency&) const;
virtual void markDependencyMember(const String& name, const Dependency&) const;
/// The rotation to use when drawing /// The rotation to use when drawing
inline Rotation getRotation() const { inline Rotation getRotation() const {
......
...@@ -204,42 +204,8 @@ void Set::clearOrderCache() { ...@@ -204,42 +204,8 @@ void Set::clearOrderCache() {
// ----------------------------------------------------------------------------- : Styling // ----------------------------------------------------------------------------- : Styling
// Extra set data, for a specific stylesheet
/* The data is not read immediatly, because we do not know the stylesheet */
class Set::Styling : public IntrusivePtrBase<Set::Styling> {
public:
IndexMap<FieldP, ValueP> data;
String unread_data;
DECLARE_REFLECTION();
};
IndexMap<FieldP, ValueP>& Set::stylingDataFor(const StyleSheet& stylesheet) { IndexMap<FieldP, ValueP>& Set::stylingDataFor(const StyleSheet& stylesheet) {
StylingP& styling = styling_data[stylesheet.name()]; return styling_data.get(stylesheet.name(), stylesheet.styling_fields);
if (!styling) {
styling = new_intrusive<Styling>();
styling->data.init(stylesheet.styling_fields);
} else if (!styling->unread_data.empty() || (styling->data.empty()) && !stylesheet.styling_fields.empty()) {
// we delayed the reading of the data, read it now
styling->data.init(stylesheet.styling_fields);
Reader reader(new_shared1<wxStringInputStream>(styling->unread_data), _("styling data of ") + stylesheet.stylesheetName());
reader.handle_greedy(styling->data);
styling->unread_data.clear();
}
return styling->data;
}
// custom reflection : read into unread_data
template <> void Reader::handle(Set::Styling& s) {
handle(s.unread_data);
}
template <> void Writer::handle(const Set::Styling& s) {
handle(s.data);
}
template <> void GetMember::handle(const Set::Styling& s) {
handle(s.data);
}
template <> void GetDefaultMember::handle(const Set::Styling& s) {
handle(s.data);
} }
// ----------------------------------------------------------------------------- : SetView // ----------------------------------------------------------------------------- : SetView
......
...@@ -52,8 +52,7 @@ class Set : public Packaged { ...@@ -52,8 +52,7 @@ class Set : public Packaged {
/** The indices should correspond to the set_fields in the Game */ /** The indices should correspond to the set_fields in the Game */
IndexMap<FieldP, ValueP> data; IndexMap<FieldP, ValueP> data;
/// Extra values for specitic stylesheets, indexed by stylesheet name /// Extra values for specitic stylesheets, indexed by stylesheet name
DECLARE_POINTER_TYPE(Styling); DelayedIndexMaps<FieldP,ValueP> styling_data;
map<String, StylingP> styling_data;
vector<CardP> cards; ///< The cards in the set vector<CardP> cards; ///< The cards in the set
vector<KeywordP> keywords; ///< Additional keywords used in this set vector<KeywordP> keywords; ///< Additional keywords used in this set
String apprentice_code; ///< Code to use for apprentice (Magic only) String apprentice_code; ///< Code to use for apprentice (Magic only)
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
#include <util/prec.hpp> #include <util/prec.hpp>
#include <gui/control/card_editor.hpp> #include <gui/control/card_editor.hpp>
DECLARE_POINTER_TYPE(ExportTemplate);
// ----------------------------------------------------------------------------- : NativeLookEditor // ----------------------------------------------------------------------------- : NativeLookEditor
/// A data editor with a platform native look /// A data editor with a platform native look
...@@ -71,7 +73,20 @@ class StylingEditor : public NativeLookEditor { ...@@ -71,7 +73,20 @@ class StylingEditor : public NativeLookEditor {
protected: protected:
virtual void onChangeSet(); virtual void onChangeSet();
};
// ----------------------------------------------------------------------------- : ExportOptionsEditor
/// Editor for export options
class ExportOptionsEditor : public NativeLookEditor {
public:
ExportOptionsEditor(Window* parent, int id, long style = 0);
/// Show the options for given export template
void showExport(const ExportTemplateP& export);
protected:
virtual void onChangeSet();
}; };
// ----------------------------------------------------------------------------- : EOF // ----------------------------------------------------------------------------- : EOF
......
...@@ -8,16 +8,23 @@ ...@@ -8,16 +8,23 @@
#include <gui/html_export_window.hpp> #include <gui/html_export_window.hpp>
#include <gui/control/package_list.hpp> #include <gui/control/package_list.hpp>
#include <data/set.hpp>
#include <data/game.hpp>
#include <data/settings.hpp>
#include <data/export_template.hpp> #include <data/export_template.hpp>
#include <util/window_id.hpp>
#include <util/error.hpp> #include <util/error.hpp>
DECLARE_POINTER_TYPE(ExportTemplate);
// ----------------------------------------------------------------------------- : HtmlExportWindow // ----------------------------------------------------------------------------- : HtmlExportWindow
HtmlExportWindow::HtmlExportWindow(Window* parent, const SetP& set) HtmlExportWindow::HtmlExportWindow(Window* parent, const SetP& set)
: wxDialog(parent,wxID_ANY,_TITLE_("export html"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxFULL_REPAINT_ON_RESIZE) : wxDialog(parent,wxID_ANY,_TITLE_("export html"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxFULL_REPAINT_ON_RESIZE)
, set(set)
{ {
// init controls // init controls
list = new PackageList (this, wxID_ANY); list = new PackageList(this, ID_EXPORT_LIST);
// init sizers // init sizers
wxSizer* s = new wxBoxSizer(wxVERTICAL); wxSizer* s = new wxBoxSizer(wxVERTICAL);
s->Add(new wxStaticText(this, wxID_ANY, _LABEL_("html template")), 0, wxALL, 4); s->Add(new wxStaticText(this, wxID_ANY, _LABEL_("html template")), 0, wxALL, 4);
...@@ -25,6 +32,9 @@ HtmlExportWindow::HtmlExportWindow(Window* parent, const SetP& set) ...@@ -25,6 +32,9 @@ HtmlExportWindow::HtmlExportWindow(Window* parent, const SetP& set)
s->Add(CreateButtonSizer(wxOK | wxCANCEL) , 0, wxEXPAND | wxALL, 8); s->Add(CreateButtonSizer(wxOK | wxCANCEL) , 0, wxEXPAND | wxALL, 8);
s->SetSizeHints(this); s->SetSizeHints(this);
SetSizer(s); SetSizer(s);
// list
list->showData<ExportTemplate>(set->game->name() + _("-*"));
list->select(settings.gameSettingsFor(*set->game).default_export);
} }
void HtmlExportWindow::onOk(wxCommandEvent&) { void HtmlExportWindow::onOk(wxCommandEvent&) {
...@@ -43,6 +53,24 @@ void HtmlExportWindow::onOk(wxCommandEvent&) { ...@@ -43,6 +53,24 @@ void HtmlExportWindow::onOk(wxCommandEvent&) {
EndModal(wxID_OK); EndModal(wxID_OK);
} }
void HtmlExportWindow::onTemplateSelect(wxCommandEvent&) {
wxBusyCursor wait;
ExportTemplateP export = list->getSelection<ExportTemplate>();
handle_pending_errors();
settings.gameSettingsFor(*set->game).default_export = export->name();
UpdateWindowUI(wxUPDATE_UI_RECURSE);
}
void HtmlExportWindow::onUpdateUI(wxUpdateUIEvent& ev) {
switch (ev.GetId()) {
case wxID_OK:
ev.Enable(list->hasSelection());
break;
}
}
BEGIN_EVENT_TABLE(HtmlExportWindow,wxDialog) BEGIN_EVENT_TABLE(HtmlExportWindow,wxDialog)
EVT_BUTTON (wxID_OK, HtmlExportWindow::onOk) EVT_GALLERY_SELECT (ID_EXPORT_LIST, HtmlExportWindow::onTemplateSelect)
EVT_BUTTON (wxID_OK, HtmlExportWindow::onOk)
EVT_UPDATE_UI (wxID_ANY, HtmlExportWindow::onUpdateUI)
END_EVENT_TABLE () END_EVENT_TABLE ()
...@@ -22,10 +22,13 @@ class HtmlExportWindow : public wxDialog { ...@@ -22,10 +22,13 @@ class HtmlExportWindow : public wxDialog {
private: private:
PackageList* list; ///< List of templates PackageList* list; ///< List of templates
SetP set; ///< Set to export
DECLARE_EVENT_TABLE(); DECLARE_EVENT_TABLE();
void onOk(wxCommandEvent&); void onOk(wxCommandEvent&);
void onTemplateSelect(wxCommandEvent&);
void onUpdateUI(wxUpdateUIEvent& ev);
}; };
// ----------------------------------------------------------------------------- : EOF // ----------------------------------------------------------------------------- : EOF
......
...@@ -50,9 +50,9 @@ NewSetWindow::NewSetWindow(Window* parent) ...@@ -50,9 +50,9 @@ NewSetWindow::NewSetWindow(Window* parent)
// init lists // init lists
game_list->showData<Game>(); game_list->showData<Game>();
try { try {
game_list->select(settings.default_game); game_list->select(settings.default_game);
} catch (FileNotFoundError e) { } catch (FileNotFoundError e) {
handle_error(e); handle_error(e);
} }
UpdateWindowUI(wxUPDATE_UI_RECURSE); UpdateWindowUI(wxUPDATE_UI_RECURSE);
} }
...@@ -62,9 +62,8 @@ void NewSetWindow::onGameSelect(wxCommandEvent&) { ...@@ -62,9 +62,8 @@ void NewSetWindow::onGameSelect(wxCommandEvent&) {
GameP game = game_list->getSelection<Game>(); GameP game = game_list->getSelection<Game>();
handle_pending_errors(); handle_pending_errors();
settings.default_game = game->name(); settings.default_game = game->name();
GameSettings& gs = settings.gameSettingsFor(*game);
stylesheet_list->showData<StyleSheet>(game->name() + _("-*")); stylesheet_list->showData<StyleSheet>(game->name() + _("-*"));
stylesheet_list->select(gs.default_stylesheet); stylesheet_list->select(settings.gameSettingsFor(*game).default_stylesheet);
UpdateWindowUI(wxUPDATE_UI_RECURSE); UpdateWindowUI(wxUPDATE_UI_RECURSE);
// resize (yuck) // resize (yuck)
SetSize(630,-1); SetSize(630,-1);
...@@ -80,8 +79,7 @@ void NewSetWindow::onStyleSheetSelect(wxCommandEvent&) { ...@@ -80,8 +79,7 @@ void NewSetWindow::onStyleSheetSelect(wxCommandEvent&) {
GameP game = game_list ->getSelection<Game>(); GameP game = game_list ->getSelection<Game>();
StyleSheetP stylesheet = stylesheet_list->getSelection<StyleSheet>(); StyleSheetP stylesheet = stylesheet_list->getSelection<StyleSheet>();
handle_pending_errors(); handle_pending_errors();
GameSettings& gs = settings.gameSettingsFor(*game); settings.gameSettingsFor(*game).default_stylesheet = stylesheet->name();
gs.default_stylesheet = stylesheet->name();
UpdateWindowUI(wxUPDATE_UI_RECURSE); UpdateWindowUI(wxUPDATE_UI_RECURSE);
} }
void NewSetWindow::onStyleSheetActivate(wxCommandEvent&) { void NewSetWindow::onStyleSheetActivate(wxCommandEvent&) {
......
...@@ -2102,6 +2102,9 @@ ...@@ -2102,6 +2102,9 @@
<File <File
RelativePath=".\util\defaultable.hpp"> RelativePath=".\util\defaultable.hpp">
</File> </File>
<File
RelativePath=".\util\delayed_index_maps.hpp">
</File>
<File <File
RelativePath=".\util\find_replace.hpp"> RelativePath=".\util\find_replace.hpp">
</File> </File>
...@@ -3212,10 +3215,10 @@ ...@@ -3212,10 +3215,10 @@
RelativePath="..\conversion-todo.txt"> RelativePath="..\conversion-todo.txt">
</File> </File>
<File <File
RelativePath="..\data\nl.mse-locale\locale"> RelativePath="..\data\en.mse-locale\locale">
</File> </File>
<File <File
RelativePath="..\data\en.mse-locale\locale"> RelativePath="..\data\nl.mse-locale\locale">
</File> </File>
<File <File
RelativePath=".\main.cpp"> RelativePath=".\main.cpp">
......
...@@ -54,7 +54,17 @@ void DataViewer::draw(RotatedDC& dc, const Color& background) { ...@@ -54,7 +54,17 @@ void DataViewer::draw(RotatedDC& dc, const Color& background) {
} catch (const Error& e) { } catch (const Error& e) {
handle_error(e, false, false); handle_error(e, false, false);
} }
// draw values // prepare viewers
FOR_EACH(v, viewers) { // draw low z index fields first
if (v->getStyle()->visible) {
try {
v->prepare(dc);
} catch (const Error& e) {
handle_error(e, false, false);
}
}
}
// draw viewers
FOR_EACH(v, viewers) { // draw low z index fields first FOR_EACH(v, viewers) { // draw low z index fields first
if (v->getStyle()->visible) {// visible if (v->getStyle()->visible) {// visible
try { try {
...@@ -133,8 +143,8 @@ void DataViewer::addStyles(IndexMap<FieldP,StyleP>& styles) { ...@@ -133,8 +143,8 @@ void DataViewer::addStyles(IndexMap<FieldP,StyleP>& styles) {
FOR_EACH(s, styles) { FOR_EACH(s, styles) {
if ((s->visible || s->visible.isScripted()) && if ((s->visible || s->visible.isScripted()) &&
nativeLook() || ( nativeLook() || (
(s->width || s->width .isScripted()) && (s->width || s->width .isScripted() || s->right || s->right .isScripted()) &&
(s->height || s->height .isScripted()))) { (s->height || s->height .isScripted() || s->bottom || s->bottom.isScripted()))) {
// no need to make a viewer for things that are always invisible // no need to make a viewer for things that are always invisible
ValueViewerP viewer = makeViewer(s); ValueViewerP viewer = makeViewer(s);
if (viewer) viewers.push_back(viewer); if (viewer) viewers.push_back(viewer);
......
...@@ -131,7 +131,7 @@ void TextViewer::drawSeparators(RotatedDC& dc) { ...@@ -131,7 +131,7 @@ void TextViewer::drawSeparators(RotatedDC& dc) {
} }
} }
void TextViewer::prepare(RotatedDC& dc, const String& text, const TextStyle& style, Context& ctx) { void TextViewer::prepare(RotatedDC& dc, const String& text, TextStyle& style, Context& ctx) {
if (lines.empty()) { if (lines.empty()) {
// not prepared yet // not prepared yet
Rotater r(dc, style.getRotation()); Rotater r(dc, style.getRotation());
...@@ -312,7 +312,7 @@ void TextViewer::prepareElements(const String& text, const TextStyle& style, Con ...@@ -312,7 +312,7 @@ void TextViewer::prepareElements(const String& text, const TextStyle& style, Con
// ----------------------------------------------------------------------------- : Layout // ----------------------------------------------------------------------------- : Layout
void TextViewer::prepareLines(RotatedDC& dc, const String& text, const TextStyle& style, Context& ctx) { void TextViewer::prepareLines(RotatedDC& dc, const String& text, TextStyle& style, Context& ctx) {
// try to layout, at different scales // try to layout, at different scales
vector<CharInfo> chars; vector<CharInfo> chars;
scale = 1; scale = 1;
...@@ -363,6 +363,19 @@ void TextViewer::prepareLines(RotatedDC& dc, const String& text, const TextStyle ...@@ -363,6 +363,19 @@ void TextViewer::prepareLines(RotatedDC& dc, const String& text, const TextStyle
// returns negative values if it fits, positive if it doesn't // returns negative values if it fits, positive if it doesn't
*/ */
// store information about the content/layout, allow this to change alignment
style.content_width = 0;
FOR_EACH(l, lines) {
style.content_width = max(style.content_width, l.width());
}
style.content_height = 0;
FOR_EACH_REVERSE(l, lines) {
style.content_height = l.top + l.line_height;
if (l.line_height) break; // not an empty line
}
style.content_lines = (int)lines.size();
style.alignment.update(ctx); // allow this to affect the alignment
// no text, find a dummy height for the single line we have // no text, find a dummy height for the single line we have
if (lines.size() == 1 && lines[0].width() < 0.0001) { if (lines.size() == 1 && lines[0].width() < 0.0001) {
if (style.always_symbol && style.symbol_font.valid()) { if (style.always_symbol && style.symbol_font.valid()) {
......
...@@ -54,7 +54,7 @@ class TextViewer { ...@@ -54,7 +54,7 @@ class TextViewer {
void drawSeparators(RotatedDC& dc); void drawSeparators(RotatedDC& dc);
/// Prepare the text for drawing, if it is not already prepared /// Prepare the text for drawing, if it is not already prepared
void prepare(RotatedDC& dc, const String& text, const TextStyle& style, Context&); void prepare(RotatedDC& dc, const String& text, TextStyle& style, Context&);
/// Reset the cached data, at a new call to draw it will be recalculated /// Reset the cached data, at a new call to draw it will be recalculated
void reset(); void reset();
...@@ -130,7 +130,7 @@ class TextViewer { ...@@ -130,7 +130,7 @@ class TextViewer {
vector<Line> lines; ///< The lines in the text box vector<Line> lines; ///< The lines in the text box
/// Prepare the lines, layout the text /// Prepare the lines, layout the text
void prepareLines(RotatedDC& dc, const String& text, const TextStyle& style, Context& ctx); void prepareLines(RotatedDC& dc, const String& text, TextStyle& style, Context& ctx);
/// Prepare the lines, layout the text; at a specific scale /// Prepare the lines, layout the text; at a specific scale
bool prepareLinesScale(RotatedDC& dc, const vector<CharInfo>& chars, const TextStyle& style, bool stop_if_too_long); bool prepareLinesScale(RotatedDC& dc, const vector<CharInfo>& chars, const TextStyle& style, bool stop_if_too_long);
/// Align the lines within the textbox /// Align the lines within the textbox
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
// ----------------------------------------------------------------------------- : TextValueViewer // ----------------------------------------------------------------------------- : TextValueViewer
void TextValueViewer::draw(RotatedDC& dc) { void TextValueViewer::prepare(RotatedDC& dc) {
if (!style().mask_filename.empty() && !style().mask.ok()) { if (!style().mask_filename.empty() && !style().mask.ok()) {
// load contour mask // load contour mask
Image image; Image image;
...@@ -21,8 +21,11 @@ void TextValueViewer::draw(RotatedDC& dc) { ...@@ -21,8 +21,11 @@ void TextValueViewer::draw(RotatedDC& dc) {
style().mask.load(image); style().mask.load(image);
} }
} }
drawFieldBorder(dc);
v.prepare(dc, value().value(), style(), viewer.getContext()); v.prepare(dc, value().value(), style(), viewer.getContext());
}
void TextValueViewer::draw(RotatedDC& dc) {
drawFieldBorder(dc);
v.draw(dc, style(), (DrawWhat)( v.draw(dc, style(), (DrawWhat)(
DRAW_NORMAL DRAW_NORMAL
| (viewer.drawBorders() ? DRAW_BORDERS : 0) | (viewer.drawBorders() ? DRAW_BORDERS : 0)
......
...@@ -21,6 +21,7 @@ class TextValueViewer : public ValueViewer { ...@@ -21,6 +21,7 @@ class TextValueViewer : public ValueViewer {
public: public:
DECLARE_VALUE_VIEWER(Text) : ValueViewer(parent,style) {} DECLARE_VALUE_VIEWER(Text) : ValueViewer(parent,style) {}
virtual void prepare(RotatedDC& dc);
virtual void draw(RotatedDC& dc); virtual void draw(RotatedDC& dc);
virtual void onValueChange(); virtual void onValueChange();
virtual void onStyleChange(); virtual void onStyleChange();
......
...@@ -39,7 +39,10 @@ class ValueViewer : public StyleListener { ...@@ -39,7 +39,10 @@ class ValueViewer : public StyleListener {
/// Return the associated value /// Return the associated value
inline const ValueP& getValue() const { return valueP; } inline const ValueP& getValue() const { return valueP; }
// Draw this value /// Prepare before drawing.
/** Scripts are updated after preparing, allowing */
virtual void prepare(RotatedDC& dc) {};
/// Draw this value
virtual void draw(RotatedDC& dc) = 0; virtual void draw(RotatedDC& dc) = 0;
/// Does this field contian the given point? /// Does this field contian the given point?
......
...@@ -22,6 +22,8 @@ enum DependencyType ...@@ -22,6 +22,8 @@ enum DependencyType
, DEP_EXTRA_CARD_FIELD ///< dependency of a script in an extra stylesheet specific card field , 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_CARD_COPY_DEP ///< copy the dependencies from a card field
, DEP_SET_COPY_DEP ///< copy the dependencies from a set field , DEP_SET_COPY_DEP ///< copy the dependencies from a set field
, DEP_DUMMY ///< used for other purposes, index and data can be anything
// in particular, this is used for determining /if/ there are dependencies
}; };
/// A 'pointer' to some script that depends on another script /// A 'pointer' to some script that depends on another script
...@@ -52,6 +54,7 @@ class Dependencies : public vector<Dependency> { ...@@ -52,6 +54,7 @@ class Dependencies : public vector<Dependency> {
public: public:
/// Add a dependency, prevents duplicates /// Add a dependency, prevents duplicates
inline void add(const Dependency& d) { inline void add(const Dependency& d) {
if (d.type == DEP_DUMMY) return;
if (find(begin(),end(),d) == end()) { if (find(begin(),end(),d) == end()) {
push_back(d); push_back(d);
} }
......
...@@ -9,12 +9,22 @@ ...@@ -9,12 +9,22 @@
#include <script/functions/functions.hpp> #include <script/functions/functions.hpp>
#include <script/functions/util.hpp> #include <script/functions/util.hpp>
#include <util/tagged_string.hpp> #include <util/tagged_string.hpp>
#include <util/error.hpp>
#include <data/set.hpp> #include <data/set.hpp>
#include <data/card.hpp> #include <data/card.hpp>
#include <data/game.hpp> #include <data/game.hpp>
DECLARE_TYPEOF_COLLECTION(pair<String COMMA ScriptValueP>); DECLARE_TYPEOF_COLLECTION(pair<String COMMA ScriptValueP>);
// ----------------------------------------------------------------------------- : Debugging
SCRIPT_FUNCTION(trace) {
SCRIPT_PARAM(String, input);
//handle_warning(_("Trace:\t") + input, false);
wxLogDebug(_("Trace:\t") + input);
SCRIPT_RETURN(input);
}
// ----------------------------------------------------------------------------- : String stuff // ----------------------------------------------------------------------------- : String stuff
// convert a string to upper case // convert a string to upper case
...@@ -607,6 +617,8 @@ SCRIPT_FUNCTION(sort) { ...@@ -607,6 +617,8 @@ SCRIPT_FUNCTION(sort) {
// ----------------------------------------------------------------------------- : Init // ----------------------------------------------------------------------------- : Init
void init_script_basic_functions(Context& ctx) { void init_script_basic_functions(Context& ctx) {
// debugging
ctx.setVariable(_("trace"), script_trace);
// string // string
ctx.setVariable(_("to upper"), script_to_upper); ctx.setVariable(_("to upper"), script_to_upper);
ctx.setVariable(_("to lower"), script_to_lower); ctx.setVariable(_("to lower"), script_to_lower);
......
...@@ -57,6 +57,7 @@ Context& SetScriptContext::getContext(const StyleSheetP& stylesheet) { ...@@ -57,6 +57,7 @@ Context& SetScriptContext::getContext(const StyleSheetP& stylesheet) {
ctx->setVariable(_("set"), new_intrusive1<ScriptObject<Set*> >(&set)); ctx->setVariable(_("set"), new_intrusive1<ScriptObject<Set*> >(&set));
ctx->setVariable(_("game"), to_script(set.game)); ctx->setVariable(_("game"), to_script(set.game));
ctx->setVariable(_("stylesheet"), to_script(stylesheet)); ctx->setVariable(_("stylesheet"), to_script(stylesheet));
ctx->setVariable(_("card style"), to_script(&stylesheet->card_style));
ctx->setVariable(_("card"), set.cards.empty() ? script_nil : to_script(set.cards.front())); // dummy value ctx->setVariable(_("card"), set.cards.empty() ? script_nil : to_script(set.cards.front())); // dummy value
ctx->setVariable(_("styling"), to_script(&set.stylingDataFor(*stylesheet))); ctx->setVariable(_("styling"), to_script(&set.stylingDataFor(*stylesheet)));
try { try {
...@@ -130,6 +131,10 @@ void SetScriptManager::initDependencies(Context& ctx, StyleSheet& stylesheet) { ...@@ -130,6 +131,10 @@ void SetScriptManager::initDependencies(Context& ctx, StyleSheet& stylesheet) {
// find dependencies of choice images and other style stuff // find dependencies of choice images and other style stuff
FOR_EACH(s, stylesheet.card_style) { FOR_EACH(s, stylesheet.card_style) {
s->initDependencies(ctx, Dependency(DEP_STYLE, s->fieldP->index, &stylesheet)); s->initDependencies(ctx, Dependency(DEP_STYLE, s->fieldP->index, &stylesheet));
// are there dependencies of this style on other style properties?
Dependency test(DEP_DUMMY, false);
s->checkContentDependencies(ctx, test);
if (test.index) s->content_dependent = true;
} }
} }
......
...@@ -34,6 +34,11 @@ void store(const ScriptValueP& val, Alignment& var); ...@@ -34,6 +34,11 @@ void store(const ScriptValueP& val, Alignment& var);
// ----------------------------------------------------------------------------- : OptionalScript // ----------------------------------------------------------------------------- : OptionalScript
template <typename T>
inline void change(T& v, const T& new_v) { v = new_v; }
template <typename T>
inline void change(Defaultable<T>& v, const Defaultable<T>& new_v) { v.assignDontChangeDefault(new_v()); }
/// An optional script /// An optional script
class OptionalScript { class OptionalScript {
public: public:
...@@ -57,7 +62,7 @@ class OptionalScript { ...@@ -57,7 +62,7 @@ class OptionalScript {
ctx.setVariable(_("value"), to_script(value)); ctx.setVariable(_("value"), to_script(value));
store(ctx.eval(*script), new_value); store(ctx.eval(*script), new_value);
if (value != new_value) { if (value != new_value) {
value = new_value; change(value, new_value);
return true; return true;
} }
} }
...@@ -66,9 +71,8 @@ class OptionalScript { ...@@ -66,9 +71,8 @@ class OptionalScript {
/// Invoke the script on a value if it is in the default state /// Invoke the script on a value if it is in the default state
template <typename T> template <typename T>
bool invokeOnDefault(Context& ctx, Defaultable<T>& value) const { bool invokeOnDefault(Context& ctx, Defaultable<T>& value) const {
if (value.isDefault() && invokeOn(ctx, value)) { if (value.isDefault()) {
value.makeDefault(); // restore defaultness return invokeOn(ctx, value);
return true;
} else { } else {
return false; return false;
} }
......
...@@ -207,7 +207,7 @@ class ScriptObject : public ScriptValue { ...@@ -207,7 +207,7 @@ class ScriptObject : public ScriptValue {
if (d) { if (d) {
return d->getMember(name); return d->getMember(name);
} else { } else {
throw ScriptValue::getMember(name); return ScriptValue::getMember(name);
} }
} }
} }
......
//+----------------------------------------------------------------------------+
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
//| Copyright: (C) 2001 - 2007 Twan van Laarhoven |
//| License: GNU General Public License 2 or later (see file COPYING) |
//+----------------------------------------------------------------------------+
#ifndef HEADER_UTIL_DELAYED_INDEX_MAPS
#define HEADER_UTIL_DELAYED_INDEX_MAPS
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <util/smart_ptr.hpp>
#include <util/index_map.hpp>
#include <util/reflect.hpp>
#include <wx/sstream.h>
// ----------------------------------------------------------------------------- : DelayedIndexMaps
template <typename Key, typename Value>
IndexMap<Key,Value>& DelayedIndexMaps<Key,Value>::get(const String& name, const vector<Key>& init_with) {
intrusive_ptr<DelayedIndexMapsData<Key,Value> >& item = data[name];
if (!item) { // no item, make a new one
item = new_intrusive<DelayedIndexMapsData<Key,Value> >();
item->read_data.init(init_with);
} else if (!item->unread_data.empty()) { // not read, read now
item->read_data.init(init_with);
Reader reader(new_shared1<wxStringInputStream>(item->unread_data), _("delayed data for ") + name);
reader.handle_greedy(item->read_data);
item->unread_data.clear();
}
return item->read_data;
}
// ----------------------------------------------------------------------------- : Reflection
// custom reflection : it's a template class
template <typename Key, typename Value> void Reader::handle(DelayedIndexMaps<Key,Value>& dim) {
handle(dim.data);
}
template <typename Key, typename Value> void Writer::handle(const DelayedIndexMaps<Key,Value>& dim) {
handle(dim.data);
}
template <typename Key, typename Value> void GetMember::handle(const DelayedIndexMaps<Key,Value>& dim) {
handle(dim.data);
}
// custom reflection : read into unread_data
template <typename Key, typename Value>
void Reader::handle(DelayedIndexMapsData<Key,Value>& d) {
handle(d.unread_data);
if (d.unread_data.empty()) d.unread_data = _("\n"); // never empty (invariant)
}
template <typename Key, typename Value>
void Writer::handle(const DelayedIndexMapsData<Key,Value>& d) {
handle(d.read_data);
}
template <typename Key, typename Value>
void GetMember::handle(const DelayedIndexMapsData<Key,Value>& d) {
handle(d.read_data);
}
template <typename Key, typename Value>
void GetDefaultMember::handle(const DelayedIndexMapsData<Key,Value>&) {
handle(d.read_data);
}
// ----------------------------------------------------------------------------- : EOF
#endif
...@@ -57,6 +57,9 @@ String pending_warnings; ...@@ -57,6 +57,9 @@ String pending_warnings;
DECLARE_TYPEOF_COLLECTION(String); DECLARE_TYPEOF_COLLECTION(String);
wxCriticalSection crit_error_handling; wxCriticalSection crit_error_handling;
void show_pending_errors();
void show_pending_warnings();
void handle_error(const String& e, bool allow_duplicate = true, bool now = true) { void handle_error(const String& e, bool allow_duplicate = true, bool now = true) {
// Thread safety // Thread safety
wxCriticalSectionLocker lock(crit_error_handling); wxCriticalSectionLocker lock(crit_error_handling);
...@@ -68,13 +71,13 @@ void handle_error(const String& e, bool allow_duplicate = true, bool now = true) ...@@ -68,13 +71,13 @@ void handle_error(const String& e, bool allow_duplicate = true, bool now = true)
previous_errors.push_back(e); previous_errors.push_back(e);
} }
// Only show errors in the main thread // Only show errors in the main thread
if (!now || !wxThread::IsMain()) { if (!pending_errors.empty()) pending_errors += _("\n\n");
if (!pending_errors.empty()) pending_errors += _("\n\n"); pending_errors += e;
pending_errors += e; // show messages
return; if (now && wxThread::IsMain()) {
show_pending_warnings(); // warnings are older, show them first
show_pending_errors();
} }
// show message
wxMessageBox(e, _("Error"), wxOK | wxICON_ERROR);
} }
void handle_error(const Error& e, bool allow_duplicate, bool now) { void handle_error(const Error& e, bool allow_duplicate, bool now) {
...@@ -83,25 +86,35 @@ void handle_error(const Error& e, bool allow_duplicate, bool now) { ...@@ -83,25 +86,35 @@ void handle_error(const Error& e, bool allow_duplicate, bool now) {
void handle_warning(const String& w, bool now) { void handle_warning(const String& w, bool now) {
// Check duplicates // Check duplicates
// TODO: thread safety wxCriticalSectionLocker lock(crit_error_handling);
// Only show errors in the main thread // Only show errors in the main thread
if (!now || !wxThread::IsMain()) { if (!pending_warnings.empty()) pending_warnings += _("\n\n");
if (!pending_warnings.empty()) pending_warnings += _("\n\n"); pending_warnings += w;
pending_warnings += w; // show messages
return; if (now && wxThread::IsMain()) {
show_pending_errors();
show_pending_warnings();
} }
// show message
wxMessageBox(w, _("Warning"), wxOK | wxICON_EXCLAMATION);
} }
void handle_pending_errors() { void handle_pending_errors() {
show_pending_errors();
show_pending_warnings();
}
void show_pending_errors() {
assert(wxThread::IsMain()); assert(wxThread::IsMain());
wxCriticalSectionLocker lock(crit_error_handling);
if (!pending_errors.empty()) { if (!pending_errors.empty()) {
handle_error(pending_errors); wxMessageBox(pending_errors, _("Error"), wxOK | wxICON_ERROR);
pending_errors.clear(); pending_errors.clear();
} }
}
void show_pending_warnings() {
assert(wxThread::IsMain());
wxCriticalSectionLocker lock(crit_error_handling);
if (!pending_warnings.empty()) { if (!pending_warnings.empty()) {
handle_warning(pending_warnings); wxMessageBox(pending_warnings, _("Warning"), wxOK | wxICON_EXCLAMATION);
pending_warnings.clear(); pending_warnings.clear();
} }
} }
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
// ----------------------------------------------------------------------------- : Includes // ----------------------------------------------------------------------------- : Includes
#include <vector> #include <vector>
#include <map>
#include <util/string.hpp>
// ----------------------------------------------------------------------------- : IndexMap // ----------------------------------------------------------------------------- : IndexMap
...@@ -117,5 +119,34 @@ class IndexMap : private vector<Value> { ...@@ -117,5 +119,34 @@ class IndexMap : private vector<Value> {
}; };
// ----------------------------------------------------------------------------- : DelayedIndexMaps
// The data for a specific name.
/* Invariant: read_data is initialized <=> unread_data.empty()
*/
template <typename Key, typename Value>
struct DelayedIndexMapsData : public IntrusivePtrBase<DelayedIndexMapsData> {
String unread_data;
IndexMap<Key,Value> read_data;
};
/// A map<String,IndexMap> where the reading of the index map depends on the name.
/** The reading is delayed until the data to initialize the map with is known.
* The only way to access data is using get()
*/
template <typename Key, typename Value>
class DelayedIndexMaps {
public:
/// Get the data for a specific name. Initialize the map with init_with (if it is not alread initialized)
IndexMap<Key,Value>& get(const String& name, const vector<Key>& init_with);
private:
map<String, intrusive_ptr<DelayedIndexMapsData<Key,Value> > > data;
friend class Reader;
friend class Writer;
friend class GetDefaultMember;
friend class GetMember;
};
// ----------------------------------------------------------------------------- : EOF // ----------------------------------------------------------------------------- : EOF
#endif #endif
...@@ -53,6 +53,8 @@ class GetDefaultMember { ...@@ -53,6 +53,8 @@ class GetDefaultMember {
template <typename T> void handle(const vector<T>& c) { value = to_script(&c); } template <typename T> void handle(const vector<T>& c) { value = to_script(&c); }
template <typename K, typename V> void handle(const map<K,V>& c) { value = to_script(&c); } template <typename K, typename V> void handle(const map<K,V>& c) { value = to_script(&c); }
template <typename K, typename V> void handle(const IndexMap<K,V>& c) { value = to_script(&c); } template <typename K, typename V> void handle(const IndexMap<K,V>& c) { value = to_script(&c); }
template <typename K, typename V> void handle(const DelayedIndexMaps<K,V>&) {}
template <typename K, typename V> void handle(const DelayedIndexMapsData<K,V>& c);
template <typename T> void handle(const intrusive_ptr<T>& p) { value = to_script(p); } template <typename T> void handle(const intrusive_ptr<T>& p) { value = to_script(p); }
void handle(const ScriptValueP&); void handle(const ScriptValueP&);
void handle(const ScriptP&); void handle(const ScriptP&);
...@@ -103,6 +105,8 @@ class GetMember : private GetDefaultMember { ...@@ -103,6 +105,8 @@ class GetMember : private GetDefaultMember {
} }
} }
} }
template <typename K, typename V> void handle(const DelayedIndexMaps<K,V>&);
template <typename K, typename V> void handle(const DelayedIndexMapsData<K,V>&);
private: private:
const String& target_name; ///< The name we are looking for const String& target_name; ///< The name we are looking for
......
...@@ -88,13 +88,15 @@ class Reader { ...@@ -88,13 +88,15 @@ class Reader {
void handle(const Char* name, vector<T>& vector); void handle(const Char* name, vector<T>& vector);
/// Reads an object of type T from the input stream /// Reads an object of type T from the input stream
template <typename T> void handle(T& object); template <typename T> void handle(T&);
/// Reads a intrusive_ptr from the input stream /// Reads a intrusive_ptr from the input stream
template <typename T> void handle(intrusive_ptr<T>& pointer); template <typename T> void handle(intrusive_ptr<T>&);
/// Reads a map from the input stream /// Reads a map from the input stream
template <typename V> void handle(map<String,V>& m); template <typename V> void handle(map<String,V>&);
/// Reads an IndexMap from the input stream, reads only keys that already exist in the map /// Reads an IndexMap from the input stream, reads only keys that already exist in the map
template <typename K, typename V> void handle(IndexMap<K,V>& m); template <typename K, typename V> void handle(IndexMap<K,V>&);
template <typename K, typename V> void handle(DelayedIndexMaps<K,V>&);
template <typename K, typename V> void handle(DelayedIndexMapsData<K,V>&);
/// Reads a Defaultable from the input stream /// Reads a Defaultable from the input stream
template <typename T> void handle(Defaultable<T>&); template <typename T> void handle(Defaultable<T>&);
/// Reads a Scriptable from the input stream /// Reads a Scriptable from the input stream
......
...@@ -58,13 +58,15 @@ class Writer { ...@@ -58,13 +58,15 @@ class Writer {
void handle(const Char* str) { handle(String(str)); } void handle(const Char* str) { handle(String(str)); }
/// Write an object of type T to the output stream /// Write an object of type T to the output stream
template <typename T> void handle(const T& object); template <typename T> void handle(const T&);
/// Write a intrusive_ptr to the output stream /// Write a intrusive_ptr to the output stream
template <typename T> void handle(const intrusive_ptr<T>& pointer); template <typename T> void handle(const intrusive_ptr<T>&);
/// Write a map to the output stream /// Write a map to the output stream
template <typename K, typename V> void handle(const map<K,V>& map); template <typename K, typename V> void handle(const map<K,V>&);
/// Write an IndexMap to the output stream /// Write an IndexMap to the output stream
template <typename K, typename V> void handle(const IndexMap<K,V>& map); template <typename K, typename V> void handle(const IndexMap<K,V>&);
template <typename K, typename V> void handle(const DelayedIndexMaps<K,V>&);
template <typename K, typename V> void handle(const DelayedIndexMapsData<K,V>&);
/// Write an object of type Defaultable<T> to the output stream /// Write an object of type Defaultable<T> to the output stream
template <typename T> void handle(const Defaultable<T>&); template <typename T> void handle(const Defaultable<T>&);
/// Write an object of type Scriptable<T> to the output stream /// Write an object of type Scriptable<T> to the output stream
......
...@@ -191,6 +191,7 @@ enum ControlID { ...@@ -191,6 +191,7 @@ enum ControlID {
, ID_GAME_LIST , ID_GAME_LIST
, ID_STYLESHEET_LIST , ID_STYLESHEET_LIST
, ID_KEYWORD_LIST , ID_KEYWORD_LIST
, ID_EXPORT_LIST
, ID_NOTES , ID_NOTES
, ID_KEYWORD , ID_KEYWORD
, ID_MATCH , ID_MATCH
......
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