[gtk+/wip/matthiasc/emoji-picker: 9/11] more wip



commit 03d3e25eb7ed1648657d7954a4e4814e0ad30e71
Author: Matthias Clasen <mclasen redhat com>
Date:   Sun Aug 6 17:36:47 2017 -0400

    more wip

 tests/gtkemojipicker.c  |  556 +++++++++++++++++++++++++++++++++++++++++++++--
 tests/gtkemojipicker.ui |  112 +++++++++-
 tests/testentryicons.c  |   19 ++-
 3 files changed, 660 insertions(+), 27 deletions(-)
---
diff --git a/tests/gtkemojipicker.c b/tests/gtkemojipicker.c
index b798e3c..2ec4e68 100644
--- a/tests/gtkemojipicker.c
+++ b/tests/gtkemojipicker.c
@@ -9,6 +9,162 @@ typedef struct {
   gunichar code2;
 } EmojiData;
 
+#if 0
+static gunichar people_plain[] = {
+  // face-positive
+  0x1f600, 0x1f601, 0x1f602, 0x1f923, 0x1f603, 0x1f604, 0x1f605, 0x1f606, 0x1f609, 0x1f60a,
+  0x1f60b, 0x1f60e, 0x1f60d, 0x1f618, 0x1f617, 0x1f619, 0x1f61a, 0x1f642, 0x1f917, 0x1f929,
+  // face-neutral
+  0x1f914, 0x1f928, 0x1f610, 0x1f611, 0x1f636, 0x1f644, 0x1f60f, 0x1f623, 0x1f625, 0x1f62e,
+  0x1f910, 0x1f62f, 0x1f62a, 0x1f62b, 0x1f634, 0x1f60c, 0x1f61b, 0x1f61c, 0x1f61d, 0x1f924,
+  0x1f612, 0x1f613, 0x1f614, 0x1f615, 0x1f643, 0x1f911, 0x1f632,
+  //face-negative
+  0x02639, 0x1f641, 0x1f616, 0x1f61e, 0x1f61f, 0x1f624, 0x1f622, 0x1f62d, 0x1f626, 0x1f627,
+  0x1f628, 0x1f629, 0x1f92f, 0x1f62c, 0x1f630, 0x1f631, 0x1f633, 0x1f92a, 0x1f635, 0x1f621,
+  0x1f620, 0x1f92c,
+  // face-sick
+  0x1f637, 0x1f912, 0x1f915, 0x1f922, 0x1f92e, 0x1f927,
+  // face-role
+  0x1f607, 0x1f920, 0x1f921, 0x1f925, 0x1f92b, 0x1f92d, 0x1f9d0, 0x1f913,
+  // face-fantasy
+  0x1f608, 0x1f47f, 0x1f479, 0x1f47a, 0x1f480, 0x02620, 0x1f47b, 0x1f47d, 0x1f47e, 0x1f916,
+  0x1f4a9,
+  // cat-face
+  0x1f63a, 0x1f638, 0x1f63b, 0x1f63c, 0x1f63d, 0x1f640, 0x1f63f, 0x1f63e,
+  // monkey-face
+  0x1f648, 0x1f649, 0x1f64a
+};
+
+static gunichar people_skin[] = {
+  // person
+  0x1f476, 0x1f9d2, 0x1f466, 0x1f467, 0x1f9d1, 0x1f468, 0x1f469, 0x1f9d3, 0x1f474, 0x1f475,
+  // person-role
+  //{ 0x1f468, 1, 0x02695 },
+  //{ 0x1f469, 1, 0x02695 },
+  //{ 0x1f468, 1, 0x1f393 },
+  //{ 0x1f469, 1, 0x1f393 },
+  //{ 0x1f468, 1, 0x1f3eb },
+  //{ 0x1f469, 1, 0x1f3eb },
+  //{ 0x1f468, 1, 0x02696 },
+  //{ 0x1f469, 1, 0x02696 },
+  //{ 0x1f468, 1, 0x1f33e },
+  //{ 0x1f469, 1, 0x1f33e },
+  //{ 0x1f468, 1, 0x1f373 },
+  //{ 0x1f469, 1, 0x1f373 },
+  //{ 0x1f468, 1, 0x1f527 },
+  //{ 0x1f469, 1, 0x1f527 },
+  //{ 0x1f468, 1, 0x1f3ed },
+  //{ 0x1f469, 1, 0x1f3ed },
+  //{ 0x1f468, 1, 0x1f4bc },
+  //{ 0x1f469, 1, 0x1f4bc },
+  //{ 0x1f468, 1, 0x1f52c },
+  //{ 0x1f469, 1, 0x1f52c },
+  //{ 0x1f468, 1, 0x1f4bb },
+  //{ 0x1f469, 1, 0x1f4bb },
+  //{ 0x1f468, 1, 0x1f3a4 },
+  //{ 0x1f469, 1, 0x1f3a4 },
+  //{ 0x1f468, 1, 0x1f3a8 },
+  //{ 0x1f469, 1, 0x1f3a8 },
+  //{ 0x1f468, 1, 0x02708 },
+  //{ 0x1f469, 1, 0x02708 },
+  //{ 0x1f468, 1, 0x1f680 },
+  //{ 0x1f469, 1, 0x1f680 },
+  //{ 0x1f468, 1, 0x1f692 },
+  //{ 0x1f469, 1, 0x1f692 },
+  0x1f46e,
+  //{ 0x1f46e, 1, 0x2642 },
+  //{ 0x1f46e, 1, 0x2640 },
+  0x1f575,
+  //{ 0x1f575, 1, 0x2642 },
+  //{ 0x1f575, 1, 0x2640 },
+  0x1f482,
+  //{ 0x1f482, 1, 0x2642 },
+  //{ 0x1f482, 1, 0x2640 },
+  0x1f477,
+  //{ 0x1f477, 1, 0x2642 },
+  //{ 0x1f477, 1, 0x2640 },
+  0x1f934,
+  //{ 0x1f934, 1, 0x2642 },
+  //{ 0x1f934, 1, 0x2640 },
+  0x1f478,
+  //{ 0x1f478, 1, 0x2642 },
+  //{ 0x1f478, 1, 0x2640 },
+  0x1f473,
+  //{ 0x1f473, 1, 0x2642 },
+  //{ 0x1f473, 1, 0x2640 },
+  0x1f472,
+  0x1f9d5,
+  0x1f9d4,
+  0x1f471,
+  //{ 0x1f471, 1, 0x2642 },
+  //{ 0x1f471, 1, 0x2640 },
+  0x1f935,
+  0x1f470,
+  0x1f930,
+  0x1f931,
+  // person-fantasy
+  0x1f47c,
+  0x1f385,
+  0x1f936,
+  0x1f9d9,
+  //{ 0x1f9d9, 1, 0x2642 },
+  //{ 0x1f9d9, 1, 0x2640 },
+  //...
+  // person-gesture
+  0x1f64d,
+  //{ 0x1f64d, 1, 0x2642 },
+  //{ 0x1f64d, 1, 0x2640 },
+  0x1f64e,
+  //{ 0x1f64e, 1, 0x2642 },
+  //{ 0x1f64e, 1, 0x2640 },
+  0x1f645,
+  //{ 0x1f645, 1, 0x2642 },
+  //{ 0x1f645, 1, 0x2640 },
+  0x1f646,
+  //{ 0x1f646, 1, 0x2642 },
+  //{ 0x1f646, 1, 0x2640 },
+  0x1f481,
+  //{ 0x1f481, 1, 0x2642 },
+  //{ 0x1f481, 1, 0x2640 },
+  0x1f64b,
+  //{ 0x1f64b, 1, 0x2642 },
+  //{ 0x1f64b, 1, 0x2640 },
+  0x1f647,
+  //{ 0x1f647, 1, 0x2642 },
+  //{ 0x1f647, 1, 0x2640 },
+  0x1f926,
+  //{ 0x1f926, 1, 0x2642 },
+  //{ 0x1f926, 1, 0x2640 },
+  0x1f937,
+  //{ 0x1f937, 1, 0x2642 },
+  //{ 0x1f937, 1, 0x2640 },
+  // person-activity
+  0x1f486,
+  //{ 0x1f486, 1, 0x2642 },
+  //{ 0x1f486, 1, 0x2640 },
+  0x1f487,
+  //{ 0x1f487, 1, 0x2642 },
+  //{ 0x1f487, 1, 0x2640 },
+  0x1f6b6,
+  //{ 0x1f6b6, 1, 0x2642 },
+  //{ 0x1f6b6, 1, 0x2640 },
+  0x1f3c3,
+  //{ 0x1f3c3, 1, 0x2642 },
+  //{ 0x1f3c3, 1, 0x2640 },
+  0x1f483,
+  0x1f57a,
+  0x1f46f,
+  //{ 0x1f46f, 1, 0x2642 },
+  //{ 0x1f46f, 1, 0x2640 },
+  //...
+  // person-sport
+  // family
+  // body
+  // emotion
+  // clothing
+};
+#endif
+
 static EmojiData people[] = {
   // face-positive
   { 0x1f600, 0, 0 },
@@ -30,10 +186,10 @@ static EmojiData people[] = {
   { 0x1f61a, 0, 0 },
   { 0x1f642, 0, 0 },
   { 0x1f917, 0, 0 },
-  //{ 0x1f929, 0, 0 },
+  { 0x1f929, 0, 0 },
   // face-neutral
   { 0x1f914, 0, 0 },
-  //{ 0x1f928, 0 },
+  { 0x1f928, 0, 0 },
   { 0x1f610, 0, 0 },
   { 0x1f611, 0, 0 },
   { 0x1f636, 0, 0 },
@@ -72,31 +228,31 @@ static EmojiData people[] = {
   { 0x1f627, 0, 0 },
   { 0x1f628, 0, 0 },
   { 0x1f629, 0, 0 },
-  //{ 0x1f92f, 0, 0 },
+  { 0x1f92f, 0, 0 },
   { 0x1f62c, 0, 0 },
   { 0x1f630, 0, 0 },
   { 0x1f631, 0, 0 },
   { 0x1f633, 0, 0 },
-  //{ 0x1f92a, 0, 0 },
+  { 0x1f92a, 0, 0 },
   { 0x1f635, 0, 0 },
   { 0x1f621, 0, 0 },
   { 0x1f620, 0, 0 },
-  //{ 0x1f92c, 0, 0 },
+  { 0x1f92c, 0, 0 },
   // face-sick
   { 0x1f637, 0, 0 },
   { 0x1f912, 0, 0 },
   { 0x1f915, 0, 0 },
   { 0x1f922, 0, 0 },
-  //{ 0x1f92e, 0, 0 },
+  { 0x1f92e, 0, 0 },
   { 0x1f927, 0, 0 },
   // face-role
   { 0x1f607, 0, 0 },
   { 0x1f920, 0, 0 },
   { 0x1f921, 0, 0 },
   { 0x1f925, 0, 0 },
-  //{ 0x1f92b, 0, 0 },
-  //{ 0x1f92d, 0, 0 },
-  //{ 0x1f9d0, 0, 0 },
+  { 0x1f92b, 0, 0 },
+  { 0x1f92d, 0, 0 },
+  { 0x1f9d0, 0, 0 },
   { 0x1f913, 0, 0 },
   // face-fantasy
   { 0x1f608, 0, 0 },
@@ -189,20 +345,20 @@ static EmojiData people[] = {
   //{ 0x1f473, 1, 0x2642 },
   //{ 0x1f473, 1, 0x2640 },
   { 0x1f472, 1, 0 },
-  //{ 0x1f9d5, 1, 0 },
-  //{ 0x1f9d4, 1, 0 },
+  { 0x1f9d5, 1, 0 },
+  { 0x1f9d4, 1, 0 },
   { 0x1f471, 1, 0 },
   //{ 0x1f471, 1, 0x2642 },
   //{ 0x1f471, 1, 0x2640 },
   { 0x1f935, 1, 0 },
   { 0x1f470, 1, 0 },
   { 0x1f930, 1, 0 },
-  //{ 0x1f931, 1, 0 },
+  { 0x1f931, 1, 0 },
   // person-fantasy
   { 0x1f47c, 1, 0 },
   { 0x1f385, 1, 0 },
   { 0x1f936, 1, 0 },
-  //{ 0x1f9d9, 1, 0 },
+  { 0x1f9d9, 1, 0 },
   //{ 0x1f9d9, 1, 0x2642 },
   //{ 0x1f9d9, 1, 0x2640 },
   //...
@@ -252,21 +408,231 @@ static EmojiData people[] = {
   { 0x1f46f, 1, 0 },
   //{ 0x1f46f, 1, 0x2642 },
   //{ 0x1f46f, 1, 0x2640 },
-  //...
+  { 0x1f9d6, 1, 0 },
+  //{ 0x1f9d6, 1, 0x2642 },
+  //{ 0x1f9d6, 1, 0x2640 },
+  { 0x1f9d7, 1, 0 },
+  //{ 0x1f9d7, 1, 0x2642 },
+  //{ 0x1f9d7, 1, 0x2640 },
+  { 0x1f9d8, 1, 0 },
+  //{ 0x1f9d8, 1, 0x2642 },
+  //{ 0x1f9d8, 1, 0x2640 },
+  { 0x1f6c0, 1, 0 },
+  { 0x1f6cc, 1, 0 },
+  { 0x1f574, 1, 0 },
+  { 0x1f5e3, 0, 0 },
+  { 0x1f464, 0, 0 },
+  { 0x1f465, 0, 0 },
   // person-sport
+  { 0x1f93a, 0, 0 },
+  { 0x1f3c7, 1, 0 },
+  { 0x026f7, 0, 0 },
+  { 0x1f3c2, 1, 0 },
+  { 0x1f3cc, 1, 0 },
+  //{ 0x1f3cc, 1, 0x2642 },
+  //{ 0x1f3cc, 1, 0x2640 },
+  { 0x1f3c4, 1, 0 },
+  //{ 0x1f3c4, 1, 0x2642 },
+  //{ 0x1f3c4, 1, 0x2640 },
+  { 0x1f6a3, 1, 0 },
+  //{ 0x1f6a3, 1, 0x2642 },
+  //{ 0x1f6a3, 1, 0x2640 },
+  { 0x1f3ca, 1, 0 },
+  //{ 0x1f3ca, 1, 0x2642 },
+  //{ 0x1f3ca, 1, 0x2640 },
+  { 0x026f9, 1, 0 },
+  //{ 0x026f9, 1, 0x2642 },
+  //{ 0x026f9, 1, 0x2640 },
+  { 0x1f3cb, 1, 0 },
+  //{ 0x1f3cb, 1, 0x2642 },
+  //{ 0x1f3cb, 1, 0x2640 },
+  { 0x1f6b4, 1, 0 },
+  //{ 0x1f6b4, 1, 0x2642 },
+  //{ 0x1f6b4, 1, 0x2640 },
+
   // family
   // body
   // emotion
   // clothing
 };
 
+static EmojiData nature[] = {
+  // animal-mammal
+  { 0x1f435, 0, 0 },
+  { 0x1f412, 0, 0 },
+  { 0x1f980, 0, 0 },
+  { 0x1f436, 0, 0 },
+  { 0x1f415, 0, 0 },
+  { 0x1f429, 0, 0 },
+  { 0x1f43A, 0, 0 },
+  { 0x1f98A, 0, 0 },
+  { 0x1f431, 0, 0 },
+  { 0x1f408, 0, 0 },
+  { 0x1f981, 0, 0 },
+  { 0x1f42f, 0, 0 },
+  { 0x1f405, 0, 0 },
+  { 0x1f406, 0, 0 },
+  { 0x1f434, 0, 0 },
+  { 0x1f984, 0, 0 },
+  { 0x1f993, 0, 0 },
+  { 0x1f989, 0, 0 },
+  { 0x1f42e, 0, 0 },
+  { 0x1f402, 0, 0 },
+  { 0x1f403, 0, 0 },
+  { 0x1f437, 0, 0 },
+  { 0x1f416, 0, 0 },
+  { 0x1f417, 0, 0 },
+  { 0x1f43d, 0, 0 },
+  { 0x1f40f, 0, 0 },
+  { 0x1f411, 0, 0 },
+  { 0x1f410, 0, 0 },
+  { 0x1f42a, 0, 0 },
+  { 0x1f42b, 0, 0 },
+  { 0x1f992, 0, 0 },
+  { 0x1f418, 0, 0 },
+  { 0x1f98f, 0, 0 },
+  { 0x1f42d, 0, 0 },
+  { 0x1f401, 0, 0 },
+  { 0x1f400, 0, 0 },
+  { 0x1f439, 0, 0 },
+  { 0x1f430, 0, 0 },
+  { 0x1f407, 0, 0 },
+  { 0x1f43f, 0, 0 },
+  { 0x1f994, 0, 0 },
+  { 0x1f987, 0, 0 },
+  { 0x1f438, 0, 0 },
+  { 0x1f428, 0, 0 },
+  { 0x1f43c, 0, 0 },
+  { 0x1f43e, 0, 0 },
+  // animal-bird
+  { 0x1f983, 0, 0 },
+  { 0x1f414, 0, 0 },
+  { 0x1f413, 0, 0 },
+  { 0x1f423, 0, 0 },
+  { 0x1f424, 0, 0 },
+  { 0x1f425, 0, 0 },
+  { 0x1f426, 0, 0 },
+  { 0x1f427, 0, 0 },
+  { 0x1f54a, 0, 0 },
+  { 0x1f985, 0, 0 },
+  { 0x1f986, 0, 0 },
+  { 0x1f989, 0, 0 },
+  // animal-amphibian
+  { 0x1f438, 0, 0 },
+  // animal-reptile
+  { 0x1f40a, 0, 0 },
+  { 0x1f422, 0, 0 },
+  { 0x1f98e, 0, 0 },
+  { 0x1f40d, 0, 0 },
+  { 0x1f432, 0, 0 },
+  { 0x1f409, 0, 0 },
+  { 0x1f995, 0, 0 },
+  { 0x1f996, 0, 0 },
+  // animal-marine
+  // animal-bug
+  // plant-flower
+  // plant-other
+};
+
+static EmojiData food[] = {
+  // food-fruit
+  { 0x1f347, 0, 0 },
+  { 0x1f348, 0, 0 },
+  { 0x1f349, 0, 0 },
+  { 0x1f34a, 0, 0 },
+  { 0x1f34b, 0, 0 },
+  { 0x1f34c, 0, 0 },
+  { 0x1f34d, 0, 0 },
+  { 0x1f34e, 0, 0 },
+  { 0x1f34f, 0, 0 },
+  { 0x1f350, 0, 0 },
+  { 0x1f351, 0, 0 },
+  { 0x1f352, 0, 0 },
+  { 0x1f353, 0, 0 },
+  { 0x1f95d, 0, 0 },
+  { 0x1f345, 0, 0 },
+  { 0x1f965, 0, 0 },
+  // food-vegetable
+  // food-prepared
+  // food-asian
+  // food-sweet
+  // drink
+  // dishware
+  { 0x1f962, 0, 0 },
+  { 0x1f37d, 0, 0 },
+  { 0x1f374, 0, 0 },
+  { 0x1f944, 0, 0 },
+  { 0x1f52a, 0, 0 },
+  { 0x1f3f, 0, 0 },
+};
+
+static EmojiData travel[] = {
+  // place-map
+  { 0x1f3f, 0, 0 },
+  // place-geographic
+  // place building
+  // place-religious
+  // place-other
+  // transport-ground
+  // transport-water
+  // transport-air
+  // hotel
+  // time
+  // sky & weather
+};
+
+static EmojiData activities[] = {
+};
+
+static EmojiData objects[] = {
+};
+
+static EmojiData symbols[] = {
+};
+
 
 struct _GtkEmojiPicker
 {
         GtkPopover parent_instance;
 
+        GtkWidget *scrolled_window;
+
         GtkWidget *people_box;
+        GtkWidget *people_heading;
+        GtkWidget *people_button;
+        GtkWidget *people_label;
+
         GtkWidget *nature_box;
+        GtkWidget *nature_heading;
+        GtkWidget *nature_button;
+        GtkWidget *nature_label;
+
+        GtkWidget *food_box;
+        GtkWidget *food_heading;
+        GtkWidget *food_button;
+        GtkWidget *food_label;
+
+        GtkWidget *travel_box;
+        GtkWidget *travel_heading;
+        GtkWidget *travel_button;
+        GtkWidget *travel_label;
+
+        GtkWidget *activities_box;
+        GtkWidget *activities_heading;
+        GtkWidget *activities_button;
+        GtkWidget *activities_label;
+
+        GtkWidget *objects_box;
+        GtkWidget *objects_heading;
+        GtkWidget *objects_button;
+        GtkWidget *objects_label;
+
+        GtkWidget *symbols_box;
+        GtkWidget *symbols_heading;
+        GtkWidget *symbols_button;
+        GtkWidget *symbols_label;
+
+        GtkWidget *scroll_to_button;
 
         GtkGesture *people_press;
 };
@@ -286,6 +652,57 @@ gtk_emoji_picker_finalize (GObject *object)
         G_OBJECT_CLASS (gtk_emoji_picker_parent_class)->finalize (object);
 }
 
+static gboolean
+scroll_in_idle (gpointer data)
+{
+        GtkEmojiPicker *picker = data;
+        GtkWidget *heading;
+        GtkAdjustment *adj;
+        GtkAllocation alloc;
+        double page_increment, value;
+        gboolean dummy;
+
+        if (picker->scroll_to_button == picker->people_button)
+                heading = picker->people_heading;
+        else if (picker->scroll_to_button == picker->nature_button)
+                heading = picker->nature_heading;
+        else if (picker->scroll_to_button == picker->food_button)
+                heading = picker->food_heading;
+        else if (picker->scroll_to_button == picker->travel_button)
+                heading = picker->travel_heading;
+        else if (picker->scroll_to_button == picker->activities_button)
+                heading = picker->activities_heading;
+        else if (picker->scroll_to_button == picker->objects_button)
+                heading = picker->objects_heading;
+        else if (picker->scroll_to_button == picker->symbols_button)
+                heading = picker->symbols_heading;
+        else
+                return G_SOURCE_REMOVE;
+
+        adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (picker->scrolled_window));
+        gtk_widget_get_allocation (heading, &alloc);
+        page_increment = gtk_adjustment_get_page_increment (adj);
+        value = gtk_adjustment_get_value (adj);
+        gtk_adjustment_set_page_increment (adj, alloc.y - value);
+        g_signal_emit_by_name (picker->scrolled_window, "scroll-child", GTK_SCROLL_PAGE_FORWARD, FALSE, 
&dummy);
+        gtk_adjustment_set_page_increment (adj, page_increment);
+
+        return G_SOURCE_REMOVE;
+}
+
+static void
+scroll_to_section (GtkButton *button,
+                   gpointer   data)
+{
+        GtkWidget *widget = GTK_WIDGET (button);
+        GtkEmojiPicker *picker = data;
+
+        if (picker->scroll_to_button != widget) {
+                picker->scroll_to_button = widget;
+                g_idle_add (scroll_in_idle, picker);
+        }
+}
+
 static void
 emoji_activated (GtkFlowBox      *box,
                  GtkFlowBoxChild *child,
@@ -399,24 +816,96 @@ add_emoji (GtkWidget  *box,
 }
 
 static void
+set_label (GtkWidget *label, gunichar code)
+{
+        char text[14];
+        char *p;
+
+        p = text;
+        p += g_unichar_to_utf8 (code, p);
+        p += g_unichar_to_utf8 (0xfe0e, p);
+        p[0] = 0;
+        gtk_label_set_label (GTK_LABEL (label), text);
+}
+
+static void
 populate_emoji_picker (GtkEmojiPicker *picker)
 {
         int i;
 
-        for (i = 0; i < G_N_ELEMENTS (people); i++) {
+        for (i = 0; i < G_N_ELEMENTS (people); i++)
                 add_emoji (picker->people_box, people[i].code, 0, people[i].is_modifier_base, 
people[i].code2);
-        }
+        for (i = 0; i < G_N_ELEMENTS (nature); i++)
+                add_emoji (picker->nature_box, nature[i].code, 0, nature[i].is_modifier_base, 
nature[i].code2);
+        for (i = 0; i < G_N_ELEMENTS (food); i++)
+                add_emoji (picker->food_box, food[i].code, 0, food[i].is_modifier_base, food[i].code2);
+
+        for (i = 0; i < G_N_ELEMENTS (travel); i++)
+                add_emoji (picker->travel_box, travel[i].code, 0, travel[i].is_modifier_base, 
travel[i].code2);
+
+        for (i = 0; i < G_N_ELEMENTS (activities); i++)
+                add_emoji (picker->activities_box, activities[i].code, 0, activities[i].is_modifier_base, 
activities[i].code2);
+
+        for (i = 0; i < G_N_ELEMENTS (objects); i++)
+                add_emoji (picker->objects_box, objects[i].code, 0, objects[i].is_modifier_base, 
objects[i].code2);
+
+        for (i = 0; i < G_N_ELEMENTS (symbols); i++)
+                add_emoji (picker->symbols_box, symbols[i].code, 0, symbols[i].is_modifier_base, 
symbols[i].code2);
+
+        set_label (picker->people_label, 0x1f642);
+        set_label (picker->nature_label, 0x1f337);
+        set_label (picker->food_label, 0x1f374);
+        set_label (picker->travel_label, 0x2708);
+        set_label (picker->activities_label, 0x1f3c3);
+        set_label (picker->objects_label, 0x1f514);
+        set_label (picker->symbols_label, 0x2764);
+}
+
+static void
+update_state (GtkWidget *heading, GtkWidget *button, double value)
+{
+        GtkAllocation alloc;
+
+        gtk_widget_get_allocation (heading, &alloc);
+        if (alloc.y <= value && value < alloc.y + alloc.height)
+                gtk_widget_set_state_flags (button, GTK_STATE_FLAG_CHECKED, FALSE);
+        else
+                gtk_widget_unset_state_flags (button, GTK_STATE_FLAG_CHECKED);
+}
+
+static void
+adj_value_changed (GtkAdjustment *adj, gpointer data)
+{
+        GtkEmojiPicker *picker = data;
+        double value = gtk_adjustment_get_value (adj);
+
+        update_state (picker->people_heading, picker->people_button, value);
+        update_state (picker->nature_heading, picker->nature_button, value);
+        update_state (picker->food_heading, picker->food_button, value);
 }
 
 static void
 gtk_emoji_picker_init (GtkEmojiPicker *picker)
 {
+        GtkCssProvider *provider;
+        GtkAdjustment *adj;
+
         gtk_widget_init_template (GTK_WIDGET (picker));
 
         picker->people_press = gtk_gesture_long_press_new (picker->people_box);
         g_signal_connect (picker->people_press, "pressed", G_CALLBACK (people_pressed_cb), picker);
 
+        provider = gtk_css_provider_new ();
+        gtk_css_provider_load_from_path (provider, "gtkemojipicker.css");
+        gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
+                                                   GTK_STYLE_PROVIDER (provider),
+                                                   GTK_STYLE_PROVIDER_PRIORITY_THEME);
+        g_object_unref (provider);
+
         populate_emoji_picker (picker);
+
+        adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (picker->scrolled_window));
+        g_signal_connect (adj, "value-changed", G_CALLBACK (adj_value_changed), picker);
 }
 
 static void
@@ -443,10 +932,45 @@ gtk_emoji_picker_class_init (GtkEmojiPickerClass *klass)
         g_bytes_unref (bytes);
         g_mapped_file_unref (mf);
 
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, scrolled_window);
+
         gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, people_box);
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, people_heading);
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, people_button);
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, people_label);
+
         gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, nature_box);
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, nature_heading);
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, nature_button);
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, nature_label);
+
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, food_box);
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, food_heading);
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, food_button);
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, food_label);
+
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, travel_box);
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, travel_heading);
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, travel_button);
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, travel_label);
+
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, activities_box);
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, activities_heading);
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, activities_button);
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, activities_label);
+
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, objects_box);
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, objects_heading);
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, objects_button);
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, objects_label);
+
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, symbols_box);
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, symbols_heading);
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, symbols_button);
+        gtk_widget_class_bind_template_child (widget_class, GtkEmojiPicker, symbols_label);
 
         gtk_widget_class_bind_template_callback (widget_class, emoji_activated);
+        gtk_widget_class_bind_template_callback (widget_class, scroll_to_section);
 }
 
 GtkWidget *
diff --git a/tests/gtkemojipicker.ui b/tests/gtkemojipicker.ui
index 6a35ed8..921f849 100644
--- a/tests/gtkemojipicker.ui
+++ b/tests/gtkemojipicker.ui
@@ -12,7 +12,7 @@
           </object>
         </child>
         <child>
-          <object class="GtkScrolledWindow" id="swin">
+          <object class="GtkScrolledWindow" id="scrolled_window">
             <property name="vexpand">1</property>
             <property name="hscrollbar-policy">never</property>
             <property name="vscrollbar-policy">automatic</property>
@@ -25,7 +25,7 @@
                 <property name="margin">6</property>
                 <property name="spacing">6</property>
                 <child>
-                  <object class="GtkLabel">
+                  <object class="GtkLabel" id="people_heading">
                     <property name="label" translatable="yes">People</property>
                     <property name="xalign">0</property>
                   </object>
@@ -41,7 +41,7 @@
                   </object>
                 </child>
                 <child>
-                  <object class="GtkLabel">
+                  <object class="GtkLabel" id="nature_heading">
                     <property name="label" translatable="yes">Nature</property>
                     <property name="xalign">0</property>
                   </object>
@@ -59,7 +59,7 @@
                   </object>
                 </child>
                 <child>
-                  <object class="GtkLabel">
+                  <object class="GtkLabel" id="food_heading">
                     <property name="label" translatable="yes">Food</property>
                     <property name="xalign">0</property>
                   </object>
@@ -77,7 +77,7 @@
                   </object>
                 </child>
                 <child>
-                  <object class="GtkLabel">
+                  <object class="GtkLabel" id="travel_heading">
                     <property name="label" translatable="yes">Travel</property>
                     <property name="xalign">0</property>
                   </object>
@@ -95,7 +95,7 @@
                   </object>
                 </child>
                 <child>
-                  <object class="GtkLabel">
+                  <object class="GtkLabel" id="activities_heading">
                     <property name="label" translatable="yes">Activities</property>
                     <property name="xalign">0</property>
                   </object>
@@ -113,7 +113,7 @@
                   </object>
                 </child>
                 <child>
-                  <object class="GtkLabel">
+                  <object class="GtkLabel" id="objects_heading">
                     <property name="label" translatable="yes">Objects</property>
                     <property name="xalign">0</property>
                   </object>
@@ -131,7 +131,7 @@
                   </object>
                 </child>
                 <child>
-                  <object class="GtkLabel">
+                  <object class="GtkLabel" id="symbols_heading">
                     <property name="label" translatable="yes">Symbols</property>
                     <property name="xalign">0</property>
                   </object>
@@ -152,6 +152,102 @@
             </child>
           </object>
         </child>
+        <child>
+          <object class="GtkBox">
+            <property name="orientation">horizontal</property>
+            <child>
+              <object class="GtkButton" id="people_button">
+                <property name="relief">none</property>
+                <signal name="clicked" handler="scroll_to_section"/>
+                <style>
+                  <class name="emojisection"/>
+                </style>
+                <child>
+                  <object class="GtkLabel" id="people_label">
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkButton" id="nature_button">
+                <property name="relief">none</property>
+                <signal name="clicked" handler="scroll_to_section"/>
+                <style>
+                  <class name="emojisection"/>
+                </style>
+                <child>
+                  <object class="GtkLabel" id="nature_label">
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkButton" id="food_button">
+                <property name="relief">none</property>
+                <signal name="clicked" handler="scroll_to_section"/>
+                <style>
+                  <class name="emojisection"/>
+                </style>
+                <child>
+                  <object class="GtkLabel" id="food_label">
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkButton" id="travel_button">
+                <property name="relief">none</property>
+                <signal name="clicked" handler="scroll_to_section"/>
+                <style>
+                  <class name="emojisection"/>
+                </style>
+                <child>
+                  <object class="GtkLabel" id="travel_label">
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkButton" id="activities_button">
+                <property name="relief">none</property>
+                <signal name="clicked" handler="scroll_to_section"/>
+                <style>
+                  <class name="emojisection"/>
+                </style>
+                <child>
+                  <object class="GtkLabel" id="activities_label">
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkButton" id="objects_button">
+                <property name="relief">none</property>
+                <signal name="clicked" handler="scroll_to_section"/>
+                <style>
+                  <class name="emojisection"/>
+                </style>
+                <child>
+                  <object class="GtkLabel" id="objects_label">
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkButton" id="symbols_button">
+                <property name="relief">none</property>
+                <signal name="clicked" handler="scroll_to_section"/>
+                <style>
+                  <class name="emojisection"/>
+                </style>
+                <child>
+                  <object class="GtkLabel" id="symbols_label">
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
       </object>
     </child>
   </template>
diff --git a/tests/testentryicons.c b/tests/testentryicons.c
index 40eb0fc..eb70c8e 100644
--- a/tests/testentryicons.c
+++ b/tests/testentryicons.c
@@ -5,9 +5,17 @@
 static void
 emoji_activated (GtkEmojiPicker *picker, const char *text, GtkEntry *entry)
 {
-        GtkEntryBuffer *buffer;
-        buffer = gtk_entry_get_buffer (entry);
-        gtk_entry_buffer_insert_text (buffer, -1, text, -1);
+        int pos, start, end;
+
+        if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start, &end))
+{
+g_print ("selection: %d %d\n", start, end);
+          gtk_editable_delete_text (GTK_EDITABLE (entry), start, end);
+}
+
+        pos = MIN (start, end);
+        gtk_editable_insert_text (GTK_EDITABLE (entry), text, -1, &pos);
+        gtk_editable_set_position (GTK_EDITABLE (entry), pos);
 }
 
 static void
@@ -275,20 +283,25 @@ main (int argc, char **argv)
   gtk_grid_attach (GTK_GRID (grid), entry, 1, 4, 1, 1);
 
   box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+  gtk_widget_set_vexpand (GTK_WIDGET (box), TRUE);
   gtk_grid_attach (GTK_GRID (grid), box, 0, 5, 3, 1);
 
   button1 = gtk_radio_button_new_with_label (NULL, "Blank");
+  gtk_widget_set_valign (button1, GTK_ALIGN_START);
   g_signal_connect (button1, "toggled", G_CALLBACK (set_blank), entry);
   gtk_container_add (GTK_CONTAINER (box), button1);
   button2 = gtk_radio_button_new_with_label (NULL, "Icon Name");
+  gtk_widget_set_valign (button2, GTK_ALIGN_START);
   gtk_radio_button_join_group (GTK_RADIO_BUTTON (button2), GTK_RADIO_BUTTON (button1));
   g_signal_connect (button2, "toggled", G_CALLBACK (set_icon_name), entry);
   gtk_container_add (GTK_CONTAINER (box), button2);
   button3 = gtk_radio_button_new_with_label (NULL, "GIcon");
+  gtk_widget_set_valign (button3, GTK_ALIGN_START);
   gtk_radio_button_join_group (GTK_RADIO_BUTTON (button3), GTK_RADIO_BUTTON (button1));
   g_signal_connect (button3, "toggled", G_CALLBACK (set_gicon), entry);
   gtk_container_add (GTK_CONTAINER (box), button3);
   button4 = gtk_radio_button_new_with_label (NULL, "Pixbuf");
+  gtk_widget_set_valign (button4, GTK_ALIGN_START);
   gtk_radio_button_join_group (GTK_RADIO_BUTTON (button4), GTK_RADIO_BUTTON (button1));
   g_signal_connect (button4, "toggled", G_CALLBACK (set_pixbuf), entry);
   gtk_container_add (GTK_CONTAINER (box), button4);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]