[yocto] [matchbox-desktop-2][PATCH 15/16] Use a GtkFlowBox instead of TakuTable

Jussi Kukkonen jussi.kukkonen at intel.com
Thu Apr 28 06:03:08 PDT 2016


Remove ~500 lines of code by using FlowBox instead of custom code

Also avoid using GtkFixed when in desktop mode

Signed-off-by: Jussi Kukkonen <jussi.kukkonen at intel.com>
---
 libtaku/Makefile.am          |   1 -
 libtaku/taku-launcher-tile.c |   8 +-
 libtaku/taku-launcher-tile.h |   2 +
 libtaku/taku-table.c         | 533 -------------------------------------------
 libtaku/taku-table.h         |  69 ------
 libtaku/taku-tile.c          |   2 +-
 src/desktop.c                | 121 +++++++---
 src/taku-category-bar.c      |  23 +-
 src/taku-category-bar.h      |   5 +-
 9 files changed, 118 insertions(+), 646 deletions(-)
 delete mode 100644 libtaku/taku-table.c
 delete mode 100644 libtaku/taku-table.h

diff --git a/libtaku/Makefile.am b/libtaku/Makefile.am
index 28f5da4..c457d9e 100644
--- a/libtaku/Makefile.am
+++ b/libtaku/Makefile.am
@@ -10,7 +10,6 @@ libtaku_a_SOURCES = \
 	taku-launcher-tile.c taku-launcher-tile.h \
 	taku-menu.h \
 	taku-menu-desktop.c \
-	taku-table.c taku-table.h \
 	taku-tile.c taku-tile.h \
 	xutil.c xutil.h \
 	taku-queue-source.c taku-queue-source.h
diff --git a/libtaku/taku-launcher-tile.c b/libtaku/taku-launcher-tile.c
index 58deafb..b453eac 100644
--- a/libtaku/taku-launcher-tile.c
+++ b/libtaku/taku-launcher-tile.c
@@ -104,7 +104,7 @@ taku_launcher_tile_finalize (GObject *object)
 }
 
 /*
- * Timeout callback to restore the state of the widget after the clicked state
+ * Timeout callback to restore the state of the widget after the activated state
  * change.
  */
 static gboolean
@@ -114,8 +114,8 @@ reset_state (gpointer data)
   return FALSE;
 }
 
-static void
-taku_launcher_tile_clicked (GtkButton *tile, gpointer user_data)
+void
+taku_launcher_tile_activate (TakuLauncherTile *tile)
 {
   TakuLauncherTile *launcher = TAKU_LAUNCHER_TILE (tile);
 
@@ -160,8 +160,6 @@ static void
 taku_launcher_tile_init (TakuLauncherTile *self)
 {
   self->priv = GET_PRIVATE (self);
-
-  g_signal_connect (self, "clicked", G_CALLBACK (taku_launcher_tile_clicked), NULL);
 }
 
 GtkWidget *
diff --git a/libtaku/taku-launcher-tile.h b/libtaku/taku-launcher-tile.h
index 62e8c74..c1b8cf9 100644
--- a/libtaku/taku-launcher-tile.h
+++ b/libtaku/taku-launcher-tile.h
@@ -72,6 +72,8 @@ GtkWidget* taku_launcher_tile_new (void);
 GtkWidget* taku_launcher_tile_new_from_item (TakuMenuItem *item);
 TakuMenuItem* taku_launcher_tile_get_item (TakuLauncherTile *tile);
 
+void taku_launcher_tile_activate (TakuLauncherTile *tile);
+
 void taku_launcher_tile_add_group (TakuLauncherTile *tile, TakuLauncherCategory *category);
 
 void taku_launcher_tile_remove_group (TakuLauncherTile *tile, TakuLauncherCategory *category);
diff --git a/libtaku/taku-table.c b/libtaku/taku-table.c
deleted file mode 100644
index fa7da18..0000000
--- a/libtaku/taku-table.c
+++ /dev/null
@@ -1,533 +0,0 @@
-/*
- * Copyright (C) 2007 OpenedHand Ltd
- *
- * 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 2 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, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <config.h>
-#include <gtk/gtk.h>
-#include <string.h>
-#include "taku-table.h"
-#include "taku-tile.h"
-
-G_DEFINE_TYPE (TakuTable, taku_table, GTK_TYPE_GRID);
-
-#define GET_PRIVATE(o) \
-  (G_TYPE_INSTANCE_GET_PRIVATE ((o), TAKU_TYPE_TABLE, TakuTablePrivate))
-
-#define DEFAULT_WIDTH 30
-
-struct _TakuTablePrivate
-{
-  int columns;
-
-  int x, y;
-  gboolean reflowing;
-
-  GSequence *seq;
-
-  gpointer filter;
-
-  GList *dummies;
-
-  GtkIMContext *im_context;
-};
-
-/* Compare two tiles lexographically */
-static int
-compare_tiles (gconstpointer a,
-               gconstpointer b,
-               gpointer      user_data)
-{
-  const char *ka, *kb;
-
-  ka = taku_tile_get_sort_key (TAKU_TILE (a));
-  kb = taku_tile_get_sort_key (TAKU_TILE (b));
-
-  if (ka != NULL && kb == NULL)
-    return 1;
-  else if (ka == NULL && kb != NULL)
-    return -1;
-  else if (ka == NULL && kb == NULL)
-    return 0;
-  else
-    return strcmp (ka, kb);
-}
-
-/* Compare two tiles exactly */
-static int
-compare_tiles_exact (gconstpointer a,
-                     gconstpointer b,
-                     gpointer      user_data)
-{
-  int ret = compare_tiles (a, b, user_data);
-
-  if (ret == 0) {
-    if (a < b)
-      ret = -1;
-    else if (a > b)
-      ret = 1;
-  }
-
-  return ret;
-}
-
-/* Normalize strings for case and representation insensitive comparison */
-static char *
-utf8_normalize_and_casefold (const char *str)
-{
-  char *norm = g_utf8_normalize (str, -1, G_NORMALIZE_ALL);
-  char *fold = g_utf8_casefold (str, -1);
-  g_free (norm);
-  return fold;
-}
-
-/* Process keypress: Focus next tile which's primary text starts with the
- * entered character */
-static void
-im_context_commit_cb (GtkIMContext *context,
-                      const char   *str,
-                      gpointer      user_data)
-{
-  TakuTable *table = TAKU_TABLE (user_data);
-  GSequenceIter *begin_iter, *iter;
-  GtkWidget *toplevel, *focused;
-  char *norm_str;
-
-  norm_str = utf8_normalize_and_casefold (str);
-
-  toplevel = gtk_widget_get_toplevel (GTK_WIDGET (table));
-  focused = gtk_window_get_focus (GTK_WINDOW (toplevel));
-  if (focused)
-    begin_iter = g_sequence_search (table->priv->seq, 
-                                      focused, compare_tiles, NULL);
-  else
-    begin_iter = g_sequence_get_begin_iter (table->priv->seq);
-
-  iter = begin_iter;
-  do {
-    TakuTile *tile;
-    const char *text;
-    char *norm_text;
-
-    if (g_sequence_iter_is_end (iter)) {
-      iter = g_sequence_get_begin_iter (table->priv->seq);
-      if (iter == begin_iter)
-        break;
-    }
-
-    tile = g_sequence_get (iter);
-    if (!gtk_widget_get_visible (GTK_WIDGET (tile)))
-      goto next;
-
-    text = taku_tile_get_search_key (tile);
-    if (text == NULL)
-      goto next;
-
-    norm_text = utf8_normalize_and_casefold (text);
-
-    if (strncmp (norm_str, norm_text, strlen (norm_str)) == 0) {
-      g_free (norm_text);
-      gtk_widget_grab_focus (GTK_WIDGET (tile));
-      break;
-    }
-
-    g_free (norm_text);
-
-next:
-    iter = g_sequence_iter_next (iter);
-  } while (iter != begin_iter);
-
-  g_free (norm_str);
-}
-
-static gboolean
-on_tile_focus (GtkWidget *widget, GdkEventFocus *event, gpointer user_data)
-{
-  GtkWidget *container = GTK_WIDGET (user_data);
-  GtkWidget *viewport = gtk_widget_get_parent (container);
-  GtkAllocation widget_alloc, viewport_alloc;
-  GtkAdjustment *adjustment;
-
-  gtk_widget_get_allocation (widget, &widget_alloc);
-  gtk_widget_get_allocation (viewport, &viewport_alloc);
-
-  /* If the lowest point of the tile is lower than the height of the viewport,
-   * or if the top of the tile is higher than the viewport is... */
-  if (widget_alloc.y +
-      widget_alloc.height > viewport_alloc.height ||
-      widget_alloc.y < viewport_alloc.height) {
-    adjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (viewport));
-
-    gtk_adjustment_clamp_page (adjustment,
-                               widget_alloc.y,
-                               widget_alloc.y +
-                               widget_alloc.height);
-  }
-
-  return FALSE;
-}
-
-static void
-reflow_foreach (gpointer widget, gpointer user_data)
-{
-  TakuTile *tile = TAKU_TILE (widget);
-  TakuTable *table = TAKU_TABLE (user_data);
-  GtkContainer *container = GTK_CONTAINER (user_data);
-
-  /* Filter out unwanted items */
-  if (table->priv->filter != NULL) {
-    if (!taku_tile_matches_filter (tile, table->priv->filter)) {
-      gtk_widget_set_child_visible (widget, FALSE);
-      return;
-    }
-  }
-
-  /* We want this item. Align. */
-  gtk_widget_set_child_visible (widget, TRUE);
-
-  gtk_container_child_set (container, GTK_WIDGET (widget),
-                           "left-attach", table->priv->x,
-                           "top-attach", table->priv->y,
-                           "width", 1,
-                           "height", 1,
-                           NULL);
-  if (++table->priv->x >= table->priv->columns) {
-    table->priv->x = 0;
-    table->priv->y++;
-  }
-}
-
-static void
-reflow (TakuTable *table)
-{
-  int i;
-
-  /* Only reflow when necessary */
-  if (!gtk_widget_get_realized (GTK_WIDGET (table)))
-    return;
-
-  /* Remove dummies */
-  while (table->priv->dummies) {
-    /* Call into the parent class straight away in order to bypass our
-     * own remove implementation. */
-    (* GTK_CONTAINER_CLASS (taku_table_parent_class)->remove)
-      (GTK_CONTAINER (table), table->priv->dummies->data);
-
-    table->priv->dummies = g_list_delete_link (table->priv->dummies,
-                                               table->priv->dummies);
-  }
-
-  /* Reflow children */
-  table->priv->x = table->priv->y = 0;
-
-  table->priv->reflowing = TRUE;
-  g_sequence_foreach (table->priv->seq, reflow_foreach, table);
-  table->priv->reflowing = FALSE;
-
-  /* Add dummy items if necessary to get required amount of columns */
-  for (i = g_sequence_get_length (table->priv->seq);
-       i < table->priv->columns; i++) {
-    GtkWidget *dummy = gtk_label_new (NULL);
-    gtk_widget_set_child_visible (dummy, TRUE);
-
-    gtk_grid_attach (GTK_GRID (table), dummy,
-                     table->priv->x, table->priv->y, 1, 1);
-    table->priv->x++;
-
-    table->priv->dummies = g_list_prepend (table->priv->dummies, dummy);
-  }
-}
-
-/*
- * Implementation of gtk_container_add, so that applications can just call that
- * and this class manages the position.
- */
-static void
-container_add (GtkContainer *container, GtkWidget *widget)
-{
-  TakuTable *self = TAKU_TABLE (container);
-
-  g_return_if_fail (self);
-  g_return_if_fail (TAKU_IS_TILE (widget));
-
-  g_sequence_insert_sorted (self->priv->seq, widget, compare_tiles, NULL);
-
-  gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 1, 1);
-
-  reflow (self);
-
-  g_signal_connect (widget, "focus-in-event", G_CALLBACK (on_tile_focus), self);
-}
-
-static void
-container_remove (GtkContainer *container, GtkWidget *widget)
-{
-  TakuTable *self = TAKU_TABLE (container);
-  GSequenceIter *iter;
-
-  g_return_if_fail (self);
-
-  /* Find the appropriate iter first */
-  iter = g_sequence_search (self->priv->seq,
-                              widget, compare_tiles_exact, NULL);
-  iter = g_sequence_iter_prev (iter);
-  if (g_sequence_iter_is_end (iter) || g_sequence_get (iter) != widget) {
-    /* We have here a dummy, or something that is not contained */
-    (* GTK_CONTAINER_CLASS (taku_table_parent_class)->remove)
-                                                (container, widget);
-
-    return;
-  }
-
-  /* And then remove it */
-  g_sequence_remove (iter);
-
-  (* GTK_CONTAINER_CLASS (taku_table_parent_class)->remove) (container, widget);
-
-  reflow (self);
-}
-
-static void
-calculate_columns (GtkWidget *widget)
-{
-  TakuTable *table = TAKU_TABLE (widget);
-  PangoContext *context;
-  PangoFontMetrics *metrics;
-  int table_width, width, new_cols;
-  guint cell_text_width = DEFAULT_WIDTH;
-
-  table_width = gtk_widget_get_allocated_width (widget);
-
-  /* If we are currently reflowing the tiles, or the final allocation hasn't
-     been decided yet, return */
-  if (!gtk_widget_get_realized (widget) ||
-      table->priv->reflowing ||
-      table_width <= 1) {
-    return;
-  }
-  context = gtk_widget_get_pango_context (widget);
-  metrics = pango_context_get_metrics (context, gtk_widget_get_style (widget)->font_desc, NULL);
-
-  gtk_widget_style_get (widget, "cell-text-width", &cell_text_width, NULL);
-
-  width = PANGO_PIXELS
-          (cell_text_width * pango_font_metrics_get_approximate_char_width (metrics));
-  new_cols = MAX (1, table_width / width);
-  if (table->priv->columns != new_cols) {
-    table->priv->columns = new_cols;
-
-    reflow (table);
-  }
-
-  pango_font_metrics_unref (metrics);
-}
-
-static void
-taku_table_realize (GtkWidget *widget)
-{
-  TakuTable *self = TAKU_TABLE (widget);
-
-  (* GTK_WIDGET_CLASS (taku_table_parent_class)->realize) (widget);
-
-  gtk_im_context_set_client_window (self->priv->im_context, gtk_widget_get_window (widget));
-
-  calculate_columns (widget);
-}
-
-static void
-taku_table_unrealize (GtkWidget *widget)
-{
-  TakuTable *self = TAKU_TABLE (widget);
-
-  gtk_im_context_set_client_window (self->priv->im_context, NULL);
-
-  (* GTK_WIDGET_CLASS (taku_table_parent_class)->unrealize) (widget);
-}
-
-static void
-on_size_allocate (GtkWidget     *widget,
-                  GtkAllocation *allocation,
-                  gpointer       user_data)
-{
-  calculate_columns (widget);
-}
-
-static void
-taku_table_style_set (GtkWidget *widget,
-                      GtkStyle  *previous_style)
-{
-  (* GTK_WIDGET_CLASS (taku_table_parent_class)->style_set)
-    (widget, previous_style);
-
-  calculate_columns (widget);
-}
-
-static int
-taku_table_focus_in_event (GtkWidget *widget, GdkEventFocus *event)
-{
-  TakuTable *self = TAKU_TABLE (widget);
-
-  gtk_im_context_focus_in (self->priv->im_context);
-
-  (* GTK_WIDGET_CLASS (taku_table_parent_class)->focus_in_event)
-    (widget, event);
-
-  return FALSE;
-}
-
-static int
-taku_table_focus_out_event (GtkWidget *widget, GdkEventFocus *event)
-{
-  TakuTable *self = TAKU_TABLE (widget);
-
-  gtk_im_context_focus_out (self->priv->im_context);
-
-  (* GTK_WIDGET_CLASS (taku_table_parent_class)->focus_out_event)
-    (widget, event);
-
-  return FALSE;
-}
-
-static gboolean
-taku_table_key_press_event (GtkWidget   *widget,
-                            GdkEventKey *event)
-{
-  TakuTable *table = TAKU_TABLE (widget);
-
-  if (gtk_im_context_filter_keypress (table->priv->im_context, event))
-    return TRUE;
-
-  return (* GTK_WIDGET_CLASS (taku_table_parent_class)->key_press_event)
-           (widget, event);
-}
-
-static void
-taku_table_grab_focus (GtkWidget *widget)
-{
-  TakuTable *table = TAKU_TABLE (widget);
-  GSequenceIter *iter;
-
-  iter = g_sequence_get_begin_iter (table->priv->seq);
-  while (!g_sequence_iter_is_end (iter)) {
-    GtkWidget *widget = g_sequence_get (iter);
-
-    if (gtk_widget_get_visible (widget)) {
-      gtk_widget_grab_focus (widget);
-
-      break;
-    }
-
-    iter = g_sequence_iter_next (iter);
-  }
-}
-
-static void
-taku_table_finalize (GObject *object)
-{
-  TakuTable *table = TAKU_TABLE (object);
-
-  g_sequence_free (table->priv->seq);
-
-  g_list_free (table->priv->dummies);
-
-  g_object_unref (table->priv->im_context);
-
-  G_OBJECT_CLASS (taku_table_parent_class)->finalize (object);
-}
-
-static void
-taku_table_class_init (TakuTableClass *klass)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
-  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
-
-  g_type_class_add_private (klass, sizeof (TakuTablePrivate));
-
-  object_class->finalize     = taku_table_finalize;
-
-  widget_class->realize         = taku_table_realize;
-  widget_class->unrealize       = taku_table_unrealize;
-  widget_class->style_set       = taku_table_style_set;
-  widget_class->focus_in_event  = taku_table_focus_in_event;
-  widget_class->focus_out_event = taku_table_focus_out_event;
-  widget_class->key_press_event = taku_table_key_press_event;
-  widget_class->grab_focus      = taku_table_grab_focus;
-
-  container_class->add    = container_add;
-  container_class->remove = container_remove;
-
-  gtk_widget_class_install_style_property (widget_class, g_param_spec_uint
-                                           ("cell-text-width", "cell text width",
-                                            "Width of the tiles in characters",
-                                            0, G_MAXUINT, DEFAULT_WIDTH,
-                                            G_PARAM_READABLE));
-
-}
-
-static void
-taku_table_init (TakuTable *self)
-{
-  self->priv = GET_PRIVATE (self);
-
-  g_signal_connect (self, "size-allocate", G_CALLBACK (on_size_allocate), NULL);
-
-  g_object_set (self,
-                "border-width", 6,
-                "row-spacing", 6,
-                "column-spacing", 6,
-                "row-homogeneous", TRUE,
-                "column-homogeneous", TRUE,
-                NULL);
-
-  self->priv->columns = 0;
-
-  self->priv->reflowing = FALSE;
-
-  self->priv->seq = g_sequence_new (NULL);
-
-  self->priv->filter = NULL;
-
-  self->priv->dummies = NULL;
-
-  self->priv->im_context = gtk_im_multicontext_new ();
-  g_signal_connect (self->priv->im_context, "commit",
-                    G_CALLBACK (im_context_commit_cb), self);
-}
-
-GtkWidget *
-taku_table_new (void)
-{
-  return g_object_new (TAKU_TYPE_TABLE, NULL);
-}
-
-void
-taku_table_set_filter (TakuTable *table, gpointer filter)
-{
-  g_return_if_fail (TAKU_IS_TABLE (table));
-
-  table->priv->filter = filter;
-
-  reflow (table);
-}
-
-gpointer
-taku_table_get_filter (TakuTable *table)
-{
-  g_return_val_if_fail (TAKU_IS_TABLE (table), NULL);
-
-  return table->priv->filter;
-}
diff --git a/libtaku/taku-table.h b/libtaku/taku-table.h
deleted file mode 100644
index 585c5d4..0000000
--- a/libtaku/taku-table.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2007 OpenedHand Ltd
- *
- * 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 2 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, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _TAKU_TABLE
-#define _TAKU_TABLE
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define TAKU_TYPE_TABLE taku_table_get_type()
-
-#define TAKU_TABLE(obj) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
-  TAKU_TYPE_TABLE, TakuTable))
-
-#define TAKU_TABLE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), \
-  TAKU_TYPE_TABLE, TakuTableClass))
-
-#define TAKU_IS_TABLE(obj) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
-  TAKU_TYPE_TABLE))
-
-#define TAKU_IS_TABLE_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), \
-  TAKU_TYPE_TABLE))
-
-#define TAKU_TABLE_GET_CLASS(obj) \
-  (G_TYPE_INSTANCE_GET_CLASS ((obj), \
-  TAKU_TYPE_TABLE, TakuTableClass))
-
-typedef struct _TakuTablePrivate TakuTablePrivate;
-
-typedef struct {
-  GtkGrid parent;
-  TakuTablePrivate *priv;
-} TakuTable;
-
-typedef struct {
-  GtkGridClass parent_class;
-} TakuTableClass;
-
-GType taku_table_get_type (void);
-
-GtkWidget* taku_table_new (void);
-
-void taku_table_set_filter (TakuTable *table, gpointer filter);
-
-gpointer taku_table_get_filter (TakuTable *table);
-
-G_END_DECLS
-
-#endif /* _TAKU_TABLE */
diff --git a/libtaku/taku-tile.c b/libtaku/taku-tile.c
index 974a164..64dd3d7 100644
--- a/libtaku/taku-tile.c
+++ b/libtaku/taku-tile.c
@@ -25,7 +25,7 @@
 #include <gtk/gtk.h>
 #include "taku-tile.h"
 
-G_DEFINE_ABSTRACT_TYPE (TakuTile, taku_tile, GTK_TYPE_BUTTON);
+G_DEFINE_ABSTRACT_TYPE (TakuTile, taku_tile, GTK_TYPE_BIN);
 
 static void
 taku_tile_class_init (TakuTileClass *klass)
diff --git a/src/desktop.c b/src/desktop.c
index 0b055c8..ddb2786 100644
--- a/src/desktop.c
+++ b/src/desktop.c
@@ -26,7 +26,6 @@
 #include <ctype.h>
 
 #include "libtaku/taku-menu.h"
-#include "libtaku/taku-table.h"
 #include "libtaku/taku-icon-tile.h"
 #include "libtaku/taku-launcher-tile.h"
 #include "taku-category-bar.h"
@@ -37,7 +36,7 @@
 
 static GList *categories;
 static TakuCategoryBar *bar;
-static TakuTable *table;
+static GtkWidget *table;
 static TakuMenu *menu;
 static GtkWidget *fixed, *box;
 
@@ -88,16 +87,14 @@ focus_cb (GtkWidget *widget, GtkDirectionType direction, gpointer user_data)
 
   if (direction == GTK_DIR_LEFT) {
     taku_category_bar_previous (bar);
-
-    gtk_widget_grab_focus (GTK_WIDGET (table));
-
+    gtk_widget_child_focus (table, GTK_DIR_LEFT);
     return TRUE;
   } else if (direction == GTK_DIR_RIGHT) {
     taku_category_bar_next (bar);
-
-    gtk_widget_grab_focus (GTK_WIDGET (table));
-
+    gtk_widget_child_focus (table, GTK_DIR_RIGHT);
     return TRUE;
+  } else if (direction == GTK_DIR_UP) {
+    gtk_flow_box_unselect_all (GTK_FLOW_BOX (table));
   }
 
   return FALSE;
@@ -140,6 +137,56 @@ workarea_changed (int x, int y, int w, int h)
   gtk_fixed_move (GTK_FIXED (fixed), box, x, y);
 }
 
+static void table_size_allocate_cb (GtkWidget    *table,
+                                    GdkRectangle *allocation,
+                                    gpointer      user_data)
+{
+  gtk_flow_box_set_min_children_per_line (GTK_FLOW_BOX (table), allocation->width / 200); 
+}
+
+static gboolean
+table_filter (GtkFlowBoxChild *child, gpointer user_data)
+{
+  TakuTile *tile = TAKU_TILE (gtk_bin_get_child (GTK_BIN (child)));
+
+  return taku_tile_matches_filter (tile, taku_category_bar_get_current (bar));
+}
+
+static gint
+table_sort (GtkFlowBoxChild *child1,
+            GtkFlowBoxChild *child2,
+            gpointer user_data)
+{
+  GtkWidget *a, *b;
+  const char *ka, *kb;
+
+  a = gtk_bin_get_child (GTK_BIN(child1));
+  b = gtk_bin_get_child (GTK_BIN(child2));
+  ka = taku_tile_get_sort_key (TAKU_TILE (a));
+  kb = taku_tile_get_sort_key (TAKU_TILE (b));
+
+  if (ka != NULL && kb == NULL)
+    return 1;
+  else if (ka == NULL && kb != NULL)
+    return -1;
+  else if (ka == NULL && kb == NULL)
+    return 0;
+  else
+    return strcmp (ka, kb);
+}
+
+static void
+table_child_activated_cb (GtkFlowBox *table,
+                          GtkFlowBoxChild *child,
+                          gpointer userdata)
+{
+  GtkWidget *tile;
+
+  tile = gtk_bin_get_child (GTK_BIN (child));
+  if (TAKU_IS_LAUNCHER_TILE (tile))
+    taku_launcher_tile_activate (TAKU_LAUNCHER_TILE (tile));
+}
+
 GtkWidget *
 create_desktop (DesktopMode mode)
 {
@@ -157,6 +204,10 @@ create_desktop (DesktopMode mode)
 
   screen = gtk_widget_get_screen (window);
 
+  /* Main VBox */
+  box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+  gtk_widget_show (box);
+
   switch (mode) {
   case MODE_DESKTOP:
     gtk_window_fullscreen (GTK_WINDOW (window));
@@ -170,34 +221,32 @@ create_desktop (DesktopMode mode)
     height = gdk_screen_get_height (screen);
     gtk_window_set_default_size (GTK_WINDOW (window), width, height);
     gtk_window_move (GTK_WINDOW (window), 0, 0);
+
+    /* This fixed is used to position the desktop itself in the work area */
+    fixed = gtk_fixed_new ();
+    gtk_widget_show (fixed);
+    gtk_container_add (GTK_CONTAINER (window), fixed);
+    gtk_fixed_put (GTK_FIXED (fixed), box, 0, 0);
+
+    /* Set a sane default in case there is no work area defined yet */
+    workarea_changed (0, 0, width, height);
+    if (mode == MODE_DESKTOP || mode == MODE_TITLEBAR) {
+      x_monitor_workarea (screen, workarea_changed);
+    }
+
     break;
   case MODE_WINDOW:
     width = 640;
     height = 480;
     gtk_window_set_default_size (GTK_WINDOW (window), width, height);
     g_signal_connect (window, "delete-event", G_CALLBACK (gtk_main_quit), NULL);
-    /* TODO: fake workarea_changed calls on window resize */
+    gtk_container_add (GTK_CONTAINER (window), box);
     break;
   default:
     g_assert_not_reached ();
   }
   gtk_widget_show (window);
 
-  /* This fixed is used to position the desktop itself in the work area */
-  fixed = gtk_fixed_new ();
-  gtk_widget_show (fixed);
-  gtk_container_add (GTK_CONTAINER (window), fixed);
-
-  /* Main VBox */
-  box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
-  gtk_widget_show (box);
-  gtk_fixed_put (GTK_FIXED (fixed), box, 0, 0);
-
-  /* Set a sane default in case there is no work area defined yet */
-  workarea_changed (0, 0, width, height);
-  if (mode == MODE_DESKTOP || mode == MODE_TITLEBAR) {
-    x_monitor_workarea (screen, workarea_changed);
-  }
 
   /* Navigation bar */
   bar = TAKU_CATEGORY_BAR (taku_category_bar_new ());
@@ -212,20 +261,36 @@ create_desktop (DesktopMode mode)
   gtk_box_pack_start (GTK_BOX (box), scrolled, TRUE, TRUE, 0);
 
   viewport = gtk_viewport_new (NULL, NULL);
+  gtk_widget_set_valign (viewport, GTK_ALIGN_START);
   gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport),
                                 GTK_SHADOW_NONE);
   gtk_widget_show (viewport);
   gtk_container_add (GTK_CONTAINER (scrolled), viewport);
 
-  table = TAKU_TABLE (taku_table_new ());
+  table = gtk_flow_box_new ();
+  gtk_flow_box_set_homogeneous (GTK_FLOW_BOX (table), TRUE);
+  gtk_flow_box_set_row_spacing (GTK_FLOW_BOX (table), 6);
+  gtk_flow_box_set_column_spacing (GTK_FLOW_BOX (table), 6);
+  g_signal_connect (table, "child-activated",
+                    G_CALLBACK (table_child_activated_cb), NULL);
+  g_signal_connect (table, "size-allocate",
+                    G_CALLBACK (table_size_allocate_cb), NULL);
   g_signal_connect_after (table, "focus", G_CALLBACK (focus_cb), NULL);
-  gtk_widget_show (GTK_WIDGET (table));
-  gtk_container_add (GTK_CONTAINER (viewport), GTK_WIDGET (table));
+  gtk_flow_box_set_filter_func (GTK_FLOW_BOX (table),
+                                (GtkFlowBoxFilterFunc)table_filter,
+                                bar, NULL);
+  gtk_flow_box_set_sort_func (GTK_FLOW_BOX (table),
+                              (GtkFlowBoxSortFunc)table_sort,
+                              NULL, NULL);
+  gtk_widget_show (table);
+  gtk_container_add (GTK_CONTAINER (viewport), table);
+  gtk_flow_box_set_vadjustment (GTK_FLOW_BOX (table),
+                                gtk_scrollable_get_vadjustment (GTK_SCROLLABLE(viewport)));
 
   menu = taku_menu_get_default ();
   categories = taku_menu_get_categories (menu);
 
-  taku_category_bar_set_table (bar, table);
+  taku_category_bar_set_table (bar, GTK_FLOW_BOX (table));
   taku_category_bar_set_categories (bar, categories);
 
   g_signal_connect (menu, "item-added", G_CALLBACK (on_item_added), NULL);
diff --git a/src/taku-category-bar.c b/src/taku-category-bar.c
index e5c5533..93bda61 100644
--- a/src/taku-category-bar.c
+++ b/src/taku-category-bar.c
@@ -21,12 +21,11 @@
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
 
-#include "libtaku/taku-table.h"
 #include "libtaku/taku-launcher-tile.h"
 
 #include "taku-category-bar.h"
 
-G_DEFINE_TYPE (TakuCategoryBar, taku_category_bar, GTK_TYPE_HBOX);
+G_DEFINE_TYPE (TakuCategoryBar, taku_category_bar, GTK_TYPE_BOX);
 
 #define GET_PRIVATE(o) \
   (G_TYPE_INSTANCE_GET_PRIVATE ((o), TAKU_TYPE_CATEGORY_BAR, TakuCategoryBarPrivate))
@@ -34,7 +33,7 @@ G_DEFINE_TYPE (TakuCategoryBar, taku_category_bar, GTK_TYPE_HBOX);
 #define LIST_DATA "taku-category-bar:list"
 
 typedef struct {
-  TakuTable *table;
+  GtkFlowBox *table;
   GList *categories;
   GList *current_category;
   GtkWidget *prev_button, *popup_button, *next_button;
@@ -78,9 +77,8 @@ set_category (TakuCategoryBar *bar, GList *category_list_item)
   category = category_list_item->data;
 
   gtk_label_set_text (priv->switcher_label, category->name);
-  taku_table_set_filter (priv->table, category);
-
   priv->current_category = category_list_item;
+  gtk_flow_box_invalidate_filter (priv->table);
 }
 
 static void
@@ -285,12 +283,12 @@ taku_category_bar_new (void)
 }
 
 void
-taku_category_bar_set_table (TakuCategoryBar *bar, TakuTable *table)
+taku_category_bar_set_table (TakuCategoryBar *bar, GtkFlowBox *table)
 {
   TakuCategoryBarPrivate *priv;
 
   g_return_if_fail (TAKU_IS_CATEGORY_BAR (bar));
-  g_return_if_fail (TAKU_IS_TABLE (table));
+  g_return_if_fail (GTK_IS_FLOW_BOX (table));
 
   priv = GET_PRIVATE (bar);
   
@@ -321,6 +319,17 @@ taku_category_bar_set_categories (TakuCategoryBar *bar, GList *categories)
   }
 }
 
+TakuLauncherCategory*
+taku_category_bar_get_current (TakuCategoryBar *bar)
+{
+  TakuCategoryBarPrivate *priv;
+
+  g_return_if_fail (TAKU_IS_CATEGORY_BAR (bar));
+  priv = GET_PRIVATE (bar);
+
+  return (TakuLauncherCategory*)priv->current_category->data;
+}
+
 void
 taku_category_bar_next (TakuCategoryBar *bar)
 {
diff --git a/src/taku-category-bar.h b/src/taku-category-bar.h
index 0bc2693..ff93e86 100644
--- a/src/taku-category-bar.h
+++ b/src/taku-category-bar.h
@@ -20,7 +20,7 @@
 #define _TAKU_CATEGORY_BAR
 
 #include <gtk/gtk.h>
-#include <libtaku/taku-table.h>
+#include "libtaku/taku-launcher-tile.h"
 
 G_BEGIN_DECLS
 
@@ -58,9 +58,10 @@ GType taku_category_bar_get_type (void);
 
 GtkWidget* taku_category_bar_new (void);
 
-void taku_category_bar_set_table (TakuCategoryBar *bar, TakuTable *table);
+void taku_category_bar_set_table (TakuCategoryBar *bar, GtkFlowBox *table);
 void taku_category_bar_set_categories (TakuCategoryBar *bar, GList *categories);
 
+TakuLauncherCategory* taku_category_bar_get_current (TakuCategoryBar *bar);
 void taku_category_bar_next (TakuCategoryBar *bar);
 void taku_category_bar_previous (TakuCategoryBar *bar);
 
-- 
2.8.1




More information about the yocto mailing list