[gnome-characters/wip/dueno/emoji: 5/5] WIP
- From: Daiki Ueno <dueno src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-characters/wip/dueno/emoji: 5/5] WIP
- Date: Mon, 21 Aug 2017 05:03:05 +0000 (UTC)
commit 5d3d54cc48bb66fbc571035d9844427eda6bb111
Author: Daiki Ueno <dueno src gnome org>
Date: Fri Aug 18 17:29:58 2017 +0200
WIP
data/mainwindow.ui | 18 +++++
src/categoryList.js | 199 ++++++++++++++++++++++++++++++++++++++++++++------
src/window.js | 108 ++++++++++++++++++++++------
3 files changed, 279 insertions(+), 46 deletions(-)
---
diff --git a/data/mainwindow.ui b/data/mainwindow.ui
index b807448..000414f 100644
--- a/data/mainwindow.ui
+++ b/data/mainwindow.ui
@@ -29,6 +29,24 @@
</packing>
</child>
<child>
+ <object class="GtkButton" id="back-button">
+ <property name="can_focus">True</property>
+ <property name="visible">False</property>
+ <style>
+ <class name="image-button"/>
+ </style>
+ <child>
+ <object class="GtkImage" id="back-button-image">
+ <property name="visible">True</property>
+ <property name="icon-name">go-previous-symbolic</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="pack-type">start</property>
+ </packing>
+ </child>
+ <child>
<object class="GtkMenuButton" id="menu-button">
<property name="can_focus">False</property>
<property name="visible">True</property>
diff --git a/src/categoryList.js b/src/categoryList.js
index fbb5833..673c148 100644
--- a/src/categoryList.js
+++ b/src/categoryList.js
@@ -1,6 +1,6 @@
// -*- Mode: js; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*-
//
-// Copyright (C) 2014-2015 Daiki Ueno <dueno src gnome org>
+// Copyright (C) 2014-2017 Daiki Ueno <dueno src gnome org>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@@ -26,60 +26,129 @@ const Gettext = imports.gettext;
const Gc = imports.gi.Gc;
const Util = imports.util;
-const BaseCategoryList = [
- {
- name: 'recent',
- category: Gc.Category.NONE,
- title: N_('Recently Used'),
- icon_name: 'document-open-recent-symbolic'
- },
+const LetterCategoryList = [
{
name: 'punctuation',
category: Gc.Category.PUNCTUATION,
title: N_('Punctuation'),
- icon_name: 'characters-punctuation-symbolic'
+ icon_name: 'characters-punctuation-symbolic',
+ action_name: 'subcategory'
},
{
name: 'arrow',
category: Gc.Category.ARROW,
title: N_('Arrows'),
- icon_name: 'characters-arrow-symbolic'
+ icon_name: 'characters-arrow-symbolic',
+ action_name: 'subcategory'
},
{
name: 'bullet',
category: Gc.Category.BULLET,
title: N_('Bullets'),
- icon_name: 'characters-bullet-symbolic'
+ icon_name: 'characters-bullet-symbolic',
+ action_name: 'subcategory'
},
{
name: 'picture',
category: Gc.Category.PICTURE,
title: N_('Pictures'),
- icon_name: 'characters-picture-symbolic'
+ icon_name: 'characters-picture-symbolic',
+ action_name: 'subcategory'
},
{
name: 'currency',
category: Gc.Category.CURRENCY,
title: N_('Currencies'),
- icon_name: 'characters-currency-symbolic'
+ icon_name: 'characters-currency-symbolic',
+ action_name: 'subcategory'
},
{
name: 'math',
category: Gc.Category.MATH,
title: N_('Math'),
- icon_name: 'characters-math-symbolic'
+ icon_name: 'characters-math-symbolic',
+ action_name: 'subcategory'
},
{
name: 'letters',
category: Gc.Category.LATIN,
title: N_('Letters'),
- icon_name: 'characters-latin-symbolic'
+ icon_name: 'characters-latin-symbolic',
+ action_name: 'subcategory'
+ }
+];
+
+const EmojiCategoryList = [
+ {
+ name: 'recent',
+ category: Gc.Category.NONE,
+ title: N_('Recently Used'),
+ icon_name: 'document-open-recent-symbolic',
+ action_name: 'subcategory'
+ },
+ {
+ name: 'emoji-smileys',
+ category: Gc.Category.EMOJI_SMILEYS,
+ title: N_('Smileys & People'),
+ icon_name: 'characters-emoji-smileys',
+ action_name: 'subcategory'
+ },
+ {
+ name: 'emoji-animals',
+ category: Gc.Category.EMOJI_ANIMALS,
+ title: N_('Animals & Nature'),
+ icon_name: 'characters-emoji-animals',
+ action_name: 'subcategory'
+ },
+ {
+ name: 'emoji-food',
+ category: Gc.Category.EMOJI_FOOD,
+ title: N_('Food & Drink'),
+ icon_name: 'characters-emoji-food',
+ action_name: 'subcategory'
+ },
+ {
+ name: 'emoji-activities',
+ category: Gc.Category.EMOJI_ACTIVITIES,
+ title: N_('Activities'),
+ icon_name: 'characters-emoji-activities',
+ action_name: 'subcategory'
},
{
- name: 'emoticon',
- category: Gc.Category.EMOTICON,
- title: N_('Emoticons'),
- icon_name: 'face-smile-symbolic'
+ name: 'emoji-travel',
+ category: Gc.Category.EMOJI_TRAVEL,
+ title: N_('Travel & Places'),
+ icon_name: 'characters-emoji-travel',
+ action_name: 'subcategory'
+ },
+ {
+ name: 'emoji-objects',
+ category: Gc.Category.EMOJI_OBJECTS,
+ title: N_('Objects'),
+ icon_name: 'characters-emoji-objects',
+ action_name: 'subcategory'
+ },
+ {
+ name: 'emoji-symbols',
+ category: Gc.Category.EMOJI_SYMBOLS,
+ title: N_('Symbols'),
+ icon_name: 'characters-emoji-symbols',
+ action_name: 'subcategory'
+ },
+ {
+ name: 'emoji-flags',
+ category: Gc.Category.EMOJI_FLAGS,
+ title: N_('Flags'),
+ icon_name: 'characters-emoji-flags',
+ action_name: 'subcategory'
+ },
+ {
+ name: 'letters',
+ category: Gc.Category.NONE,
+ title: N_('Letters & Symbols'),
+ icon_name: 'characters-latin-symbolic',
+ secondary_icon_name: 'go-next-symbolic',
+ action_name: 'category',
}
];
@@ -106,11 +175,18 @@ const CategoryListRowWidget = new Lang.Class({
halign: Gtk.Align.START });
label.get_style_context().add_class('category-label');
hbox.pack_start(label, true, true, 0);
+
+ if (category.secondary_icon_name) {
+ let icon = new Gio.ThemedIcon({ name: category.secondary_icon_name });
+ let image = Gtk.Image.new_from_gicon(icon, Gtk.IconSize.BUTTON);
+ image.get_style_context().add_class('category-icon');
+ hbox.pack_start(image, false, false, 2);
+ }
}
});
-var CategoryListWidget = new Lang.Class({
- Name: 'CategoryListWidget',
+const LetterCategoryListWidget = new Lang.Class({
+ Name: 'LetterCategoryListWidget',
Extends: Gtk.ListBox,
_init: function(params) {
@@ -132,8 +208,8 @@ var CategoryListWidget = new Lang.Class({
vfunc_row_selected: function(row) {
if (row != null) {
let toplevel = row.get_toplevel();
- let category = toplevel.lookup_action('category');
- category.activate(new GLib.Variant('s', row.category.name));
+ let action = toplevel.lookup_action('subcategory');
+ action.activate(new GLib.Variant('s', row.category.name));
}
},
@@ -248,7 +324,7 @@ var CategoryListWidget = new Lang.Class({
if (this._categoryList != null)
return;
- this._categoryList = BaseCategoryList.slice();
+ this._categoryList = LetterCategoryList.slice();
// Populate the "scripts" element of the "Letter" category
// object, based on the current locale and the input-sources
@@ -281,3 +357,78 @@ var CategoryListWidget = new Lang.Class({
return null;
}
});
+
+const EmojiCategoryListWidget = new Lang.Class({
+ Name: 'EmojiCategoryListWidget',
+ Extends: Gtk.ListBox,
+
+ _init: function(params) {
+ params = Params.fill(params, {});
+ this.parent(params);
+
+ this.get_style_context().add_class('categories');
+
+ this._categoryList = EmojiCategoryList.slice();
+
+ for (let index in this._categoryList) {
+ let category = this._categoryList[index];
+ let rowWidget = new CategoryListRowWidget({}, category);
+ rowWidget.get_style_context().add_class('category');
+ // Add a separator over the "Letters & Symbols" category
+ if (category.name == 'letters') {
+ let separator = new Gtk.Separator();
+ let separatorRowWidget = new Gtk.ListBoxRow({
+ selectable: false
+ });
+ separatorRowWidget.add(separator);
+ this.add(separatorRowWidget);
+ }
+ this.add(rowWidget);
+ }
+ },
+
+ vfunc_row_selected: function(row) {
+ if (row != null && row.selectable) {
+ let toplevel = row.get_toplevel();
+ let action = toplevel.lookup_action(row.category.action_name);
+ action.activate(new GLib.Variant('s', row.category.name));
+ }
+ },
+
+ getCategoryList: function() {
+ return this._categoryList;
+ },
+
+ getCategory: function(name) {
+ for (let index in this._categoryList) {
+ let category = this._categoryList[index];
+ if (category.name == name)
+ return category;
+ }
+ return null;
+ }
+});
+
+var CategoryListView = new Lang.Class({
+ Name: 'CategoryListView',
+ Extends: Gtk.Stack,
+
+ _init: function(params) {
+ params = Params.fill(params, {
+ hexpand: true, vexpand: true,
+ transition_type: Gtk.StackTransitionType.SLIDE_RIGHT
+ });
+ this.parent(params);
+
+ let emojiCategoryList = new EmojiCategoryListWidget({});
+ this.add_named(emojiCategoryList, 'emojis');
+ let letterCategoryList = new LetterCategoryListWidget({});
+ this.add_named(letterCategoryList, 'letters');
+
+ this.set_visible_child_name('emojis');
+ },
+
+ getCategoryList: function() {
+ return ['emojis', 'letters'];
+ }
+});
diff --git a/src/window.js b/src/window.js
index 83acdb4..580f70c 100644
--- a/src/window.js
+++ b/src/window.js
@@ -24,6 +24,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+const Gc = imports.gi.Gc;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
@@ -44,7 +45,7 @@ var MainWindow = new Lang.Class({
Extends: Gtk.ApplicationWindow,
Template: 'resource:///org/gnome/Characters/mainwindow.ui',
InternalChildren: ['main-headerbar', 'search-active-button',
- 'search-bar', 'search-entry',
+ 'search-bar', 'search-entry', 'back-button',
'menu-button',
'main-grid', 'main-hbox', 'sidebar-grid'],
Properties: {
@@ -74,7 +75,11 @@ var MainWindow = new Lang.Class({
{ name: 'category',
activate: this._category,
parameter_type: new GLib.VariantType('s'),
- state: new GLib.Variant('s', 'punctuation') },
+ state: new GLib.Variant('s', 'emojis') },
+ { name: 'subcategory',
+ activate: this._subcategory,
+ parameter_type: new GLib.VariantType('s'),
+ state: new GLib.Variant('s', 'emoji-smileys') },
{ name: 'character',
activate: this._character,
parameter_type: new GLib.VariantType('s') },
@@ -96,24 +101,31 @@ var MainWindow = new Lang.Class({
this._search_entry.connect('search-changed',
Lang.bind(this, this._handleSearchChanged));
+ this._back_button.connect('clicked',
+ Lang.bind(this, function() {
+ let action = this.lookup_action('category');
+ action.activate(new GLib.Variant('s', 'emojis'));
+ }));
+ this._back_button.bind_property('visible',
+ this._search_active_button, 'visible',
+ GObject.BindingFlags.SYNC_CREATE |
+ GObject.BindingFlags.INVERT_BOOLEAN);
+
this._menu_popover = new Menu.MenuPopover({});
this._menu_button.set_popover(this._menu_popover);
- this._categoryList =
- new CategoryList.CategoryListWidget({ vexpand: true });
+ this._categoryListView =
+ new CategoryList.CategoryListView({ vexpand: true });
let scroll = new Gtk.ScrolledWindow({
hscrollbar_policy: Gtk.PolicyType.NEVER,
hexpand: false,
});
- scroll.add(this._categoryList);
+ scroll.add(this._categoryListView);
this._sidebar_grid.add(scroll);
- this._mainView = new MainView({ categoryList: this._categoryList });
-
- if (this._mainView.recentCharacters.length == 0) {
- let row = this._categoryList.get_row_at_index(1);
- this._categoryList.select_row(row);
- }
+ this._mainView = new MainView({
+ categoryListView: this._categoryListView
+ });
this._main_hbox.pack_start(this._mainView, true, true, 0);
this._main_grid.show_all();
@@ -123,6 +135,22 @@ var MainWindow = new Lang.Class({
this.connect('key-press-event', Lang.bind(this, this._handleKeyPress));
},
+ vfunc_map: function() {
+ this.parent();
+ this._selectFirstSubcategory();
+ },
+
+ // Select the first subcategory which contains at least one character.
+ _selectFirstSubcategory: function() {
+ let categoryList = this._categoryListView.get_visible_child();
+ let index = 0;
+ let row = categoryList.get_row_at_index(index);
+ if (row.category.name == 'recent' &&
+ this._mainView.recentCharacters.length == 0)
+ index++;
+ categoryList.select_row(categoryList.get_row_at_index(index));
+ },
+
get search_active() {
return this._searchActive;
},
@@ -200,7 +228,35 @@ var MainWindow = new Lang.Class({
let [name, length] = v.get_string()
- let category = this._categoryList.getCategory(name);
+ this._categoryListView.set_visible_child_name(name);
+ let categoryList = this._categoryListView.get_visible_child();
+ if (categoryList == null)
+ return;
+
+ this._selectFirstSubcategory();
+ let category = categoryList.get_selected_row().category;
+
+ if (name == 'emojis') {
+ this._back_button.hide();
+ } else {
+ this._back_button.show();
+ }
+
+ Util.assertNotEqual(category, null);
+ this._mainView.setPage(category);
+ this._updateTitle(category.title);
+ },
+
+ _subcategory: function(action, v) {
+ this.search_active = false;
+
+ let [name, length] = v.get_string()
+
+ let categoryList = this._categoryListView.get_visible_child();
+ if (categoryList == null)
+ return;
+
+ let category = categoryList.getCategory(name);
Util.assertNotEqual(category, null);
this._mainView.setPage(category);
@@ -262,7 +318,7 @@ const MainView = new Lang.Class({
},
_init: function(params) {
- let filtered = Params.filter(params, { categoryList: null });
+ let filtered = Params.filter(params, { categoryListView: null });
params = Params.fill(params, {
hexpand: true, vexpand: true,
transition_type: Gtk.StackTransitionType.CROSSFADE
@@ -271,17 +327,25 @@ const MainView = new Lang.Class({
this._filterFontFamily = null;
this._characterLists = {};
- this._categoryList = filtered.categoryList;
+ this._categoryListView = filtered.categoryListView;
let characterList;
- let categories = this._categoryList.getCategoryList();
- for (let index in categories) {
- let category = categories[index];
- characterList = this._createCharacterList(
- category.name, _('%s Character List').format(category.title));
- // FIXME: Can't use GtkContainer.child_get_property.
- characterList.title = category.title;
- this.add_titled(characterList, category.name, category.title);
+ let categories = this._categoryListView.getCategoryList();
+
+ for (let i in categories) {
+ let category = categories[i];
+ let categoryList = this._categoryListView.get_child_by_name(category);
+ let subcategories = categoryList.getCategoryList();
+ for (let j in subcategories) {
+ let subcategory = subcategories[j];
+ if (subcategory.action_name != 'subcategory')
+ continue;
+ characterList = this._createCharacterList(
+ subcategory.name, _('%s Character List').format(subcategory.title));
+ // FIXME: Can't use GtkContainer.child_get_property.
+ characterList.title = subcategory.title;
+ this.add_titled(characterList, subcategory.name, subcategory.title);
+ }
}
characterList = this._createCharacterList(
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]