diff options
author | rmacqueen <rorymacqueen@gmail.com> | 2013-07-31 20:12:11 -0700 |
---|---|---|
committer | rmacqueen <rorymacqueen@gmail.com> | 2013-07-31 20:12:11 -0700 |
commit | b3c6b3d7f27e5b35e6ef40ba566eec346a9eb94b (patch) | |
tree | 3d3dc8b596deeb4f5bd442b92268c4a61a82023c /wikipedia | |
parent | 57a5e900af89b74cdebb67955ab37dff85d2400a (diff) | |
parent | 1bb95b00195b2ad561c7239773e7c936f44b8962 (diff) |
Merge pull request #204 from endlessm/issues/182
Issues/182
Diffstat (limited to 'wikipedia')
-rw-r--r-- | wikipedia/data/css/endless_brazil.css | 17 | ||||
-rw-r--r-- | wikipedia/src/endless_wikipedia/EndlessWikipedia.js | 3 | ||||
-rw-r--r-- | wikipedia/src/endless_wikipedia/PrebuiltFrontPage.js | 33 | ||||
-rw-r--r-- | wikipedia/src/presenters/domain_wiki_presenter.js | 2 | ||||
-rw-r--r-- | wikipedia/src/utils.js | 8 | ||||
-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.js | 65 | ||||
-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.js | 16 | ||||
-rw-r--r-- | wikipedia/src/views/title_label_view.js | 102 |
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); + } +}); |