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:
twanvl
2007-06-22 23:12:41 +00:00
parent 97e0e8d6d6
commit e46cbe66b2
33 changed files with 384 additions and 138 deletions
+6 -44
View File
@@ -12,7 +12,7 @@
#include <data/field.hpp>
#include <util/error.hpp>
#include <util/reflect.hpp>
#include <wx/sstream.h>
#include <util/delayed_index_maps.hpp>
DECLARE_TYPEOF_COLLECTION(FieldP);
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) {
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) {
REFLECT(stylesheet);
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);
}
// ----------------------------------------------------------------------------- : 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
View File
@@ -41,8 +41,7 @@ class Card : public IntrusivePtrVirtualBase {
StyleSheetP stylesheet;
/// Extra values for specitic stylesheets, indexed by stylesheet name
DECLARE_POINTER_TYPE(Styling);
map<String, StylingP> extra_data;
DelayedIndexMaps<FieldP,ValueP> extra_data;
/// Styling information for a particular stylesheet
IndexMap<FieldP, ValueP>& extraDataFor(const StyleSheet& stylesheet) ;
+4
View File
@@ -7,9 +7,13 @@
// ----------------------------------------------------------------------------- : Includes
#include <data/export_template.hpp>
#include <data/game.hpp>
#include <data/field.hpp>
// ----------------------------------------------------------------------------- : Export template, basics
ExportTemplate::ExportTemplate() {}
String ExportTemplate::typeNameStatic() { return _("export-template"); }
String ExportTemplate::typeName() const { return _("export-template"); }
+11 -4
View File
@@ -13,16 +13,23 @@
#include <util/io/package.hpp>
#include <script/scriptable.hpp>
DECLARE_POINTER_TYPE(Game);
DECLARE_POINTER_TYPE(Field);
DECLARE_POINTER_TYPE(Style);
// ----------------------------------------------------------------------------- : ExportTemplate
/// A template for exporting sets to HTML or text format
class ExportTemplate : public Packaged {
public:
ExportTemplate();
OptionalScript script; ///< Export script
String file_type; ///< Type of the created file, in "name|*.ext" format
bool create_directory; ///< The export creates an entire directory
GameP game; ///< Game this template is for
OptionalScript script; ///< Export script
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();
virtual String typeName() const;
+49 -3
View File
@@ -85,7 +85,10 @@ Style::Style(const FieldP& field)
, z_index(0)
, left(0), top(0)
, width(0), height(0)
, right(0), bottom(0)
, visible(true)
, automatic_side(AUTO_UNKNOWN)
, content_dependent(false)
{}
Style::~Style() {}
@@ -93,9 +96,11 @@ Style::~Style() {}
IMPLEMENT_REFLECTION(Style) {
REFLECT(z_index);
REFLECT(left);
REFLECT(top);
REFLECT(width);
REFLECT(right);
REFLECT(top);
REFLECT(height);
REFLECT(bottom);
REFLECT(visible);
}
@@ -107,11 +112,35 @@ template <> StyleP read_new<Style>(Reader&) {
}
bool Style::update(Context& ctx) {
return left .update(ctx)
| top .update(ctx)
bool changed =
left .update(ctx)
| width .update(ctx)
| right .update(ctx)
| top .update(ctx)
| height .update(ctx)
| bottom .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 {
@@ -121,6 +150,23 @@ void Style::initDependencies(Context& ctx, const Dependency& dep) const {
// height .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
+16
View File
@@ -88,7 +88,14 @@ class Style : public IntrusivePtrVirtualBase {
int z_index; ///< Stacking of values of this field, higher = on top
Scriptable<double> left, top; ///< 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?
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 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
/** Only use for things that need invalidate() */
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
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; }
template <> StyleP read_new<Style>(Reader&);
void mark_dependency_member(const Style& style, const String& name, const Dependency& dep);
// ----------------------------------------------------------------------------- : StyleListener
/// An object that can respond when a style changes;
+20
View File
@@ -68,6 +68,18 @@ void TextStyle::initDependencies(Context& ctx, const Dependency& dep) const {
// 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) {
REFLECT(image);
@@ -75,6 +87,13 @@ IMPLEMENT_REFLECTION(TextBackground) {
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) {
REFLECT_BASE(Style);
REFLECT(font);
@@ -99,6 +118,7 @@ IMPLEMENT_REFLECTION(TextStyle) {
REFLECT(text_background);
REFLECT(text_background_left);
REFLECT(text_background_right);
reflect_content(tag, *this);
}
// ----------------------------------------------------------------------------- : TextValue
+5
View File
@@ -80,9 +80,14 @@ class TextStyle : public Style {
Direction direction; ///< In what direction is text layed out?
TextBackgroundP text_background; ///< Image behind the text
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 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
inline Rotation getRotation() const {
+1 -35
View File
@@ -204,42 +204,8 @@ void Set::clearOrderCache() {
// ----------------------------------------------------------------------------- : 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) {
StylingP& styling = styling_data[stylesheet.name()];
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);
return styling_data.get(stylesheet.name(), stylesheet.styling_fields);
}
// ----------------------------------------------------------------------------- : SetView
+1 -2
View File
@@ -52,8 +52,7 @@ class Set : public Packaged {
/** The indices should correspond to the set_fields in the Game */
IndexMap<FieldP, ValueP> data;
/// Extra values for specitic stylesheets, indexed by stylesheet name
DECLARE_POINTER_TYPE(Styling);
map<String, StylingP> styling_data;
DelayedIndexMaps<FieldP,ValueP> styling_data;
vector<CardP> cards; ///< The cards in the set
vector<KeywordP> keywords; ///< Additional keywords used in this set
String apprentice_code; ///< Code to use for apprentice (Magic only)