Commit fb9b3d0f authored by coppro's avatar coppro

Added thread-safety to thumbnail request system.

Marked symbol requests as not being thread-safe.
Added icon to symbol editor
Made *.* actually register on *
parent 1d7d1041
...@@ -33,7 +33,7 @@ String import_formats() { ...@@ -33,7 +33,7 @@ String import_formats() {
type_strings += _("|") + f->name() + _("|*.") + f->extension(); type_strings += _("|") + f->name() + _("|*.") + f->extension();
} }
} }
return _("Set files|") + all_extensions + type_strings + _("|All files (*.*)|*.*"); return _("Set files|") + all_extensions + type_strings + _("|All files (*.*)|*");
} }
String export_formats(const Game& game) { String export_formats(const Game& game) {
......
...@@ -59,7 +59,7 @@ void export_mws(Window* parent, const SetP& set) { ...@@ -59,7 +59,7 @@ void export_mws(Window* parent, const SetP& set) {
// Select filename // Select filename
String name = wxFileSelector(_("Export to file"),_(""),_(""),_(""), String name = wxFileSelector(_("Export to file"),_(""),_(""),_(""),
_("Text files (*.txt)|*.txt|All Files|*.*"), _("Text files (*.txt)|*.txt|All Files|*"),
wxSAVE | wxOVERWRITE_PROMPT, parent); wxSAVE | wxOVERWRITE_PROMPT, parent);
if (name.empty()) return; if (name.empty()) return;
wxBusyCursor busy; wxBusyCursor busy;
......
...@@ -45,6 +45,9 @@ class GeneratedImage : public ScriptValue { ...@@ -45,6 +45,9 @@ class GeneratedImage : public ScriptValue {
/// Equality should mean that every pixel in the generated images is the same if the same options are used /// Equality should mean that every pixel in the generated images is the same if the same options are used
virtual bool operator == (const GeneratedImage& that) const = 0; virtual bool operator == (const GeneratedImage& that) const = 0;
inline bool operator != (const GeneratedImage& that) const { return !(*this == that); } inline bool operator != (const GeneratedImage& that) const { return !(*this == that); }
/// Can this image be generated safely from another thread?
virtual bool threadSafe() const = 0;
virtual ScriptType type() const; virtual ScriptType type() const;
virtual String typeName() const; virtual String typeName() const;
...@@ -61,6 +64,8 @@ class LinearBlendImage : public GeneratedImage { ...@@ -61,6 +64,8 @@ class LinearBlendImage : public GeneratedImage {
virtual Image generate(const Options& opt) const; virtual Image generate(const Options& opt) const;
virtual ImageCombine combine() const; virtual ImageCombine combine() const;
virtual bool operator == (const GeneratedImage& that) const; virtual bool operator == (const GeneratedImage& that) const;
virtual bool threadSafe() const {return true;}
private: private:
GeneratedImageP image1, image2; GeneratedImageP image1, image2;
double x1, y1, x2, y2; double x1, y1, x2, y2;
...@@ -77,6 +82,8 @@ class MaskedBlendImage : public GeneratedImage { ...@@ -77,6 +82,8 @@ class MaskedBlendImage : public GeneratedImage {
virtual Image generate(const Options& opt) const; virtual Image generate(const Options& opt) const;
virtual ImageCombine combine() const; virtual ImageCombine combine() const;
virtual bool operator == (const GeneratedImage& that) const; virtual bool operator == (const GeneratedImage& that) const;
virtual bool threadSafe() const {return true;}
private: private:
GeneratedImageP light, dark, mask; GeneratedImageP light, dark, mask;
}; };
...@@ -92,6 +99,8 @@ class CombineBlendImage : public GeneratedImage { ...@@ -92,6 +99,8 @@ class CombineBlendImage : public GeneratedImage {
virtual Image generate(const Options& opt) const; virtual Image generate(const Options& opt) const;
virtual ImageCombine combine() const; virtual ImageCombine combine() const;
virtual bool operator == (const GeneratedImage& that) const; virtual bool operator == (const GeneratedImage& that) const;
virtual bool threadSafe() const {return true;}
private: private:
GeneratedImageP image1, image2; GeneratedImageP image1, image2;
ImageCombine image_combine; ImageCombine image_combine;
...@@ -108,6 +117,8 @@ class SetMaskImage : public GeneratedImage { ...@@ -108,6 +117,8 @@ class SetMaskImage : public GeneratedImage {
virtual Image generate(const Options& opt) const; virtual Image generate(const Options& opt) const;
virtual ImageCombine combine() const; virtual ImageCombine combine() const;
virtual bool operator == (const GeneratedImage& that) const; virtual bool operator == (const GeneratedImage& that) const;
virtual bool threadSafe() const {return true;}
private: private:
GeneratedImageP image, mask; GeneratedImageP image, mask;
}; };
...@@ -123,6 +134,8 @@ class SetCombineImage : public GeneratedImage { ...@@ -123,6 +134,8 @@ class SetCombineImage : public GeneratedImage {
virtual Image generate(const Options& opt) const; virtual Image generate(const Options& opt) const;
virtual ImageCombine combine() const; virtual ImageCombine combine() const;
virtual bool operator == (const GeneratedImage& that) const; virtual bool operator == (const GeneratedImage& that) const;
virtual bool threadSafe() const {return true;}
private: private:
GeneratedImageP image; GeneratedImageP image;
ImageCombine image_combine; ImageCombine image_combine;
...@@ -138,6 +151,8 @@ class PackagedImage : public GeneratedImage { ...@@ -138,6 +151,8 @@ class PackagedImage : public GeneratedImage {
{} {}
virtual Image generate(const Options& opt) const; virtual Image generate(const Options& opt) const;
virtual bool operator == (const GeneratedImage& that) const; virtual bool operator == (const GeneratedImage& that) const;
virtual bool threadSafe() const {return true;}
private: private:
String filename; String filename;
}; };
...@@ -152,6 +167,8 @@ class BuiltInImage : public GeneratedImage { ...@@ -152,6 +167,8 @@ class BuiltInImage : public GeneratedImage {
{} {}
virtual Image generate(const Options& opt) const; virtual Image generate(const Options& opt) const;
virtual bool operator == (const GeneratedImage& that) const; virtual bool operator == (const GeneratedImage& that) const;
virtual bool threadSafe() const {return true;}
private: private:
String name; String name;
}; };
...@@ -165,6 +182,8 @@ class SymbolToImage : public GeneratedImage { ...@@ -165,6 +182,8 @@ class SymbolToImage : public GeneratedImage {
~SymbolToImage(); ~SymbolToImage();
virtual Image generate(const Options& opt) const; virtual Image generate(const Options& opt) const;
virtual bool operator == (const GeneratedImage& that) const; virtual bool operator == (const GeneratedImage& that) const;
virtual bool threadSafe() const {return false;}
private: private:
SymbolToImage(const SymbolToImage&); // copy ctor SymbolToImage(const SymbolToImage&); // copy ctor
String filename; String filename;
......
...@@ -84,6 +84,8 @@ class CardThumbnailRequest : public ThumbnailRequest { ...@@ -84,6 +84,8 @@ class CardThumbnailRequest : public ThumbnailRequest {
parent->Refresh(false); parent->Refresh(false);
} }
} }
virtual bool threadSafe() const {return true;}
private: private:
String filename; String filename;
}; };
......
...@@ -29,7 +29,7 @@ class PackageList : public GalleryList { ...@@ -29,7 +29,7 @@ class PackageList : public GalleryList {
} }
/// Shows packages that match a specific patern /// Shows packages that match a specific patern
void showData(const String& pattern = _("*.*")); void showData(const String& pattern = _("*"));
/// Clears this list /// Clears this list
void clear(); void clear();
......
...@@ -73,7 +73,7 @@ void ImagesExportWindow::onOk(wxCommandEvent&) { ...@@ -73,7 +73,7 @@ void ImagesExportWindow::onOk(wxCommandEvent&) {
ScriptP filename_script = parse(gs.images_export_filename, true); ScriptP filename_script = parse(gs.images_export_filename, true);
// Select filename // Select filename
String name = wxFileSelector(_TITLE_("export images"),_(""), _LABEL_("filename is ignored"),_(""), String name = wxFileSelector(_TITLE_("export images"),_(""), _LABEL_("filename is ignored"),_(""),
_LABEL_("filename is ignored")+_("|*.*"), wxSAVE, this); _LABEL_("filename is ignored")+_("|*"), wxSAVE, this);
if (name.empty()) return; if (name.empty()) return;
wxFileName fn(name); wxFileName fn(name);
// Export // Export
......
...@@ -54,6 +54,7 @@ SymbolWindow::SymbolWindow(Window* parent, const SymbolValueP& value, const SetP ...@@ -54,6 +54,7 @@ SymbolWindow::SymbolWindow(Window* parent, const SymbolValueP& value, const SetP
void SymbolWindow::init(Window* parent, SymbolP symbol) { void SymbolWindow::init(Window* parent, SymbolP symbol) {
Create(parent, wxID_ANY, _TITLE_("symbol editor"), wxDefaultPosition, wxSize(600,600), wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE); Create(parent, wxID_ANY, _TITLE_("symbol editor"), wxDefaultPosition, wxSize(600,600), wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE);
SetIcon(load_resource_icon(_("app")));
inSelectionEvent = false; inSelectionEvent = false;
// Menu bar // Menu bar
......
...@@ -130,17 +130,41 @@ void ThumbnailThread::request(const ThumbnailRequestP& request) { ...@@ -130,17 +130,41 @@ void ThumbnailThread::request(const ThumbnailRequestP& request) {
return; return;
} }
} }
request_names.insert(request); if (request->threadSafe()) {
// request generation request_names.insert(request);
{ // request generation
wxMutexLocker lock(mutex); {
open_requests.push_back(request); wxMutexLocker lock(mutex);
open_requests.push_back(request);
}
// is there a worker?
if (!worker) {
worker = new ThumbnailThreadWorker(this);
worker->Create();
worker->Run();
}
} }
// is there a worker? else {
if (!worker) { Image img;
worker = new ThumbnailThreadWorker(this); try {
worker->Create(); img = request->generate();
worker->Run(); } catch (const Error& e) {
handle_error(e, false, false);
} catch (...) {
}
// store in cache
if (img.Ok()) {
String filename = image_cache_dir() + safe_filename(request->cache_name) + _(".png");
img.SaveFile(filename, wxBITMAP_TYPE_PNG);
// set modification time
wxFileName fn(filename);
fn.SetTimes(0, &request->modified, 0);
}
{
wxMutexLocker lock(mutex);
closed_requests.push_back(make_pair(request,img));
completed.Signal();
}
} }
} }
......
...@@ -31,6 +31,9 @@ class ThumbnailRequest : public IntrusivePtrVirtualBase { ...@@ -31,6 +31,9 @@ class ThumbnailRequest : public IntrusivePtrVirtualBase {
virtual Image generate() = 0; virtual Image generate() = 0;
/// Store the thumbnail, called from the main thread /// Store the thumbnail, called from the main thread
virtual void store(const Image&) = 0; virtual void store(const Image&) = 0;
/// Can the thumbnail safely be generated from another thread?
virtual bool threadSafe() const = 0;
/// Object that requested the thumbnail /// Object that requested the thumbnail
void* const owner; void* const owner;
......
...@@ -23,6 +23,9 @@ class ChoiceThumbnailRequest : public ThumbnailRequest { ...@@ -23,6 +23,9 @@ class ChoiceThumbnailRequest : public ThumbnailRequest {
ChoiceThumbnailRequest(ValueViewer* cve, int id, bool from_disk); ChoiceThumbnailRequest(ValueViewer* cve, int id, bool from_disk);
virtual Image generate(); virtual Image generate();
virtual void store(const Image&); virtual void store(const Image&);
bool isThreadSafe;
virtual bool threadSafe() const {return isThreadSafe;}
private: private:
StyleSheetP stylesheet; StyleSheetP stylesheet;
int id; int id;
...@@ -37,7 +40,12 @@ ChoiceThumbnailRequest::ChoiceThumbnailRequest(ValueViewer* cve, int id, bool fr ...@@ -37,7 +40,12 @@ ChoiceThumbnailRequest::ChoiceThumbnailRequest(ValueViewer* cve, int id, bool fr
) )
, stylesheet(cve->viewer.stylesheet) , stylesheet(cve->viewer.stylesheet)
, id(id) , id(id)
{} {
ChoiceValueEditor& e = *(ChoiceValueEditor*)cve;
String name = cannocial_name_form(e.field().choices->choiceName(id));
ScriptableImage& img = e.style().choice_images[name];
isThreadSafe = img.threadSafe();
}
Image ChoiceThumbnailRequest::generate() { Image ChoiceThumbnailRequest::generate() {
ChoiceValueEditor& cve = *(ChoiceValueEditor*)owner; ChoiceValueEditor& cve = *(ChoiceValueEditor*)owner;
......
...@@ -45,6 +45,9 @@ class ScriptableImage { ...@@ -45,6 +45,9 @@ 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);
} }
/// Can this be safely generated from another thread?
bool threadSafe() const {return value->threadSafe();}
private: private:
OptionalScript script; ///< The script, not really optional OptionalScript script; ///< The script, not really optional
......
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