Commit 5513c521 authored by twanvl's avatar twanvl

Added icon for MSE in packages window;

Added resample(image,width,height), instead of always passing in images
parent b8a1c609
......@@ -15,7 +15,7 @@
#include <data/export_template.hpp>
#include <util/io/package_manager.hpp>
#include <util/platform.hpp>
#include <script/to_value.hpp>
#include <gui/util.hpp> // load_resource_image
#include <wx/filename.h>
#include <wx/wfstream.h>
#include <wx/zipstrm.h>
......@@ -195,10 +195,20 @@ PackageDescription::PackageDescription(const Packaged& package)
if (full_name.empty()) full_name = short_name;
// installer group
if (installer_group.empty()) {
// "game-style.mse-something" -> "game/style" -> "game"
installer_group = replace_all(package.name(),_("-"),_("/"));
size_t pos = installer_group.find_last_of(_('/'));
// "game-style.mse-something" -> "game/style_short_name"
installer_group = package.name();
size_t pos = installer_group.find_last_of(_('-'));
if (pos != String::npos) installer_group.resize(pos);
if (!installer_group.empty()) {
installer_group = _("unclassified/") + replace_all(installer_group,_("-"),_("/")) + _("/");
} else {
installer_group = _("unclassified/");
}
if (dynamic_cast<const Game*>(&package)) {
installer_group += _("Game files");
} else {
installer_group += short_name;
}
}
// icon
InputStreamP file = const_cast<Packaged&>(package).openIconFile();
......@@ -219,6 +229,9 @@ IMPLEMENT_REFLECTION_NO_SCRIPT(PackageDescription) {
void PackageDescription::merge(const PackageDescription& p2) {
if (!icon.Ok() && !icon_url) icon = p2.icon;
if (installer_group.empty()) installer_group = p2.installer_group;
if (short_name.empty()) short_name = p2.short_name;
if (full_name.empty()) full_name = p2.full_name;
}
IMPLEMENT_REFLECTION_NO_SCRIPT(InstallerDescription) {
......@@ -454,9 +467,10 @@ InstallablePackageP mse_installable_package() {
mse_version->version = app_version;
PackageDescriptionP mse_description(new PackageDescription);
mse_description->name = mse_package;
mse_description->short_name = mse_description->full_name = _TITLE_("magic set editor");
mse_description->short_name = mse_description->full_name = mse_description->installer_group
= _TITLE_("magic set editor");
mse_description->position_hint = -100;
//mse_description->icon = load_resource_image(_("mse_icon"));
mse_description->icon = load_resource_image(_("installer_program"));
//mse_description->description = _LABEL_("magic set editor package");
return new_intrusive2<InstallablePackage>(mse_version,mse_description);
}
......@@ -99,6 +99,7 @@ enum PackageStatus
, PACKAGE_INSTALLABLE = 0x0110 ///< Package can be installed (it makes sense to do so)
, PACKAGE_UPDATES = 0x0111 ///< Remote updates available
, PACKAGE_MODIFIED = 0x1001 ///< Local changes made
, PACKAGE_MISSING_DEP = 0x0200 ///< Missing a dependency for installation
, PACKAGE_CONFLICTS = PACKAGE_UPDATES | PACKAGE_MODIFIED
};
......
......@@ -31,24 +31,18 @@ Image conform_image(const Image& img, const GeneratedImage::Options& options) {
if ((iw == options.width && ih == options.height) || (options.width == 0 && options.height == 0)) {
// zoom?
if (options.zoom != 1.0) {
Image resampled_image(iw * options.zoom, ih * options.zoom, false);
resample(image, resampled_image);
image = resampled_image;
image = resample(image, iw * options.zoom, ih * options.zoom);
} else {
// already the right size
}
} else if (options.height == 0) {
// width is given, determine height
int h = options.width * ih / iw;
Image resampled_image(options.width, h, false);
resample(image, resampled_image);
image = resampled_image;
image = resample(image, options.width, h);
} else if (options.width == 0) {
// height is given, determine width
int w = options.height * iw / ih;
Image resampled_image(w, options.height, false);
resample(image, resampled_image);
image = resampled_image;
image = resample(image, w, options.height);
} else if (options.preserve_aspect == ASPECT_FIT) {
// determine actual size of resulting image
int w, h;
......@@ -59,18 +53,14 @@ Image conform_image(const Image& img, const GeneratedImage::Options& options) {
w = options.height * iw / ih;
h = options.height;
}
Image resampled_image(w, h, false);
resample(image, resampled_image);
image = resampled_image;
image = resample(image, w, h);
} else {
Image resampled_image(options.width, options.height, false);
if (options.preserve_aspect == ASPECT_BORDER && (options.width < options.height * 3) && (options.height < options.width * 3)) {
// preserve the aspect ratio if there is not too much difference
resample_preserve_aspect(image, resampled_image);
image = resample_preserve_aspect(image, options.width, options.height);
} else {
resample(image, resampled_image);
image = resample(image, options.width, options.height);
}
image = resampled_image;
}
// saturate?
if (options.saturate) {
......
......@@ -21,6 +21,7 @@
/// Resample (resize) an image, uses bilenear filtering
void resample(const Image& img_in, Image& img_out);
Image resample(const Image& img_in, int width, int height);
/// Resamples an image, first clips the input image to a specified rectangle
/** The selected rectangle is resampled into the entire output image */
......@@ -35,6 +36,7 @@ enum PreserveAspect
/// Resample an image, but preserve the aspect ratio by adding a transparent border around the output if needed.
void resample_preserve_aspect(const Image& img_in, Image& img_out);
Image resample_preserve_aspect(const Image& img_in, int width, int height);
/// Resample an image to create a sharp result by applying a sharpening filter
/** Amount must be between 0 and 100 */
......
......@@ -125,6 +125,15 @@ void resample_pass(const Image& img_in, Image& img_out, int offset_in, int offse
void resample(const Image& img_in, Image& img_out) {
resample_and_clip(img_in, img_out, wxRect(0, 0, img_in.GetWidth(), img_in.GetHeight()));
}
Image resample(const Image& img_in, int width, int height) {
if (img_in.GetWidth() == width && img_in.GetHeight() == height) {
return img_in; // already the right size
} else {
Image img_out(width,height,false);
resample(img_in, img_out);
return img_out;
}
}
void resample_and_clip(const Image& img_in, Image& img_out, wxRect rect) {
// mask to alpha
......@@ -171,6 +180,16 @@ void resample_preserve_aspect(const Image& img_in, Image& img_out) {
resample_pass(img_temp, img_out, 0, offset_out, img_in.GetHeight(), img_temp.GetWidth(), rheight, img_out.GetWidth(), rwidth, 1, 1);
}
Image resample_preserve_aspect(const Image& img_in, int width, int height) {
if (img_in.GetWidth() == width && img_in.GetHeight() == height) {
return img_in; // already the right size
} else {
Image img_out(width,height,false);
resample_preserve_aspect(img_in, img_out);
return img_out;
}
}
// ----------------------------------------------------------------------------- : Sharpening
void sharp_downsample(const Image& img_in, Image& img_out, int amount);
......
......@@ -65,9 +65,7 @@ class CardThumbnailRequest : public ThumbnailRequest {
if (image.LoadFile(*parent->set->openIn(filename))) {
// two step anti aliased resampling
image.Rescale(36, 28); // step 1: no anti aliassing
Image image2(18, 14, false); // step 2: with anti aliassing
resample(image, image2);
return image2;
return resample(image, 18, 14); // step 2: with anti aliassing
} else {
return Image();
}
......
......@@ -541,8 +541,7 @@ void ImageSliceSelector::createBitmap() {
// create image, resampled to fit in control
wxSize s = GetClientSize();
int width = s.GetWidth() - 2*border, height = s.GetHeight() - 2*border;
Image img(width, height, false);
resample(slice.source, img);
Image img = resample(slice.source, width, height);
bitmap = Bitmap(img);
scaleX = (double)width / slice.source.GetWidth();
scaleY = (double)height / slice.source.GetHeight();
......
......@@ -139,14 +139,31 @@ class PackageUpdateList : public TreeList {
typedef intrusive_ptr<TreeItem> TreeItemP;
class TreeItem : public Item {
public:
TreeItem() : position_type(TYPE_OTHER), position_hint(1000000) {}
String label;
vector<TreeItemP> children;
InstallablePackageP package;
Bitmap icon, icon_grey;
// positioning
enum PackageType {
TYPE_PROG,
TYPE_LOCALE,
TYPE_GAME,
TYPE_STYLESHEET,
TYPE_EXPORT_TEMPLATE,
TYPE_SYMBOL_FONT,
TYPE_INCLUDE,
TYPE_FONT,
TYPE_OTHER,
} position_type;
int position_hint;
void add(const InstallablePackageP& package, const String& path, int level = -1);
void toItems(vector<TreeList::ItemP>& items);
void setIcon(const Image& image);
bool highlight() const;
static PackageType package_type(const PackageDescription& desc);
};
};
......@@ -156,6 +173,22 @@ DECLARE_TYPEOF_COLLECTION(PackageUpdateList::TreeItemP);
void PackageUpdateList::TreeItem::add(const InstallablePackageP& package, const String& path, int level) {
// this node
this->level = level;
PackageType new_type = package_type(*package->description);
int new_hint = package->description->position_hint;
if (new_type < position_type || (new_type == position_type && new_hint < position_hint)) {
// this is a lower position hint, use it
position_type = new_type;
position_hint = new_hint;
}
// end of the path?
if (path.empty()) {
assert(!this->package);
this->package = package;
return;
}
// split path
size_t pos = path.find_first_of(_('/'));
String name = path.substr(0,pos);
String rest = pos == String::npos ? _("") : path.substr(pos+1);
......@@ -163,17 +196,12 @@ void PackageUpdateList::TreeItem::add(const InstallablePackageP& package, const
FOR_EACH(ti, children) {
if (ti->label == name) {
// already have this child
if (pos == String::npos) {
if (ti->package) {
// two packages with the same path
TreeItemP ti2(new TreeItem);
ti2->level = level + 1;
ti2->label = name;
ti2->package = package;
children.insert(ti_IT.first, ti2);
} else {
ti->package = package;
}
if (pos == String::npos && ti->package) {
// two packages with the same path
TreeItemP ti2(new TreeItem);
ti2->label = name;
children.insert(ti_IT.first, ti2);
ti2->add(package, rest, level + 1);
} else {
ti->add(package, rest, level + 1);
}
......@@ -183,20 +211,15 @@ void PackageUpdateList::TreeItem::add(const InstallablePackageP& package, const
// don't have this child
TreeItemP ti(new TreeItem);
children.push_back(ti);
ti->level = level + 1;
ti->label = name;
if (pos == String::npos) {
ti->package = package;
} else {
ti->add(package, rest, level + 1);
}
ti->add(package, rest, level + 1);
}
bool compare_pos_hint(const PackageUpdateList::TreeItemP& a, const PackageUpdateList::TreeItemP& b) {
int pa = a->package ? a->package->description->position_hint : 0;
int pb = b->package ? b->package->description->position_hint : 0;
if (pa < pb) return true;
if (pa > pb) return false;
if (a->position_type < b->position_type) return true;
if (a->position_type > b->position_type) return false;
if (a->position_hint < b->position_hint) return true;
if (a->position_hint > b->position_hint) return false;
return a->label < b->label;
}
......@@ -214,6 +237,38 @@ bool PackageUpdateList::TreeItem::highlight() const {
return false;
}
PackageUpdateList::TreeItem::PackageType PackageUpdateList::TreeItem::package_type(const PackageDescription& desc) {
if (desc.name == mse_package) return TYPE_PROG;
size_t pos = desc.name.find_last_of(_('.'));
if (pos == String::npos) return TYPE_OTHER;
if (is_substr(desc.name,pos,_(".mse-locale"))) return TYPE_LOCALE;
if (is_substr(desc.name,pos,_(".mse-game"))) return TYPE_GAME;
if (is_substr(desc.name,pos,_(".mse-style"))) return TYPE_STYLESHEET;
if (is_substr(desc.name,pos,_(".mse-export-template"))) return TYPE_EXPORT_TEMPLATE;
if (is_substr(desc.name,pos,_(".mse-symbol-font"))) return TYPE_SYMBOL_FONT;
if (is_substr(desc.name,pos,_(".mse-include"))) return TYPE_INCLUDE;
if (is_substr(desc.name,pos,_(".ttf"))) return TYPE_FONT;
return TYPE_OTHER;
}
void PackageUpdateList::TreeItem::setIcon(const Image& img) {
Image image = img;
int iw = image.GetWidth(), ih = image.GetHeight();
if (ih > 107) {
int w = 107 * iw / ih;
image = resample(image, w, 107);
} else if (iw > 107) {
int h = 107 * ih / iw;
image = resample(image, 107, h);
}
if (package) package->description->icon = image;
Image resampled = resample_preserve_aspect(image,16,16);
icon = Bitmap(resampled);
saturate(resampled, -.75);
set_alpha(resampled,0.5);
icon_grey = Bitmap(resampled);
}
// ----------------------------------------------------------------------------- : PackageIconRequest
/// wx doesn't allow seeking on InputStreams from a wxURL
......@@ -273,13 +328,7 @@ class PackageIconRequest : public ThumbnailRequest {
}
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);
saturate(resampled, -.75);
set_alpha(resampled,0.5);
ti->icon_grey = Bitmap(resampled);
ti->setIcon(image);
list->Refresh(false);
}
private:
......@@ -294,8 +343,7 @@ void PackageUpdateList::initItems() {
TreeItem root;
FOR_EACH(ip, parent->installable_packages) {
String group = ip->description->installer_group;
if (!group.empty()) group += _("/");
group += ip->description->short_name;
if (group.empty()) group = _("custom");
root.add(ip, group);
}
// tree to treelist items
......@@ -307,23 +355,17 @@ void PackageUpdateList::initItems() {
const InstallablePackageP& p = ti.package;
Image image;
if (p && p->description->icon.Ok()) {
Image resampled(16,16,false);
resample_preserve_aspect(p->description->icon, resampled);
image = resampled;
ti.setIcon(p->description->icon);
} else if (p) {
image = load_resource_image(_("installer_package"));
} else if (ti.label == _("locales")) {
image = load_resource_image(_("installer_locales"));
ti.setIcon(load_resource_image(_("installer_package")));
if (!p->description->icon_url.empty()) {
// download icon
thumbnail_thread.request(new_intrusive2<PackageIconRequest>(this,&ti));
}
} else if (ti.position_type == TreeItem::TYPE_LOCALE) {
ti.setIcon(load_resource_image(_("installer_locales")));
} else {
image = load_resource_image(_("installer_group"));
}
ti.icon = Bitmap(image);
saturate(image, -.75);
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<PackageIconRequest>(this,&ti));
ti.setIcon(load_resource_image(_("installer_group")));
}
}
}
......@@ -336,7 +378,7 @@ void PackageUpdateList::drawItem(DC& dc, size_t index, size_t column, int x, int
const Bitmap& bmp = ti.highlight() ? ti.icon : ti.icon_grey;
if (bmp.Ok()) dc.DrawBitmap(bmp,x,y);
dc.SetTextForeground(color);
dc.DrawText(ti.label, x+18, y+2);
dc.DrawText(capitalize_sentence(ti.label), x+18, y+2);
} else if (column == 1 && ti.package) {
// Status
int stat = ti.package->status;
......
......@@ -77,9 +77,9 @@ void StatCategoryList::drawItem(DC& dc, int x, int y, size_t item, bool selected
if (!cat.icon_filename.empty() && !cat.icon.Ok()) {
InputStreamP file = game->openIn(cat.icon_filename);
Image img(*file);
Image resampled(21, 21);
resample_preserve_aspect(img, resampled);
if (img.Ok()) cat.icon = Bitmap(resampled);
if (img.Ok()) {
cat.icon = Bitmap(resample_preserve_aspect(img, 21, 21));
}
}
if (cat.icon.Ok()) {
dc.DrawBitmap(cat.icon, x+1, y+1);
......
......@@ -129,9 +129,7 @@ void ImageValueViewer::loadMask(const Rotation& rot) const {
Image image;
InputStreamP image_file = viewer.stylesheet->openIn(style().mask_filename);
if (image.LoadFile(*image_file)) {
Image resampled(w,h);
resample(image, resampled);
alpha_mask = new_intrusive1<AlphaMask>(resampled);
alpha_mask = new_intrusive1<AlphaMask>(resample(image,w,h));
}
}
......
......@@ -38,9 +38,7 @@ void PackageChoiceValueViewer::initItems() {
Image image;
InputStreamP stream = p->openIconFile();
if (stream && image.LoadFile(*stream)) {
Image resampled(16,16,false);
resample(image, resampled);
i.image = Bitmap(resampled);
i.image = Bitmap(resample(image, 16,16));
}
items.push_back(i);
}
......
......@@ -172,6 +172,7 @@ edit_symbol IMAGE "../common/edit_symbol.png"
installer_group IMAGE "../common/installer_group.png"
installer_package IMAGE "../common/installer_package.png"
installer_locales IMAGE "../common/installer_locales.png"
installer_program IMAGE "../common/installer_program.png"
//installer_font IMAGE "../common/installer_font.png"
// -------------------------------------------------------- : WX
......
......@@ -155,7 +155,7 @@ String capitalize(const String& s) {
}
String capitalize_sentence(const String& s) {
String ret = s.Lower();
String ret = s;//.Lower();
if (!ret.empty()) {
ret[0] = toUpper(ret[0]);
}
......
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