From 3ceec52c1c31b84f48f23874ccd54de584ef3377 Mon Sep 17 00:00:00 2001 From: twanvl Date: Sat, 29 Dec 2007 23:51:19 +0000 Subject: [PATCH] - no longer try to draw fields with huge or negative size - download icons of packages git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@799 0fc631ac-6414-0410-93d0-97cfa31319b6 --- data/en.mse-locale/locale | 35 +++------ src/data/export_template.cpp | 2 +- src/data/field.cpp | 43 +++++++--- src/data/field.hpp | 5 ++ src/data/installer.cpp | 5 ++ src/data/installer.hpp | 12 +-- src/data/set.cpp | 2 +- src/data/stylesheet.cpp | 2 +- src/gfx/image_effects.cpp | 2 +- src/gui/control/card_editor.cpp | 2 +- src/gui/packages_window.cpp | 91 +++++++++++++++++++++- src/gui/thumbnail_thread.hpp | 2 +- src/render/card/viewer.cpp | 9 +-- src/resource/common/expected_locale_keys | 53 +++++++------ src/resource/common/installer_package.png | Bin 462 -> 682 bytes 15 files changed, 176 insertions(+), 89 deletions(-) diff --git a/data/en.mse-locale/locale b/data/en.mse-locale/locale index af23a5da..69f6ba82 100644 --- a/data/en.mse-locale/locale +++ b/data/en.mse-locale/locale @@ -456,8 +456,6 @@ label: # Packages window package name: Package - package installed version: Installed version - package remote version: Latest version package status: Status package action: Action @@ -516,10 +514,7 @@ button: keep old: Keep old files number: Add a number to the filename number overwrite: Add a number to the filename, overwrite previous exports - - # Update checker - close: &Close - + # Auto replace use auto replace: Use auto replace add item: &Add @@ -549,7 +544,7 @@ title: open set: Open Set save set: Save Set As save image: Save Image - updates available: Updates Available + #updates available: Updates Available save changes: Save Changes? select stylesheet: Select Stylesheet #preferences @@ -577,11 +572,10 @@ title: auto replaces: Auto Replace # Package Update Window - package list: Package Updates - package type: Package Type - package name: Package Name - package status: Current Status - new status: New Status + packages window: Package Manager + installing updates: Installing updates + + cannot create file: Cannot create file ############################################################## Action (undo/redo) names action: @@ -679,7 +673,7 @@ error: images used for blending must have the same size: Images used for blending must have the same size # Error from files - no game specified for the set: No game specified for the set + no game specified: No game specified for the %s no stylesheet specified for the set: No stylesheet specified for the set stylesheet and set refer to different game: stylesheet and set don't refer to the same game, this is an error in the stylesheet file @@ -704,8 +698,7 @@ error: dimension not found: There is no statistics dimension '%s' # Package update window - no packages: Found no package updates. - checking updates: Checking for updates. +# checking updates: Checking for updates. can't download installer: Unable to download installer for package %s from %s. Nothing has been installed. @@ -742,6 +735,7 @@ type: game: game set: set stylesheet: stylesheet + export template:export template card: card field: field style: style @@ -768,17 +762,6 @@ type: point: point points: points - # Package manager - installed: installed - uninstalled: uninstalled - upgradeable: upgradeable - - install: install - uninstall: uninstall - upgrade: upgrade - do nothing: do nothing - new mse: MSE outdated - ############################################################## Magic game: diff --git a/src/data/export_template.cpp b/src/data/export_template.cpp index 013e8c45..1db16403 100644 --- a/src/data/export_template.cpp +++ b/src/data/export_template.cpp @@ -23,7 +23,7 @@ String ExportTemplate::typeName() const { return _("export-template"); } void ExportTemplate::validate(Version) { if (!game) { - throw Error(_ERROR_("no game specified for export template")); + throw Error(_ERROR_1_("no game specified",_TYPE_("export template"))); } // an export template depends on the game it is made for requireDependency(game.get()); diff --git a/src/data/field.cpp b/src/data/field.cpp index 03637fee..38955b32 100644 --- a/src/data/field.cpp +++ b/src/data/field.cpp @@ -97,9 +97,9 @@ intrusive_ptr read_new(Reader& reader) { Style::Style(const FieldP& field) : fieldP(field) , z_index(0) - , left(-1), top(-1) - , width(-1), height(-1) - , right(-1), bottom(-1) + , left (1000000), top (1000000) + , width(0), height(0) + , right(1000000), bottom(1000000) , angle(0) , visible(true) , automatic_side(AUTO_UNKNOWN) @@ -139,14 +139,14 @@ int Style::update(Context& ctx) { | visible.update(ctx); // determine automatic_side and attachment of rotation point if (automatic_side == AUTO_UNKNOWN) { - if (right == -1) automatic_side = (AutomaticSide)(automatic_side | AUTO_RIGHT); - else if (width == -1) automatic_side = (AutomaticSide)(automatic_side | AUTO_WIDTH); - else if (left == -1) automatic_side = (AutomaticSide)(automatic_side | AUTO_LEFT); - else automatic_side = (AutomaticSide)(automatic_side | AUTO_LR); - if (bottom == -1) automatic_side = (AutomaticSide)(automatic_side | AUTO_BOTTOM); - else if (height == -1) automatic_side = (AutomaticSide)(automatic_side | AUTO_HEIGHT); - else if (top == -1) automatic_side = (AutomaticSide)(automatic_side | AUTO_TOP); - else automatic_side = (AutomaticSide)(automatic_side | AUTO_TB); + if (right == 1000000) automatic_side = (AutomaticSide)(automatic_side | AUTO_RIGHT); + else if (width == 0) automatic_side = (AutomaticSide)(automatic_side | AUTO_WIDTH); + else if (left == 1000000) automatic_side = (AutomaticSide)(automatic_side | AUTO_LEFT); + else automatic_side = (AutomaticSide)(automatic_side | AUTO_LR); + if (bottom == 1000000) automatic_side = (AutomaticSide)(automatic_side | AUTO_BOTTOM); + else if (height == 0) automatic_side = (AutomaticSide)(automatic_side | AUTO_HEIGHT); + else if (top == 1000000) automatic_side = (AutomaticSide)(automatic_side | AUTO_TOP); + else automatic_side = (AutomaticSide)(automatic_side | AUTO_TB); changed = true; } if (!changed) return CHANGE_NONE; @@ -171,10 +171,31 @@ int Style::update(Context& ctx) { top = top + height * (1 - c); } } + if (width < 0) width = -width; + if (height < 0) height = -height; // done return CHANGE_OTHER; } +bool Style::isVisible() const { + return visible + && (width) > 0 + && abs(left) < 100000 + && abs(right) < 100000 + && (height) > 0 + && abs(top) < 100000 + && abs(bottom) < 100000; +} +bool Style::hasSize() const { + int h = (abs(width) > 0 || width .isScripted()) + + (abs(left) < 100000 || left .isScripted()) + + (abs(right) < 100000 || right .isScripted()); + int v = (abs(height) > 0 || height.isScripted()) + + (abs(top) < 100000 || top .isScripted()) + + (abs(bottom) < 100000 || bottom.isScripted()); + return h >= 2 && v >= 2; +} + void Style::initDependencies(Context& ctx, const Dependency& dep) const { // left .initDependencies(ctx,dep); // top .initDependencies(ctx,dep); diff --git a/src/data/field.hpp b/src/data/field.hpp index adb9e190..5d53519e 100644 --- a/src/data/field.hpp +++ b/src/data/field.hpp @@ -115,6 +115,11 @@ class Style : public IntrusivePtrVirtualBase { inline RealRect getExternalRect() const { return RealRect (left, top, width, height); } inline RealRect getInternalRect() const { return RealRect(0, 0, width, height); } + /// Does this style have a non-zero size (or is it scripted)? + bool hasSize() const; + /// Is this style visible, and does it have a sane size + bool isVisible() const; + /// Get a copy of this style virtual StyleP clone() const = 0; diff --git a/src/data/installer.cpp b/src/data/installer.cpp index a714d89f..6f72e986 100644 --- a/src/data/installer.cpp +++ b/src/data/installer.cpp @@ -217,6 +217,10 @@ IMPLEMENT_REFLECTION_NO_SCRIPT(PackageDescription) { REFLECT_N("depends ons", dependencies); } +void PackageDescription::merge(const PackageDescription& p2) { + if (!icon.Ok() && !icon_url) icon = p2.icon; +} + IMPLEMENT_REFLECTION_NO_SCRIPT(InstallerDescription) { REFLECT(packages); } @@ -290,6 +294,7 @@ bool InstallablePackage::has(PackageAction act) const { void InstallablePackage::merge(const InstallablePackage& p) { if (!installed) installed = p.installed; if (!installer) { + p.description->merge(*description); description = p.description; // installer has new description installer = p.installer; } diff --git a/src/data/installer.hpp b/src/data/installer.hpp index a77cfc65..f05a52fe 100644 --- a/src/data/installer.hpp +++ b/src/data/installer.hpp @@ -26,15 +26,6 @@ class Installer : public Packaged { String prefered_filename; ///< What filename should be used (by default) vector packages; ///< Packages to install - /* - /// Load an installer from a file, and run it - static void installFrom(const String& filename, bool message_on_success, bool local); - /// Install all the packages - void install(bool local, bool check_dependencies = true); - /// Install a specific package - void install(const String& package); - */ - /// Add a package to the installer (if it is not already added). /** If the package is named *.mse-installer uses it as the filename instead */ void addPackage(const String& package); @@ -67,6 +58,9 @@ class PackageDescription : public IntrusivePtrBase { String description; ///< Changelog/description vector dependencies; ///< Dependencies of this package + /// Merge two descriptions a package. This package takes precedence + void merge(const PackageDescription& p2); + DECLARE_REFLECTION(); }; diff --git a/src/data/set.cpp b/src/data/set.cpp index 41c606ee..328ca725 100644 --- a/src/data/set.cpp +++ b/src/data/set.cpp @@ -134,7 +134,7 @@ void Set::validate(Version file_app_version) { Packaged::validate(file_app_version); // are the if (!game) { - throw Error(_ERROR_("no game specified for the set")); + throw Error(_ERROR_1_("no game specified",_TYPE_("set"))); } if (!stylesheet) { // TODO : Allow user to select a different style diff --git a/src/data/stylesheet.cpp b/src/data/stylesheet.cpp index 7ba8d57b..17ae00b9 100644 --- a/src/data/stylesheet.cpp +++ b/src/data/stylesheet.cpp @@ -67,7 +67,7 @@ String StyleSheet::typeName() const { return _("style"); } void StyleSheet::validate(Version ver) { Packaged::validate(ver); if (!game) { - throw Error(_ERROR_("no game specified for stylesheet")); + throw Error(_ERROR_1_("no game specified",_TYPE_("stylesheet"))); } // a stylsheet depends on the game it is made for requireDependency(game.get()); diff --git a/src/gfx/image_effects.cpp b/src/gfx/image_effects.cpp index b0041799..1e3190ab 100644 --- a/src/gfx/image_effects.cpp +++ b/src/gfx/image_effects.cpp @@ -31,7 +31,7 @@ void saturate(Image& image, int amount) { } } -void desaturate(Image& image) { +void desaturate(Image& image/*, int amount*/) { Byte* pix = image.GetData(); Byte* end = pix + image.GetWidth() * image.GetHeight() * 3; while (pix != end) { diff --git a/src/gui/control/card_editor.cpp b/src/gui/control/card_editor.cpp index ae809caa..576be249 100644 --- a/src/gui/control/card_editor.cpp +++ b/src/gui/control/card_editor.cpp @@ -138,7 +138,7 @@ void DataEditor::createTabIndex() { by_tab_index.clear(); FOR_EACH(v, viewers) { ValueEditor* e = v->getEditor(); - if (e && v->getField()->editable && v->getStyle()->visible) { + if (e && v->getField()->editable && v->getStyle()->isVisible()) { by_tab_index.push_back(v.get()); } } diff --git a/src/gui/packages_window.cpp b/src/gui/packages_window.cpp index 7d7c94af..68a943c9 100644 --- a/src/gui/packages_window.cpp +++ b/src/gui/packages_window.cpp @@ -9,13 +9,14 @@ #include #include #include -//%#include +#include #include #include #include #include #include #include +#include #include #include #include @@ -111,6 +112,9 @@ class PackageUpdateList : public TreeList { item_height = max(item_height,17); rebuild(); } + ~PackageUpdateList() { + thumbnail_thread.abort(this); + } InstallablePackageP getSelection() const { return selection == NOTHING ? InstallablePackageP() : get(selection); @@ -130,10 +134,9 @@ class PackageUpdateList : public TreeList { private: PackagesWindow* parent; - class TreeItem; public: + class TreeItem; typedef intrusive_ptr TreeItemP; - private: class TreeItem : public Item { public: String label; @@ -147,6 +150,8 @@ class PackageUpdateList : public TreeList { }; }; +// ----------------------------------------------------------------------------- : PackageUpdateList::TreeItem + DECLARE_TYPEOF_COLLECTION(PackageUpdateList::TreeItemP); @@ -209,6 +214,80 @@ bool PackageUpdateList::TreeItem::highlight() const { return false; } +// ----------------------------------------------------------------------------- : PackageIconRequest + +/// wx doesn't allow seeking on InputStreams from a wxURL +/// The built in buffer class is too stupid to seek, so we must do it ourselfs +class SeekAtStartInputStream : public wxFilterInputStream { + public: + SeekAtStartInputStream(wxInputStream& stream) + : wxFilterInputStream(stream) + , buffer_pos(0) + { + m_parent_i_stream->Read(buffer, 1024); + buffer_size = m_parent_i_stream->LastRead(); + } + + bool IsSeekable() const { return true; } + protected: + virtual size_t OnSysRead(void *buffer, size_t bufsize) { + size_t len = min(buffer_size - buffer_pos, bufsize); + memcpy(buffer, this->buffer + buffer_pos, len); + buffer_pos += len; + m_parent_i_stream->Read((Byte*)buffer + len, bufsize - len); + return m_parent_i_stream->LastRead() + len; + } + virtual wxFileOffset OnSysSeek(wxFileOffset seek, wxSeekMode mode) { + if (mode == wxFromStart) buffer_pos = seek; + else if (mode == wxFromCurrent) buffer_pos += seek; + else assert(false); + assert(buffer_pos < buffer_size); + return buffer_pos; + } + virtual wxFileOffset OnSysTell() const { + assert(buffer_pos < buffer_size); + return buffer_pos; + } + private: + size_t buffer_size, buffer_pos; + Byte buffer[1024]; +}; + +class PackageIconRequest : public ThumbnailRequest { + public: + PackageIconRequest(PackageUpdateList* list, PackageUpdateList::TreeItem* ti) + : ThumbnailRequest( + list, + _("package_") + ti->package->description->icon_url + _("_") + ti->package->description->version.toString(), + wxDateTime(1,wxDateTime::Jan,2000)) + , list(list), ti(ti) + {} + + virtual Image generate() { + wxURL url(ti->package->description->icon_url); + scoped_ptr isP(url.GetInputStream()); + if (!isP) return wxImage(); + SeekAtStartInputStream is2(*isP); + Image result(is2); + return result; + } + virtual void store(const Image& image) { + if (!image.Ok()) return; + ti->package->description->icon = image; + Image resampled(16,16,false); + resample_preserve_aspect(image,resampled); + ti->icon = Bitmap(resampled); + desaturate(resampled); + set_alpha(resampled,0.5); + ti->icon_grey = Bitmap(resampled); + list->Refresh(false); + } + private: + PackageUpdateList* list; + PackageUpdateList::TreeItem* ti; +}; + +// ----------------------------------------------------------------------------- : PackageUpdateList : implementation void PackageUpdateList::initItems() { // packages to tree @@ -242,6 +321,10 @@ void PackageUpdateList::initItems() { desaturate(image); set_alpha(image, 0.5); ti.icon_grey = Bitmap(image); + if (p && !p->description->icon.Ok() && !p->description->icon_url.empty()) { + // download icon + thumbnail_thread.request(new_intrusive2(this,&ti)); + } } } @@ -367,7 +450,7 @@ END_EVENT_TABLE() // ----------------------------------------------------------------------------- : PackagesWindow PackagesWindow::PackagesWindow(Window* parent, bool download_package_list) - : wxDialog(parent, wxID_ANY, _TITLE_("package list"), wxDefaultPosition, wxSize(640,480), wxDEFAULT_DIALOG_STYLE | wxCLIP_CHILDREN | wxRESIZE_BORDER) + : wxDialog(parent, wxID_ANY, _TITLE_("packages window"), wxDefaultPosition, wxSize(640,480), wxDEFAULT_DIALOG_STYLE | wxCLIP_CHILDREN | wxRESIZE_BORDER) , where(is_install_local(settings.install_type) ? PACKAGE_LOCAL : PACKAGE_GLOBAL) , waiting_for_list(download_package_list) { diff --git a/src/gui/thumbnail_thread.hpp b/src/gui/thumbnail_thread.hpp index 7e63926a..0e2f4531 100644 --- a/src/gui/thumbnail_thread.hpp +++ b/src/gui/thumbnail_thread.hpp @@ -33,7 +33,7 @@ class ThumbnailRequest : public IntrusivePtrVirtualBase { virtual void store(const Image&) = 0; /// Can the thumbnail safely be generated from another thread? - virtual bool threadSafe() const = 0; + virtual bool threadSafe() const { return true; } /// Object that requested the thumbnail void* const owner; diff --git a/src/render/card/viewer.cpp b/src/render/card/viewer.cpp index a1d090a1..a10d7b07 100644 --- a/src/render/card/viewer.cpp +++ b/src/render/card/viewer.cpp @@ -44,7 +44,7 @@ void DataViewer::draw(RotatedDC& dc, const Color& background) { // prepare viewers bool changed_content_properties = false; FOR_EACH(v, viewers) { // draw low z index fields first - if (v->getStyle()->visible) { + if (v->getStyle()->isVisible()) { Rotater r(dc, v->getRotation()); try { if (v->prepare(dc)) { @@ -60,7 +60,7 @@ void DataViewer::draw(RotatedDC& dc, const Color& background) { } // draw viewers FOR_EACH(v, viewers) { // draw low z index fields first - if (v->getStyle()->visible) {// visible + if (v->getStyle()->isVisible()) {// visible Rotater r(dc, v->getRotation()); try { drawViewer(dc, *v); @@ -155,10 +155,7 @@ void DataViewer::setStyles(const StyleSheetP& stylesheet, IndexMap& styles) { FOR_EACH(s, styles) { - if ((s->visible || s->visible.isScripted()) && - (nativeLook() || ( - (s->width != -1 || s->width .isScripted() || s->right != -1 || s->right .isScripted()) && - (s->height != -1 || s->height .isScripted() || s->bottom != -1 || s->bottom.isScripted())))) { + if ((s->visible || s->visible.isScripted()) && (nativeLook() || s->hasSize())) { // no need to make a viewer for things that are always invisible ValueViewerP viewer = makeViewer(s); if (viewer) viewers.push_back(viewer); diff --git a/src/resource/common/expected_locale_keys b/src/resource/common/expected_locale_keys index dfb7f594..823edf1c 100644 --- a/src/resource/common/expected_locale_keys +++ b/src/resource/common/expected_locale_keys @@ -1,6 +1,6 @@ # This file contains the keys expected to be in MSE locales # It was automatically generated by tools/locale/locale.pl -# Generated on Mon Sep 24 22:07:59 2007 +# Generated on Sat Dec 29 23:09:36 2007 action: add control point: 0 @@ -42,9 +42,8 @@ button: add item: 0 always: 0 browse: 0 - check updates: 0 check now: 0 - close: 0 + check updates: 0 defaults: 0 edit symbol: 0 enabled: 0 @@ -52,6 +51,7 @@ button: high quality: 0 if internet connection exists: 0 insert parameter: 0 + install package: 0 keep old: 0 last opened set: 0 move down: 0 @@ -64,6 +64,7 @@ button: overwrite: 0 refer parameter: 0 remove item: 0 + remove package: 0 select: optional, 0 select all: 0 select none: 0 @@ -71,6 +72,7 @@ button: show editing hints: 0 show lines: 0 symbol gallery: optional, 0 + upgrade package: 0 use auto replace: 0 use custom styling options: 0 use for all cards: 0 @@ -80,11 +82,13 @@ error: aborting parsing: 0 can't convert: 2 can't convert value: 3 - checking updates: 0 + can't download installer: 2 + cannot create file: 1 checking updates failed: 0 coordinates for blending overlap: 0 dependency not given: 4 dimension not found: 1 + downloading updates: 0 expected key: 1 file not found: 2 file not found package like: 2 @@ -94,10 +98,10 @@ error: images used for blending must have the same size: 0 in function: 2 in parameter: 2 + installing updates: 0 internal error: 1 newer version: 2 - no game specified for the set: 0 - no packages: 0 + no game specified: 1 no stylesheet specified for the set: 0 no updates: 0 package not found: 1 @@ -252,13 +256,24 @@ label: game type: 0 html export options: 0 html template: 0 + install package: 0 keyword: 0 language: 0 + magic set editor package: optional, 0 match: 0 mode: 0 original: 0 + package action: 0 + package conflicts: 0 + package installable: 0 + package installed: 0 + package modified: 0 + package name: 0 + package status: 0 + package updates: 0 percent of normal: 0 reminder: 0 + remove package: 0 result: 0 save changes: 1 select cards print: 0 @@ -271,20 +286,17 @@ label: style type: 0 stylesheet not found: 1 styling options: 0 + upgrade package: 0 uses: 0 zoom: 0 - package name: 0 - package status: 0 menu: about: 0 add card: 0 add cards: 0 add keyword: 0 - apply changes: 0 auto replace: 0 basic shapes: 0 bold: 0 - cancel changes: 0 card list columns: 0 cards: 0 cards tab: 0 @@ -310,7 +322,6 @@ menu: help: 0 index: 0 insert symbol: 0 - install package: 0 italic: 0 keywords: 0 keywords tab: 0 @@ -335,7 +346,6 @@ menu: reminder text: 0 remove card: 0 remove keyword: 0 - remove package: 0 replace: 0 rotate: 0 rotate 0: 0 @@ -356,28 +366,25 @@ menu: tool: 0 undo: 1 ungroup: 0 - upgrade package: 0 website: 0 window: 0 title: %s - magic set editor: 1 about: 0 auto replaces: 0 + cannot create file: 0 directories: 0 display: 0 export cancelled: 0 export html: 0 export images: 0 global: 0 + installing updates: 0 locate apprentice: 0 magic set editor: 0 new set: 0 - new status: 0 open set: 0 - package list: 0 - package name: 0 - package status: 0 - package type: 0 + packages window: 0 preferences: 0 print preview: 0 save changes: 0 @@ -393,7 +400,6 @@ title: untitled: 0 update check: 0 updates: 0 - updates available: 0 tool: add symmetry: 0 basic shapes: 0 @@ -491,19 +497,16 @@ type: collection: 0 collection of: 1 color: 0 - do nothing: 0 double: 0 ellipse: 0 + export template: 0 field: 0 function: 0 game: 0 group: 0 hexagon: 0 image: 0 - install: 0 - installed: 0 integer: 0 - new mse: 0 nil: 0 object: 0 pentagon: 0 @@ -523,8 +526,4 @@ type: style: 0 stylesheet: 0 triangle: 0 - uninstall: 0 - uninstalled: 0 - upgrade: 0 - upgradeable: 0 value: 0 diff --git a/src/resource/common/installer_package.png b/src/resource/common/installer_package.png index efd0a4f3bc32450dd5a80c62a051bd02a5c2b181..83704cbdabe7f0f6e359786c5f8f6dc0c2de90ce 100644 GIT binary patch delta 628 zcmV-)0*n351F8j(83+ad00C(9&-albEPnz=NklCMkDdklt>^biQ)zCiY6u|B$|i;!Jrt41OpNQMOxbel~%-1X`vJ0j9V(w<;Ai>9_|;{n4ws`~QSp2)O~#($KO;Gee9K_q%c35UMh;|}HC0tNT28o`xUCad zO*El7cI3?PUNeQf_kxUy77QNTl?Qp^=KaS%<^+9%#yfpG@>DE{O7dSZEq^`RDHIBD z90z@aN$q2dIm|5qs_PHJ&&1F_^jjCuIK#unNyz$X