Commit f232b978 authored by Tristan Van Berkom's avatar Tristan Van Berkom
Browse files

* gladeui/glade-popup.c: Allow adding new actions to action groups from the...

	* gladeui/glade-popup.c: Allow adding new actions to action groups from the palette ("Add widget here").

	* plugins/gtk+/glade-accels.[ch]: Moved individual accelerator [de]serialization here, special integration
	  for action types, for actions only show one accelerator and dont load/save the "activate" signal name.

	* plugins/gtk+/glade-gtk.c, plugins/gtk+/gtk+.xml.in: Added support for GtkActionGroup <--> GtkAction
	  relationships and support for editing/loading/saving of accelerators which can be associated with
	  actions inside an action group.
parent 2cf0d26f
...@@ -25,7 +25,16 @@ ...@@ -25,7 +25,16 @@
* gladeui/glade-widget.c: GladeWidget takes a new "support-changed" to broadcast support changes * gladeui/glade-widget.c: GladeWidget takes a new "support-changed" to broadcast support changes
on the widget. on the widget.
* gladeui/glade-popup.c: Allow adding new actions to action groups from the palette ("Add widget here").
* plugins/gtk+/glade-accels.[ch]: Moved individual accelerator [de]serialization here, special integration
for action types, for actions only show one accelerator and dont load/save the "activate" signal name.
* plugins/gtk+/glade-gtk.c, plugins/gtk+/gtk+.xml.in: Added support for GtkActionGroup <--> GtkAction
relationships and support for editing/loading/saving of accelerators which can be associated with
actions inside an action group.
2010-03-28 Tristan Van Berkom <tvb@gnome.org> 2010-03-28 Tristan Van Berkom <tvb@gnome.org>
* gladeui/Makefile.am, gladeui/glade-cell-renderer-icon.[ch]: Added activatable pixbuf renderer * gladeui/Makefile.am, gladeui/glade-cell-renderer-icon.[ch]: Added activatable pixbuf renderer
......
...@@ -99,6 +99,20 @@ glade_popup_placeholder_add_cb (GtkMenuItem *item, GladePlaceholder *placeholder ...@@ -99,6 +99,20 @@ glade_popup_placeholder_add_cb (GtkMenuItem *item, GladePlaceholder *placeholder
} }
} }
static void
glade_popup_action_add_cb (GtkMenuItem *item, GladeWidget *group)
{
GladeWidgetAdaptor *adaptor;
adaptor = glade_palette_get_current_item (glade_app_get_palette ());
g_return_if_fail (adaptor != NULL);
glade_command_create (adaptor, group,
NULL, glade_widget_get_project (group));
glade_palette_deselect_current_item (glade_app_get_palette(), TRUE);
}
static void static void
glade_popup_root_add_cb (GtkMenuItem *item, gpointer *user_data) glade_popup_root_add_cb (GtkMenuItem *item, gpointer *user_data)
{ {
...@@ -423,6 +437,7 @@ glade_popup_create_menu (GladeWidget *widget, ...@@ -423,6 +437,7 @@ glade_popup_create_menu (GladeWidget *widget,
gboolean packing) gboolean packing)
{ {
GladeProjectFormat fmt; GladeProjectFormat fmt;
GladeWidgetAdaptor *current_item;
GladeProject *project; GladeProject *project;
GtkWidget *popup_menu; GtkWidget *popup_menu;
GtkWidget *separator; GtkWidget *separator;
...@@ -431,7 +446,7 @@ glade_popup_create_menu (GladeWidget *widget, ...@@ -431,7 +446,7 @@ glade_popup_create_menu (GladeWidget *widget,
GladePlaceholder *tmp_placeholder; GladePlaceholder *tmp_placeholder;
gchar *book; gchar *book;
sensitive = glade_palette_get_current_item (glade_app_get_palette ()) != NULL; sensitive = (current_item = glade_palette_get_current_item (glade_app_get_palette ())) != NULL;
/* Resolve project format first... */ /* Resolve project format first... */
project = widget ? glade_widget_get_project (widget) : project = widget ? glade_widget_get_project (widget) :
...@@ -441,13 +456,27 @@ glade_popup_create_menu (GladeWidget *widget, ...@@ -441,13 +456,27 @@ glade_popup_create_menu (GladeWidget *widget,
popup_menu = gtk_menu_new (); popup_menu = gtk_menu_new ();
if (sensitive) if (current_item)
{ {
tmp_placeholder = placeholder;
if (!tmp_placeholder && widget) /* Special case for GtkAction accelerators */
tmp_placeholder = find_placeholder (glade_widget_get_object (widget)); if (widget && GTK_IS_ACTION_GROUP (widget->object) &&
glade_popup_append_item (popup_menu, NULL, _("_Add widget here"), NULL, tmp_placeholder != NULL, (current_item->type == GTK_TYPE_ACTION ||
glade_popup_placeholder_add_cb, tmp_placeholder); g_type_is_a (current_item->type, GTK_TYPE_ACTION)))
{
glade_popup_append_item (popup_menu, NULL, _("_Add widget here"), NULL, TRUE,
glade_popup_action_add_cb, widget);
}
else
{
tmp_placeholder = placeholder;
if (!tmp_placeholder && widget)
tmp_placeholder = find_placeholder (glade_widget_get_object (widget));
glade_popup_append_item (popup_menu, NULL, _("_Add widget here"), NULL, tmp_placeholder != NULL,
glade_popup_placeholder_add_cb, tmp_placeholder);
}
glade_popup_append_item (popup_menu, NULL, _("Add widget as _toplevel"), NULL, glade_popup_append_item (popup_menu, NULL, _("Add widget as _toplevel"), NULL,
fmt != GLADE_PROJECT_FORMAT_LIBGLADE, fmt != GLADE_PROJECT_FORMAT_LIBGLADE,
glade_popup_root_add_cb, NULL); glade_popup_root_add_cb, NULL);
......
...@@ -218,8 +218,16 @@ glade_eprop_accel_populate_view (GladeEditorProperty *eprop, ...@@ -218,8 +218,16 @@ glade_eprop_accel_populate_view (GladeEditorProperty *eprop,
{ {
sclass = list->data; sclass = list->data;
/* Special case for GtkAction accelerators */
if (adaptor->type == GTK_TYPE_ACTION ||
g_type_is_a (adaptor->type, GTK_TYPE_ACTION))
{
if (g_strcmp0 (sclass->type, "GtkAction") != 0 ||
g_strcmp0 (sclass->name, "activate") != 0)
continue;
}
/* Only action signals have accelerators. */ /* Only action signals have accelerators. */
if ((sclass->query.signal_flags & G_SIGNAL_ACTION) == 0) else if ((sclass->query.signal_flags & G_SIGNAL_ACTION) == 0)
continue; continue;
if (g_list_find_custom (eprop_accel->parent_iters, if (g_list_find_custom (eprop_accel->parent_iters,
...@@ -249,8 +257,16 @@ glade_eprop_accel_populate_view (GladeEditorProperty *eprop, ...@@ -249,8 +257,16 @@ glade_eprop_accel_populate_view (GladeEditorProperty *eprop,
{ {
sclass = list->data; sclass = list->data;
/* Special case for GtkAction accelerators */
if (adaptor->type == GTK_TYPE_ACTION ||
g_type_is_a (adaptor->type, GTK_TYPE_ACTION))
{
if (g_strcmp0 (sclass->type, "GtkAction") != 0 ||
g_strcmp0 (sclass->name, "activate") != 0)
continue;
}
/* Only action signals have accelerators. */ /* Only action signals have accelerators. */
if ((sclass->query.signal_flags & G_SIGNAL_ACTION) == 0) else if ((sclass->query.signal_flags & G_SIGNAL_ACTION) == 0)
continue; continue;
if ((found = g_list_find_custom (eprop_accel->parent_iters, if ((found = g_list_find_custom (eprop_accel->parent_iters,
...@@ -289,6 +305,12 @@ glade_eprop_accel_populate_view (GladeEditorProperty *eprop, ...@@ -289,6 +305,12 @@ glade_eprop_accel_populate_view (GladeEditorProperty *eprop,
g_free (accel_text); g_free (accel_text);
} }
/* Special case for GtkAction accelerators */
if ((adaptor->type == GTK_TYPE_ACTION ||
g_type_is_a (adaptor->type, GTK_TYPE_ACTION)) &&
g_list_length (accelerators) > 0)
continue;
/* Append a new empty slot at the end */ /* Append a new empty slot at the end */
gtk_tree_store_append (model, &iter, parent_tab->iter); gtk_tree_store_append (model, &iter, parent_tab->iter);
gtk_tree_store_set gtk_tree_store_set
...@@ -321,11 +343,17 @@ accel_edited (GtkCellRendererAccel *accel, ...@@ -321,11 +343,17 @@ accel_edited (GtkCellRendererAccel *accel,
gboolean key_was_set; gboolean key_was_set;
GtkTreeIter iter, parent_iter, new_iter; GtkTreeIter iter, parent_iter, new_iter;
gchar *accel_text; gchar *accel_text;
GladeWidgetAdaptor *adaptor =
glade_widget_adaptor_from_pclass (GLADE_EDITOR_PROPERTY (eprop_accel)->klass);
gboolean is_action;
if (!gtk_tree_model_get_iter_from_string (eprop_accel->model, if (!gtk_tree_model_get_iter_from_string (eprop_accel->model,
&iter, path_string)) &iter, path_string))
return; return;
is_action = (adaptor->type == GTK_TYPE_ACTION ||
g_type_is_a (adaptor->type, GTK_TYPE_ACTION));
gtk_tree_model_get (eprop_accel->model, &iter, gtk_tree_model_get (eprop_accel->model, &iter,
ACCEL_COLUMN_KEY_ENTERED, &key_was_set, ACCEL_COLUMN_KEY_ENTERED, &key_was_set,
-1); -1);
...@@ -346,7 +374,7 @@ accel_edited (GtkCellRendererAccel *accel, ...@@ -346,7 +374,7 @@ accel_edited (GtkCellRendererAccel *accel,
/* Append a new one if needed /* Append a new one if needed
*/ */
if (key_was_set == FALSE && if (is_action == FALSE && key_was_set == FALSE &&
gtk_tree_model_iter_parent (eprop_accel->model, gtk_tree_model_iter_parent (eprop_accel->model,
&parent_iter, &iter)) &parent_iter, &iter))
{ {
...@@ -601,3 +629,223 @@ glade_eprop_accel_create_input (GladeEditorProperty *eprop) ...@@ -601,3 +629,223 @@ glade_eprop_accel_create_input (GladeEditorProperty *eprop)
return hbox; return hbox;
} }
static GdkModifierType
glade_gtk_parse_modifiers (const gchar *string)
{
const gchar *pos = string;
GdkModifierType modifiers = 0;
while (pos && pos[0])
{
if (!strncmp(pos, "GDK_", 4)) {
pos += 4;
if (!strncmp(pos, "SHIFT_MASK", 10)) {
modifiers |= GDK_SHIFT_MASK;
pos += 10;
} else if (!strncmp(pos, "LOCK_MASK", 9)) {
modifiers |= GDK_LOCK_MASK;
pos += 9;
} else if (!strncmp(pos, "CONTROL_MASK", 12)) {
modifiers |= GDK_CONTROL_MASK;
pos += 12;
} else if (!strncmp(pos, "MOD", 3) &&
!strncmp(pos+4, "_MASK", 5)) {
switch (pos[3]) {
case '1':
modifiers |= GDK_MOD1_MASK; break;
case '2':
modifiers |= GDK_MOD2_MASK; break;
case '3':
modifiers |= GDK_MOD3_MASK; break;
case '4':
modifiers |= GDK_MOD4_MASK; break;
case '5':
modifiers |= GDK_MOD5_MASK; break;
}
pos += 9;
} else if (!strncmp(pos, "BUTTON", 6) &&
!strncmp(pos+7, "_MASK", 5)) {
switch (pos[6]) {
case '1':
modifiers |= GDK_BUTTON1_MASK; break;
case '2':
modifiers |= GDK_BUTTON2_MASK; break;
case '3':
modifiers |= GDK_BUTTON3_MASK; break;
case '4':
modifiers |= GDK_BUTTON4_MASK; break;
case '5':
modifiers |= GDK_BUTTON5_MASK; break;
}
pos += 12;
} else if (!strncmp(pos, "RELEASE_MASK", 12)) {
modifiers |= GDK_RELEASE_MASK;
pos += 12;
} else
pos++;
} else
pos++;
}
return modifiers;
}
static gchar *
glade_gtk_modifier_string_from_bits (GdkModifierType modifiers)
{
GString *string = g_string_new ("");
if (modifiers & GDK_SHIFT_MASK) {
if (string->len > 0)
g_string_append (string, " | ");
g_string_append (string, "GDK_SHIFT_MASK");
}
if (modifiers & GDK_LOCK_MASK) {
if (string->len > 0)
g_string_append (string, " | ");
g_string_append (string, "GDK_LOCK_MASK");
}
if (modifiers & GDK_CONTROL_MASK) {
if (string->len > 0)
g_string_append (string, " | ");
g_string_append (string, "GDK_CONTROL_MASK");
}
if (modifiers & GDK_MOD1_MASK) {
if (string->len > 0)
g_string_append (string, " | ");
g_string_append (string, "GDK_MOD1_MASK");
}
if (modifiers & GDK_MOD2_MASK) {
if (string->len > 0)
g_string_append (string, " | ");
g_string_append (string, "GDK_MOD2_MASK");
}
if (modifiers & GDK_MOD3_MASK) {
if (string->len > 0)
g_string_append (string, " | ");
g_string_append (string, "GDK_MOD3_MASK");
}
if (modifiers & GDK_MOD4_MASK) {
if (string->len > 0)
g_string_append (string, " | ");
g_string_append (string, "GDK_MOD4_MASK");
}
if (modifiers & GDK_MOD5_MASK) {
if (string->len > 0)
g_string_append (string, " | ");
g_string_append (string, "GDK_MOD5_MASK");
}
if (modifiers & GDK_BUTTON1_MASK) {
if (string->len > 0)
g_string_append (string, " | ");
g_string_append (string, "GDK_BUTTON1_MASK");
}
if (modifiers & GDK_BUTTON2_MASK) {
if (string->len > 0)
g_string_append (string, " | ");
g_string_append (string, "GDK_BUTTON2_MASK");
}
if (modifiers & GDK_BUTTON3_MASK) {
if (string->len > 0)
g_string_append (string, " | ");
g_string_append (string, "GDK_BUTTON3_MASK");
}
if (modifiers & GDK_BUTTON4_MASK) {
if (string->len > 0)
g_string_append (string, " | ");
g_string_append (string, "GDK_BUTTON4_MASK");
}
if (modifiers & GDK_BUTTON5_MASK) {
if (string->len > 0)
g_string_append (string, " | ");
g_string_append (string, "GDK_BUTTON5_MASK");
}
if (modifiers & GDK_RELEASE_MASK) {
if (string->len > 0)
g_string_append (string, " | ");
g_string_append (string, "GDK_RELEASE_MASK");
}
if (string->len > 0)
return g_string_free (string, FALSE);
g_string_free (string, TRUE);
return NULL;
}
GladeAccelInfo *
glade_accel_read (GladeXmlNode *node,
gboolean require_signal)
{
GladeAccelInfo *ainfo;
gchar *key, *modifiers, *signal;
g_return_val_if_fail (node != NULL, NULL);
if (!glade_xml_node_verify (node, GLADE_TAG_ACCEL))
return NULL;
/* Get from xml... */
key = glade_xml_get_property_string_required
(node, GLADE_TAG_ACCEL_KEY, NULL);
if (require_signal)
signal = glade_xml_get_property_string_required (node, GLADE_TAG_ACCEL_SIGNAL, NULL);
else
signal = glade_xml_get_property_string (node, GLADE_TAG_ACCEL_SIGNAL);
modifiers = glade_xml_get_property_string (node, GLADE_TAG_ACCEL_MODIFIERS);
/* translate to GladeAccelInfo... */
ainfo = g_new0 (GladeAccelInfo, 1);
ainfo->key = gdk_keyval_from_name(key);
ainfo->signal = signal; /* take string ownership... */
ainfo->modifiers = glade_gtk_parse_modifiers (modifiers);
g_free (modifiers);
return ainfo;
}
GladeXmlNode *
glade_accel_write (GladeAccelInfo *accel,
GladeXmlContext *context,
gboolean write_signal)
{
GladeXmlNode *accel_node;
gchar *modifiers;
g_return_val_if_fail (accel != NULL, NULL);
g_return_val_if_fail (context != NULL, NULL);
accel_node = glade_xml_node_new (context, GLADE_TAG_ACCEL);
modifiers = glade_gtk_modifier_string_from_bits (accel->modifiers);
glade_xml_node_set_property_string (accel_node, GLADE_TAG_ACCEL_KEY,
gdk_keyval_name(accel->key));
if (write_signal)
glade_xml_node_set_property_string (accel_node, GLADE_TAG_ACCEL_SIGNAL,
accel->signal);
glade_xml_node_set_property_string (accel_node, GLADE_TAG_ACCEL_MODIFIERS,
modifiers);
g_free (modifiers);
return accel_node;
}
...@@ -11,6 +11,15 @@ G_BEGIN_DECLS ...@@ -11,6 +11,15 @@ G_BEGIN_DECLS
#define GLADE_TYPE_EPROP_ACCEL (glade_eprop_accel_get_type()) #define GLADE_TYPE_EPROP_ACCEL (glade_eprop_accel_get_type())
#define GLADE_TAG_ACCEL "accelerator"
#define GLADE_TAG_ACCEL_KEY "key"
#define GLADE_TAG_ACCEL_MODIFIERS "modifiers"
#define GLADE_TAG_ACCEL_SIGNAL "signal"
#define GLADE_TAG_ACCEL_GROUPS "accel-groups"
#define GLADE_TAG_ACCEL_GROUP "group"
typedef struct _GladeKey GladeKey; typedef struct _GladeKey GladeKey;
typedef struct _GladeAccelInfo GladeAccelInfo; typedef struct _GladeAccelInfo GladeAccelInfo;
...@@ -40,6 +49,12 @@ void glade_accel_list_free (GList *accels); ...@@ -40,6 +49,12 @@ void glade_accel_list_free (GList *accels);
gchar *glade_accels_make_string (GList *accels); gchar *glade_accels_make_string (GList *accels);
GladeAccelInfo *glade_accel_read (GladeXmlNode *node,
gboolean require_signal);
GladeXmlNode *glade_accel_write (GladeAccelInfo *accel_info,
GladeXmlContext *context,
gboolean write_signal);
G_END_DECLS G_END_DECLS
#endif /* __GLADE_ACCELS_H__ */ #endif /* __GLADE_ACCELS_H__ */
...@@ -235,17 +235,14 @@ glade_gtk_widget_depends (GladeWidgetAdaptor *adaptor, ...@@ -235,17 +235,14 @@ glade_gtk_widget_depends (GladeWidgetAdaptor *adaptor,
GladeWidget *widget, GladeWidget *widget,
GladeWidget *another) GladeWidget *another)
{ {
if (GTK_IS_ICON_FACTORY (another->object)) if (GTK_IS_ICON_FACTORY (another->object) ||
GTK_IS_ACTION (another->object) ||
GTK_IS_ACTION_GROUP (another->object))
return TRUE; return TRUE;
return GWA_GET_CLASS (G_TYPE_OBJECT)->depends (adaptor, widget, another); return GWA_GET_CLASS (G_TYPE_OBJECT)->depends (adaptor, widget, another);
} }
#define GLADE_TAG_ACCEL "accelerator"
#define GLADE_TAG_ACCEL_KEY "key"
#define GLADE_TAG_ACCEL_MODIFIERS "modifiers"
#define GLADE_TAG_ACCEL_SIGNAL "signal"
#define GLADE_TAG_A11Y_A11Y "accessibility" #define GLADE_TAG_A11Y_A11Y "accessibility"
#define GLADE_TAG_A11Y_ACTION_NAME "action_name" /* We should make -/_ synonymous */ #define GLADE_TAG_A11Y_ACTION_NAME "action_name" /* We should make -/_ synonymous */
#define GLADE_TAG_A11Y_DESC "description" #define GLADE_TAG_A11Y_DESC "description"
...@@ -296,69 +293,10 @@ static const gchar *atk_relations_list[] = { ...@@ -296,69 +293,10 @@ static const gchar *atk_relations_list[] = {
NULL NULL
}; };
static GdkModifierType
glade_gtk_parse_modifiers (const gchar *string)
{
const gchar *pos = string;
GdkModifierType modifiers = 0;
while (pos && pos[0])
{
if (!strncmp(pos, "GDK_", 4)) {
pos += 4;
if (!strncmp(pos, "SHIFT_MASK", 10)) {
modifiers |= GDK_SHIFT_MASK;
pos += 10;
} else if (!strncmp(pos, "LOCK_MASK", 9)) {
modifiers |= GDK_LOCK_MASK;
pos += 9;
} else if (!strncmp(pos, "CONTROL_MASK", 12)) {
modifiers |= GDK_CONTROL_MASK;
pos += 12;
} else if (!strncmp(pos, "MOD", 3) &&
!strncmp(pos+4, "_MASK", 5)) {
switch (pos[3]) {
case '1':
modifiers |= GDK_MOD1_MASK; break;
case '2':
modifiers |= GDK_MOD2_MASK; break;
case '3':
modifiers |= GDK_MOD3_MASK; break;
case '4':
modifiers |= GDK_MOD4_MASK; break;
case '5':
modifiers |= GDK_MOD5_MASK; break;
}
pos += 9;
} else if (!strncmp(pos, "BUTTON", 6) &&
!strncmp(pos+7, "_MASK", 5)) {
switch (pos[6]) {
case '1':
modifiers |= GDK_BUTTON1_MASK; break;
case '2':
modifiers |= GDK_BUTTON2_MASK; break;
case '3':
modifiers |= GDK_BUTTON3_MASK; break;
case '4':
modifiers |= GDK_BUTTON4_MASK; break;
case '5':
modifiers |= GDK_BUTTON5_MASK; break;
}
pos += 12;
} else if (!strncmp(pos, "RELEASE_MASK", 12)) {
modifiers |= GDK_RELEASE_MASK;
pos += 12;
} else
pos++;
} else
pos++;
}
return modifiers;
}
static void static void
glade_gtk_widget_read_accels (GladeWidget *widget, glade_gtk_read_accels (GladeWidget *widget,
GladeXmlNode *node) GladeXmlNode *node,
gboolean require_signal)
{ {
GladeProperty *property; GladeProperty *property;
GladeXmlNode *prop; GladeXmlNode *prop;
...@@ -369,27 +307,11 @@ glade_gtk_widget_read_accels (GladeWidget *widget, ...@@ -369,27 +307,11 @@ glade_gtk_widget_read_accels (GladeWidget *widget,
for (prop = glade_xml_node_get_children (node); for (prop = glade_xml_node_get_children (node);
prop; prop = glade_xml_node_next (prop)) prop; prop = glade_xml_node_next (prop))
{ {
gchar *key, *modifiers, *signal;
if (!glade_xml_node_verify_silent (prop, GLADE_TAG_ACCEL)) if (!glade_xml_node_verify_silent (prop, GLADE_TAG_ACCEL))
continue; continue;
/* Get from xml... */ if ((ainfo = glade_accel_read (prop, require_signal)) != NULL)
key = glade_xml_get_property_string_required accels = g_list_prepend (accels, ainfo);
(prop, GLADE_TAG_ACCEL_KEY, NULL);
signal = glade_xml_get_property_string_required
(prop, GLADE_TAG_ACCEL_SIGNAL, NULL);
modifiers = glade_xml_get_property_string (prop, GLADE_TAG_ACCEL_MODIFIERS);
/* translate to GladeAccelInfo... */
ainfo = g_new0 (GladeAccelInfo, 1);
ainfo->key = gdk_keyval_from_name(key);
ainfo->signal = signal; /* take string ownership... */
ainfo->modifiers = glade_gtk_parse_modifiers (modifiers);