[gnome-flashback/wip/segeiger/inputmethods] Candiate Area draft



commit 0de492c5a409767ff20d31cc0e8c3e508f3edb51
Author: Sebastian Geiger <sbastig gmx net>
Date:   Tue Jan 12 16:33:38 2016 +0100

    Candiate Area draft

 .../libinput-sources/gf-candidate-area.c           |  256 ++++++++++++++++++++
 .../libinput-sources/gf-candidate-area.h           |   51 ++++
 .../libinput-sources/gf-candidate-popup.c          |   61 +++++
 3 files changed, 368 insertions(+), 0 deletions(-)
---
diff --git a/gnome-flashback/libinput-sources/gf-candidate-area.c 
b/gnome-flashback/libinput-sources/gf-candidate-area.c
new file mode 100644
index 0000000..5d06f94
--- /dev/null
+++ b/gnome-flashback/libinput-sources/gf-candidate-area.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2015 Sebastian Geiger
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gf-candidate-area.h"
+
+#define MAX_CANDIDATES_PER_PAGE 16
+
+const char* DEFAULT_INDEX_LABELS[] = { "1", "2", "3", "4", "5", "6", "7", "8",
+                                       "9", "0", "a", "b", "c", "d", "e", "f" };
+
+struct _GfCandidateArea
+{
+  GObject parent;
+
+  GtkWidget        *box_layout;
+  GtkWidget        *button_box;
+  GtkWidget        *prev_button;
+  GtkWidget        *next_button;
+
+  GList            *candidate_boxes;
+
+  int               orientation;
+  int               cursor_position;
+};
+
+enum
+{
+  SIGNAL_CANDIDATE_CLICKED,
+  SIGNAL_PREV_PAGE,
+  SIGNAL_NEXT_PAGE,
+
+  SIGNAL_LAST
+};
+
+static guint signals[SIGNAL_LAST] = { 0 };
+
+static gboolean
+button_clicked_cb (GtkWidget *widget,
+                   GdkEvent  *event,
+                   gpointer   user_data)
+{
+  int i;
+  int index;
+  GfCandidateArea *area;
+  GList *list;
+
+  index = -1;
+  area = GF_CANDIDATE_AREA (user_data);
+  list = area->candidate_boxes;
+
+  for (i = 0; i < MAX_CANDIDATES_PER_PAGE; i++)
+    {
+      if (list->data == widget) {
+        index = i;
+      }
+    }
+  g_signal_emit (area,  signals[SIGNAL_CANDIDATE_CLICKED], 0, i, event);
+
+  return GDK_EVENT_PROPAGATE;
+}
+
+static gboolean
+prev_button_clicked_cb (GtkButton *button,
+                        gpointer  *user_data)
+{
+  GfCandidateArea *area;
+
+  area = GF_CANDIDATE_AREA (user_data);
+
+  g_signal_emit (area, signals[SIGNAL_PREV_PAGE], 0);
+
+  return GDK_EVENT_PROPAGATE;
+}
+
+static gboolean
+next_button_clicked_cb (GtkButton *button,
+                        gpointer  *user_data)
+{
+  GfCandidateArea *area;
+
+  area = GF_CANDIDATE_AREA (user_data);
+
+  g_signal_emit (area, signals[SIGNAL_NEXT_PAGE], 0);
+
+  return GDK_EVENT_PROPAGATE;
+}
+
+void
+gf_candidate_area_set_orientation (GfCandidateArea *area,
+                                   IBusOrientation orientation)
+{
+  if (area->orientation == orientation)
+    return;
+
+  area->orientation = orientation;
+
+  if (area->orientation == IBUS_ORIENTATION_HORIZONTAL)
+    {
+      //TODO
+    }
+  else
+    {
+      //TODO
+    }
+}
+
+void
+gf_candidate_area_set_candidates (GfCandidateArea *area,
+                                  GList *indexes,
+                                  GList *candidates,
+                                  int cursor_position,
+                                  gboolean cursor_visible)
+{
+  guint i;
+  for (i = 0; i < MAX_CANDIDATES_PER_PAGE; i++)
+    {
+      gboolean visible;
+      GtkWidget *box;
+      GList *children;
+      GtkWidget *index_label;
+      GtkWidget *candidate_label;
+      gchar *index_text;
+
+      visible = i < g_list_length (candidates);
+      box = g_list_nth (area->candidate_boxes, i)->data;
+      gtk_widget_set_visible (box, visible);
+
+      if (!visible)
+        continue;
+
+      children = gtk_container_get_children (GTK_CONTAINER (box));
+      index_label = children->data;
+      candidate_label = children->next->data;
+
+      if (indexes && g_list_nth (indexes, i)->data)
+        {
+          index_text = g_strdup (g_list_nth (indexes, i)->data);
+        }
+      else
+        {
+          index_text = g_strdup (DEFAULT_INDEX_LABELS [i]);
+        }
+
+      gtk_label_set_text (GTK_LABEL(index_label), index_text);
+      gtk_label_set_text (GTK_LABEL (candidate_label),
+                          g_list_nth (candidates, i)->data);
+
+      g_free (index_text);
+    }
+
+  //TODO: Remove 'selected' pseudo-class
+
+  area->cursor_position = cursor_position;
+
+  if (cursor_visible)
+  {
+    //TODO: Add 'selected' style class
+  }
+}
+
+void
+gf_candidate_area_update_buttons (GfCandidateArea *area,
+                                  gboolean wraps_around,
+                                  gint page,
+                                  gint n_pages)
+{
+  if (n_pages < 2)
+    {
+      gtk_widget_hide (area->button_box);
+      return;
+    }
+
+  gtk_widget_show (area->button_box);
+
+  gtk_widget_set_sensitive (area->prev_button, wraps_around || page > 0);
+  gtk_widget_set_sensitive (area->next_button,
+                            wraps_around || page < n_pages - 1);
+}
+
+GtkWidget *
+gf_candidate_area_get_box_layout (GfCandidateArea *area)
+{
+  return area->box_layout;
+}
+
+static void
+gf_candidate_area_class_init (GfCandidateAreaClass *area_class)
+{
+  signals[SIGNAL_CANDIDATE_CLICKED] =
+    g_signal_new ("candidate_clicked", G_OBJECT_CLASS_TYPE (area_class),
+                  G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE,
+                  1, G_TYPE_INT, GDK_TYPE_EVENT);
+
+  signals[SIGNAL_PREV_PAGE] =
+      g_signal_new ("candidate_clicked", G_OBJECT_CLASS_TYPE (area_class),
+                    G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
+
+  signals[SIGNAL_NEXT_PAGE] =
+      g_signal_new ("candidate_clicked", G_OBJECT_CLASS_TYPE (area_class),
+                    G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
+}
+
+static void
+gf_candidate_area_init (GfCandidateArea *area)
+{
+  int i;
+
+  for (i = 0; i < MAX_CANDIDATES_PER_PAGE; i++)
+    {
+      GtkWidget *box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+      GtkWidget *index_label = gtk_label_new ("");
+      GtkWidget *candidate_label = gtk_label_new ("");
+
+      gtk_container_add (GTK_CONTAINER (box), index_label);
+      gtk_container_add (GTK_CONTAINER (box), candidate_label);
+      gtk_container_add (GTK_CONTAINER (area->box_layout), box);
+
+      area->candidate_boxes = g_list_append (area->candidate_boxes, box);
+
+      g_signal_connect (box, "button-release-event",
+                        G_CALLBACK (button_clicked_cb), area);
+    }
+
+  area->button_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+  area->prev_button = gtk_button_new_with_label ("Prev");
+  area->next_button = gtk_button_new_with_label ("Next");
+
+  gtk_container_add (GTK_CONTAINER (area->button_box), area->prev_button);
+  gtk_container_add (GTK_CONTAINER (area->button_box), area->next_button);
+  gtk_container_add (GTK_CONTAINER (area->box_layout), area->button_box);
+
+  g_signal_connect (area->prev_button, "clicked",
+                    G_CALLBACK (prev_button_clicked_cb), area);
+  g_signal_connect (area->next_button, "clicked",
+                    G_CALLBACK (next_button_clicked_cb), area);
+}
+
+GfCandidateArea*
+gf_candidate_area_new (void)
+{
+    return g_object_new (GF_TYPE_CANDIDATE_AREA, NULL);
+}
diff --git a/gnome-flashback/libinput-sources/gf-candidate-area.h 
b/gnome-flashback/libinput-sources/gf-candidate-area.h
new file mode 100644
index 0000000..ef81709
--- /dev/null
+++ b/gnome-flashback/libinput-sources/gf-candidate-area.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015 Sebastian Geiger
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GF_CANDIDATE_AREA_H
+#define GF_CANDIDATE_AREA_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <ibus.h>
+
+G_BEGIN_DECLS
+
+#define GF_TYPE_CANDIDATE_AREA gf_candidate_area_get_type ()
+G_DECLARE_FINAL_TYPE (GfCandidateArea, gf_candidate_area,
+                      GF, CANDIDATE_AREA, GObject)
+
+GfCandidateArea *gf_candidate_area_new             (void);
+
+void             gf_candidate_area_set_orientation (GfCandidateArea *area,
+                                                    IBusOrientation  orientation);
+
+void             gf_candidate_area_set_candidates  (GfCandidateArea *area,
+                                                    GList           *indexes,
+                                                    GList           *candidates,
+                                                    int              cursor_position,
+                                                    gboolean         cursor_visible);
+
+void             gf_candidate_area_update_buttons  (GfCandidateArea *area,
+                                                    gboolean wraps_around,
+                                                    gint page,
+                                                    gint n_pages);
+
+GtkWidget       *gf_candidate_area_get_box_layout  (GfCandidateArea *area);
+
+G_END_DECLS
+
+#endif
diff --git a/gnome-flashback/libinput-sources/gf-candidate-popup.c 
b/gnome-flashback/libinput-sources/gf-candidate-popup.c
index 32d6a63..dfaa67b 100644
--- a/gnome-flashback/libinput-sources/gf-candidate-popup.c
+++ b/gnome-flashback/libinput-sources/gf-candidate-popup.c
@@ -18,12 +18,23 @@
 #include "config.h"
 
 #include "gf-candidate-popup.h"
+#include "gf-candidate-area.h"
+
+#include "gtk/gtk.h"
 
 struct _GfCandidatePopup
 {
   GObject           parent;
 
   IBusPanelService *service;
+
+  GfCandidateArea  *candidateArea;
+  GtkWidget        *window;
+
+  GtkWidget        *pre_edit_text;
+  GtkWidget        *aux_text;
+
+  GtkWidget        *box_layout;
 };
 
 G_DEFINE_TYPE (GfCandidatePopup, gf_candidate_popup, G_TYPE_OBJECT)
@@ -85,6 +96,7 @@ update_lookup_table_cb (IBusPanelService *service,
                         gboolean          visible,
                         gpointer          user_data)
 {
+
 }
 
 static void
@@ -107,6 +119,31 @@ focus_out_cb (IBusPanelService *service,
 }
 
 static void
+area_page_prev_cb (GfCandidateArea *area,
+                   gpointer         user_data)
+{
+
+}
+
+static void
+area_page_next_cb (GfCandidateArea *area,
+                   gpointer         user_data)
+{
+
+}
+
+static void
+area_candidate_clicked_cb (GfCandidateArea *area,
+                           gint             index,
+                           GdkEvent        *event,
+                           gpointer         user_data
+
+)
+{
+
+}
+
+static void
 gf_candidate_popup_dispose (GObject *object)
 {
   GfCandidatePopup *popup;
@@ -131,6 +168,30 @@ gf_candidate_popup_class_init (GfCandidatePopupClass *popup_class)
 static void
 gf_candidate_popup_init (GfCandidatePopup *popup)
 {
+  popup->candidateArea = gf_candidate_area_new();
+
+  popup->box_layout = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+  popup->window = gtk_window_new (GTK_WINDOW_POPUP);
+  gtk_window_set_position (GTK_WINDOW (popup->window), GTK_WIN_POS_CENTER);
+
+  gtk_container_add (GTK_CONTAINER (popup->window), popup->box_layout);
+
+  popup->pre_edit_text = gtk_label_new ("Pre_Edit_Text");
+  popup->aux_text = gtk_label_new ("Aux_Text");
+
+  gtk_container_add (GTK_CONTAINER (popup->box_layout), popup->pre_edit_text);
+  gtk_container_add (GTK_CONTAINER (popup->box_layout), popup->aux_text);
+
+  gtk_container_add (GTK_CONTAINER (popup->box_layout),
+                     gf_candidate_area_get_box_layout (popup->candidateArea));
+
+  g_signal_connect (popup->candidateArea, "previous-page",
+                    G_CALLBACK (area_page_prev_cb), popup);
+  g_signal_connect (popup->candidateArea, "next-page",
+                    G_CALLBACK (area_page_next_cb), popup);
+  g_signal_connect (popup->candidateArea, "candidate-clicked",
+                    G_CALLBACK (area_candidate_clicked_cb), popup);
 }
 
 GfCandidatePopup *


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