summaryrefslogtreecommitdiff
path: root/wikipedia/src
diff options
context:
space:
mode:
Diffstat (limited to 'wikipedia/src')
-rw-r--r--wikipedia/src/endless_brazil.js17
-rw-r--r--wikipedia/src/endless_wikipedia/ArticleList.js50
-rw-r--r--wikipedia/src/endless_wikipedia/BackButton.js18
-rw-r--r--wikipedia/src/endless_wikipedia/CategoryButton.js125
-rw-r--r--wikipedia/src/endless_wikipedia/CategorySelector.js39
-rw-r--r--wikipedia/src/endless_wikipedia/EndlessWikipedia.js31
-rw-r--r--wikipedia/src/endless_wikipedia/PrebuiltArticlesPage.js87
-rw-r--r--wikipedia/src/endless_wikipedia/PrebuiltCategoryPage.js85
-rw-r--r--wikipedia/src/endless_wikipedia/PrebuiltFrontPage.js67
-rw-r--r--wikipedia/src/endless_wikipedia/PrebuiltWikipediaApplication.js127
-rw-r--r--wikipedia/src/endless_wikipedia/WikipediaApplication.js85
-rw-r--r--wikipedia/src/endless_wikipedia/models/WikipediaModel.js59
12 files changed, 790 insertions, 0 deletions
diff --git a/wikipedia/src/endless_brazil.js b/wikipedia/src/endless_brazil.js
new file mode 100644
index 0000000..21726fd
--- /dev/null
+++ b/wikipedia/src/endless_brazil.js
@@ -0,0 +1,17 @@
+const Endless = imports.gi.Endless;
+const Gdk = imports.gi.Gdk;
+const Gio = imports.gi.Gio;
+const Gtk = imports.gi.Gtk;
+
+// Local imports
+imports.searchPath.unshift(Endless.getCurrentFileDir());
+const EndlessWikipedia = imports.endless_wikipedia.EndlessWikipedia;
+
+// Load GResource bundle
+let resource = Gio.Resource.load(Endless.getCurrentFileDir() + '/../data/endless_brazil.gresource');
+resource._register();
+
+let app = new EndlessWikipedia.PrebuiltWikipediaApplication({
+ categories_uri: 'resource:///com/endlessm/brazil/brazil_categories.json'
+});
+app.run(ARGV);
diff --git a/wikipedia/src/endless_wikipedia/ArticleList.js b/wikipedia/src/endless_wikipedia/ArticleList.js
new file mode 100644
index 0000000..b79e2e8
--- /dev/null
+++ b/wikipedia/src/endless_wikipedia/ArticleList.js
@@ -0,0 +1,50 @@
+const GObject = imports.gi.GObject;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+
+const ArticleList = new Lang.Class({
+ Name: 'ArticleList',
+ Extends: Gtk.ScrolledWindow,
+ Signals: {
+ 'article-chosen': {
+ param_types: [GObject.TYPE_STRING, GObject.TYPE_STRING]
+ }
+ },
+
+ _init: function(props) {
+ props = props || {};
+ props.hscrollbar_policy = Gtk.PolicyType.NEVER;
+ props.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC,
+ this.parent(props);
+
+ this._grid = new Gtk.Grid({
+ orientation: Gtk.Orientation.VERTICAL,
+ vexpand: true
+ });
+ this.add(this._grid);
+ },
+
+ // Takes a list of dictionaries with keys 'title' and 'url'
+ setArticles: function(articles) {
+ // Remove all existing article links
+ this._grid.get_children().forEach(function(element, index, obj) {
+ this._grid.remove(element);
+ }, this);
+
+ // Create new ones
+ articles.forEach(function(element, index, obj) {
+ var button = Gtk.Button.new_with_label(element.title.toUpperCase());
+ button.image = Gtk.Image.new_from_icon_name('go-next-symbolic',
+ Gtk.IconSize.BUTTON);
+ button.always_show_image = true; // Don't do this, see BackButton.js
+ button.image_position = Gtk.PositionType.RIGHT;
+ button.xalign = 0;
+
+ button.connect('clicked', Lang.bind(this, function() {
+ this.emit('article-chosen', element.title, element.url);
+ }));
+ button.show();
+ this._grid.add(button);
+ }, this);
+ }
+});
diff --git a/wikipedia/src/endless_wikipedia/BackButton.js b/wikipedia/src/endless_wikipedia/BackButton.js
new file mode 100644
index 0000000..cfb3155
--- /dev/null
+++ b/wikipedia/src/endless_wikipedia/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/src/endless_wikipedia/CategoryButton.js b/wikipedia/src/endless_wikipedia/CategoryButton.js
new file mode 100644
index 0000000..e1b428e
--- /dev/null
+++ b/wikipedia/src/endless_wikipedia/CategoryButton.js
@@ -0,0 +1,125 @@
+const GdkPixbuf = imports.gi.GdkPixbuf;
+const GObject = imports.gi.GObject;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+
+GObject.ParamFlags.READWRITE = GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE;
+
+function _resourceUriToPath(uri) {
+ if(uri.startsWith('resource://'))
+ return uri.slice('resource://'.length);
+ throw new Error('Resource URI did not start with "resource://"');
+}
+
+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({
+ vexpand: false,
+ valign: Gtk.Align.END,
+ halign: Gtk.Align.FILL
+ })
+ this._label = new Gtk.Label({
+ halign: Gtk.Align.START
+ });
+ 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.add(this._label);
+ 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 res_path = _resourceUriToPath(value);
+ let allocation = this.get_allocation();
+ this._updateImage(res_path, allocation.width, allocation.height);
+ }
+ },
+
+ 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);
+ this._updateImage(_resourceUriToPath(this._image_uri),
+ allocation.width, allocation.height);
+ },
+
+ // HANDLERS
+
+ _onButtonPress: function(widget, event) {
+ this.emit('clicked')
+ },
+
+ // 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.new_subpixbuf(0, 0, width, height);
+ this._image.set_from_pixbuf(cropped_pixbuf);
+ }
+});
diff --git a/wikipedia/src/endless_wikipedia/CategorySelector.js b/wikipedia/src/endless_wikipedia/CategorySelector.js
new file mode 100644
index 0000000..f5b7b14
--- /dev/null
+++ b/wikipedia/src/endless_wikipedia/CategorySelector.js
@@ -0,0 +1,39 @@
+const GObject = imports.gi.GObject;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+
+const CategoryButton = imports.endless_wikipedia.CategoryButton;
+
+const CategorySelector = new Lang.Class({
+ Name: 'CategorySelector',
+ Extends: Gtk.Grid,
+ Signals: {
+ 'category-chosen': {
+ param_types: [GObject.TYPE_STRING, GObject.TYPE_INT]
+ }
+ },
+
+ _init: function(props) {
+ props = props || {};
+ props.row_homogeneous = true;
+ props.column_homogeneous = true;
+ 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_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/src/endless_wikipedia/EndlessWikipedia.js b/wikipedia/src/endless_wikipedia/EndlessWikipedia.js
new file mode 100644
index 0000000..0f12986
--- /dev/null
+++ b/wikipedia/src/endless_wikipedia/EndlessWikipedia.js
@@ -0,0 +1,31 @@
+const _WikipediaApplication = imports.endless_wikipedia.WikipediaApplication;
+this.WikipediaApplication = _WikipediaApplication.WikipediaApplication;
+
+const _PrebuiltWikipediaApplication = imports.endless_wikipedia.PrebuiltWikipediaApplication;
+this.PrebuiltWikipediaApplication = _PrebuiltWikipediaApplication.PrebuiltWikipediaApplication;
+
+const _PrebuiltFrontPage = imports.endless_wikipedia.PrebuiltFrontPage;
+this.PrebuiltFrontPage = _PrebuiltFrontPage.PrebuiltFrontPage;
+
+const _PrebuiltCategoryPage = imports.endless_wikipedia.PrebuiltCategoryPage;
+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;
+
+const _BackButton = imports.endless_wikipedia.BackButton;
+this.BackButton = _BackButton.BackButton;
+
+const STYLE_CLASS_TITLE = 'title';
+const STYLE_CLASS_PREBUILT = 'prebuilt';
+const STYLE_CLASS_CATEGORY = 'category';
+const STYLE_CLASS_ARTICLE = 'article';
+const STYLE_CLASS_FRONT_PAGE = 'front-page';
+const STYLE_CLASS_CATEGORY_PAGE = 'category-page';
+const STYLE_CLASS_ARTICLES_PAGE = 'articles-page';
diff --git a/wikipedia/src/endless_wikipedia/PrebuiltArticlesPage.js b/wikipedia/src/endless_wikipedia/PrebuiltArticlesPage.js
new file mode 100644
index 0000000..12d9b45
--- /dev/null
+++ b/wikipedia/src/endless_wikipedia/PrebuiltArticlesPage.js
@@ -0,0 +1,87 @@
+const GObject = imports.gi.GObject;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+
+const EndlessWikipedia = imports.endless_wikipedia.EndlessWikipedia;
+
+GObject.ParamFlags.READWRITE = GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE;
+
+const PrebuiltArticlesPage = new Lang.Class({
+ Name: 'PrebuiltArticlesPage',
+ Extends: Gtk.Frame,
+ Properties: {
+ 'title': GObject.ParamSpec.string('title',
+ 'Article title',
+ 'Human-readable title for the article to be displayed',
+ GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
+ ''),
+ 'article-uri': GObject.ParamSpec.string('article-uri',
+ 'Article URI',
+ 'Last component of the Wikipedia URI for the article',
+ GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
+ '')
+ },
+
+ _init: function(props) {
+ this._title = null;
+ this._article_uri = null;
+
+ // Create widgets
+ this._grid = new Gtk.Grid({
+ orientation: Gtk.Orientation.VERTICAL,
+ expand: true
+ });
+ this._title_label = new Gtk.Label({
+ vexpand: false,
+ halign: Gtk.Align.START
+ });
+ this._separator = new Gtk.Separator({
+ orientation: Gtk.Orientation.HORIZONTAL,
+ vexpand: false
+ });
+ this._wiki_view = new Gtk.Label({
+ vexpand: true
+ });
+
+ this.parent(props);
+
+ this._grid.add(this._title_label);
+ this._grid.add(this._separator);
+ this._grid.add(this._wiki_view);
+ this.add(this._grid);
+
+ // Add style contexts for CSS
+ let context = this._title_label.get_style_context();
+ context.add_class(EndlessWikipedia.STYLE_CLASS_TITLE);
+ context.add_class(EndlessWikipedia.STYLE_CLASS_ARTICLE);
+ context.add_class(EndlessWikipedia.STYLE_CLASS_ARTICLES_PAGE);
+ context.add_class(EndlessWikipedia.STYLE_CLASS_PREBUILT);
+ let context = this._separator.get_style_context();
+ context.add_class(EndlessWikipedia.STYLE_CLASS_ARTICLES_PAGE);
+ let context = this._wiki_view.get_style_context();
+ context.add_class(EndlessWikipedia.STYLE_CLASS_ARTICLES_PAGE);
+ let context = this.get_style_context();
+ context.add_class(EndlessWikipedia.STYLE_CLASS_ARTICLES_PAGE);
+ },
+
+ get title() {
+ return this._title;
+ },
+
+ set title(value) {
+ this._title = value;
+ if(this._title_label)
+ this._title_label.label = value.toUpperCase();
+ },
+
+ get article_uri() {
+ return this._article_uri;
+ },
+
+ set article_uri(value) {
+ this._article_uri = value;
+ if(this._wiki_view)
+ this._wiki_view.label = 'This is a "webview" displaying the ' +
+ 'article http://en.wikipedia.org/wiki/%s'.format(value);
+ }
+}); \ No newline at end of file
diff --git a/wikipedia/src/endless_wikipedia/PrebuiltCategoryPage.js b/wikipedia/src/endless_wikipedia/PrebuiltCategoryPage.js
new file mode 100644
index 0000000..3831c63
--- /dev/null
+++ b/wikipedia/src/endless_wikipedia/PrebuiltCategoryPage.js
@@ -0,0 +1,85 @@
+const GObject = imports.gi.GObject;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+
+const EndlessWikipedia = imports.endless_wikipedia.EndlessWikipedia;
+
+GObject.ParamFlags.READWRITE = GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE;
+
+const PrebuiltCategoryPage = new Lang.Class({
+ Name: 'PrebuiltCategoryPage',
+ Extends: Gtk.Frame,
+ Properties: {
+ 'title': GObject.ParamSpec.string('title',
+ 'Name of category',
+ 'Name of the category to be displayed at the top of the category page',
+ GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
+ ''),
+ 'description': GObject.ParamSpec.string('description',
+ 'Description',
+ 'Description of the category (excerpt from Wiki text)',
+ GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
+ '')
+ },
+
+ _init: function(props) {
+ this._title = null;
+ this._description = null;
+
+ this._grid = new Gtk.Grid({
+ orientation: Gtk.Orientation.VERTICAL,
+ expand: true
+ });
+ this._title_label = new Gtk.Label({
+ vexpand: false,
+ halign: Gtk.Align.START
+ });
+ this._separator = new Gtk.Separator({
+ orientation: Gtk.Orientation.HORIZONTAL,
+ vexpand: false
+ });
+ this._description_label = new Gtk.Label({
+ valign: Gtk.Align.START,
+ halign: Gtk.Align.START
+ });
+
+ this.parent(props);
+
+ this._grid.add(this._title_label);
+ this._grid.add(this._separator);
+ this._grid.add(this._description_label);
+ this.add(this._grid);
+
+ let context = this._title_label.get_style_context();
+ context.add_class(EndlessWikipedia.STYLE_CLASS_TITLE);
+ context.add_class(EndlessWikipedia.STYLE_CLASS_CATEGORY);
+ context.add_class(EndlessWikipedia.STYLE_CLASS_CATEGORY_PAGE);
+ context.add_class(EndlessWikipedia.STYLE_CLASS_PREBUILT);
+ let context = this._separator.get_style_context();
+ context.add_class(EndlessWikipedia.STYLE_CLASS_CATEGORY_PAGE);
+ let context = this._description_label.get_style_context();
+ context.add_class(EndlessWikipedia.STYLE_CLASS_CATEGORY_PAGE);
+ let context = this.get_style_context();
+ context.add_class(EndlessWikipedia.STYLE_CLASS_CATEGORY_PAGE);
+ },
+
+ get title() {
+ return this._title;
+ },
+
+ set title(value) {
+ this._title = value;
+ if(this._title_label)
+ this._title_label.label = value.toUpperCase();
+ },
+
+ get description() {
+ return this._description;
+ },
+
+ set description(value) {
+ this._description = value;
+ if(this._description_label)
+ this._description_label.label = value;
+ }
+}); \ No newline at end of file
diff --git a/wikipedia/src/endless_wikipedia/PrebuiltFrontPage.js b/wikipedia/src/endless_wikipedia/PrebuiltFrontPage.js
new file mode 100644
index 0000000..fed6a75
--- /dev/null
+++ b/wikipedia/src/endless_wikipedia/PrebuiltFrontPage.js
@@ -0,0 +1,67 @@
+const GObject = imports.gi.GObject;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+
+const EndlessWikipedia = imports.endless_wikipedia.EndlessWikipedia;
+
+GObject.ParamFlags.READWRITE = GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE;
+
+const PrebuiltFrontPage = new Lang.Class({
+ Name: 'PrebuiltFrontPage',
+ Extends: Gtk.Grid,
+ Properties: {
+ 'title': GObject.ParamSpec.string('title',
+ 'Front page title',
+ 'Name of the Wikipedia-based application',
+ GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT,
+ '')
+ },
+ Signals: {
+ 'category-chosen': {
+ param_types: [GObject.TYPE_STRING, GObject.TYPE_INT]
+ }
+ },
+
+ _init: function(props) {
+ this._title = null;
+
+ this._title_label = new Gtk.Label({
+ expand: true,
+ halign: Gtk.Align.START,
+ valign: Gtk.Align.END
+ });
+ 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();
+
+ props = props || {};
+ props.orientation = Gtk.Orientation.VERTICAL;
+ this.parent(props);
+
+ this.add(this._title_label);
+ this.add(this._category_selector);
+ this._category_selector.connect('category-chosen',
+ Lang.bind(this, this._onCategoryChosen));
+ },
+
+ get title() {
+ return this._title;
+ },
+
+ set title(value) {
+ this._title = value;
+ if(this._title_label)
+ this._title_label.label = value.toUpperCase();
+ },
+
+ setCategories: function(categories) {
+ this._category_selector.setCategories(categories);
+ },
+
+ // Proxy signal
+ _onCategoryChosen: function(widget, title, index) {
+ this.emit('category-chosen', title, index);
+ }
+}); \ No newline at end of file
diff --git a/wikipedia/src/endless_wikipedia/PrebuiltWikipediaApplication.js b/wikipedia/src/endless_wikipedia/PrebuiltWikipediaApplication.js
new file mode 100644
index 0000000..7b2ebbd
--- /dev/null
+++ b/wikipedia/src/endless_wikipedia/PrebuiltWikipediaApplication.js
@@ -0,0 +1,127 @@
+const Endless = imports.gi.Endless;
+const Format = imports.format;
+const Lang = imports.lang;
+const Gtk = imports.gi.Gtk;
+
+const EndlessWikipedia = imports.endless_wikipedia.EndlessWikipedia;
+
+const _ = function(x) { return x; };
+
+String.prototype.format = Format.format;
+
+const PrebuiltWikipediaApplication = new Lang.Class({
+ Name: 'PrebuiltWikipediaApplication',
+ Extends: EndlessWikipedia.WikipediaApplication,
+
+ _init: function(props) {
+ this.parent(props);
+ },
+
+ vfunc_startup: function() {
+ this.parent();
+
+ // Front page
+ this._front_page = new EndlessWikipedia.PrebuiltFrontPage({
+ title: this.application_name
+ });
+ this._front_page.setCategories(this.getCategories());
+ this._front_page.connect('category-chosen',
+ Lang.bind(this, this._onCategoryClicked));
+
+ // Category page
+ this._category_page = new Gtk.Grid({
+ orientation: Gtk.Orientation.HORIZONTAL
+ });
+ this._category_view = new EndlessWikipedia.PrebuiltCategoryPage();
+ // _category_article_list is eventually going to be the same widget as
+ // _article_list, so that's why it's not built into the
+ // PrebuiltCategoryPage
+ this._category_article_list = new EndlessWikipedia.ArticleList({
+ halign: Gtk.Align.END,
+ hexpand: false
+ });
+ this._category_page.add(this._category_view);
+ this._category_page.add(this._category_article_list);
+
+ this._category_back_button = new EndlessWikipedia.BackButton({
+ label: _('START')
+ });
+ this._category_back_button.show();
+
+ this._category_article_list.connect('article-chosen',
+ Lang.bind(this, this._onArticleClicked));
+ this._category_back_button.connect('clicked',
+ Lang.bind(this, this._onCategoryBackClicked));
+
+ // Article page
+ this._article_page = new Gtk.Grid({
+ orientation: Gtk.Orientation.HORIZONTAL
+ });
+ this._article_view = new EndlessWikipedia.PrebuiltArticlesPage();
+ this._article_list = new EndlessWikipedia.ArticleList({
+ halign: Gtk.Align.START,
+ hexpand: false
+ });
+ this._article_page.add(this._article_list);
+ this._article_page.add(this._article_view);
+
+ this._article_back_button = new EndlessWikipedia.BackButton();
+ this._article_back_button.show();
+
+ this._article_list.connect('article-chosen',
+ Lang.bind(this, this._onArticleClicked));
+ this._article_back_button.connect('clicked',
+ Lang.bind(this, this._onArticleBackClicked));
+
+ // Build window
+ this._window = new Endless.Window({
+ title: this.application_name,
+ application: this
+ });
+ this._window.page_manager.transition_duration = 200; // ms
+ this._window.page_manager.add(this._front_page, {
+ name: 'front'
+ });
+ this._window.page_manager.add(this._category_page, {
+ name: 'category',
+ left_topbar_widget: this._category_back_button
+ });
+ this._window.page_manager.add(this._article_page, {
+ name: 'article',
+ left_topbar_widget: this._article_back_button
+ })
+ this._window.show_all();
+ },
+
+ _onCategoryClicked: function(page, title, index) {
+ let category = this.getCategories()[index];
+ let articles = this.getArticlesForCategoryIndex(index);
+
+ this._category_view.title = category.title;
+ this._category_view.description = category.content;
+ this._category_article_list.setArticles(articles);
+ this._article_list.setArticles(articles);
+ this._article_back_button.label = category.title.toUpperCase();
+
+ this._window.page_manager.transition_type = Endless.PageManagerTransitionType.SLIDE_LEFT;
+ this._window.page_manager.visible_page_name = 'category';
+ },
+
+ _onArticleClicked: function(article_list, title, uri) {
+ this._article_view.title = title;
+ this._article_view.article_uri = uri;
+
+ this._window.page_manager.transition_type = Endless.PageManagerTransitionType.SLIDE_LEFT;
+ this._window.page_manager.visible_page_name = 'article';
+ },
+
+ _onCategoryBackClicked: function(button) {
+ this._window.page_manager.transition_type = Endless.PageManagerTransitionType.SLIDE_RIGHT;
+ this._window.page_manager.visible_page_name = 'front';
+ },
+
+ _onArticleBackClicked: function(button) {
+ this._window.page_manager.transition_type = Endless.PageManagerTransitionType.SLIDE_RIGHT;
+ this._window.page_manager.visible_page_name = 'category';
+ }
+});
diff --git a/wikipedia/src/endless_wikipedia/WikipediaApplication.js b/wikipedia/src/endless_wikipedia/WikipediaApplication.js
new file mode 100644
index 0000000..b1cd6ff
--- /dev/null
+++ b/wikipedia/src/endless_wikipedia/WikipediaApplication.js
@@ -0,0 +1,85 @@
+const Lang = imports.lang;
+const GObject = imports.gi.GObject;
+const Gio = imports.gi.Gio;
+
+GObject.ParamFlags.READWRITE = GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE;
+
+const WikipediaApplication = new Lang.Class({
+ Name: 'WikipediaApplication',
+ Extends: Endless.Application,
+ Properties: {
+ // resource:// URI for the categories JSON file
+ 'categories-uri': GObject.ParamSpec.string('categories-uri',
+ 'Category file URI',
+ 'URI for the data file describing the categories and articles',
+ GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
+ ''),
+
+ // Name of the Wikipedia-based application, e.g. 'Brazil', 'Math'
+ 'application-name': GObject.ParamSpec.string('application-name',
+ 'Application name',
+ 'Name of the Wikipedia-based application',
+ GObject.ParamFlags.READABLE,
+ '')
+ },
+
+ _init: function(props) {
+ this._categories_uri = null;
+ this._categories = null;
+ this.parent(props);
+ },
+
+ // PROPERTIES
+
+ get categories_uri() {
+ return this._categories_uri;
+ },
+
+ set categories_uri(value) {
+ this._categories_uri = value;
+ },
+
+ get application_name() {
+ if(this._categories)
+ return this._categories.app_name;
+ return undefined;
+ },
+
+ // VIRTUAL FUNCTIONS
+
+ vfunc_startup: function() {
+ this.parent();
+
+ let category_file = Gio.File.new_for_uri(this.categories_uri);
+ let [success, category_json, etag] = category_file.load_contents(null);
+ this._categories = JSON.parse(category_json);
+
+ // Doesn't belong here
+ let provider = new Gtk.CssProvider();
+ let css_file = Gio.File.new_for_uri('resource:///com/endlessm/brazil/css/endless_brazil.css')
+ provider.load_from_file(css_file);
+ Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
+ },
+
+ // PUBLIC API
+
+ getCategories: function() {
+ let category_list = this._categories.categories.map(function(element, index, obj) {
+ return {
+ title: element.category_name,
+ image_uri: element.image_uri,
+ content: element.content_text
+ };
+ })
+ return category_list;
+ },
+
+ getArticlesForCategory: function(category_title) {
+ //...
+ },
+
+ getArticlesForCategoryIndex: function(index) {
+ return this._categories.categories[index].articles;
+ }
+
+});
diff --git a/wikipedia/src/endless_wikipedia/models/WikipediaModel.js b/wikipedia/src/endless_wikipedia/models/WikipediaModel.js
new file mode 100644
index 0000000..d6660b8
--- /dev/null
+++ b/wikipedia/src/endless_wikipedia/models/WikipediaModel.js
@@ -0,0 +1,59 @@
+const Endless = imports.gi.Endless;
+const Gio = imports.gi.Gio;
+const GObject = imports.gi.GObject;
+const Json = imports.gi.Json;
+const Lang = imports.lang;
+
+// Local libraries
+//const CategoryModel = imports.models.category_model;
+const JsonUtils = imports.models.utils.json_utils;
+
+const CONTENT_DIRECTORY = Endless.getCurrentFileDir() + "/../../content/";
+const DEFAULT_METADATA_FILE = CONTENT_DIRECTORY + "metadata.json";
+
+const WikipediaModel = new Lang.Class({
+ Name: "WikipediaModel",
+ Extends: GObject.Object,
+
+ _init: function(f) {
+
+ let jsonFile;
+ jsonFile = f || DEFAULT_METADATA_FILE;
+
+ this._categories = new Array();
+
+ this.initFromJsonFile(jsonFile);
+ },
+
+ initFromJsonFile: function(theFile) {
+
+ let parser = new Json.Parser();
+
+ try {
+ parser.load_from_file(theFile);
+
+ let root = parser.get_root();
+ let reader = new Json.Reader();
+ reader.root = root;
+
+ reader.read_member("categories");
+ let categoryCount = reader.count_elements();
+ for(let i=0; i<categoryCount; i++) {
+ reader.read_element(i);
+ print("hello");
+ let vId = reader.get_string_value();
+ //let newCategory = new CategoryModel.CategoryModel({ id: vId });
+ //this._categories.push(newCategory);
+
+ reader.end_element();
+ }
+ reader.end_member();
+ } catch (e) {
+ throw e;
+ }
+ },
+
+ getCategories: function() {
+ return this._categories;
+ },
+});