summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--wikipedia/Makefile.am52
-rw-r--r--wikipedia/README.md4
-rwxr-xr-xwikipedia/autogen.sh40
-rw-r--r--wikipedia/commit-msg16
-rw-r--r--wikipedia/configure.ac69
-rw-r--r--wikipedia/data/category_images/cuisine.jpgbin0 -> 83940 bytes
-rw-r--r--wikipedia/data/category_images/history.jpgbin0 -> 24291 bytes
-rw-r--r--wikipedia/data/css/endless_brazil.css28
-rw-r--r--wikipedia/data/endless_brazil.gresource.xml9
-rw-r--r--wikipedia/m4/as-linguas.m426
-rw-r--r--wikipedia/po/Makevars41
-rw-r--r--wikipedia/po/POTFILES.in1
-rw-r--r--wikipedia/po/eos-brazil.pot0
-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
25 files changed, 1076 insertions, 0 deletions
diff --git a/wikipedia/Makefile.am b/wikipedia/Makefile.am
new file mode 100644
index 0000000..5cb2c94
--- /dev/null
+++ b/wikipedia/Makefile.am
@@ -0,0 +1,52 @@
+## Process this file with automake to produce Makefile.in
+
+# Copyright 2013 Endless Mobile, Inc.
+
+## -----------
+## Makefile.am
+## -----------
+## Please keep this file well-commented.
+
+# Subdirectories where we also want to run make
+SUBDIRS = po
+
+# Our Autoconf macros are kept in the m4/ directory
+ACLOCAL_AMFLAGS = -I m4
+
+# Generated files that 'make clean' should erase
+CLEANFILES =
+DISTCLEANFILES =
+EXTRA_DIST =
+
+# # # BUILD RULES # # #
+
+resource_files = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir)/data --generate-dependencies $(srcdir)/data/endless_brazil.gresource.xml)
+data/endless_brazil.gresource: data/endless_brazil.gresource.xml $(resource_files)
+ $(AM_V_GEN) $(MKDIR_P) $(builddir)/data && \
+ $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir)/data $<
+CLEANFILES += data/endless_brazil.gresource
+
+eos-brazil: Makefile
+ echo "gjs $(pkgdatadir)/src/endless_brazil.js" >$@
+CLEANFILES += eos-brazil
+
+# # # INSTALL RULES # # #
+
+js_sources = \
+ src/endless_brazil.js \
+ src/endless_wikipedia/EndlessWikipedia.js \
+ src/endless_wikipedia/PrebuiltWikipediaApplication.js \
+ $(NULL)
+nobase_pkgdata_DATA = \
+ data/endless_brazil.gresource \
+ $(js_sources) \
+ $(NULL)
+bin_SCRIPTS = eos-brazil
+
+EXTRA_DIST += \
+ $(js_sources) \
+ $(resource_files) \
+ data/endless_brazil.gresource.xml \
+ $(NULL)
+
+# # # TESTS # # #
diff --git a/wikipedia/README.md b/wikipedia/README.md
new file mode 100644
index 0000000..efcaa65
--- /dev/null
+++ b/wikipedia/README.md
@@ -0,0 +1,4 @@
+eos-wikipedia-brazil
+====================
+
+Brazil application based on the wikipedia database
diff --git a/wikipedia/autogen.sh b/wikipedia/autogen.sh
new file mode 100755
index 0000000..b8e046a
--- /dev/null
+++ b/wikipedia/autogen.sh
@@ -0,0 +1,40 @@
+# Bootstrap script for Endless Programming app
+# Run this script on a clean source checkout to get ready for building.
+
+FILE_MUST_EXIST=src/endless_brazil.js
+POT_FILE=po/eos-brazil.pot
+
+test -n "$srcdir" || srcdir=`dirname "$0"`
+test -n "$srcdir" || srcdir=.
+olddir=`pwd`
+
+cd $srcdir
+test -f $FILE_MUST_EXIST || {
+ echo "You must run this script in the top-level checkout directory"
+ exit 1
+}
+
+# Install our commit message script if a git repo
+if [ -d .git ]; then
+ cp commit-msg .git/hooks/commit-msg
+ chmod +x .git/hooks/commit-msg
+fi
+
+# GNU gettext automake support doesn't get along with git
+# https://bugzilla.gnome.org/show_bug.cgi?id=661128
+touch -t 200001010000 $POT_FILE
+
+# NOCONFIGURE is used by gnome-common
+if test -z "$NOCONFIGURE"; then
+ echo "This script will run ./configure automatically. If you wish to pass "
+ echo "any arguments to it, please specify them on the $0 "
+ echo "command line. To disable this behavior, have NOCONFIGURE=1 in your "
+ echo "environment."
+fi
+
+# Run the actual tools to prepare the clean checkout
+autoreconf -fi || exit $?
+rm -f po/Makevars.template
+
+cd "$olddir"
+test -n "$NOCONFIGURE" || "./configure" "$@"
diff --git a/wikipedia/commit-msg b/wikipedia/commit-msg
new file mode 100644
index 0000000..7e5992f
--- /dev/null
+++ b/wikipedia/commit-msg
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+# move this script to the .git/hooks directory for your repo.
+# make sure to chmod +x .git/hooks/commit-msg
+
+repo=$(basename `git rev-parse --show-toplevel`)
+branch=`git rev-parse --abbrev-ref HEAD`
+
+if [[ $branch == issues/* ]]; then
+ issue=$(echo "$branch" | awk -F/ '{ print $2 }')
+ link="[endlessm/$repo#$issue]"
+ echo "issue link: $link"
+ echo $link >> $1
+fi
+
+exit 0
diff --git a/wikipedia/configure.ac b/wikipedia/configure.ac
new file mode 100644
index 0000000..edb9dad
--- /dev/null
+++ b/wikipedia/configure.ac
@@ -0,0 +1,69 @@
+dnl Process this file with autoconf to produce configure
+
+# Copyright 2013 Endless Mobile, Inc.
+
+dnl ------------
+dnl configure.ac
+dnl ------------
+dnl Please keep this file well-commented. Autotools involve a lot of magical
+dnl incantations, and it is easy to mess things up if you don't know what you
+dnl are doing.
+
+# Initialization
+# --------------
+# Initialize Autoconf: package name, version, bug report address, tarball name,
+# website
+AC_INIT([Endless Brazil], [0],
+ [], [eos-brazil], [http://endlessm.com])
+# Initialize Automake: enable all warnings and do not insist on GNU standards
+# no-portability suppresses warnings about syntax specific to GNU make
+AM_INIT_AUTOMAKE([-Wall -Wno-portability foreign 1.11])
+# Avoid spewing garbage over the terminal ('make V=1' to see the garbage)
+AM_SILENT_RULES([yes])
+# Keep Autotools macros local to this source tree
+AC_CONFIG_MACRO_DIR([m4])
+
+AC_CACHE_SAVE
+
+# Required versions of libraries
+# Update these whenever you use a function that requires a certain API version
+EOS_SDK_REQUIREMENT="endless-0"
+
+# Gettext package name
+GETTEXT_PACKAGE=$PACKAGE
+AC_SUBST(GETTEXT_PACKAGE)
+AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, ["$GETTEXT_PACKAGE"],
+ [Package name for Gettext])
+# Detect which languages are available
+AS_ALL_LINGUAS
+
+# Required build tools
+# --------------------
+# Make sure we can create directory hierarchies
+AC_PROG_MKDIR_P
+# Library configuration tool
+PKG_PROG_PKG_CONFIG
+# Gettext
+AM_GNU_GETTEXT([external])
+AM_GNU_GETTEXT_VERSION([0.18.1])
+# Various tools
+GLIB_COMPILE_RESOURCES=`$PKG_CONFIG --variable glib_compile_resources gio-2.0`
+AC_SUBST(GLIB_COMPILE_RESOURCES)
+
+AC_CACHE_SAVE
+
+# Required libraries
+# ------------------
+PKG_CHECK_MODULES([EOS_BRAZIL], [$EOS_SDK_REQUIREMENT])
+
+AC_CACHE_SAVE
+
+# Output
+# ------
+# List files here that the configure script should output
+AC_CONFIG_FILES([
+ Makefile
+ po/Makefile.in
+])
+# Do the output
+AC_OUTPUT
diff --git a/wikipedia/data/category_images/cuisine.jpg b/wikipedia/data/category_images/cuisine.jpg
new file mode 100644
index 0000000..860ec32
--- /dev/null
+++ b/wikipedia/data/category_images/cuisine.jpg
Binary files differ
diff --git a/wikipedia/data/category_images/history.jpg b/wikipedia/data/category_images/history.jpg
new file mode 100644
index 0000000..57bab62
--- /dev/null
+++ b/wikipedia/data/category_images/history.jpg
Binary files differ
diff --git a/wikipedia/data/css/endless_brazil.css b/wikipedia/data/css/endless_brazil.css
new file mode 100644
index 0000000..42d8382
--- /dev/null
+++ b/wikipedia/data/css/endless_brazil.css
@@ -0,0 +1,28 @@
+* {
+ font-family: "Benton Sans";
+}
+
+.title {
+ font-size: 48pt;
+}
+
+.title.category.front-page {
+ font-size: 36pt;
+ color: #a0a0a0;
+}
+
+Gjs_ArticleList .button {
+ border-top: 1px solid #555753;
+ padding: 10px;
+ background-color: #d3d7cf;
+ color: black;
+}
+
+Gjs_ArticleList .button:hover {
+ color: #555753;
+}
+
+.articles-page {
+ color: black;
+ background-color: #babdb6;
+} \ No newline at end of file
diff --git a/wikipedia/data/endless_brazil.gresource.xml b/wikipedia/data/endless_brazil.gresource.xml
new file mode 100644
index 0000000..7b9f502
--- /dev/null
+++ b/wikipedia/data/endless_brazil.gresource.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/com/endlessm/brazil">
+ <file compressed="true">brazil_categories.json</file>
+ <file compressed="true">css/endless_brazil.css</file>
+ <file>category_images/cuisine.jpg</file>
+ <file>category_images/history.jpg</file>
+ </gresource>
+</gresources>
diff --git a/wikipedia/m4/as-linguas.m4 b/wikipedia/m4/as-linguas.m4
new file mode 100644
index 0000000..8b4e07f
--- /dev/null
+++ b/wikipedia/m4/as-linguas.m4
@@ -0,0 +1,26 @@
+# Set ALL_LINGUAS based on the .po files present. Optional argument is the
+# name of the po directory. $podir/LINGUAS.ignore can be used to ignore a
+# subset of the po files.
+
+# Public domain, according to Emmanuele
+
+AC_DEFUN([AS_ALL_LINGUAS],
+[
+ AC_MSG_CHECKING([for linguas])
+ podir="m4_default([$1],[$srcdir/po])"
+ linguas=`cd $podir && ls *.po 2>/dev/null | awk 'BEGIN { FS="."; ORS=" " } { print $[]1 }'`
+ if test -f "$podir/LINGUAS.ignore"; then
+ ALL_LINGUAS="";
+ ignore_linguas=`sed -n -e 's/^\s\+\|\s\+$//g' -e '/^#/b' -e '/\S/!b' \
+ -e 's/\s\+/\n/g' -e p "$podir/LINGUAS.ignore"`;
+ for lang in $linguas; do
+ if ! echo "$ignore_linguas" | grep -q "^${lang}$"; then
+ ALL_LINGUAS="$ALL_LINGUAS $lang";
+ fi;
+ done;
+ else
+ ALL_LINGUAS="$linguas";
+ fi;
+ AC_SUBST([ALL_LINGUAS])
+ AC_MSG_RESULT($ALL_LINGUAS)
+])
diff --git a/wikipedia/po/Makevars b/wikipedia/po/Makevars
new file mode 100644
index 0000000..095c32a
--- /dev/null
+++ b/wikipedia/po/Makevars
@@ -0,0 +1,41 @@
+# Makefile variables for PO directory in any package using GNU gettext.
+
+# Usually the message domain is the same as the package name.
+DOMAIN = $(PACKAGE)
+
+# These two variables depend on the location of this directory.
+subdir = po
+top_builddir = ..
+
+# These options get passed to xgettext.
+XGETTEXT_OPTIONS = --keyword=_ --keyword=N_
+
+# This is the copyright holder that gets inserted into the header of the
+# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding
+# package. (Note that the msgstr strings, extracted from the package's
+# sources, belong to the copyright holder of the package.) Translators are
+# expected to transfer the copyright for their translations to this person
+# or entity, or to disclaim their copyright. The empty string stands for
+# the public domain; in this case the translators are expected to disclaim
+# their copyright.
+COPYRIGHT_HOLDER = Endless Mobile, Inc.
+
+# This is the email address or URL to which the translators shall report
+# bugs in the untranslated strings:
+# - Strings which are not entire sentences, see the maintainer guidelines
+# in the GNU gettext documentation, section 'Preparing Strings'.
+# - Strings which use unclear terms or require additional context to be
+# understood.
+# - Strings which make invalid assumptions about notation of date, time or
+# money.
+# - Pluralisation problems.
+# - Incorrect English spelling.
+# - Incorrect formatting.
+# It can be your email address, or a mailing list address where translators
+# can write to without being subscribed, or the URL of a web page through
+# which the translators can contact you.
+MSGID_BUGS_ADDRESS = philip@endlessm.com
+
+# This is the list of locale categories, beyond LC_MESSAGES, for which the
+# message catalogs shall be used. It is usually empty.
+EXTRA_LOCALE_CATEGORIES =
diff --git a/wikipedia/po/POTFILES.in b/wikipedia/po/POTFILES.in
new file mode 100644
index 0000000..fc8cc34
--- /dev/null
+++ b/wikipedia/po/POTFILES.in
@@ -0,0 +1 @@
+src/endless_wikipedia/PrebuiltWikipediaApplication.js \ No newline at end of file
diff --git a/wikipedia/po/eos-brazil.pot b/wikipedia/po/eos-brazil.pot
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wikipedia/po/eos-brazil.pot
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;
+ },
+});