summaryrefslogtreecommitdiff
path: root/wikipedia
diff options
context:
space:
mode:
authorrmacqueen <rorymacqueen@gmail.com>2013-07-31 20:12:11 -0700
committerrmacqueen <rorymacqueen@gmail.com>2013-07-31 20:12:11 -0700
commitb3c6b3d7f27e5b35e6ef40ba566eec346a9eb94b (patch)
tree3d3dc8b596deeb4f5bd442b92268c4a61a82023c /wikipedia
parent57a5e900af89b74cdebb67955ab37dff85d2400a (diff)
parent1bb95b00195b2ad561c7239773e7c936f44b8962 (diff)
Merge pull request #204 from endlessm/issues/182
Issues/182
Diffstat (limited to 'wikipedia')
-rw-r--r--wikipedia/data/css/endless_brazil.css17
-rw-r--r--wikipedia/src/endless_wikipedia/EndlessWikipedia.js3
-rw-r--r--wikipedia/src/endless_wikipedia/PrebuiltFrontPage.js33
-rw-r--r--wikipedia/src/presenters/domain_wiki_presenter.js2
-rw-r--r--wikipedia/src/utils.js8
-rw-r--r--wikipedia/src/views/category_button.js (renamed from wikipedia/src/endless_wikipedia/CategoryButton.js)56
-rw-r--r--wikipedia/src/views/category_layout_manager.js65
-rw-r--r--wikipedia/src/views/category_selector_view.js (renamed from wikipedia/src/endless_wikipedia/CategorySelector.js)16
-rw-r--r--wikipedia/src/views/domain_wiki_view.js16
-rw-r--r--wikipedia/src/views/title_label_view.js102
10 files changed, 269 insertions, 49 deletions
diff --git a/wikipedia/data/css/endless_brazil.css b/wikipedia/data/css/endless_brazil.css
index f8dabb3..8b17f65 100644
--- a/wikipedia/data/css/endless_brazil.css
+++ b/wikipedia/data/css/endless_brazil.css
@@ -2,13 +2,16 @@
font-family: "BentonSans Regular";
}
-.title {
- font-size: 48pt;
+.title.front-page {
+ font-family: "BentonSans Thin";
+ font-size: 100px;
+ color: #ffffff;
+ text-shadow: 0px 1px 0px alpha(#23326e, 0.15);
}
.title.category.front-page {
- font-size: 36pt;
- color: #a0a0a0;
+ font-family: "BentonSans ExtraLight";
+ font-size: 40px;
}
Gjs_ArticleList{
@@ -55,4 +58,8 @@ Gjs_ArticleList .button:active {
font-family: "BentonSans Light";
font-size: 52px;
color: rgba(255, 255, 255, 0.9);
-} \ No newline at end of file
+}
+
+Gjs_CategoryButton GtkEventBox:hover {
+ background-color: alpha(#212121, 0.5);
+}
diff --git a/wikipedia/src/endless_wikipedia/EndlessWikipedia.js b/wikipedia/src/endless_wikipedia/EndlessWikipedia.js
index 9028173..398ce1b 100644
--- a/wikipedia/src/endless_wikipedia/EndlessWikipedia.js
+++ b/wikipedia/src/endless_wikipedia/EndlessWikipedia.js
@@ -13,9 +13,6 @@ this.PrebuiltCategoryPage = _PrebuiltCategoryPage.PrebuiltCategoryPage;
const _PrebuiltArticlesPage = imports.endless_wikipedia.PrebuiltArticlesPage;
this.PrebuiltArticlesPage = _PrebuiltArticlesPage.PrebuiltArticlesPage;
-const _CategorySelector = imports.endless_wikipedia.CategorySelector;
-this.CategorySelector = _CategorySelector.CategorySelector;
-
const _ArticleList = imports.endless_wikipedia.ArticleList;
this.ArticleList = _ArticleList.ArticleList;
diff --git a/wikipedia/src/endless_wikipedia/PrebuiltFrontPage.js b/wikipedia/src/endless_wikipedia/PrebuiltFrontPage.js
index fed6a75..36fdd2c 100644
--- a/wikipedia/src/endless_wikipedia/PrebuiltFrontPage.js
+++ b/wikipedia/src/endless_wikipedia/PrebuiltFrontPage.js
@@ -3,6 +3,10 @@ const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const EndlessWikipedia = imports.endless_wikipedia.EndlessWikipedia;
+const CategorySelectorView = imports.views.category_selector_view;
+const TitleLabelView = imports.views.title_label_view;
+
+const TITLE_CATEGORY_COLUMN_SPACING = 10; // pixels
GObject.ParamFlags.READWRITE = GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE;
@@ -14,6 +18,11 @@ const PrebuiltFrontPage = new Lang.Class({
'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,
'')
},
Signals: {
@@ -24,20 +33,18 @@ const PrebuiltFrontPage = new Lang.Class({
_init: function(props) {
this._title = null;
+ this._image_uri = null;
- this._title_label = new Gtk.Label({
- expand: true,
- halign: Gtk.Align.START,
- valign: Gtk.Align.END
- });
+ this._title_label = new TitleLabelView.TitleLabelView();
let context = this._title_label.get_style_context()
context.add_class(EndlessWikipedia.STYLE_CLASS_TITLE);
context.add_class(EndlessWikipedia.STYLE_CLASS_PREBUILT);
context.add_class(EndlessWikipedia.STYLE_CLASS_FRONT_PAGE);
- this._category_selector = new EndlessWikipedia.CategorySelector();
+ this._category_selector = new CategorySelectorView.CategorySelectorView();
props = props || {};
- props.orientation = Gtk.Orientation.VERTICAL;
+ props.orientation = Gtk.Orientation.HORIZONTAL;
+ props.column_spacing = TITLE_CATEGORY_COLUMN_SPACING;
this.parent(props);
this.add(this._title_label);
@@ -52,8 +59,16 @@ const PrebuiltFrontPage = new Lang.Class({
set title(value) {
this._title = value;
- if(this._title_label)
- this._title_label.label = value.toUpperCase();
+ this._title_label.title = value;
+ },
+
+ get image_uri() {
+ return this._image_uri;
+ },
+
+ set image_uri(value) {
+ this._image_uri = value;
+ this._title_label.image_uri = value;
},
setCategories: function(categories) {
diff --git a/wikipedia/src/presenters/domain_wiki_presenter.js b/wikipedia/src/presenters/domain_wiki_presenter.js
index 9d010e3..151bae6 100644
--- a/wikipedia/src/presenters/domain_wiki_presenter.js
+++ b/wikipedia/src/presenters/domain_wiki_presenter.js
@@ -61,7 +61,7 @@ const DomainWikiPresenter = new Lang.Class({
category_models.push(categoryModel);
}
this._domain_wiki_model.addCategories(category_models);
- this._domain_wiki_view.set_front_page_info(this._image_uri);
+ this._domain_wiki_view.set_front_page_info(this._application_name, this._image_uri);
},
initCategory: function(category){
diff --git a/wikipedia/src/utils.js b/wikipedia/src/utils.js
index 08c372f..d2cb544 100644
--- a/wikipedia/src/utils.js
+++ b/wikipedia/src/utils.js
@@ -176,3 +176,11 @@ function _clutter_allocation_printer(actor, box, flag) {
function print_clutter_actor_allocation(actor) {
actor.connect('allocation-changed', _clutter_allocation_printer);
}
+
+// Convenience function to convert a resource URI to a resource path, for
+// APIs that expect a path rather than an URI
+function resourceUriToPath(uri) {
+ if(uri.startsWith('resource://'))
+ return uri.slice('resource://'.length);
+ throw new Error('Resource URI did not start with "resource://"');
+}
diff --git a/wikipedia/src/endless_wikipedia/CategoryButton.js b/wikipedia/src/views/category_button.js
index 8df4e18..782dd17 100644
--- a/wikipedia/src/endless_wikipedia/CategoryButton.js
+++ b/wikipedia/src/views/category_button.js
@@ -3,13 +3,14 @@ const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
-GObject.ParamFlags.READWRITE = GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE;
+const Utils = imports.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
-function _resourceUriToPath(uri) {
- if(uri.startsWith('resource://'))
- return uri.slice('resource://'.length);
- throw new Error('Resource URI did not start with "resource://"');
-}
+GObject.ParamFlags.READWRITE = GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE;
const CategoryButton = new Lang.Class({
Name: 'CategoryButton',
@@ -40,13 +41,40 @@ const CategoryButton = new Lang.Class({
this._overlay = new Gtk.Overlay();
this._eventbox = new Gtk.EventBox({
- vexpand: false,
- valign: Gtk.Align.END,
- halign: Gtk.Align.FILL
- })
+ 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,
+ hexpand: true,
halign: Gtk.Align.START
});
+ this._arrow = new Gtk.Image({
+ resource: '/com/endlessm/brazil/assets/category_hover_arrow.png',
+ margin_right: CATEGORY_BUTTON_RIGHT_MARGIN,
+ margin_bottom: CATEGORY_BUTTON_BOTTOM_MARGIN,
+ 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);
@@ -63,7 +91,9 @@ const CategoryButton = new Lang.Class({
// Put widgets together
this.add(this._overlay);
this._overlay.add(this._image);
- this._eventbox.add(this._label);
+ 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();
@@ -79,7 +109,7 @@ const CategoryButton = new Lang.Class({
set image_uri(value) {
this._image_uri = value;
if(this._image) {
- let res_path = _resourceUriToPath(value);
+ let res_path = Utils.resourceUriToPath(value);
let allocation = this.get_allocation();
this._updateImage(res_path, allocation.width, allocation.height);
}
@@ -99,7 +129,7 @@ const CategoryButton = new Lang.Class({
vfunc_size_allocate: function(allocation) {
this.parent(allocation);
- this._updateImage(_resourceUriToPath(this._image_uri),
+ this._updateImage(Utils.resourceUriToPath(this._image_uri),
allocation.width, allocation.height);
},
diff --git a/wikipedia/src/views/category_layout_manager.js b/wikipedia/src/views/category_layout_manager.js
new file mode 100644
index 0000000..a7be3bb
--- /dev/null
+++ b/wikipedia/src/views/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/src/endless_wikipedia/CategorySelector.js b/wikipedia/src/views/category_selector_view.js
index f5b7b14..fa34aa1 100644
--- a/wikipedia/src/endless_wikipedia/CategorySelector.js
+++ b/wikipedia/src/views/category_selector_view.js
@@ -2,11 +2,15 @@ const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
-const CategoryButton = imports.endless_wikipedia.CategoryButton;
+const CategoryButton = imports.views.category_button;
+const CategoryLayoutManager = imports.views.category_layout_manager;
-const CategorySelector = new Lang.Class({
- Name: 'CategorySelector',
- Extends: Gtk.Grid,
+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]
@@ -15,8 +19,8 @@ const CategorySelector = new Lang.Class({
_init: function(props) {
props = props || {};
- props.row_homogeneous = true;
- props.column_homogeneous = true;
+ props.column_spacing = CATEGORY_COLUMN_SPACING;
+ props.row_spacing = CATEGORY_ROW_SPACING;
this.parent(props);
},
diff --git a/wikipedia/src/views/domain_wiki_view.js b/wikipedia/src/views/domain_wiki_view.js
index 8783504..36062b2 100644
--- a/wikipedia/src/views/domain_wiki_view.js
+++ b/wikipedia/src/views/domain_wiki_view.js
@@ -51,9 +51,7 @@ const DomainWikiView = new Lang.Class({
},
create_front_page: function(){
- this._front_page = new EndlessWikipedia.PrebuiltFrontPage({
- title: "Brazil App"
- });
+ this._front_page = new EndlessWikipedia.PrebuiltFrontPage();
this._front_page.connect('category-chosen',
Lang.bind(this, this._onCategoryClicked));
},
@@ -113,15 +111,9 @@ const DomainWikiView = new Lang.Class({
this._presenter = presenter;
},
- set_front_page_info: function(image_uri) {
- /*
- * TODO: This is a stub function that sets the front page
- * info. The front page needs its domain-specific image set.
- * Currently, the domain-specific image for the Brazil App is
- * the same image used in the food category.
- */
-
- return;
+ set_front_page_info: function(title, image_uri) {
+ this._front_page.title = title;
+ this._front_page.image_uri = image_uri;
},
set_category_info: function(category, articles) {
diff --git a/wikipedia/src/views/title_label_view.js b/wikipedia/src/views/title_label_view.js
new file mode 100644
index 0000000..336492c
--- /dev/null
+++ b/wikipedia/src/views/title_label_view.js
@@ -0,0 +1,102 @@
+const GdkPixbuf = imports.gi.GdkPixbuf;
+const GObject = imports.gi.GObject;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+
+const Utils = imports.utils;
+
+const TITLE_LABEL_SCREEN_WIDTH_PERCENTAGE = 0.37;
+const TITLE_LABEL_LEFT_MARGIN = 20; // pixels
+const TITLE_LABEL_BOTTOM_MARGIN = 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
+ });
+ this._image = new Gtk.Image();
+
+ 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);
+ this._updateImage(Utils.resourceUriToPath(this._image_uri),
+ allocation.width, allocation.height);
+ },
+
+ // 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();
+ this._updateImage(res_path, allocation.width, allocation.height);
+ }
+ },
+
+ // PRIVATE
+
+ _updateImage: function(res_path, width, height) {
+ let [source_width, source_height] = [width, height];
+ if(width > height)
+ source_height = -1;
+ else
+ source_width = -1;
+ let source_pixbuf = GdkPixbuf.Pixbuf.new_from_resource_at_scale(res_path,
+ source_width, source_height, true);
+ let cropped_pixbuf = source_pixbuf;
+ if(width < source_pixbuf.width || height < source_pixbuf.height)
+ cropped_pixbuf = source_pixbuf.new_subpixbuf(0, 0, width, height);
+ this._image.set_from_pixbuf(cropped_pixbuf);
+ }
+});