mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 04:57:00 -04:00
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 git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@428 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
+6
-44
@@ -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 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
|||||||
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) {}
|
|
||||||
|
|||||||
+1
-2
@@ -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 @@
|
|||||||
// ----------------------------------------------------------------------------- : 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 @@
|
|||||||
#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;
|
||||||
|
|||||||
+49
-3
@@ -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() {}
|
|||||||
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&) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
|||||||
// 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 {
|
|||||||
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 {
|
|||||||
/// 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; }
|
|||||||
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 {
|
|||||||
// 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) {
|
|||||||
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) {
|
|||||||
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 {
|
|||||||
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 {
|
||||||
|
|||||||
+1
-35
@@ -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
|
||||||
|
|||||||
+1
-2
@@ -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 @@
|
|||||||
#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 {
|
|||||||
|
|
||||||
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 @@
|
|||||||
|
|
||||||
#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)
|
|||||||
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&) {
|
|||||||
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 {
|
|||||||
|
|
||||||
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)
|
|||||||
// 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&) {
|
|||||||
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&) {
|
|||||||
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&) {
|
||||||
|
|||||||
+5
-2
@@ -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 @@
|
|||||||
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) {
|
|||||||
} 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) {
|
|||||||
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) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------- : 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
|
|||||||
// 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 {
|
|||||||
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 {
|
|||||||
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 @@
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------- : 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) {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
/// 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
|
|||||||
, 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> {
|
|||||||
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 @@
|
|||||||
#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) {
|
|||||||
// ----------------------------------------------------------------------------- : 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) {
|
|||||||
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) {
|
|||||||
// 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);
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------- : 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 {
|
|||||||
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 {
|
|||||||
/// 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 {
|
|||||||
if (d) {
|
if (d) {
|
||||||
return d->getMember(name);
|
return d->getMember(name);
|
||||||
} else {
|
} else {
|
||||||
throw ScriptValue::getMember(name);
|
return ScriptValue::getMember(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
//+----------------------------------------------------------------------------+
|
||||||
|
//| 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
|
||||||
+28
-15
@@ -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)
|
|||||||
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) {
|
|||||||
|
|
||||||
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 @@
|
|||||||
// ----------------------------------------------------------------------------- : Includes
|
// ----------------------------------------------------------------------------- : Includes
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <util/string.hpp>
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : IndexMap
|
// ----------------------------------------------------------------------------- : IndexMap
|
||||||
|
|
||||||
@@ -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 {
|
|||||||
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 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
, 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
|
||||||
|
|||||||
Reference in New Issue
Block a user