[gtk+/list-selection: 2/6] listbox: Add multi-selection API



commit 733ef5ecf33dbb75fda2d43205699ecd7ed789e5
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Mar 28 19:21:57 2014 -0400

    listbox: Add multi-selection API
    
    This commit adds API for dealing with multi-selection. It is identical
    to the flow box API for this purpose. The implementation is still limited
    to single-selection, and will be updated in subsequent commits.

 gtk/gtklistbox.c |  228 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 gtk/gtklistbox.h |   28 ++++++-
 2 files changed, 251 insertions(+), 5 deletions(-)
---
diff --git a/gtk/gtklistbox.c b/gtk/gtklistbox.c
index c4bc26c..d032fbb 100644
--- a/gtk/gtklistbox.c
+++ b/gtk/gtklistbox.c
@@ -107,6 +107,9 @@ enum {
   ACTIVATE_CURSOR_ROW,
   TOGGLE_CURSOR_ROW,
   MOVE_CURSOR,
+  SELECTED_ROWS_CHANGED,
+  SELECT_ALL,
+  UNSELECT_ALL,
   LAST_SIGNAL
 };
 
@@ -377,6 +380,8 @@ gtk_list_box_class_init (GtkListBoxClass *klass)
    * The ::row-selected signal is emitted when a new row is selected, or
    * (with a %NULL @row) when the selection is cleared.
    *
+   * Also see #GtkListBox::selected-rows-changed.
+   *
    * Since: 3.10
    */
   signals[ROW_SELECTED] =
@@ -390,6 +395,63 @@ gtk_list_box_class_init (GtkListBoxClass *klass)
                   GTK_TYPE_LIST_BOX_ROW);
 
   /**
+   * GtkListBox::selected-rows-changed:
+   * @list_box: the #GtkListBox on wich the signal is emitted
+   *
+   * The ::selected-rows-changed signal is emitted when the
+   * set of selected rows changes.
+   *
+   * Since: 3.14
+   */
+  signals[SELECTED_ROWS_CHANGED] = g_signal_new ("selected-rows-changed",
+                                                 GTK_TYPE_LIST_BOX,
+                                                 G_SIGNAL_RUN_FIRST,
+                                                 G_STRUCT_OFFSET (GtkListBoxClass, selected_rows_changed),
+                                                 NULL, NULL,
+                                                 g_cclosure_marshal_VOID__VOID,
+                                                 G_TYPE_NONE, 0);
+
+  /**
+   * GtkListBox::select-all:
+   * @box: the #GtkListBox on which the signal is emitted
+   *
+   * The ::select-all signal is a [keybinding signal][GtkBindingSignal]
+   * which gets emitted to select all children of the box, if the selection
+   * mode permits it.
+   *
+   * The default bindings for this signal is Ctrl-a.
+   *
+   * Since: 3.14
+   */
+  signals[SELECT_ALL] = g_signal_new ("select-all",
+                                      GTK_TYPE_LIST_BOX,
+                                      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                                      G_STRUCT_OFFSET (GtkListBoxClass, select_all),
+                                      NULL, NULL,
+                                      g_cclosure_marshal_VOID__VOID,
+                                      G_TYPE_NONE, 0);
+
+  /**
+   * GtkListBox::unselect-all:
+   * @box: the #GtkListBox on which the signal is emitted
+   * 
+   * The ::unselect-all signal is a [keybinding signal][GtkBindingSignal]
+   * which gets emitted to unselect all children of the box, if the selection
+   * mode permits it.
+   *
+   * The default bindings for this signal is Ctrl-Shift-a.
+   *
+   * Since: 3.14
+   */
+  signals[UNSELECT_ALL] = g_signal_new ("unselect-all",
+                                      GTK_TYPE_LIST_BOX,
+                                      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                                      G_STRUCT_OFFSET (GtkListBoxClass, unselect_all),
+                                      NULL, NULL,
+                                      g_cclosure_marshal_VOID__VOID,
+                                      G_TYPE_NONE, 0);
+
+  /**
    * GtkListBox::row-activated:
    * @list_box: the #GtkListBox
    * @row: the activated row
@@ -576,10 +638,142 @@ gtk_list_box_select_row (GtkListBox    *list_box,
                          GtkListBoxRow *row)
 {
   g_return_if_fail (GTK_IS_LIST_BOX (list_box));
+  g_return_if_fail (row == NULL || GTK_IS_LIST_BOX_ROW (row));
 
   gtk_list_box_update_selected (list_box, row);
 }
 
+/**   
+ * gtk_list_box_unselect_row:
+ * @list_box: a #GtkListBox
+ * @row: the row to unselected
+ *
+ * Unselects a single row of @list_box, if the selection
+ * mode allows it.
+ *
+ * Since: 3.14
+ */                       
+void
+gtk_list_box_unselect_row (GtkListBox    *list_box,
+                           GtkListBoxRow *row)
+{
+  g_return_if_fail (GTK_IS_LIST_BOX (list_box));
+  g_return_if_fail (GTK_IS_LIST_BOX_ROW (row));
+  
+  gtk_list_box_update_selected (list_box, NULL);
+} 
+
+/**
+ * gtk_list_box_select_all:
+ * @list_box: a #GtkListBox
+ *
+ * Select all children of @list_box, if the selection
+ * mode allows it.
+ *
+ * Since: 3.14
+ */
+void
+gtk_list_box_select_all (GtkListBox *list_box)
+{
+  g_return_if_fail (GTK_IS_LIST_BOX (list_box));
+}
+
+/**
+ * gtk_list_box_unselect_all:
+ * @list_box: a #GtkListBox
+ *
+ * Unselect all children of @list_box, if the selection
+ * mode allows it.
+ *
+ * Since: 3.14
+ */
+void
+gtk_list_box_unselect_all (GtkListBox *list_box)
+{
+  g_return_if_fail (GTK_IS_LIST_BOX (list_box));
+
+  gtk_list_box_update_selected (list_box, NULL);
+}
+
+/**
+ * GtkListBoxForeachFunc:
+ * @list_box: a #GtkListBox
+ * @row: a #GtkListBoxRow
+ * @user_data: (closure): user data
+ *
+ * A function used by gtk_list_box_selected_foreach().
+ * It will be called on every selected child of the @list_box.
+ *
+ * Since: 3.14
+ */
+
+/**
+ * gtk_list_box_selected_foreach:
+ * @list_box: a #GtkListBox
+ * @func: (scope call): the function to call for each selected child
+ * @data: user data to pass to the function
+ *
+ * Calls a function for each selected child.
+ *
+ * Note that the selection cannot be modified from within
+ * this function.
+ *
+ * Since: 3.14
+ */
+void
+gtk_list_box_selected_foreach (GtkListBox            *list_box,
+                               GtkListBoxForeachFunc  func,
+                               gpointer               data)
+{
+  GtkListBoxPrivate *priv = gtk_list_box_get_instance_private (list_box);
+  GtkListBoxRow *row;
+  GSequenceIter *iter;
+
+  g_return_if_fail (GTK_IS_LIST_BOX (list_box));
+
+  for (iter = g_sequence_get_begin_iter (priv->children);
+       !g_sequence_iter_is_end (iter);
+       iter = g_sequence_iter_next (iter))
+    {
+      row = g_sequence_get (iter);
+      if (gtk_list_box_row_is_selected (row))
+        (*func) (list_box, row, data);
+    }
+}
+
+/**
+ * gtk_list_box_get_selected_children:
+ * @list_box: a #GtkListBox
+ *
+ * Creates a list of all selected children.
+ *
+ * Returns: (element-type GtkListBoxRow) (transfer container):
+ *     A #GList containing the #GtkWidget for each selected child.
+ *     Free with g_list_free() when done.
+ *
+ * Since: 3.14
+ */
+GList *
+gtk_list_box_get_selected_children (GtkListBox *list_box)
+{
+  GtkListBoxPrivate *priv = gtk_list_box_get_instance_private (list_box);
+  GtkListBoxRow *row;
+  GSequenceIter *iter;
+  GList *selected = NULL;
+
+  g_return_val_if_fail (GTK_IS_LIST_BOX (list_box), NULL);
+
+  for (iter = g_sequence_get_begin_iter (priv->children);
+       !g_sequence_iter_is_end (iter);
+       iter = g_sequence_iter_next (iter))
+    {
+      row = g_sequence_get (iter);
+      if (gtk_list_box_row_is_selected (row))
+        selected = g_list_prepend (selected, row);
+    }
+
+  return g_list_reverse (selected);
+}
 
 /**
  * gtk_list_box_set_placeholder:
@@ -1099,8 +1293,10 @@ gtk_list_box_update_selected (GtkListBox    *list_box,
         gtk_widget_set_state_flags (GTK_WIDGET (priv->selected_row),
                                     GTK_STATE_FLAG_SELECTED,
                                     FALSE);
-      g_signal_emit (list_box, signals[ROW_SELECTED], 0,
-                     priv->selected_row);
+
+      g_signal_emit (list_box, signals[ROW_SELECTED], 0, priv->selected_row);
+      g_signal_emit (list_box, signals[SELECTED_ROWS_CHANGED], 0);
+
       gtk_widget_queue_draw (GTK_WIDGET (list_box));
     }
   _gtk_list_box_accessible_selection_changed (list_box);
@@ -2812,6 +3008,34 @@ gtk_list_box_row_get_index (GtkListBoxRow *row)
   return -1;
 }
 
+/**
+ * gtk_list_box_row_is_selected:
+ * @row: a #GtkListBoxRow
+ *
+ * Returns whether the child is currently selected in its
+ * #GtkListBox container.
+ *
+ * Returns: %TRUE if @row is selected
+ *
+ * Since: 3.14
+ */
+gboolean
+gtk_list_box_row_is_selected (GtkListBoxRow *row)
+{
+  GtkListBox *list_box;
+  GtkListBoxPrivate *priv;
+
+  g_return_val_if_fail (GTK_IS_LIST_BOX_ROW (row), FALSE);
+
+  list_box = gtk_list_box_row_get_box (row);
+  if (list_box == NULL)
+    return FALSE;
+
+  priv = gtk_list_box_get_instance_private (list_box);
+
+  return priv->selected_row == row;
+}
+
 static void
 gtk_list_box_row_finalize (GObject *obj)
 {
diff --git a/gtk/gtklistbox.h b/gtk/gtklistbox.h
index 7b2a832..88cce2b 100644
--- a/gtk/gtklistbox.h
+++ b/gtk/gtklistbox.h
@@ -73,6 +73,9 @@ struct _GtkListBoxClass
   void (*move_cursor)         (GtkListBox      *list_box,
                                GtkMovementStep  step,
                                gint             count);
+  void (*selected_rows_changed) (GtkListBox    *box);
+  void (*select_all)            (GtkListBox    *box);
+  void (*unselect_all)          (GtkListBox    *box);
 
   /*< private >*/
 
@@ -80,9 +83,6 @@ struct _GtkListBoxClass
   void (*_gtk_reserved1) (void);
   void (*_gtk_reserved2) (void);
   void (*_gtk_reserved3) (void);
-  void (*_gtk_reserved4) (void);
-  void (*_gtk_reserved5) (void);
-  void (*_gtk_reserved6) (void);
 };
 
 #define GTK_TYPE_LIST_BOX_ROW            (gtk_list_box_row_get_type ())
@@ -180,6 +180,8 @@ gint       gtk_list_box_row_get_index     (GtkListBoxRow *row);
 GDK_AVAILABLE_IN_3_10
 void       gtk_list_box_row_changed       (GtkListBoxRow *row);
 
+GDK_AVAILABLE_IN_3_14
+gboolean   gtk_list_box_row_is_selected   (GtkListBoxRow *row);
 
 GDK_AVAILABLE_IN_3_10
 GType          gtk_list_box_get_type                     (void) G_GNUC_CONST;
@@ -209,6 +211,25 @@ void           gtk_list_box_set_adjustment               (GtkListBox
                                                           GtkAdjustment                 *adjustment);
 GDK_AVAILABLE_IN_3_10
 GtkAdjustment *gtk_list_box_get_adjustment               (GtkListBox                    *list_box);
+
+typedef void (* GtkListBoxForeachFunc) (GtkListBox      *box,
+                                        GtkListBoxRow   *row,
+                                        gpointer         user_data);
+
+GDK_AVAILABLE_IN_3_14
+void           gtk_list_box_selected_foreach             (GtkListBox                    *list_box,
+                                                          GtkListBoxForeachFunc          func,
+                                                          gpointer                       data);
+GDK_AVAILABLE_IN_3_14
+GList         *gtk_list_box_get_selected_rows            (GtkListBox                    *list_box);
+GDK_AVAILABLE_IN_3_14
+void           gtk_list_box_unselect_row                 (GtkListBox                    *list_box,
+                                                          GtkListBoxRow                 *row);
+GDK_AVAILABLE_IN_3_14
+void           gtk_list_box_select_all                   (GtkListBox                    *list_box);
+GDK_AVAILABLE_IN_3_14
+void           gtk_list_box_unselect_all                 (GtkListBox                    *list_box);
+
 GDK_AVAILABLE_IN_3_10
 void           gtk_list_box_set_selection_mode           (GtkListBox                    *list_box,
                                                           GtkSelectionMode               mode);
@@ -249,6 +270,7 @@ GDK_AVAILABLE_IN_3_10
 GtkWidget*     gtk_list_box_new                          (void);
 
 
+
 G_END_DECLS
 
 #endif


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