Commit 5602cec0 authored by twanvl's avatar twanvl

Reverted resource references for combine_something, you can't use tool_image...

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
parent f35c9392
...@@ -143,6 +143,7 @@ TextValueAction* typing_action(const TextValueP& value, size_t start, size_t end ...@@ -143,6 +143,7 @@ TextValueAction* typing_action(const TextValueP& value, size_t start, size_t end
} }
} }
// ----------------------------------------------------------------------------- : Event // ----------------------------------------------------------------------------- : Event
String ScriptValueEvent::getName(bool) const { String ScriptValueEvent::getName(bool) const {
...@@ -152,3 +153,12 @@ String ScriptValueEvent::getName(bool) const { ...@@ -152,3 +153,12 @@ String ScriptValueEvent::getName(bool) const {
void ScriptValueEvent::perform(bool) { void ScriptValueEvent::perform(bool) {
assert(false); // this action is just an event, it should not be performed 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 @@ ...@@ -19,7 +19,9 @@
#include <util/defaultable.hpp> #include <util/defaultable.hpp>
class Card; class Card;
class StyleSheet;
DECLARE_POINTER_TYPE(Value); DECLARE_POINTER_TYPE(Value);
DECLARE_POINTER_TYPE(Style);
DECLARE_POINTER_TYPE(TextValue); DECLARE_POINTER_TYPE(TextValue);
DECLARE_POINTER_TYPE(ChoiceValue); DECLARE_POINTER_TYPE(ChoiceValue);
DECLARE_POINTER_TYPE(ColorValue); DECLARE_POINTER_TYPE(ColorValue);
...@@ -87,5 +89,19 @@ class ScriptValueEvent : public Action { ...@@ -87,5 +89,19 @@ class ScriptValueEvent : public Action {
const Value* value; ///< The modified value 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 // ----------------------------------------------------------------------------- : EOF
#endif #endif
...@@ -111,11 +111,11 @@ bool Style::update(Context& ctx) { ...@@ -111,11 +111,11 @@ bool Style::update(Context& ctx) {
} }
void Style::initDependencies(Context& ctx, const Dependency& dep) const { void Style::initDependencies(Context& ctx, const Dependency& dep) const {
left .initDependencies(ctx,dep); /// left .initDependencies(ctx,dep);
top .initDependencies(ctx,dep); // top .initDependencies(ctx,dep);
width .initDependencies(ctx,dep); // width .initDependencies(ctx,dep);
height .initDependencies(ctx,dep); // height .initDependencies(ctx,dep);
visible.initDependencies(ctx,dep); // visible.initDependencies(ctx,dep);
} }
// ----------------------------------------------------------------------------- : Value // ----------------------------------------------------------------------------- : Value
......
...@@ -102,7 +102,10 @@ class Style { ...@@ -102,7 +102,10 @@ class Style {
/// Update scripted values of this style, return true if anything has changed /// Update scripted values of this style, return true if anything has changed
virtual bool update(Context&); virtual bool update(Context&);
/// 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() */
virtual void initDependencies(Context&, const Dependency&) const; virtual void initDependencies(Context&, const Dependency&) const;
/// Invalidate scripted images for this style
virtual void invalidate() {}
private: private:
DECLARE_REFLECTION_VIRTUAL(); DECLARE_REFLECTION_VIRTUAL();
......
...@@ -167,19 +167,15 @@ ChoiceStyle::ChoiceStyle(const ChoiceFieldP& field) ...@@ -167,19 +167,15 @@ ChoiceStyle::ChoiceStyle(const ChoiceFieldP& field)
, combine(COMBINE_NORMAL) , combine(COMBINE_NORMAL)
, alignment(ALIGN_STRETCH) , alignment(ALIGN_STRETCH)
, thumbnails(nullptr) , thumbnails(nullptr)
, thumbnail_age(1) // thumbnails were made before the beginning of time
, invalidated_images(false)
{} {}
ChoiceStyle::~ChoiceStyle() { ChoiceStyle::~ChoiceStyle() {
delete thumbnails; delete thumbnails;
} }
// TODO
/*
void ChoiceStyle::invalidate() {
// rebuild choice images
}
*/
bool ChoiceStyle::update(Context& ctx) { bool ChoiceStyle::update(Context& ctx) {
// Don't update the choice images, leave that to invalidate() // Don't update the choice images, leave that to invalidate()
return Style::update(ctx); return Style::update(ctx);
...@@ -190,6 +186,18 @@ void ChoiceStyle::initDependencies(Context& ctx, const Dependency& dep) const { ...@@ -190,6 +186,18 @@ void ChoiceStyle::initDependencies(Context& ctx, const Dependency& dep) const {
ci.second.initDependencies(ctx, dep); 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) { void ChoiceStyle::loadMask(Package& pkg) {
if (mask.Ok() || mask_filename.empty()) return; if (mask.Ok() || mask_filename.empty()) return;
......
...@@ -129,12 +129,14 @@ class ChoiceStyle : public Style { ...@@ -129,12 +129,14 @@ class ChoiceStyle : public Style {
Image mask; ///< The actual mask image Image mask; ///< The actual mask image
wxImageList* thumbnails; ///< Thumbnails for the choices wxImageList* thumbnails; ///< Thumbnails for the choices
Age thumbnail_age; ///< Age the thumbnails were generated 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 /// Load the mask image, if it's not already done
void loadMask(Package& pkg); void loadMask(Package& pkg);
virtual bool update(Context&); virtual bool update(Context&);
virtual void initDependencies(Context&, const Dependency&) const; virtual void initDependencies(Context&, const Dependency&) const;
virtual void invalidate();
private: private:
DECLARE_REFLECTION(); DECLARE_REFLECTION();
......
...@@ -62,8 +62,8 @@ bool TextStyle::update(Context& ctx) { ...@@ -62,8 +62,8 @@ bool TextStyle::update(Context& ctx) {
} }
void TextStyle::initDependencies(Context& ctx, const Dependency& dep) const { void TextStyle::initDependencies(Context& ctx, const Dependency& dep) const {
Style ::initDependencies(ctx, dep); Style ::initDependencies(ctx, dep);
font .initDependencies(ctx, dep); // font .initDependencies(ctx, dep);
symbol_font.initDependencies(ctx, dep); // symbol_font.initDependencies(ctx, dep);
} }
IMPLEMENT_REFLECTION(TextStyle) { IMPLEMENT_REFLECTION(TextStyle) {
......
...@@ -20,12 +20,12 @@ SymbolPartList::SymbolPartList(Window* parent, int id, SymbolP symbol) ...@@ -20,12 +20,12 @@ SymbolPartList::SymbolPartList(Window* parent, int id, SymbolP symbol)
// Create image list // Create image list
wxImageList* images = new wxImageList(16,16); wxImageList* images = new wxImageList(16,16);
// NOTE: this is based on the order of the SymbolPartCombine enum! // NOTE: this is based on the order of the SymbolPartCombine enum!
images->Add(load_resource_tool_image(_("combine_or"))); images->Add(load_resource_image(_("combine_or")));
images->Add(load_resource_tool_image(_("combine_sub"))); images->Add(load_resource_image(_("combine_sub")));
images->Add(load_resource_tool_image(_("combine_and"))); images->Add(load_resource_image(_("combine_and")));
images->Add(load_resource_tool_image(_("combine_xor"))); images->Add(load_resource_image(_("combine_xor")));
images->Add(load_resource_tool_image(_("combine_over"))); images->Add(load_resource_image(_("combine_over")));
images->Add(load_resource_tool_image(_("combine_border"))); images->Add(load_resource_image(_("combine_border")));
AssignImageList(images, wxIMAGE_LIST_SMALL); AssignImageList(images, wxIMAGE_LIST_SMALL);
// create columns // create columns
InsertColumn(0, _("Name")); InsertColumn(0, _("Name"));
......
...@@ -107,12 +107,12 @@ void SymbolSelectEditor::drawRotationCenter(DC& dc, const Vector2D& pos) { ...@@ -107,12 +107,12 @@ void SymbolSelectEditor::drawRotationCenter(DC& dc, const Vector2D& pos) {
void SymbolSelectEditor::initUI(wxToolBar* tb, wxMenuBar* mb) { void SymbolSelectEditor::initUI(wxToolBar* tb, wxMenuBar* mb) {
tb->AddSeparator(); 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_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_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_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_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_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) // 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_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_tool_image(_("combine_border")), wxNullBitmap, wxITEM_CHECK, _("Draw as a border"), _("Draws this shape as a border")); 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(); tb->Realize();
} }
void SymbolSelectEditor::destroyUI(wxToolBar* tb, wxMenuBar* mb) { void SymbolSelectEditor::destroyUI(wxToolBar* tb, wxMenuBar* mb) {
......
...@@ -46,6 +46,8 @@ wxCursor load_resource_cursor(const String& name); ...@@ -46,6 +46,8 @@ wxCursor load_resource_cursor(const String& name);
wxIcon load_resource_icon(const String& name); wxIcon load_resource_icon(const String& name);
/// Load an image for use in a toolbar (filename: tool/...) from a resource /// 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); wxBitmap load_resource_tool_image(const String& name);
// ----------------------------------------------------------------------------- : Platform look // ----------------------------------------------------------------------------- : Platform look
......
...@@ -19,7 +19,7 @@ DECLARE_TYPEOF_COLLECTION(ChoiceField::ChoiceP); ...@@ -19,7 +19,7 @@ DECLARE_TYPEOF_COLLECTION(ChoiceField::ChoiceP);
class ChoiceThumbnailRequest : public ThumbnailRequest { class ChoiceThumbnailRequest : public ThumbnailRequest {
public: public:
ChoiceThumbnailRequest(ChoiceValueEditor* cve, int id); ChoiceThumbnailRequest(ChoiceValueEditor* cve, int id, bool from_disk);
virtual Image generate(); virtual Image generate();
virtual void store(const Image&); virtual void store(const Image&);
private: private:
...@@ -27,11 +27,13 @@ class ChoiceThumbnailRequest : public ThumbnailRequest { ...@@ -27,11 +27,13 @@ class ChoiceThumbnailRequest : public ThumbnailRequest {
int id; int id;
}; };
ChoiceThumbnailRequest::ChoiceThumbnailRequest(ChoiceValueEditor* cve, int id) ChoiceThumbnailRequest::ChoiceThumbnailRequest(ChoiceValueEditor* cve, int id, bool from_disk)
: ThumbnailRequest( : ThumbnailRequest(
cve, cve,
cve->viewer.stylesheet->name() + _("/") + cve->field().name + _("/") << id, cve->viewer.stylesheet->name() + _("/") + cve->field().name + _("/") << id,
cve->viewer.stylesheet->lastModified()) from_disk ? cve->viewer.stylesheet->lastModified()
: wxDateTime::Now()
)
, stylesheet(cve->viewer.stylesheet) , stylesheet(cve->viewer.stylesheet)
, id(id) , id(id)
{} {}
...@@ -195,10 +197,11 @@ void DropDownChoiceList::generateThumbnailImages() { ...@@ -195,10 +197,11 @@ void DropDownChoiceList::generateThumbnailImages() {
for (int i = 0 ; i < end ; ++i) { for (int i = 0 ; i < end ; ++i) {
String name = cannocial_name_form(group->choiceName(i)); String name = cannocial_name_form(group->choiceName(i));
ScriptableImage& img = cve.style().choice_images[name]; 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 // TODO : handle the case where image i was previously skipped
// request this thumbnail // 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(); cve.style().thumbnail_age.update();
......
...@@ -78,6 +78,7 @@ void WelcomeWindow::draw(DC& dc) { ...@@ -78,6 +78,7 @@ void WelcomeWindow::draw(DC& dc) {
void WelcomeWindow::onOpenSet(wxCommandEvent&) { void WelcomeWindow::onOpenSet(wxCommandEvent&) {
wxFileDialog dlg(this, _TITLE_("open set"), wxEmptyString, wxEmptyString, import_formats(), wxOPEN); wxFileDialog dlg(this, _TITLE_("open set"), wxEmptyString, wxEmptyString, import_formats(), wxOPEN);
if (dlg.ShowModal() == wxID_OK) { if (dlg.ShowModal() == wxID_OK) {
wxBusyCursor wait;
close(import_set(dlg.GetPath())); close(import_set(dlg.GetPath()));
} }
} }
...@@ -95,6 +96,7 @@ shared_ptr<T> open_package(const String& filename) { ...@@ -95,6 +96,7 @@ shared_ptr<T> open_package(const String& filename) {
} }
void WelcomeWindow::onOpenLast(wxCommandEvent&) { void WelcomeWindow::onOpenLast(wxCommandEvent&) {
wxBusyCursor wait;
assert(!settings.recent_sets.empty()); assert(!settings.recent_sets.empty());
close( open_package<Set>(settings.recent_sets.front()) ); close( open_package<Set>(settings.recent_sets.front()) );
} }
......
...@@ -146,4 +146,16 @@ void DataViewer::onAction(const Action& action, bool undone) { ...@@ -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) { ...@@ -264,7 +264,9 @@ SCRIPT_FUNCTION(symbol_variation) {
throw ScriptError(_("Variation of symbol not found ('") + variation + _("')")); throw ScriptError(_("Variation of symbol not found ('") + variation + _("')"));
} else { } else {
// SCRIPT_RETURN(last_update_age() >= value->filename.last_update_age); // 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 { ...@@ -71,6 +71,10 @@ class ScriptableImage {
inline void initDependencies(Context& ctx, const Dependency& dep) const { inline void initDependencies(Context& ctx, const Dependency& dep) const {
script.initDependencies(ctx, dep); script.initDependencies(ctx, dep);
} }
/// Invalidate the cached image
inline void invalidate() {
cache = ScriptImageP();
}
private: private:
OptionalScript script; ///< The script, not really optional OptionalScript script; ///< The script, not really optional
......
...@@ -279,7 +279,14 @@ void SetScriptManager::alsoUpdate(deque<ToUpdate>& to_update, const vector<Depen ...@@ -279,7 +279,14 @@ void SetScriptManager::alsoUpdate(deque<ToUpdate>& to_update, const vector<Depen
} }
break; break;
} case DEP_STYLE: { } 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; break;
} case DEP_CARD_COPY_DEP: { } case DEP_CARD_COPY_DEP: {
// propagate dependencies from another field // propagate dependencies from another field
......
...@@ -12,6 +12,6 @@ ...@@ -12,6 +12,6 @@
// what a waste of a source file... // 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); IMPLEMENT_DYNAMIC_ARG(AtomicIntEquiv, last_update_age, 0);
...@@ -23,6 +23,11 @@ class Age { ...@@ -23,6 +23,11 @@ class Age {
Age() { Age() {
update(); 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) {} Age(AtomicIntEquiv age) : age(age) {}
/// Update the age to become the newest one /// Update the age to become the newest one
......
...@@ -48,7 +48,6 @@ enum MenuID { ...@@ -48,7 +48,6 @@ enum MenuID {
, ID_EDIT_COPY = wxID_COPY , ID_EDIT_COPY = wxID_COPY
, ID_EDIT_PASTE = wxID_PASTE , ID_EDIT_PASTE = wxID_PASTE
, ID_EDIT_DELETE = 101 , ID_EDIT_DELETE = 101
, ID_EDIT_DUPLICATE = 102
, ID_EDIT_FIND = wxID_FIND , ID_EDIT_FIND = wxID_FIND
, ID_EDIT_FIND_NEXT = 103 , ID_EDIT_FIND_NEXT = 103
, ID_EDIT_REPLACE = wxID_REPLACE , ID_EDIT_REPLACE = wxID_REPLACE
...@@ -117,6 +116,7 @@ enum ChildMenuID { ...@@ -117,6 +116,7 @@ enum ChildMenuID {
, ID_PART_OVERLAP = ID_PART + 4//PART_OVERLAP , ID_PART_OVERLAP = ID_PART + 4//PART_OVERLAP
, ID_PART_BORDER = ID_PART + 5//PART_BORDER , ID_PART_BORDER = ID_PART + 5//PART_BORDER
, ID_PART_MAX , ID_PART_MAX
, ID_EDIT_DUPLICATE // duplicating symbol parts
// SymbolPointEditor toolbar/menu // SymbolPointEditor toolbar/menu
, ID_SEGMENT = 2101 , ID_SEGMENT = 2101
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment