mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 21:06:59 -04:00
Reverted resource references for combine_something, you can't use tool_image here, because on MSW that only works for .bmps'
Added dependency stuff to invalidate Choice images; Fixed 'duplicate' in symbol editor git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@197 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
@@ -143,6 +143,7 @@ TextValueAction* typing_action(const TextValueP& value, size_t start, size_t end
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------- : Event
|
||||
|
||||
String ScriptValueEvent::getName(bool) const {
|
||||
@@ -152,3 +153,12 @@ String ScriptValueEvent::getName(bool) const {
|
||||
void ScriptValueEvent::perform(bool) {
|
||||
assert(false); // this action is just an event, it should not be performed
|
||||
}
|
||||
|
||||
|
||||
String ScriptStyleEvent::getName(bool) const {
|
||||
assert(false); // this action is just an event, getName shouldn't be called
|
||||
throw InternalError(_("ScriptStyleEvent::getName"));
|
||||
}
|
||||
void ScriptStyleEvent::perform(bool) {
|
||||
assert(false); // this action is just an event, it should not be performed
|
||||
}
|
||||
|
||||
@@ -19,7 +19,9 @@
|
||||
#include <util/defaultable.hpp>
|
||||
|
||||
class Card;
|
||||
class StyleSheet;
|
||||
DECLARE_POINTER_TYPE(Value);
|
||||
DECLARE_POINTER_TYPE(Style);
|
||||
DECLARE_POINTER_TYPE(TextValue);
|
||||
DECLARE_POINTER_TYPE(ChoiceValue);
|
||||
DECLARE_POINTER_TYPE(ColorValue);
|
||||
@@ -87,5 +89,19 @@ class ScriptValueEvent : public Action {
|
||||
const Value* value; ///< The modified value
|
||||
};
|
||||
|
||||
/// Notification that a script caused a style to change
|
||||
class ScriptStyleEvent : public Action {
|
||||
public:
|
||||
inline ScriptStyleEvent(const StyleSheet* stylesheet, const Style* style)
|
||||
: stylesheet(stylesheet), style(style)
|
||||
{}
|
||||
|
||||
virtual String getName(bool to_undo) const;
|
||||
virtual void perform(bool to_undo);
|
||||
|
||||
const StyleSheet* stylesheet; ///< StyleSheet the style is for
|
||||
const Style* style; ///< The modified style
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
#endif
|
||||
|
||||
+5
-5
@@ -111,11 +111,11 @@ bool Style::update(Context& ctx) {
|
||||
}
|
||||
|
||||
void Style::initDependencies(Context& ctx, const Dependency& dep) const {
|
||||
left .initDependencies(ctx,dep);
|
||||
top .initDependencies(ctx,dep);
|
||||
width .initDependencies(ctx,dep);
|
||||
height .initDependencies(ctx,dep);
|
||||
visible.initDependencies(ctx,dep);
|
||||
/// left .initDependencies(ctx,dep);
|
||||
// top .initDependencies(ctx,dep);
|
||||
// width .initDependencies(ctx,dep);
|
||||
// height .initDependencies(ctx,dep);
|
||||
// visible.initDependencies(ctx,dep);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Value
|
||||
|
||||
@@ -102,7 +102,10 @@ class Style {
|
||||
/// Update scripted values of this style, return true if anything has changed
|
||||
virtual bool update(Context&);
|
||||
/// 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;
|
||||
/// Invalidate scripted images for this style
|
||||
virtual void invalidate() {}
|
||||
|
||||
private:
|
||||
DECLARE_REFLECTION_VIRTUAL();
|
||||
|
||||
@@ -167,19 +167,15 @@ ChoiceStyle::ChoiceStyle(const ChoiceFieldP& field)
|
||||
, combine(COMBINE_NORMAL)
|
||||
, alignment(ALIGN_STRETCH)
|
||||
, thumbnails(nullptr)
|
||||
, thumbnail_age(1) // thumbnails were made before the beginning of time
|
||||
, invalidated_images(false)
|
||||
{}
|
||||
|
||||
ChoiceStyle::~ChoiceStyle() {
|
||||
delete thumbnails;
|
||||
}
|
||||
|
||||
// TODO
|
||||
/*
|
||||
void ChoiceStyle::invalidate() {
|
||||
// rebuild choice images
|
||||
}
|
||||
|
||||
*/
|
||||
bool ChoiceStyle::update(Context& ctx) {
|
||||
// Don't update the choice images, leave that to invalidate()
|
||||
return Style::update(ctx);
|
||||
@@ -190,6 +186,18 @@ void ChoiceStyle::initDependencies(Context& ctx, const Dependency& dep) const {
|
||||
ci.second.initDependencies(ctx, dep);
|
||||
}
|
||||
}
|
||||
void ChoiceStyle::invalidate() {
|
||||
// rebuild choice images
|
||||
// TODO: Don't use this; rely on upToDate() instead
|
||||
FOR_EACH(ci, choice_images) {
|
||||
// TODO : only invalidate images that actually have dependencies
|
||||
ci.second.invalidate();
|
||||
}
|
||||
if (thumbnails) {
|
||||
thumbnails->RemoveAll();
|
||||
}
|
||||
invalidated_images = true;
|
||||
}
|
||||
|
||||
void ChoiceStyle::loadMask(Package& pkg) {
|
||||
if (mask.Ok() || mask_filename.empty()) return;
|
||||
|
||||
@@ -129,12 +129,14 @@ class ChoiceStyle : public Style {
|
||||
Image mask; ///< The actual mask image
|
||||
wxImageList* thumbnails; ///< Thumbnails for the choices
|
||||
Age thumbnail_age; ///< Age the thumbnails were generated
|
||||
bool invalidated_images; ///< Have the images been invalidated?
|
||||
|
||||
/// Load the mask image, if it's not already done
|
||||
void loadMask(Package& pkg);
|
||||
|
||||
virtual bool update(Context&);
|
||||
virtual void initDependencies(Context&, const Dependency&) const;
|
||||
virtual void invalidate();
|
||||
|
||||
private:
|
||||
DECLARE_REFLECTION();
|
||||
|
||||
@@ -62,8 +62,8 @@ bool TextStyle::update(Context& ctx) {
|
||||
}
|
||||
void TextStyle::initDependencies(Context& ctx, const Dependency& dep) const {
|
||||
Style ::initDependencies(ctx, dep);
|
||||
font .initDependencies(ctx, dep);
|
||||
symbol_font.initDependencies(ctx, dep);
|
||||
// font .initDependencies(ctx, dep);
|
||||
// symbol_font.initDependencies(ctx, dep);
|
||||
}
|
||||
|
||||
IMPLEMENT_REFLECTION(TextStyle) {
|
||||
|
||||
@@ -20,12 +20,12 @@ SymbolPartList::SymbolPartList(Window* parent, int id, SymbolP symbol)
|
||||
// Create image list
|
||||
wxImageList* images = new wxImageList(16,16);
|
||||
// NOTE: this is based on the order of the SymbolPartCombine enum!
|
||||
images->Add(load_resource_tool_image(_("combine_or")));
|
||||
images->Add(load_resource_tool_image(_("combine_sub")));
|
||||
images->Add(load_resource_tool_image(_("combine_and")));
|
||||
images->Add(load_resource_tool_image(_("combine_xor")));
|
||||
images->Add(load_resource_tool_image(_("combine_over")));
|
||||
images->Add(load_resource_tool_image(_("combine_border")));
|
||||
images->Add(load_resource_image(_("combine_or")));
|
||||
images->Add(load_resource_image(_("combine_sub")));
|
||||
images->Add(load_resource_image(_("combine_and")));
|
||||
images->Add(load_resource_image(_("combine_xor")));
|
||||
images->Add(load_resource_image(_("combine_over")));
|
||||
images->Add(load_resource_image(_("combine_border")));
|
||||
AssignImageList(images, wxIMAGE_LIST_SMALL);
|
||||
// create columns
|
||||
InsertColumn(0, _("Name"));
|
||||
|
||||
@@ -107,12 +107,12 @@ void SymbolSelectEditor::drawRotationCenter(DC& dc, const Vector2D& pos) {
|
||||
|
||||
void SymbolSelectEditor::initUI(wxToolBar* tb, wxMenuBar* mb) {
|
||||
tb->AddSeparator();
|
||||
tb->AddTool(ID_PART_MERGE, _("Merge"), load_resource_tool_image(_("combine_or")), wxNullBitmap, wxITEM_CHECK, _("Merge with shapes below"), _("Merges this shape with those below it"));
|
||||
tb->AddTool(ID_PART_SUBTRACT, _("Subtract"), load_resource_tool_image(_("combine_sub_dark")), wxNullBitmap, wxITEM_CHECK, _("Subtract from shapes below"), _("Subtracts this shape from shapes below it, leaves only the area in that shape that is not in this shape"));
|
||||
tb->AddTool(ID_PART_INTERSECTION, _("Intersect"), load_resource_tool_image(_("combine_and_dark")), wxNullBitmap, wxITEM_CHECK, _("Intersect with shapes below"), _("Intersects this shape with shapes below it, leaves only the area in both shapes"));
|
||||
tb->AddTool(ID_PART_MERGE, _("Merge"), load_resource_image(_("combine_or")), wxNullBitmap, wxITEM_CHECK, _("Merge with shapes below"), _("Merges this shape with those below it"));
|
||||
tb->AddTool(ID_PART_SUBTRACT, _("Subtract"), load_resource_image(_("combine_sub_dark")), wxNullBitmap, wxITEM_CHECK, _("Subtract from shapes below"), _("Subtracts this shape from shapes below it, leaves only the area in that shape that is not in this shape"));
|
||||
tb->AddTool(ID_PART_INTERSECTION, _("Intersect"), load_resource_image(_("combine_and_dark")), wxNullBitmap, wxITEM_CHECK, _("Intersect with shapes below"), _("Intersects this shape with shapes below it, leaves only the area in both shapes"));
|
||||
// note: difference doesn't work (yet)
|
||||
tb->AddTool(ID_PART_OVERLAP, _("Overlap"), load_resource_tool_image(_("combine_over")), wxNullBitmap, wxITEM_CHECK, _("Place above other shapes"), _("Place this shape, and its border above shapes below it"));
|
||||
tb->AddTool(ID_PART_BORDER, _("Border"), load_resource_tool_image(_("combine_border")), wxNullBitmap, wxITEM_CHECK, _("Draw as a border"), _("Draws this shape as a border"));
|
||||
tb->AddTool(ID_PART_OVERLAP, _("Overlap"), load_resource_image(_("combine_over")), wxNullBitmap, wxITEM_CHECK, _("Place above other shapes"), _("Place this shape, and its border above shapes below it"));
|
||||
tb->AddTool(ID_PART_BORDER, _("Border"), load_resource_image(_("combine_border")), wxNullBitmap, wxITEM_CHECK, _("Draw as a border"), _("Draws this shape as a border"));
|
||||
tb->Realize();
|
||||
}
|
||||
void SymbolSelectEditor::destroyUI(wxToolBar* tb, wxMenuBar* mb) {
|
||||
|
||||
@@ -46,6 +46,8 @@ wxCursor load_resource_cursor(const String& name);
|
||||
wxIcon load_resource_icon(const String& name);
|
||||
|
||||
/// Load an image for use in a toolbar (filename: tool/...) from a resource
|
||||
/** Note: should ONLY be used for ".bmp" images for now
|
||||
*/
|
||||
wxBitmap load_resource_tool_image(const String& name);
|
||||
|
||||
// ----------------------------------------------------------------------------- : Platform look
|
||||
|
||||
@@ -19,7 +19,7 @@ DECLARE_TYPEOF_COLLECTION(ChoiceField::ChoiceP);
|
||||
|
||||
class ChoiceThumbnailRequest : public ThumbnailRequest {
|
||||
public:
|
||||
ChoiceThumbnailRequest(ChoiceValueEditor* cve, int id);
|
||||
ChoiceThumbnailRequest(ChoiceValueEditor* cve, int id, bool from_disk);
|
||||
virtual Image generate();
|
||||
virtual void store(const Image&);
|
||||
private:
|
||||
@@ -27,11 +27,13 @@ class ChoiceThumbnailRequest : public ThumbnailRequest {
|
||||
int id;
|
||||
};
|
||||
|
||||
ChoiceThumbnailRequest::ChoiceThumbnailRequest(ChoiceValueEditor* cve, int id)
|
||||
ChoiceThumbnailRequest::ChoiceThumbnailRequest(ChoiceValueEditor* cve, int id, bool from_disk)
|
||||
: ThumbnailRequest(
|
||||
cve,
|
||||
cve->viewer.stylesheet->name() + _("/") + cve->field().name + _("/") << id,
|
||||
cve->viewer.stylesheet->lastModified())
|
||||
from_disk ? cve->viewer.stylesheet->lastModified()
|
||||
: wxDateTime::Now()
|
||||
)
|
||||
, stylesheet(cve->viewer.stylesheet)
|
||||
, id(id)
|
||||
{}
|
||||
@@ -195,10 +197,11 @@ void DropDownChoiceList::generateThumbnailImages() {
|
||||
for (int i = 0 ; i < end ; ++i) {
|
||||
String name = cannocial_name_form(group->choiceName(i));
|
||||
ScriptableImage& img = cve.style().choice_images[name];
|
||||
if (i >= image_count || !img.upToDate(ctx, cve.style().thumbnail_age)) {
|
||||
bool up_to_date = img.upToDate(ctx, cve.style().thumbnail_age);
|
||||
if (i >= image_count || !up_to_date) {
|
||||
// TODO : handle the case where image i was previously skipped
|
||||
// request this thumbnail
|
||||
thumbnail_thread.request( new_shared2<ChoiceThumbnailRequest>(&cve, i) );
|
||||
thumbnail_thread.request( new_shared3<ChoiceThumbnailRequest>(&cve, i, up_to_date && !cve.style().invalidated_images) );
|
||||
}
|
||||
}
|
||||
cve.style().thumbnail_age.update();
|
||||
|
||||
@@ -78,6 +78,7 @@ void WelcomeWindow::draw(DC& dc) {
|
||||
void WelcomeWindow::onOpenSet(wxCommandEvent&) {
|
||||
wxFileDialog dlg(this, _TITLE_("open set"), wxEmptyString, wxEmptyString, import_formats(), wxOPEN);
|
||||
if (dlg.ShowModal() == wxID_OK) {
|
||||
wxBusyCursor wait;
|
||||
close(import_set(dlg.GetPath()));
|
||||
}
|
||||
}
|
||||
@@ -95,6 +96,7 @@ shared_ptr<T> open_package(const String& filename) {
|
||||
}
|
||||
|
||||
void WelcomeWindow::onOpenLast(wxCommandEvent&) {
|
||||
wxBusyCursor wait;
|
||||
assert(!settings.recent_sets.empty());
|
||||
close( open_package<Set>(settings.recent_sets.front()) );
|
||||
}
|
||||
|
||||
@@ -146,4 +146,16 @@ void DataViewer::onAction(const Action& action, bool undone) {
|
||||
}
|
||||
}
|
||||
}
|
||||
TYPE_CASE(action, ScriptStyleEvent) {
|
||||
if (action.stylesheet == stylesheet.get()) {
|
||||
FOR_EACH(v, viewers) {
|
||||
if (v->getStyle().get() == action.style) {
|
||||
// refresh the viewer
|
||||
v->onStyleChange();
|
||||
onChange();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,7 +264,9 @@ SCRIPT_FUNCTION(symbol_variation) {
|
||||
throw ScriptError(_("Variation of symbol not found ('") + variation + _("')"));
|
||||
} else {
|
||||
// SCRIPT_RETURN(last_update_age() >= value->filename.last_update_age);
|
||||
SCRIPT_RETURN(true);
|
||||
SCRIPT_RETURN(last_update_age() > 1); // the symbol was created/loaded after program start,
|
||||
// don't use cached images
|
||||
// SCRIPT_RETURN(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,10 @@ class ScriptableImage {
|
||||
inline void initDependencies(Context& ctx, const Dependency& dep) const {
|
||||
script.initDependencies(ctx, dep);
|
||||
}
|
||||
/// Invalidate the cached image
|
||||
inline void invalidate() {
|
||||
cache = ScriptImageP();
|
||||
}
|
||||
|
||||
private:
|
||||
OptionalScript script; ///< The script, not really optional
|
||||
|
||||
@@ -279,7 +279,14 @@ void SetScriptManager::alsoUpdate(deque<ToUpdate>& to_update, const vector<Depen
|
||||
}
|
||||
break;
|
||||
} case DEP_STYLE: {
|
||||
// TODO
|
||||
// a generated image has become invalid, there is not much we can do
|
||||
// because the index is not exact enough, it only gives the field
|
||||
StyleSheet* stylesheet = reinterpret_cast<StyleSheet*>(d.data);
|
||||
StyleP style = stylesheet->card_style.at(d.index);
|
||||
style->invalidate();
|
||||
// something changed, send event
|
||||
ScriptStyleEvent change(stylesheet, style.get());
|
||||
set.actions.tellListeners(change, false);
|
||||
break;
|
||||
} case DEP_CARD_COPY_DEP: {
|
||||
// propagate dependencies from another field
|
||||
|
||||
+1
-1
@@ -12,6 +12,6 @@
|
||||
|
||||
// what a waste of a source file...
|
||||
|
||||
AtomicInt Age::new_age(0);
|
||||
AtomicInt Age::new_age(2);
|
||||
|
||||
IMPLEMENT_DYNAMIC_ARG(AtomicIntEquiv, last_update_age, 0);
|
||||
|
||||
@@ -23,6 +23,11 @@ class Age {
|
||||
Age() {
|
||||
update();
|
||||
}
|
||||
/// Create a special age
|
||||
/** 0: dummy value, used for other purposes
|
||||
* 1: before 'beginning of time', the age conceptually just before program start
|
||||
* 2..: normal ages
|
||||
*/
|
||||
Age(AtomicIntEquiv age) : age(age) {}
|
||||
|
||||
/// Update the age to become the newest one
|
||||
|
||||
@@ -48,7 +48,6 @@ enum MenuID {
|
||||
, ID_EDIT_COPY = wxID_COPY
|
||||
, ID_EDIT_PASTE = wxID_PASTE
|
||||
, ID_EDIT_DELETE = 101
|
||||
, ID_EDIT_DUPLICATE = 102
|
||||
, ID_EDIT_FIND = wxID_FIND
|
||||
, ID_EDIT_FIND_NEXT = 103
|
||||
, ID_EDIT_REPLACE = wxID_REPLACE
|
||||
@@ -117,6 +116,7 @@ enum ChildMenuID {
|
||||
, ID_PART_OVERLAP = ID_PART + 4//PART_OVERLAP
|
||||
, ID_PART_BORDER = ID_PART + 5//PART_BORDER
|
||||
, ID_PART_MAX
|
||||
, ID_EDIT_DUPLICATE // duplicating symbol parts
|
||||
|
||||
// SymbolPointEditor toolbar/menu
|
||||
, ID_SEGMENT = 2101
|
||||
|
||||
Reference in New Issue
Block a user