]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkradioaction.c
entrycompletion: Don't reconnect signals all the time
[~andy/gtk] / gtk / gtkradioaction.c
index 38959da49e13cb1fa14069587ea62b9a3eec6fbc..4a5aaa786f1e27d340bd2fa8485529cc56a78bf3 100644 (file)
@@ -14,9 +14,7 @@
  * Library General Public License for more details.
  *
  * You should have received a copy of the GNU Library General Public
- * License along with the Gnome Library; see the file COPYING.LIB.  If not,
- * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
 
-#include <config.h>
+#include "config.h"
 
 #include "gtkradioaction.h"
 #include "gtkradiomenuitem.h"
-#include "gtktoggleactionprivate.h"
 #include "gtktoggletoolbutton.h"
 #include "gtkintl.h"
+#include "gtkprivate.h"
+
+/**
+ * SECTION:gtkradioaction
+ * @Short_description: An action of which only one in a group can be active
+ * @Title: GtkRadioAction
+ *
+ * A #GtkRadioAction is similar to #GtkRadioMenuItem. A number of radio
+ * actions can be linked together so that only one may be active at any
+ * one time.
+ */
 
-#define GTK_RADIO_ACTION_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_RADIO_ACTION, GtkRadioActionPrivate))
 
 struct _GtkRadioActionPrivate 
 {
@@ -53,11 +60,11 @@ enum
 enum 
 {
   PROP_0,
-  PROP_VALUE
+  PROP_VALUE,
+  PROP_GROUP,
+  PROP_CURRENT_VALUE
 };
 
-static void gtk_radio_action_init         (GtkRadioAction *action);
-static void gtk_radio_action_class_init   (GtkRadioActionClass *class);
 static void gtk_radio_action_finalize     (GObject *object);
 static void gtk_radio_action_set_property (GObject         *object,
                                           guint            prop_id,
@@ -71,35 +78,8 @@ static void gtk_radio_action_activate     (GtkAction *action);
 static GtkWidget *create_menu_item        (GtkAction *action);
 
 
-GType
-gtk_radio_action_get_type (void)
-{
-  static GtkType type = 0;
+G_DEFINE_TYPE (GtkRadioAction, gtk_radio_action, GTK_TYPE_TOGGLE_ACTION)
 
-  if (!type)
-    {
-      static const GTypeInfo type_info =
-      {
-        sizeof (GtkRadioActionClass),
-        (GBaseInitFunc) NULL,
-        (GBaseFinalizeFunc) NULL,
-        (GClassInitFunc) gtk_radio_action_class_init,
-        (GClassFinalizeFunc) NULL,
-        NULL,
-        
-        sizeof (GtkRadioAction),
-        0, /* n_preallocs */
-        (GInstanceInitFunc) gtk_radio_action_init,
-      };
-
-      type = g_type_register_static (GTK_TYPE_TOGGLE_ACTION,
-                                     "GtkRadioAction",
-                                     &type_info, 0);
-    }
-  return type;
-}
-
-static GObjectClass *parent_class = NULL;
 static guint         radio_action_signals[LAST_SIGNAL] = { 0 };
 
 static void
@@ -108,7 +88,6 @@ gtk_radio_action_class_init (GtkRadioActionClass *klass)
   GObjectClass *gobject_class;
   GtkActionClass *action_class;
 
-  parent_class = g_type_class_peek_parent (klass);
   gobject_class = G_OBJECT_CLASS (klass);
   action_class = GTK_ACTION_CLASS (klass);
 
@@ -134,12 +113,45 @@ gtk_radio_action_class_init (GtkRadioActionClass *klass)
   g_object_class_install_property (gobject_class,
                                   PROP_VALUE,
                                   g_param_spec_int ("value",
-                                                    _("The value"),
-                                                    _("The value returned by gtk_radio_action_get_current_value() when this action is the current action of its group."),
+                                                    P_("The value"),
+                                                    P_("The value returned by gtk_radio_action_get_current_value() when this action is the current action of its group."),
+                                                    G_MININT,
+                                                    G_MAXINT,
+                                                    0,
+                                                    GTK_PARAM_READWRITE));
+
+  /**
+   * GtkRadioAction:group:
+   *
+   * Sets a new group for a radio action.
+   *
+   * Since: 2.4
+   */
+  g_object_class_install_property (gobject_class,
+                                  PROP_GROUP,
+                                  g_param_spec_object ("group",
+                                                       P_("Group"),
+                                                       P_("The radio action whose group this action belongs to."),
+                                                       GTK_TYPE_RADIO_ACTION,
+                                                       GTK_PARAM_WRITABLE));
+
+  /**
+   * GtkRadioAction:current-value:
+   *
+   * The value property of the currently active member of the group to which
+   * this action belongs. 
+   *
+   * Since: 2.10
+   */
+  g_object_class_install_property (gobject_class,
+                                  PROP_CURRENT_VALUE,
+                                   g_param_spec_int ("current-value",
+                                                    P_("The current value"),
+                                                    P_("The value property of the currently active member of the group to which this action belongs."),
                                                     G_MININT,
                                                     G_MAXINT,
                                                     0,
-                                                    G_PARAM_READWRITE));
+                                                    GTK_PARAM_READWRITE));
 
   /**
    * GtkRadioAction::changed:
@@ -153,7 +165,7 @@ gtk_radio_action_class_init (GtkRadioActionClass *klass)
    * Since: 2.4
    */
   radio_action_signals[CHANGED] =
-    g_signal_new ("changed",
+    g_signal_new (I_("changed"),
                  G_OBJECT_CLASS_TYPE (klass),
                  G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
                  G_STRUCT_OFFSET (GtkRadioActionClass, changed),  NULL, NULL,
@@ -166,9 +178,51 @@ gtk_radio_action_class_init (GtkRadioActionClass *klass)
 static void
 gtk_radio_action_init (GtkRadioAction *action)
 {
-  action->private_data = GTK_RADIO_ACTION_GET_PRIVATE (action);
+  action->private_data = G_TYPE_INSTANCE_GET_PRIVATE (action,
+                                                      GTK_TYPE_RADIO_ACTION,
+                                                      GtkRadioActionPrivate);
+
   action->private_data->group = g_slist_prepend (NULL, action);
   action->private_data->value = 0;
+
+  gtk_toggle_action_set_draw_as_radio (GTK_TOGGLE_ACTION (action), TRUE);
+}
+
+/**
+ * gtk_radio_action_new:
+ * @name: A unique name for the action
+ * @label: (allow-none): The label displayed in menu items and on buttons,
+ *   or %NULL
+ * @tooltip: (allow-none): A tooltip for this action, or %NULL
+ * @stock_id: (allow-none): The stock icon to display in widgets representing
+ *   this action, or %NULL
+ * @value: The value which gtk_radio_action_get_current_value() should
+ *   return if this action is selected.
+ *
+ * Creates a new #GtkRadioAction object. To add the action to
+ * a #GtkActionGroup and set the accelerator for the action,
+ * call gtk_action_group_add_action_with_accel().
+ *
+ * Return value: a new #GtkRadioAction
+ *
+ * Since: 2.4
+ */
+GtkRadioAction *
+gtk_radio_action_new (const gchar *name,
+                     const gchar *label,
+                     const gchar *tooltip,
+                     const gchar *stock_id,
+                     gint value)
+{
+  g_return_val_if_fail (name != NULL, NULL);
+
+  return g_object_new (GTK_TYPE_RADIO_ACTION,
+                       "name", name,
+                       "label", label,
+                       "tooltip", tooltip,
+                       "stock-id", stock_id,
+                       "value", value,
+                       NULL);
 }
 
 static void
@@ -191,8 +245,7 @@ gtk_radio_action_finalize (GObject *object)
       tmp_action->private_data->group = action->private_data->group;
     }
 
-  if (parent_class->finalize)
-    (* parent_class->finalize) (object);
+  G_OBJECT_CLASS (gtk_radio_action_parent_class)->finalize (object);
 }
 
 static void
@@ -210,6 +263,24 @@ gtk_radio_action_set_property (GObject         *object,
     case PROP_VALUE:
       radio_action->private_data->value = g_value_get_int (value);
       break;
+    case PROP_GROUP: 
+      {
+       GtkRadioAction *arg;
+       GSList *slist = NULL;
+       
+       if (G_VALUE_HOLDS_OBJECT (value)) 
+         {
+           arg = GTK_RADIO_ACTION (g_value_get_object (value));
+           if (arg)
+             slist = gtk_radio_action_get_group (arg);
+           gtk_radio_action_set_group (radio_action, slist);
+         }
+      }
+      break;
+    case PROP_CURRENT_VALUE:
+      gtk_radio_action_set_current_value (radio_action,
+                                          g_value_get_int (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -231,6 +302,10 @@ gtk_radio_action_get_property (GObject    *object,
     case PROP_VALUE:
       g_value_set_int (value, radio_action->private_data->value);
       break;
+    case PROP_CURRENT_VALUE:
+      g_value_set_int (value,
+                       gtk_radio_action_get_current_value (radio_action));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -244,11 +319,13 @@ gtk_radio_action_activate (GtkAction *action)
   GtkToggleAction *toggle_action;
   GtkToggleAction *tmp_action;
   GSList *tmp_list;
+  gboolean active;
 
   radio_action = GTK_RADIO_ACTION (action);
   toggle_action = GTK_TOGGLE_ACTION (action);
 
-  if (toggle_action->private_data->active)
+  active = gtk_toggle_action_get_active (toggle_action);
+  if (active)
     {
       tmp_list = radio_action->private_data->group;
 
@@ -257,16 +334,20 @@ gtk_radio_action_activate (GtkAction *action)
          tmp_action = tmp_list->data;
          tmp_list = tmp_list->next;
 
-         if (tmp_action->private_data->active && (tmp_action != toggle_action)) 
+         if (gtk_toggle_action_get_active (tmp_action) &&
+              (tmp_action != toggle_action))
            {
-             toggle_action->private_data->active = !toggle_action->private_data->active;
+              _gtk_toggle_action_set_active (toggle_action, !active);
+
              break;
            }
        }
+      g_object_notify (G_OBJECT (action), "active");
     }
   else
     {
-      toggle_action->private_data->active = !toggle_action->private_data->active;
+      _gtk_toggle_action_set_active (toggle_action, !active);
+      g_object_notify (G_OBJECT (action), "active");
 
       tmp_list = radio_action->private_data->group;
       while (tmp_list)
@@ -274,9 +355,10 @@ gtk_radio_action_activate (GtkAction *action)
          tmp_action = tmp_list->data;
          tmp_list = tmp_list->next;
 
-         if (tmp_action->private_data->active && (tmp_action != toggle_action))
+          if (gtk_toggle_action_get_active (tmp_action) &&
+              (tmp_action != toggle_action))
            {
-             gtk_action_activate (GTK_ACTION (tmp_action));
+             _gtk_action_emit_activate (GTK_ACTION (tmp_action));
              break;
            }
        }
@@ -287,6 +369,8 @@ gtk_radio_action_activate (GtkAction *action)
          tmp_action = tmp_list->data;
          tmp_list = tmp_list->next;
          
+          g_object_notify (G_OBJECT (tmp_action), "current-value");
+
          g_signal_emit (tmp_action, radio_action_signals[CHANGED], 0, radio_action);
        }
     }
@@ -298,7 +382,7 @@ static GtkWidget *
 create_menu_item (GtkAction *action)
 {
   return g_object_new (GTK_TYPE_CHECK_MENU_ITEM, 
-                      "draw_as_radio", TRUE,
+                      "draw-as-radio", TRUE,
                       NULL);
 }
 
@@ -306,9 +390,25 @@ create_menu_item (GtkAction *action)
  * gtk_radio_action_get_group:
  * @action: the action object
  *
- * Returns the list representing the radio group for this object
+ * Returns the list representing the radio group for this object.
+ * Note that the returned list is only valid until the next change
+ * to the group. 
+ *
+ * A common way to set up a group of radio group is the following:
+ * |[
+ *   GSList *group = NULL;
+ *   GtkRadioAction *action;
+ *  
+ *   while (/&ast; more actions to add &ast;/)
+ *     {
+ *        action = gtk_radio_action_new (...);
+ *        
+ *        gtk_radio_action_set_group (action, group);
+ *        group = gtk_radio_action_get_group (action);
+ *     }
+ * ]|
  *
- * Returns: the list representing the radio group for this object
+ * Returns:  (element-type GtkRadioAction) (transfer none): the list representing the radio group for this object
  *
  * Since: 2.4
  */
@@ -323,7 +423,7 @@ gtk_radio_action_get_group (GtkRadioAction *action)
 /**
  * gtk_radio_action_set_group:
  * @action: the action object
- * @group: a list representing a radio group
+ * @group: (element-type GtkRadioAction): a list representing a radio group
  *
  * Sets the radio group for the radio action object.
  *
@@ -369,11 +469,66 @@ gtk_radio_action_set_group (GtkRadioAction *action,
     }
 }
 
+/**
+ * gtk_radio_action_join_group:
+ * @action: the action object
+ * @group_source: (allow-none): a radio action object whos group we are 
+ *   joining, or %NULL to remove the radio action from its group
+ *
+ * Joins a radio action object to the group of another radio action object.
+ *
+ * Use this in language bindings instead of the gtk_radio_action_get_group() 
+ * and gtk_radio_action_set_group() methods
+ *
+ * A common way to set up a group of radio actions is the following:
+ * |[
+ *   GtkRadioAction *action;
+ *   GtkRadioAction *last_action;
+ *  
+ *   while (/&ast; more actions to add &ast;/)
+ *     {
+ *        action = gtk_radio_action_new (...);
+ *        
+ *        gtk_radio_action_join_group (action, last_action);
+ *        last_action = action;
+ *     }
+ * ]|
+ * 
+ * Since: 3.0
+ */
+void
+gtk_radio_action_join_group (GtkRadioAction *action, 
+                            GtkRadioAction *group_source)
+{
+  g_return_if_fail (GTK_IS_RADIO_ACTION (action));
+  g_return_if_fail (group_source == NULL || GTK_IS_RADIO_ACTION (group_source));  
+
+  if (group_source)
+    {
+      GSList *group;
+      group = gtk_radio_action_get_group (group_source);
+      
+      if (!group)
+        {
+          /* if we are not already part of a group we need to set up a new one
+             and then get the newly created group */  
+          gtk_radio_action_set_group (group_source, NULL);
+          group = gtk_radio_action_get_group (group_source);
+        }
+
+      gtk_radio_action_set_group (action, group);
+    }
+  else
+    {
+      gtk_radio_action_set_group (action, NULL);
+    }
+}
+
 /**
  * gtk_radio_action_get_current_value:
  * @action: a #GtkRadioAction
  * 
- * Obtains the value property of the the currently active member of 
+ * Obtains the value property of the currently active member of 
  * the group to which @action belongs.
  * 
  * Return value: The value of the currently active group member
@@ -393,10 +548,50 @@ gtk_radio_action_get_current_value (GtkRadioAction *action)
        {
          GtkToggleAction *toggle_action = slist->data;
 
-         if (toggle_action->private_data->active)
+         if (gtk_toggle_action_get_active (toggle_action))
            return GTK_RADIO_ACTION (toggle_action)->private_data->value;
        }
     }
 
   return action->private_data->value;
 }
+
+/**
+ * gtk_radio_action_set_current_value:
+ * @action: a #GtkRadioAction
+ * @current_value: the new value
+ * 
+ * Sets the currently active group member to the member with value
+ * property @current_value.
+ *
+ * Since: 2.10
+ **/
+void
+gtk_radio_action_set_current_value (GtkRadioAction *action,
+                                    gint            current_value)
+{
+  GSList *slist;
+
+  g_return_if_fail (GTK_IS_RADIO_ACTION (action));
+
+  if (action->private_data->group)
+    {
+      for (slist = action->private_data->group; slist; slist = slist->next)
+       {
+         GtkRadioAction *radio_action = slist->data;
+
+         if (radio_action->private_data->value == current_value)
+            {
+              gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (radio_action),
+                                            TRUE);
+              return;
+            }
+       }
+    }
+
+  if (action->private_data->value == current_value)
+    gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
+  else
+    g_warning ("Radio group does not contain an action with value '%d'",
+              current_value);
+}