summaryrefslogtreecommitdiff
path: root/wikipedia/widgets
diff options
context:
space:
mode:
authorRory MacQueen <rorymacqueen@gmail.com>2013-08-15 15:41:36 -0700
committerRory MacQueen <rorymacqueen@gmail.com>2013-08-15 15:41:36 -0700
commitfd81565c5527b99dd212b03c2f329a00e146f03b (patch)
tree7f3afa3eaf6258d34e98abf611f79cbfdb417ecf /wikipedia/widgets
parent544c137fc8524c5929c7672768775763ea10d848 (diff)
Reorganized import paths
Moved all widgets into widgets directory. Changed Endless Wikipedia file to expose wikipedia web view [endlessm/eos-sdk#260]
Diffstat (limited to 'wikipedia/widgets')
-rw-r--r--wikipedia/widgets/BackButton.js18
-rw-r--r--wikipedia/widgets/BoxWithBg.js19
-rw-r--r--wikipedia/widgets/SideBarButton.js39
-rw-r--r--wikipedia/widgets/TextButton.js58
-rw-r--r--wikipedia/widgets/category_button.js146
-rw-r--r--wikipedia/widgets/category_layout_manager.js65
-rw-r--r--wikipedia/widgets/category_selector_view.js43
-rw-r--r--wikipedia/widgets/scaled_image.js159
-rw-r--r--wikipedia/widgets/title_label_view.js95
9 files changed, 642 insertions, 0 deletions
diff --git a/wikipedia/widgets/BackButton.js b/wikipedia/widgets/BackButton.js
new file mode 100644
index 0000000..cfb3155
--- /dev/null
+++ b/wikipedia/widgets/BackButton.js
@@ -0,0 +1,18 @@
+const GObject = imports.gi.GObject;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+
+const BackButton = new Lang.Class({
+ Name: 'BackButton',
+ Extends: Gtk.Button,
+
+ _init: function(props) {
+ props = props || {};
+ props.image = Gtk.Image.new_from_icon_name('go-previous-symbolic',
+ Gtk.IconSize.BUTTON);
+ props.always_show_image = true;
+ // Don't do that. What should actually happen is the system-wide setting
+ // that controls whether buttons show images should be changed.
+ this.parent(props);
+ }
+});
diff --git a/wikipedia/widgets/BoxWithBg.js b/wikipedia/widgets/BoxWithBg.js
new file mode 100644
index 0000000..1ae9404
--- /dev/null
+++ b/wikipedia/widgets/BoxWithBg.js
@@ -0,0 +1,19 @@
+const GObject = imports.gi.GObject;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+
+const BoxWithBg = new Lang.Class({
+ Name: "BoxWithBg",
+ Extends: Gtk.Box,
+
+ vfunc_draw: function(cairoContext) {
+ let width = this.get_allocated_width();
+ let height = this.get_allocated_height();
+ let context = this.get_style_context();
+ Gtk.render_background(context, cairoContext, 0, 0, width, height);
+ Gtk.render_frame(context, cairoContext, 0, 0, width, height);
+
+ return this.parent(cairoContext);
+ }
+});
+
diff --git a/wikipedia/widgets/SideBarButton.js b/wikipedia/widgets/SideBarButton.js
new file mode 100644
index 0000000..b602d6c
--- /dev/null
+++ b/wikipedia/widgets/SideBarButton.js
@@ -0,0 +1,39 @@
+const Lang = imports.lang;
+const Gdk = imports.gi.Gdk;
+const GdkPixbuf = imports.gi.GdkPixbuf;
+const Gtk = imports.gi.Gtk;
+
+const SideBarButton = new Lang.Class({
+ Name: 'EndlessSideBarButton',
+ Extends: Gtk.Button,
+
+ // This is a button for the article list widget. It has a label and an icon image.
+ // The icon image will only appear on hover or press of button
+ _init: function(hover_icon_path, params) {
+ this.parent(params);
+
+ this.set_size_request(40, -1);
+
+ this._image = new Gtk.Image({
+ resource: hover_icon_path,
+ no_show_all: true
+ });
+
+ this.add(this._image);
+
+ this.connect('state-changed', Lang.bind(this, this._update_appearance));
+ },
+
+ _update_appearance: function(widget, state) {
+ // If button is hovered over and/or pressed, then show the arrow icon
+ if (widget.get_state_flags() & Gtk.StateFlags.ACTIVE ||
+ widget.get_state_flags() & Gtk.StateFlags.PRELIGHT) {
+ this._image.show();
+ return false; // don't block event
+ }
+ // If no hover or press, then hide the arrow icon
+ this._image.hide();
+ return false; // don't block event
+ }
+});
+
diff --git a/wikipedia/widgets/TextButton.js b/wikipedia/widgets/TextButton.js
new file mode 100644
index 0000000..834826f
--- /dev/null
+++ b/wikipedia/widgets/TextButton.js
@@ -0,0 +1,58 @@
+const Lang = imports.lang;
+const Gdk = imports.gi.Gdk;
+const GdkPixbuf = imports.gi.GdkPixbuf;
+const Gtk = imports.gi.Gtk;
+const Pango = imports.gi.Pango;
+
+// This is an approximate number of characters that will keep the label from
+// going over its specified width
+const ARTICLE_LABEL_MAX_WIDTH_CHARS = 24;
+
+const TextButton = new Lang.Class({
+ Name: 'EndlessTextButton',
+ Extends: Gtk.Button,
+
+ // This is a button for the article list widget. It has a label and an icon image.
+ // The icon image will only appear on hover or press of button
+ _init: function(hover_icon_path, label_text, params) {
+ params.hexpand = true;
+ this.parent(params);
+
+ this._hover_icon_pixbuf = GdkPixbuf.Pixbuf.new_from_resource(hover_icon_path);
+
+ this._image = new Gtk.Image({
+ no_show_all: true
+ });
+ this._image.set_from_pixbuf(this._hover_icon_pixbuf);
+
+ this._box = new Gtk.Box({
+ orientation: Gtk.Orientation.HORIZONTAL
+ });
+
+ this._label = new Gtk.Label({
+ label: label_text.toUpperCase(),
+ max_width_chars: ARTICLE_LABEL_MAX_WIDTH_CHARS,
+ ellipsize: Pango.EllipsizeMode.END
+ });
+
+ this._box.pack_start(this._label, false, false, 0);
+ this._box.pack_end(this._image, false, false, 0);
+
+ this.add(this._box);
+ this.connect('state-changed', Lang.bind(this, this._update_appearance));
+ this.show_all();
+ },
+
+ _update_appearance: function(widget, state) {
+ // If button is hovered over and/or pressed, then show the arrow icon
+ if (widget.get_state_flags() & Gtk.StateFlags.ACTIVE ||
+ widget.get_state_flags() & Gtk.StateFlags.PRELIGHT) {
+ this._image.show();
+ return false;
+ }
+ // If no hover or press, then hide the arrow icon
+ this._image.hide();
+ return false;
+ }
+});
+
diff --git a/wikipedia/widgets/category_button.js b/wikipedia/widgets/category_button.js
new file mode 100644
index 0000000..77812f1
--- /dev/null
+++ b/wikipedia/widgets/category_button.js
@@ -0,0 +1,146 @@
+const Gdk = imports.gi.Gdk;
+const GdkPixbuf = imports.gi.GdkPixbuf;
+const GObject = imports.gi.GObject;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+
+const Utils = imports.wikipedia.utils;
+
+const CATEGORY_LABEL_LEFT_MARGIN = 25; // pixels
+const CATEGORY_LABEL_BOTTOM_MARGIN = 20; // pixels
+const CATEGORY_BUTTON_RIGHT_MARGIN = 20; // pixels
+const CATEGORY_BUTTON_BOTTOM_MARGIN = 20; // pixels
+const CATEGORY_LABEL_BENTON_SANS_CORRECTION = 0; // pixels
+const _HOVER_ARROW_URI = '/com/endlessm/wikipedia-domain/assets/category_hover_arrow.png';
+
+GObject.ParamFlags.READWRITE = GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE;
+
+const CategoryButton = new Lang.Class({
+ Name: 'CategoryButton',
+ Extends: Gtk.EventBox,
+ Properties: {
+ // resource URI for the category's accompanying image
+ 'image-uri': GObject.ParamSpec.string('image-uri',
+ 'Image URI',
+ 'Resource URI for the image file accompanying the category',
+ GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
+ ''),
+
+ // Title of the category to display
+ 'category-title': GObject.ParamSpec.string('category-title',
+ 'Category title',
+ 'Display name for the category',
+ GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
+ '')
+ },
+ Signals: {
+ 'clicked': {}
+ },
+
+ _init: function(props) {
+ // Get ready for property construction
+ this._image_uri = null;
+ this._category_title = null;
+
+ this._overlay = new Gtk.Overlay();
+ this._eventbox = new Gtk.EventBox({
+ expand: true
+ });
+ this._eventbox_grid = new Gtk.Grid({
+ orientation: Gtk.Orientation.HORIZONTAL,
+ hexpand: true,
+ valign: Gtk.Align.END
+ });
+ this._label = new Gtk.Label({
+ margin_left: CATEGORY_LABEL_LEFT_MARGIN,
+ margin_bottom: CATEGORY_LABEL_BOTTOM_MARGIN - CATEGORY_LABEL_BENTON_SANS_CORRECTION,
+ hexpand: true,
+ halign: Gtk.Align.START
+ });
+ this._arrow = new Gtk.Image({
+ resource: _HOVER_ARROW_URI,
+ margin_right: CATEGORY_BUTTON_RIGHT_MARGIN,
+ margin_bottom: CATEGORY_BUTTON_BOTTOM_MARGIN - CATEGORY_LABEL_BENTON_SANS_CORRECTION,
+ halign: Gtk.Align.END,
+ no_show_all: true
+ });
+
+ this._eventbox.add_events(Gdk.EventMask.ENTER_NOTIFY_MASK |
+ Gdk.EventMask.LEAVE_NOTIFY_MASK);
+ this._eventbox.connect('enter-notify-event',
+ Lang.bind(this, function(widget, event) {
+ this._eventbox.set_state_flags(Gtk.StateFlags.PRELIGHT, false);
+ this._arrow.show();
+ }));
+ this._eventbox.connect('leave-notify-event',
+ Lang.bind(this, function(widget, event) {
+ this._eventbox.unset_state_flags(Gtk.StateFlags.PRELIGHT);
+ this._arrow.hide();
+ }));
+
+ let context = this._label.get_style_context();
+ context.add_class(EndlessWikipedia.STYLE_CLASS_TITLE);
+ context.add_class(EndlessWikipedia.STYLE_CLASS_CATEGORY);
+ context.add_class(EndlessWikipedia.STYLE_CLASS_FRONT_PAGE);
+ this._image = new Gtk.Image({
+ expand: true,
+ halign: Gtk.Align.FILL,
+ valign: Gtk.Align.FILL
+ });
+
+ // Parent constructor sets all properties
+ this.parent(props);
+
+ // Put widgets together
+ this.add(this._overlay);
+ this._overlay.add(this._image);
+ this._eventbox_grid.add(this._label);
+ this._eventbox_grid.add(this._arrow);
+ this._eventbox.add(this._eventbox_grid);
+ this._overlay.add_overlay(this._eventbox);
+ this.show_all();
+
+ // Connect signals
+ this.connect('button-press-event',
+ Lang.bind(this, this._onButtonPress));
+ },
+
+ get image_uri() {
+ return this._image_uri;
+ },
+
+ set image_uri(value) {
+ this._image_uri = value;
+ if(this._image) {
+ let allocation = this.get_allocation();
+ let new_pixbuf = Utils.load_pixbuf_cover(Utils.resourceUriToPath(this._image_uri),
+ allocation.width, allocation.height);
+ this._image.set_from_pixbuf(new_pixbuf);
+ }
+ },
+
+ get category_title() {
+ return this._category_title;
+ },
+
+ set category_title(value) {
+ this._category_title = value;
+ if(this._label)
+ this._label.set_text(value.toUpperCase());
+ },
+
+ // OVERRIDES
+
+ vfunc_size_allocate: function(allocation) {
+ this.parent(allocation);
+ let new_pixbuf = Utils.load_pixbuf_cover(Utils.resourceUriToPath(this._image_uri),
+ allocation.width, allocation.height);
+ this._image.set_from_pixbuf(new_pixbuf);
+ },
+
+ // HANDLERS
+
+ _onButtonPress: function(widget, event) {
+ this.emit('clicked')
+ }
+});
diff --git a/wikipedia/widgets/category_layout_manager.js b/wikipedia/widgets/category_layout_manager.js
new file mode 100644
index 0000000..a7be3bb
--- /dev/null
+++ b/wikipedia/widgets/category_layout_manager.js
@@ -0,0 +1,65 @@
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+
+const CategoryLayoutManager = new Lang.Class({
+ Name: 'CategoryLayoutManager',
+ Extends: Gtk.Grid,
+
+ _init: function(props) {
+ props = props || {};
+ props.column_homogeneous = true;
+ props.row_homogeneous = true;
+ this.parent(props);
+
+ this._childWidgets = [];
+ },
+
+ // Distribute children in two columns, except for the last one if an odd
+ // number; that should span two columns
+ _redistributeChildren: function() {
+ let numChildren = this._childWidgets.length;
+ let oddNumber = numChildren % 2 == 1;
+ this._childWidgets.forEach(function(child, index) {
+ let column = index % 2;
+ let row = Math.floor(index / 2);
+
+ if(child.get_parent() === this)
+ Gtk.Container.prototype.remove.call(this,
+ this._childWidgets[index]);
+
+ if(oddNumber && index == numChildren - 1)
+ this.attach(child, 0, row, 2, 1);
+ else
+ this.attach(child, column, row, 1, 1);
+ }, this);
+ },
+
+ add: function(child) {
+ this._childWidgets.push(child);
+ this._redistributeChildren();
+ },
+
+ remove: function(child) {
+ let index = this._childWidgets.indexOf(child);
+ if(index == -1) {
+ printerr('Widget', System.addressOf(child),
+ 'is not contained in CategoryLayoutManager');
+ return;
+ }
+ this._childWidgets.splice(index, 1); // remove
+ this._redistributeChildren();
+ }
+});
+
+// Gtk.init(null);
+// let w = new Gtk.Window();
+// let g = new CategoryLayoutManager();
+// let count = 7;
+// for(let i = 0; i < count; i++) {
+// let widget = new Gtk.Button({label: 'Widget ' + i});
+// g.add(widget);
+// }
+// w.add(g);
+// w.connect('destroy', Gtk.main_quit);
+// w.show_all();
+// Gtk.main();
diff --git a/wikipedia/widgets/category_selector_view.js b/wikipedia/widgets/category_selector_view.js
new file mode 100644
index 0000000..776bf52
--- /dev/null
+++ b/wikipedia/widgets/category_selector_view.js
@@ -0,0 +1,43 @@
+const GObject = imports.gi.GObject;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+
+const CategoryButton = imports.wikipedia.widgets.category_button;
+const CategoryLayoutManager = imports.wikipedia.widgets.category_layout_manager;
+
+const CATEGORY_COLUMN_SPACING = 10; // pixels
+const CATEGORY_ROW_SPACING = 10; // pixels
+
+const CategorySelectorView = new Lang.Class({
+ Name: 'CategorySelectorView',
+ Extends: CategoryLayoutManager.CategoryLayoutManager,
+ Signals: {
+ 'category-chosen': {
+ param_types: [GObject.TYPE_STRING, GObject.TYPE_INT]
+ }
+ },
+
+ _init: function(props) {
+ props = props || {};
+ props.column_spacing = CATEGORY_COLUMN_SPACING;
+ props.row_spacing = CATEGORY_ROW_SPACING;
+ this.parent(props);
+ },
+
+ // Takes an array of dictionaries with keys 'title' and 'image_uri'
+ setCategories: function(categories) {
+ categories.forEach(function(category, index, obj) {
+ let button = new CategoryButton.CategoryButton({
+ category_title: category.title,
+ image_uri: category.image_thumbnail_uri
+ });
+ button.index = index;
+ button.connect('clicked', Lang.bind(this, this._onButtonClicked));
+ this.add(button);
+ }, this);
+ },
+
+ _onButtonClicked: function(button) {
+ this.emit('category-chosen', button.category_title, button.index);
+ }
+}); \ No newline at end of file
diff --git a/wikipedia/widgets/scaled_image.js b/wikipedia/widgets/scaled_image.js
new file mode 100644
index 0000000..9808914
--- /dev/null
+++ b/wikipedia/widgets/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(width);
+ 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();
diff --git a/wikipedia/widgets/title_label_view.js b/wikipedia/widgets/title_label_view.js
new file mode 100644
index 0000000..f3f599e
--- /dev/null
+++ b/wikipedia/widgets/title_label_view.js
@@ -0,0 +1,95 @@
+const GdkPixbuf = imports.gi.GdkPixbuf;
+const GObject = imports.gi.GObject;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+
+const Utils = imports.wikipedia.utils;
+
+const TITLE_LABEL_SCREEN_WIDTH_PERCENTAGE = 0.37;
+const TITLE_LABEL_LEFT_MARGIN = 20; // pixels
+const TITLE_LABEL_BOTTOM_MARGIN = 20; // pixels
+const TITLE_LABEL_BENTON_SANS_CORRECTION = 20; // pixels
+
+const TitleLabelView = new Lang.Class({
+ Name: 'TitleLabelView',
+ Extends: Gtk.Overlay,
+ Properties: {
+ 'title': GObject.ParamSpec.string('title',
+ 'Front page title',
+ 'Name of the Wikipedia-based application',
+ GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
+ ''),
+ 'image-uri': GObject.ParamSpec.string('image-uri',
+ 'Image URI',
+ 'Image URI for title image',
+ GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
+ '')
+ },
+
+ _init: function(props) {
+ this._title = null;
+ this._image_uri = null;
+ this._label = new Gtk.Label({
+ halign: Gtk.Align.START,
+ valign: Gtk.Align.END,
+ margin_left: TITLE_LABEL_LEFT_MARGIN,
+ margin_bottom: TITLE_LABEL_BOTTOM_MARGIN - TITLE_LABEL_BENTON_SANS_CORRECTION
+ });
+ this._image = new Gtk.Image();
+
+ let context = this._label.get_style_context()
+ context.add_class(EndlessWikipedia.STYLE_CLASS_TITLE);
+
+ this.parent(props);
+
+ this.add(this._image);
+ this.add_overlay(this._label);
+ },
+
+ // OVERRIDES
+
+ // Ensure that this widget is 37% of the window's width
+ vfunc_get_preferred_width: function() {
+ let toplevel = this.get_toplevel();
+ if(toplevel == null)
+ return this.parent();
+ let width = toplevel.get_allocated_width() * TITLE_LABEL_SCREEN_WIDTH_PERCENTAGE;
+ return [width, width];
+ },
+
+ vfunc_size_allocate: function(allocation) {
+ this.parent(allocation);
+ if(this._image_uri !== "" && this._image_uri != null) {
+ let new_pixbuf = Utils.load_pixbuf_cover(Utils.resourceUriToPath(this._image_uri),
+ allocation.width, allocation.height);
+ this._image.set_from_pixbuf(new_pixbuf);
+ }
+ },
+
+ // PROPERTIES
+
+ get title() {
+ return this._title;
+ },
+
+ set title(value) {
+ this._title = value;
+ if(this._label)
+ this._label.label = value.toUpperCase();
+ },
+
+ get image_uri() {
+ return this._image_uri;
+ },
+
+ set image_uri(value) {
+ this._image_uri = value;
+ if(this._image) {
+ let res_path = Utils.resourceUriToPath(value);
+ let allocation = this.get_allocation();
+ let new_pixbuf = Utils.load_pixbuf_cover(Utils.resourceUriToPath(this._image_uri),
+ allocation.width, allocation.height);
+ this._image.set_from_pixbuf(new_pixbuf);
+ }
+ }
+});