2009-01-13 Claudio Saavedra <csaavedra@igalia.com>
[hildon] / src / hildon-picker-button.c
index 6b3e2b0..d6a93ae 100644 (file)
  * the common use cases of buttons to select date and time, you can use #HildonDateButton
  * and #HildonTimeButton.
  *
+ * <example>
+ * <programlisting>
+ * GtkWidget *
+ * create_selector (void)
+ * {
+ *   GtkWidget *selector;
+ * <!-- -->
+ *   selector = hildon_touch_selector_new_text ();
+ * <!-- -->
+ *   hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), "America");
+ *   hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), "Europe");
+ *   hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), "Asia");
+ *   hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), "Africa");
+ *   hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), "Australia");
+ * <!-- -->
+ *   hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, 2);
+ * <!-- -->
+ *   return selector;
+ * }
+ * <!-- -->
+ * GtkWidget *
+ * create_button (HildonTouchSelector *selector)
+ * {
+ *   GtkWidget *button;
+ * <!-- -->
+ *   button = hildon_picker_button_new (HILDON_SIZE_AUTO, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
+ *   hildon_button_set_title (HILDON_BUTTON (button), "Continent");
+ * <!-- -->
+ *   hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (button),
+ *                                      HILDON_TOUCH_SELECTOR (selector));
+ * <!-- -->
+ *   return button;
+ * }
+ * </programlisting>
+ * </example>
  */
 
 #include "hildon-picker-button.h"
@@ -64,6 +99,15 @@ enum
 
 static guint picker_button_signals[LAST_SIGNAL] = { 0 };
 
+static gboolean
+_current_selector_empty                         (HildonPickerButton *button);
+static void
+hildon_picker_button_selector_selection_changed (HildonTouchSelector * selector,
+                                                 gint column,
+                                                 gpointer user_data);
+
+
+
 static void
 hildon_picker_button_get_property (GObject * object, guint property_id,
                                    GValue * value, GParamSpec * pspec)
@@ -108,6 +152,9 @@ hildon_picker_button_finalize (GObject * object)
   priv = GET_PRIVATE (object);
 
   if (priv->selector) {
+    g_signal_handlers_disconnect_by_func (priv->selector,
+                                          hildon_picker_button_selector_selection_changed,
+                                          object);
     g_object_unref (priv->selector);
     priv->selector = NULL;
   }
@@ -116,15 +163,43 @@ hildon_picker_button_finalize (GObject * object)
     priv->dialog = NULL;
   }
 
+  if (priv->done_button_text) {
+    g_free (priv->done_button_text);
+    priv->done_button_text = NULL;
+  }
+
   G_OBJECT_CLASS (hildon_picker_button_parent_class)->finalize (object);
 }
 
 static void
+hildon_picker_button_on_dialog_response (GtkDialog *dialog,
+                                         gint       response,
+                                         gpointer   user_data)
+{
+  HildonPickerButton *button;
+  HildonPickerButtonPrivate *priv;
+  gchar *value;
+
+  button = HILDON_PICKER_BUTTON (user_data);
+  priv = GET_PRIVATE (button);
+
+  switch (response) {
+  case GTK_RESPONSE_OK:
+    value = hildon_touch_selector_get_current_text
+      (HILDON_TOUCH_SELECTOR (priv->selector));
+    hildon_button_set_value (HILDON_BUTTON (button), value);
+    g_free (value);
+    g_signal_emit (button, picker_button_signals[VALUE_CHANGED], 0);
+    break;
+  }
+  gtk_widget_hide (priv->dialog);
+}
+
+static void
 hildon_picker_button_clicked (GtkButton * button)
 {
   GtkWidget *parent;
   HildonPickerButtonPrivate *priv;
-  gint response;
 
   priv = GET_PRIVATE (HILDON_PICKER_BUTTON (button));
 
@@ -152,17 +227,39 @@ hildon_picker_button_clicked (GtkButton * button)
                           hildon_button_get_title (HILDON_BUTTON (button)));
   }
 
-  response = gtk_dialog_run (GTK_DIALOG (priv->dialog));
-  switch (response) {
-  case GTK_RESPONSE_OK:
-    hildon_button_set_value (HILDON_BUTTON (button),
-                             hildon_touch_selector_get_current_text
-                             (HILDON_TOUCH_SELECTOR (priv->selector)));
-    g_signal_emit (HILDON_PICKER_BUTTON (button),
-                   picker_button_signals[VALUE_CHANGED], 0);
-    break;
+  if (_current_selector_empty (HILDON_PICKER_BUTTON (button))) {
+    g_warning ("There are no elements in the selector. Nothing to show.");
+  } else {
+    g_signal_connect (priv->dialog, "response",
+                      G_CALLBACK (hildon_picker_button_on_dialog_response),
+                      button);
+    g_signal_connect (priv->dialog, "delete-event",
+                      G_CALLBACK (gtk_widget_hide_on_delete),
+                      NULL);
+    gtk_window_present (GTK_WINDOW (priv->dialog));
+  }
+}
+
+static void
+hildon_picker_button_selector_selection_changed (HildonTouchSelector * selector,
+                                                 gint column,
+                                                 gpointer user_data)
+
+{
+  gchar *value;
+  HildonPickerButton *button = HILDON_PICKER_BUTTON (user_data);
+  HildonPickerButtonPrivate *priv = GET_PRIVATE (button);
+
+  if (!GTK_IS_WINDOW (priv->dialog) ||
+      !GTK_WIDGET_VISIBLE (GTK_WINDOW (priv->dialog))) {
+    value = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (priv->selector));
+    if (value) {
+      hildon_button_set_value (HILDON_BUTTON (button), value);
+      g_free (value);
+      g_signal_emit (HILDON_PICKER_BUTTON (button),
+                     picker_button_signals[VALUE_CHANGED], 0);
+    }
   }
-  gtk_widget_hide (priv->dialog);
 }
 
 static void
@@ -200,6 +297,8 @@ hildon_picker_button_class_init (HildonPickerButtonClass * klass)
    *
    * The ::value-changed signal is emitted each time the user chooses a different
    * item from the #HildonTouchSelector related, and the value label gets updated.
+   *
+   * Since: 2.2
    */
   picker_button_signals[VALUE_CHANGED] =
     g_signal_new ("value-changed",
@@ -220,6 +319,37 @@ hildon_picker_button_init (HildonPickerButton * self)
   priv->dialog = NULL;
   priv->selector = NULL;
   priv->done_button_text = NULL;
+
+  hildon_button_set_style (HILDON_BUTTON (self),
+                           HILDON_BUTTON_STYLE_PICKER);
+}
+
+static gboolean
+_current_selector_empty (HildonPickerButton *button)
+{
+  HildonPickerButtonPrivate *priv;
+  HildonTouchSelector *selector = NULL;
+  GtkTreeModel *model = NULL;
+  GtkTreeIter iter;
+  gint i = 0;
+
+  priv = GET_PRIVATE (button);
+  selector = HILDON_TOUCH_SELECTOR (priv->selector);
+
+  g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), TRUE);
+
+  if (hildon_touch_selector_has_multiple_selection (selector)) {
+    return FALSE;
+  } else {
+    for (i=0; i < hildon_touch_selector_get_num_columns (selector); i++) {
+      model = hildon_touch_selector_get_model (selector, i);
+
+      if (gtk_tree_model_get_iter_first (model, &iter)) {
+        return FALSE;
+      }
+    }
+    return TRUE;
+  }
 }
 
 /**
@@ -232,6 +362,8 @@ hildon_picker_button_init (HildonPickerButton * self)
  * parameters.
  *
  * Returns: a newly created #HildonPickerButton
+ *
+ * Since: 2.2
  **/
 GtkWidget *
 hildon_picker_button_new (HildonSizeType          size,
@@ -240,7 +372,8 @@ hildon_picker_button_new (HildonSizeType          size,
   GtkWidget *button;
 
   button = g_object_new (HILDON_TYPE_PICKER_BUTTON,
-                         "arrangement", arrangement, "size", size, NULL);
+                         "arrangement", arrangement, "size", size,
+                         NULL);
 
   return button;
 }
@@ -252,13 +385,15 @@ hildon_picker_button_new (HildonSizeType          size,
  *
  * Sets @selector as the #HildonTouchSelector to be shown in the
  * #HildonPickerDialog that @button brings up.
+ *
+ * Since: 2.2
  **/
 void
 hildon_picker_button_set_selector (HildonPickerButton * button,
                                    HildonTouchSelector * selector)
 {
   HildonPickerButtonPrivate *priv;
-  const gchar *value;
+  gchar *value;
 
   g_return_if_fail (HILDON_IS_PICKER_BUTTON (button));
   g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
@@ -266,14 +401,22 @@ hildon_picker_button_set_selector (HildonPickerButton * button,
   priv = GET_PRIVATE (button);
 
   if (priv->selector) {
+    g_signal_handlers_disconnect_by_func (priv->selector,
+                                          hildon_picker_button_selector_selection_changed,
+                                          button);
     g_object_unref (priv->selector);
   }
 
   priv->selector = g_object_ref (selector);
 
+  g_signal_connect (G_OBJECT (selector), "changed",
+                    G_CALLBACK (hildon_picker_button_selector_selection_changed),
+                    button);
+
   value = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (priv->selector));
   if (value) {
     hildon_button_set_value (HILDON_BUTTON (button), value);
+    g_free (value);
     g_signal_emit (HILDON_PICKER_BUTTON (button),
                    picker_button_signals[VALUE_CHANGED], 0);
   }
@@ -286,6 +429,8 @@ hildon_picker_button_set_selector (HildonPickerButton * button,
  * Retrieves the #HildonTouchSelector associated to @button.
  *
  * Returns: a #HildonTouchSelector
+ *
+ * Since: 2.2
  **/
 HildonTouchSelector *
 hildon_picker_button_get_selector (HildonPickerButton * button)
@@ -308,6 +453,8 @@ hildon_picker_button_get_selector (HildonPickerButton * button)
  * one is used.
  *
  * Returns: an integer which is the index of the currently active item, or -1 if there's no active item.
+ *
+ * Since: 2.2
  **/
 gint
 hildon_picker_button_get_active                 (HildonPickerButton * button)
@@ -328,6 +475,8 @@ hildon_picker_button_get_active                 (HildonPickerButton * button)
  * Sets the active item of the #HildonTouchSelector associated to
  * @button to @index. If the selector has several columns, only the
  * first one is used.
+ *
+ * Since: 2.2
  **/
 void
 hildon_picker_button_set_active                 (HildonPickerButton * button,
@@ -354,6 +503,8 @@ hildon_picker_button_set_active                 (HildonPickerButton * button,
  *
  * Returns: the custom string to be used, or %NULL if the default
  * #HildonPickerDialog::done-button-text is to be used.
+ *
+ * Since: 2.2
  **/
 const gchar *
 hildon_picker_button_get_done_button_text (HildonPickerButton *button)
@@ -372,9 +523,11 @@ hildon_picker_button_get_done_button_text (HildonPickerButton *button)
  * @button: a #HildonPickerButton
  * @done_button_text: a string
  *
- * Sets a custom string to be used in the \"done\" button in the #HildonPickerDialog
- * launched. If not set, the default HildonPickerButton::done-button-text property
+ * Sets a custom string to be used in the "done" button in #HildonPickerDialog.
+ * If unset, the default HildonPickerButton::done-button-text property
  * value will be used.
+ *
+ * Since: 2.2
  **/
 void
 hildon_picker_button_set_done_button_text (HildonPickerButton *button,
@@ -389,4 +542,9 @@ hildon_picker_button_set_done_button_text (HildonPickerButton *button,
 
   g_free (priv->done_button_text);
   priv->done_button_text = g_strdup (done_button_text);
+
+  if (priv->dialog) {
+    hildon_picker_dialog_set_done_label (HILDON_PICKER_DIALOG (priv->dialog),
+                                         priv->done_button_text);
+  }
 }