mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 21:06:59 -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:
@@ -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);
|
||||
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) {
|
||||
// Thread safety
|
||||
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);
|
||||
}
|
||||
// Only show errors in the main thread
|
||||
if (!now || !wxThread::IsMain()) {
|
||||
if (!pending_errors.empty()) pending_errors += _("\n\n");
|
||||
pending_errors += e;
|
||||
return;
|
||||
if (!pending_errors.empty()) pending_errors += _("\n\n");
|
||||
pending_errors += e;
|
||||
// show messages
|
||||
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) {
|
||||
@@ -83,25 +86,35 @@ void handle_error(const Error& e, bool allow_duplicate, bool now) {
|
||||
|
||||
void handle_warning(const String& w, bool now) {
|
||||
// Check duplicates
|
||||
// TODO: thread safety
|
||||
wxCriticalSectionLocker lock(crit_error_handling);
|
||||
// Only show errors in the main thread
|
||||
if (!now || !wxThread::IsMain()) {
|
||||
if (!pending_warnings.empty()) pending_warnings += _("\n\n");
|
||||
pending_warnings += w;
|
||||
return;
|
||||
if (!pending_warnings.empty()) pending_warnings += _("\n\n");
|
||||
pending_warnings += w;
|
||||
// show messages
|
||||
if (now && wxThread::IsMain()) {
|
||||
show_pending_errors();
|
||||
show_pending_warnings();
|
||||
}
|
||||
// show message
|
||||
wxMessageBox(w, _("Warning"), wxOK | wxICON_EXCLAMATION);
|
||||
}
|
||||
|
||||
void handle_pending_errors() {
|
||||
show_pending_errors();
|
||||
show_pending_warnings();
|
||||
}
|
||||
|
||||
void show_pending_errors() {
|
||||
assert(wxThread::IsMain());
|
||||
wxCriticalSectionLocker lock(crit_error_handling);
|
||||
if (!pending_errors.empty()) {
|
||||
handle_error(pending_errors);
|
||||
wxMessageBox(pending_errors, _("Error"), wxOK | wxICON_ERROR);
|
||||
pending_errors.clear();
|
||||
}
|
||||
}
|
||||
void show_pending_warnings() {
|
||||
assert(wxThread::IsMain());
|
||||
wxCriticalSectionLocker lock(crit_error_handling);
|
||||
if (!pending_warnings.empty()) {
|
||||
handle_warning(pending_warnings);
|
||||
wxMessageBox(pending_warnings, _("Warning"), wxOK | wxICON_EXCLAMATION);
|
||||
pending_warnings.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
// ----------------------------------------------------------------------------- : Includes
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <util/string.hpp>
|
||||
|
||||
// ----------------------------------------------------------------------------- : 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
|
||||
#endif
|
||||
|
||||
@@ -53,6 +53,8 @@ class GetDefaultMember {
|
||||
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 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); }
|
||||
void handle(const ScriptValueP&);
|
||||
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:
|
||||
const String& target_name; ///< The name we are looking for
|
||||
|
||||
@@ -88,13 +88,15 @@ class Reader {
|
||||
void handle(const Char* name, vector<T>& vector);
|
||||
|
||||
/// 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
|
||||
template <typename T> void handle(intrusive_ptr<T>& pointer);
|
||||
template <typename T> void handle(intrusive_ptr<T>&);
|
||||
/// 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
|
||||
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
|
||||
template <typename T> void handle(Defaultable<T>&);
|
||||
/// Reads a Scriptable from the input stream
|
||||
|
||||
@@ -58,13 +58,15 @@ class Writer {
|
||||
void handle(const Char* str) { handle(String(str)); }
|
||||
|
||||
/// 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
|
||||
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
|
||||
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
|
||||
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
|
||||
template <typename T> void handle(const Defaultable<T>&);
|
||||
/// Write an object of type Scriptable<T> to the output stream
|
||||
|
||||
@@ -191,6 +191,7 @@ enum ControlID {
|
||||
, ID_GAME_LIST
|
||||
, ID_STYLESHEET_LIST
|
||||
, ID_KEYWORD_LIST
|
||||
, ID_EXPORT_LIST
|
||||
, ID_NOTES
|
||||
, ID_KEYWORD
|
||||
, ID_MATCH
|
||||
|
||||
Reference in New Issue
Block a user