From e42f33570c872225232cea878b7540009245b11a Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Wed, 31 Jul 2013 09:33:11 -0700 Subject: ScaledImage class for oversized assets ScaledImage takes an asset resource path and a constraint (horizontal or vertical) and resizes the asset to fit the constraint. [endlessm/eos-sdk#188] --- .../src/endless_wikipedia/PrebuiltCategoryPage.js | 19 ++- wikipedia/src/scaled_image.js | 159 +++++++++++++++++++++ 2 files changed, 171 insertions(+), 7 deletions(-) create mode 100644 wikipedia/src/scaled_image.js (limited to 'wikipedia') diff --git a/wikipedia/src/endless_wikipedia/PrebuiltCategoryPage.js b/wikipedia/src/endless_wikipedia/PrebuiltCategoryPage.js index f46ca2a..754c038 100644 --- a/wikipedia/src/endless_wikipedia/PrebuiltCategoryPage.js +++ b/wikipedia/src/endless_wikipedia/PrebuiltCategoryPage.js @@ -4,6 +4,7 @@ const Gtk = imports.gi.Gtk; const Lang = imports.lang; const EndlessWikipedia = imports.endless_wikipedia.EndlessWikipedia; +const ScaledImage = imports.scaled_image; GObject.ParamFlags.READWRITE = GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE; @@ -67,17 +68,21 @@ const PrebuiltCategoryPage = new Lang.Class({ vexpand: false }); - this._submenu_separator = new Gtk.Image({ - halign:Gtk.Align.END, - resource: "/com/endlessm/brazil/assets/submenu_separator_shadow_a.png" + this._submenu_separator = new ScaledImage.ScaledImage({ + resource: "/com/endlessm/brazil/assets/submenu_separator_shadow_a.png", + constraint: Gtk.Orientation.VERTICAL, + halign: Gtk.Align.END }); - this._splash_separator = new Gtk.Image({ - resource: "/com/endlessm/brazil/assets/category_splash_separator_shadow.png" + this._splash_separator = new ScaledImage.ScaledImage({ + resource: "/com/endlessm/brazil/assets/category_splash_separator_shadow.png", + constraint: Gtk.Orientation.VERTICAL, + halign: Gtk.Align.END }); - this._description_separator = new Gtk.Image({ - resource: "/com/endlessm/brazil/assets/introduction_title_separator.png" + this._description_separator = new ScaledImage.ScaledImage({ + resource: "/com/endlessm/brazil/assets/introduction_title_separator.png", + constraint: Gtk.Orientation.HORIZONTAL }); this._description_label = new Gtk.Label({ diff --git a/wikipedia/src/scaled_image.js b/wikipedia/src/scaled_image.js new file mode 100644 index 0000000..7d25b7f --- /dev/null +++ b/wikipedia/src/scaled_image.js @@ -0,0 +1,159 @@ +const Format = imports.format; +const GdkPixbuf = imports.gi.GdkPixbuf; +const GObject = imports.gi.GObject; +const Gtk = imports.gi.Gtk; +const Lang = imports.lang; + +String.prototype.format = Format.format; +GObject.ParamFlags.READWRITE = GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE; + +const BACKGROUND_CSS_TEMPLATE = "\ +Gjs_ScaledImage {\n\ + background-image: url('resource://%s');\n\ + background-size: %s;\n\ + background-position: %s %s;\n\ + background-repeat: no-repeat;\n\ +}"; + +const ScaledImage = new Lang.Class({ + Name: 'ScaledImage', + Extends: Gtk.EventBox, + Properties: { + 'constraint': GObject.ParamSpec.enum('constraint', + 'Constraint direction', + 'Orientation in which the size of the image should be constrained', + GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT, + Gtk.Orientation, Gtk.Orientation.HORIZONTAL), + 'resource': GObject.ParamSpec.string('resource', + 'Resource path', + 'Resource path for the image', + GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT, + '') + }, + + _init: function(props) { + this._constraint = null; + this._resource_path = null; + this._pixbuf = null; + this._css_provider = null; + this.parent(props); + }, + + // OVERRIDES + + vfunc_get_request_mode: function() { + if(this._constraint == Gtk.Orientation.HORIZONTAL) + return Gtk.SizeRequestMode.HEIGHT_FOR_WIDTH; + return Gtk.SizeRequestMode.WIDTH_FOR_HEIGHT; + }, + + vfunc_get_preferred_width_for_height: function(height) { + if(!this._pixbuf) + return this.parent(height); + let source_width = this._pixbuf.width; + let source_height = this._pixbuf.height; + let width = (height / source_height) * source_width; + return [width, width]; + }, + + vfunc_get_preferred_height_for_width: function(width) { + if(!this._pixbuf) + return this.parent(height); + let source_width = this._pixbuf.width; + let source_height = this._pixbuf.height; + let height = (width / source_width) * source_height; + return [height, height]; + }, + + vfunc_size_allocate: function(allocation) { + if(this._constraint == Gtk.Orientation.VERTICAL + && this.valign != Gtk.Align.FILL) { + printerr("ScaledImage Warning: Setting constraint to VERTICAL and\ + valign to anything but FILL makes no sense"); + this.valign = Gtk.Align.FILL; + } + if(this._constraint == Gtk.Orientation.HORIZONTAL + && this.halign != Gtk.Align.FILL) { + printerr("ScaledImage Warning: Setting constraint to HORIZONTAL and\ + halign to anything but FILL makes no sense"); + this.halign = Gtk.Align.FILL; + } + this.parent(allocation); + }, + + // PROPERTIES + + get constraint() { + return this._constraint; + }, + + set constraint(value) { + this._constraint = value; + }, + + get resource() { + return this._resource_path; + }, + + set resource(value) { + this._resource_path = value; + this._pixbuf = GdkPixbuf.Pixbuf.new_from_resource(this._resource_path); + this._updateImage(); + }, + + // PRIVATE + + _gtk_align_to_css_align: function(align, orientation) { + switch(align) { + case Gtk.Align.START: + if(orientation == Gtk.Orientation.VERTICAL) + return "top"; + return "left"; + case Gtk.Align.END: + if(orientation == Gtk.Orientation.VERTICAL) + return "bottom"; + return "right"; + } + return "center"; + }, + + _updateImage: function() { + if(this._resource_path === null) + return; + + let context = this.get_style_context(); + + if(this._css_provider !== null) + context.remove_provider(this._css_provider); + + let scaling; + if(this._constraint == Gtk.Orientation.HORIZONTAL) + scaling = "100% auto"; + else + scaling = "auto 100%"; + + let css = BACKGROUND_CSS_TEMPLATE.format(this._resource_path, scaling, + this._gtk_align_to_css_align(this.valign, Gtk.Orientation.VERTICAL), + this._gtk_align_to_css_align(this.halign, + Gtk.Orientation.HORIZONTAL)); + this._css_provider = new Gtk.CssProvider(); + this._css_provider.load_from_data(css); + context.add_provider(this._css_provider, + Gtk.STYLE_PROVIDER_PRIORITY_USER); + } +}); + +// const Gio = imports.gi.Gio; +// Gtk.init(null); +// let resource = Gio.Resource.load('data/endless_brazil.gresource'); +// resource._register(); +// let w = new Gtk.Window(); +// let i = new ScaledImage({ +// resource: '/com/endlessm/brazil/category_images/cuisine.jpg', +// constraint: Gtk.Orientation.HORIZONTAL, +// valign: Gtk.Align.END, +// }); +// w.add(i); +// w.connect('destroy', Gtk.main_quit); +// w.show_all(); +// Gtk.main(); -- cgit v1.2.3