Commit ac879843 authored by Matthias Clasen's avatar Matthias Clasen Committed by Matthias Clasen
Browse files

Support subclasses in RC files. (#142417, Todd Berman, patch based on a

2006-03-23  Matthias Clasen  <mclasen@redhat.com>

	Support subclasses in RC files.  (#142417, Todd Berman, patch
	based on a patch by Benjamin Berg)

	* gtk/gtkrc.h:
	* gtk/gtkrc.c: Support <classname> elements in widget_class paths
	in rc files which match any classes derived from named class.

	(_gtk_rc_init): Use the new syntax in the default rc string.

	* gtk/gtkbindings.c: Support the new syntax for bindings too.

	* tests/testrc.c: Tests for widget_class path matching
parent efbac090
2006-03-23 Matthias Clasen <mclasen@redhat.com>
Support subclasses in RC files. (#142417, Todd Berman, patch
based on a patch by Benjamin Berg)
* gtk/gtkrc.h:
* gtk/gtkrc.c: Support <classname> elements in widget_class paths
in rc files which match any classes derived from named class.
(_gtk_rc_init): Use the new syntax in the default rc string.
* gtk/gtkbindings.c: Support the new syntax for bindings too.
* tests/testrc.c: Tests for widget_class path matching
2006-03-23 Carlos Garnacho <carlosg@gnome.org> 2006-03-23 Carlos Garnacho <carlosg@gnome.org>
* gtk/gtkdnd.c (gtk_drag_dest_motion): make sure that gdk_drag_event() * gtk/gtkdnd.c (gtk_drag_dest_motion): make sure that gdk_drag_event()
......
2006-03-23 Matthias Clasen <mclasen@redhat.com>
Support subclasses in RC files. (#142417, Todd Berman, patch
based on a patch by Benjamin Berg)
* gtk/gtkrc.h:
* gtk/gtkrc.c: Support <classname> elements in widget_class paths
in rc files which match any classes derived from named class.
(_gtk_rc_init): Use the new syntax in the default rc string.
* gtk/gtkbindings.c: Support the new syntax for bindings too.
* tests/testrc.c: Tests for widget_class path matching
2006-03-23 Carlos Garnacho <carlosg@gnome.org> 2006-03-23 Carlos Garnacho <carlosg@gnome.org>
* gtk/gtkdnd.c (gtk_drag_dest_motion): make sure that gdk_drag_event() * gtk/gtkdnd.c (gtk_drag_dest_motion): make sure that gdk_drag_event()
......
...@@ -44,9 +44,11 @@ ...@@ -44,9 +44,11 @@
/* --- structures --- */ /* --- structures --- */
typedef struct { typedef struct {
GtkPathType type;
GPatternSpec *pspec; GPatternSpec *pspec;
gpointer user_data; GSList *path;
guint seq_id; gpointer user_data;
guint seq_id;
} PatternSpec; } PatternSpec;
...@@ -59,6 +61,15 @@ static GQuark key_id_class_binding_set = 0; ...@@ -59,6 +61,15 @@ static GQuark key_id_class_binding_set = 0;
/* --- functions --- */ /* --- functions --- */
static void
pattern_spec_free (PatternSpec *pspec)
{
_gtk_rc_free_widget_class_path (pspec->path);
if (pspec->pspec)
g_pattern_spec_free (pspec->pspec);
g_free (pspec);
}
static GtkBindingSignal* static GtkBindingSignal*
binding_signal_new (const gchar *signal_name, binding_signal_new (const gchar *signal_name,
guint n_args) guint n_args)
...@@ -869,7 +880,18 @@ gtk_binding_set_add_path (GtkBindingSet *binding_set, ...@@ -869,7 +880,18 @@ gtk_binding_set_add_path (GtkBindingSet *binding_set,
} }
pspec = g_new (PatternSpec, 1); pspec = g_new (PatternSpec, 1);
pspec->pspec = g_pattern_spec_new (path_pattern); pspec->type = path_type;
if (path_type == GTK_PATH_WIDGET_CLASS)
{
pspec->pspec = NULL;
pspec->path = _gtk_rc_parse_widget_class_path (path_pattern);
}
else
{
pspec->pspec = g_pattern_spec_new (path_pattern);
pspec->path = NULL;
}
pspec->seq_id = priority << 28; pspec->seq_id = priority << 28;
pspec->user_data = binding_set; pspec->user_data = binding_set;
...@@ -885,8 +907,7 @@ gtk_binding_set_add_path (GtkBindingSet *binding_set, ...@@ -885,8 +907,7 @@ gtk_binding_set_add_path (GtkBindingSet *binding_set,
{ {
GtkPathPriorityType lprio = tmp_pspec->seq_id >> 28; GtkPathPriorityType lprio = tmp_pspec->seq_id >> 28;
g_pattern_spec_free (pspec->pspec); pattern_spec_free (pspec);
g_free (pspec);
pspec = NULL; pspec = NULL;
if (lprio < priority) if (lprio < priority)
{ {
...@@ -907,25 +928,32 @@ static gboolean ...@@ -907,25 +928,32 @@ static gboolean
binding_match_activate (GSList *pspec_list, binding_match_activate (GSList *pspec_list,
GtkObject *object, GtkObject *object,
guint path_length, guint path_length,
const gchar *path, gchar *path,
const gchar *path_reversed) gchar *path_reversed)
{ {
GSList *slist; GSList *slist;
for (slist = pspec_list; slist; slist = slist->next) for (slist = pspec_list; slist; slist = slist->next)
{ {
PatternSpec *pspec; PatternSpec *pspec;
GtkBindingSet *binding_set;
binding_set = NULL;
pspec = slist->data; pspec = slist->data;
if (g_pattern_match (pspec->pspec, path_length, path, path_reversed))
{ if (pspec->type == GTK_PATH_WIDGET_CLASS)
GtkBindingSet *binding_set; {
if (_gtk_rc_match_widget_class (pspec->path, path_length, path, path_reversed))
binding_set = pspec->user_data; binding_set = pspec->user_data;
}
else
{
if (g_pattern_match (pspec->pspec, path_length, path, path_reversed))
binding_set = pspec->user_data;
}
if (gtk_binding_entry_activate (binding_set->current, object)) if (binding_set && gtk_binding_entry_activate (binding_set->current, object))
return TRUE; return TRUE;
}
} }
return FALSE; return FALSE;
...@@ -1052,14 +1080,15 @@ gtk_bindings_activate_list (GtkObject *object, ...@@ -1052,14 +1080,15 @@ gtk_bindings_activate_list (GtkObject *object,
while (class_type && !handled) while (class_type && !handled)
{ {
guint path_length; guint path_length;
const gchar *path; gchar *path;
gchar *path_reversed; gchar *path_reversed;
path = g_type_name (class_type); path = g_strdup (g_type_name (class_type));
path_reversed = g_strdup (path); path_reversed = g_strdup (path);
g_strreverse (path_reversed); g_strreverse (path_reversed);
path_length = strlen (path); path_length = strlen (path);
handled = binding_match_activate (patterns, object, path_length, path, path_reversed); handled = binding_match_activate (patterns, object, path_length, path, path_reversed);
g_free (path);
g_free (path_reversed); g_free (path_reversed);
class_type = g_type_parent (class_type); class_type = g_type_parent (class_type);
...@@ -1417,8 +1446,7 @@ free_pattern_specs (GSList *pattern_specs) ...@@ -1417,8 +1446,7 @@ free_pattern_specs (GSList *pattern_specs)
pspec = slist->data; pspec = slist->data;
g_pattern_spec_free (pspec->pspec); pattern_spec_free (pspec);
g_free (pspec);
} }
g_slist_free (pattern_specs); g_slist_free (pattern_specs);
......
...@@ -66,21 +66,43 @@ typedef struct _GtkRcSet GtkRcSet; ...@@ -66,21 +66,43 @@ typedef struct _GtkRcSet GtkRcSet;
typedef struct _GtkRcNode GtkRcNode; typedef struct _GtkRcNode GtkRcNode;
typedef struct _GtkRcFile GtkRcFile; typedef struct _GtkRcFile GtkRcFile;
enum
{
PATH_ELT_PSPEC,
PATH_ELT_UNRESOLVED,
PATH_ELT_TYPE
};
typedef struct
{
gint type;
union
{
GType class_type;
gchar *class_name;
GPatternSpec *pspec;
} elt;
} PathElt;
struct _GtkRcSet struct _GtkRcSet
{ {
GtkPathType type;
GPatternSpec *pspec; GPatternSpec *pspec;
GtkRcStyle *rc_style; GSList *path;
gint priority;
GtkRcStyle *rc_style;
gint priority;
}; };
struct _GtkRcFile struct _GtkRcFile
{ {
gboolean is_string; /* If TRUE, name is a string to parse with gtk_rc_parse_string() */
time_t mtime; time_t mtime;
gchar *name; gchar *name;
gchar *canonical_name; gchar *canonical_name;
gchar *directory; gchar *directory;
guint reload; guint reload : 1;
guint is_string : 1; /* If TRUE, name is a string to parse with gtk_rc_parse_string() */
}; };
#define GTK_RC_MAX_PIXMAP_PATHS 128 #define GTK_RC_MAX_PIXMAP_PATHS 128
...@@ -130,8 +152,8 @@ static GtkRcStyle* gtk_rc_style_find (GtkRcContext *context, ...@@ -130,8 +152,8 @@ static GtkRcStyle* gtk_rc_style_find (GtkRcContext *context,
static GSList * gtk_rc_styles_match (GSList *rc_styles, static GSList * gtk_rc_styles_match (GSList *rc_styles,
GSList *sets, GSList *sets,
guint path_length, guint path_length,
const gchar *path, gchar *path,
const gchar *path_reversed); gchar *path_reversed);
static GtkStyle * gtk_rc_style_to_style (GtkRcContext *context, static GtkStyle * gtk_rc_style_to_style (GtkRcContext *context,
GtkRcStyle *rc_style); GtkRcStyle *rc_style);
static GtkStyle* gtk_rc_init_style (GtkRcContext *context, static GtkStyle* gtk_rc_init_style (GtkRcContext *context,
...@@ -213,6 +235,7 @@ static GtkRcStyle* gtk_rc_style_real_create_rc_style (GtkRcStyle *rc_style) ...@@ -213,6 +235,7 @@ static GtkRcStyle* gtk_rc_style_real_create_rc_style (GtkRcStyle *rc_style)
static GtkStyle* gtk_rc_style_real_create_style (GtkRcStyle *rc_style); static GtkStyle* gtk_rc_style_real_create_style (GtkRcStyle *rc_style);
static gint gtk_rc_properties_cmp (gconstpointer bsearch_node1, static gint gtk_rc_properties_cmp (gconstpointer bsearch_node1,
gconstpointer bsearch_node2); gconstpointer bsearch_node2);
static void gtk_rc_set_free (GtkRcSet *rc_set);
static gpointer parent_class = NULL; static gpointer parent_class = NULL;
...@@ -737,19 +760,8 @@ _gtk_rc_init (void) ...@@ -737,19 +760,8 @@ _gtk_rc_init (void)
"\n" "\n"
"class \"GtkProgressBar\" style : gtk \"gtk-default-progress-bar-style\"\n" "class \"GtkProgressBar\" style : gtk \"gtk-default-progress-bar-style\"\n"
"widget \"gtk-tooltips*\" style : gtk \"gtk-default-tooltips-style\"\n" "widget \"gtk-tooltips*\" style : gtk \"gtk-default-tooltips-style\"\n"
"class \"GtkMenuItem\" style : gtk \"gtk-default-menu-item-style\"\n" "widget_class \"*<GtkMenuItem>*\" style : gtk \"gtk-default-menu-item-style\"\n"
"widget_class \"*.GtkMenuItem.*\" style : gtk \"gtk-default-menu-item-style\"\n" "widget_class \"*<GtkMenuBar>*<GtkMenuItem>\" style : gtk \"gtk-default-menu-bar-item-style\"\n"
"widget_class \"*.GtkAccelMenuItem.*\" style : gtk \"gtk-default-menu-item-style\"\n"
"widget_class \"*.GtkRadioMenuItem.*\" style : gtk \"gtk-default-menu-item-style\"\n"
"widget_class \"*.GtkCheckMenuItem.*\" style : gtk \"gtk-default-menu-item-style\"\n"
"widget_class \"*.GtkImageMenuItem.*\" style : gtk \"gtk-default-menu-item-style\"\n"
"widget_class \"*.GtkSeparatorMenuItem.*\" style : gtk \"gtk-default-menu-item-style\"\n"
"widget_class \"*.GtkCellViewMenuItem.*\" style : gtk \"gtk-default-menu-item-style\"\n"
"widget_class \"*GtkMenuBar*GtkMenuItem\" style : gtk \"gtk-default-menu-bar-item-style\"\n"
"widget_class \"*GtkMenuBar*GtkAccelMenuItem\" style : gtk \"gtk-default-menu-bar-item-style\"\n"
"widget_class \"*GtkMenuBar*GtkRadioMenuItem\" style : gtk \"gtk-default-menu-bar-item-style\"\n"
"widget_class \"*GtkMenuBar*GtkCheckMenuItem\" style : gtk \"gtk-default-menu-bar-item-style\"\n"
"widget_class \"*GtkMenuBar*GtkImageMenuItem\" style : gtk \"gtk-default-menu-bar-item-style\"\n"
); );
} }
...@@ -1329,8 +1341,7 @@ gtk_rc_free_rc_sets (GSList *slist) ...@@ -1329,8 +1341,7 @@ gtk_rc_free_rc_sets (GSList *slist)
GtkRcSet *rc_set; GtkRcSet *rc_set;
rc_set = slist->data; rc_set = slist->data;
g_pattern_spec_free (rc_set->pspec); gtk_rc_set_free (rc_set);
g_free (rc_set);
slist = slist->next; slist = slist->next;
} }
...@@ -1623,8 +1634,8 @@ static GSList * ...@@ -1623,8 +1634,8 @@ static GSList *
gtk_rc_styles_match (GSList *rc_styles, gtk_rc_styles_match (GSList *rc_styles,
GSList *sets, GSList *sets,
guint path_length, guint path_length,
const gchar *path, gchar *path,
const gchar *path_reversed) gchar *path_reversed)
{ {
GtkRcSet *rc_set; GtkRcSet *rc_set;
...@@ -1634,10 +1645,18 @@ gtk_rc_styles_match (GSList *rc_styles, ...@@ -1634,10 +1645,18 @@ gtk_rc_styles_match (GSList *rc_styles,
rc_set = sets->data; rc_set = sets->data;
sets = sets->next; sets = sets->next;
if (g_pattern_match (rc_set->pspec, path_length, path, path_reversed)) if (rc_set->type == GTK_PATH_WIDGET_CLASS)
rc_styles = g_slist_append (rc_styles, rc_set); {
if (_gtk_rc_match_widget_class (rc_set->path, path_length, path, path_reversed))
rc_styles = g_slist_append (rc_styles, rc_set);
}
else
{
if (g_pattern_match (rc_set->pspec, path_length, path, path_reversed))
rc_styles = g_slist_append (rc_styles, rc_set);
}
} }
return rc_styles; return rc_styles;
} }
...@@ -1746,16 +1765,17 @@ gtk_rc_get_style (GtkWidget *widget) ...@@ -1746,16 +1765,17 @@ gtk_rc_get_style (GtkWidget *widget)
type = G_TYPE_FROM_INSTANCE (widget); type = G_TYPE_FROM_INSTANCE (widget);
while (type) while (type)
{ {
const gchar *path; gchar *path;
gchar *path_reversed; gchar *path_reversed;
guint path_length; guint path_length;
path = g_type_name (type); path = g_strdup (g_type_name (type));
path_length = strlen (path); path_length = strlen (path);
path_reversed = g_strdup (path); path_reversed = g_strdup (path);
g_strreverse (path_reversed); g_strreverse (path_reversed);
rc_styles = gtk_rc_styles_match (rc_styles, context->rc_sets_class, path_length, path, path_reversed); rc_styles = gtk_rc_styles_match (rc_styles, context->rc_sets_class, path_length, path, path_reversed);
g_free (path);
g_free (path_reversed); g_free (path_reversed);
type = g_type_parent (type); type = g_type_parent (type);
...@@ -1832,27 +1852,33 @@ gtk_rc_get_style_by_paths (GtkSettings *settings, ...@@ -1832,27 +1852,33 @@ gtk_rc_get_style_by_paths (GtkSettings *settings,
if (widget_path && context->rc_sets_widget) if (widget_path && context->rc_sets_widget)
{ {
gchar *path;
gchar *path_reversed; gchar *path_reversed;
guint path_length; guint path_length;
path_length = strlen (widget_path); path_length = strlen (widget_path);
path = g_strdup (widget_path);
path_reversed = g_strdup (widget_path); path_reversed = g_strdup (widget_path);
g_strreverse (path_reversed); g_strreverse (path_reversed);
rc_styles = gtk_rc_styles_match (rc_styles, context->rc_sets_widget, path_length, widget_path, path_reversed); rc_styles = gtk_rc_styles_match (rc_styles, context->rc_sets_widget, path_length, path, path_reversed);
g_free (path);
g_free (path_reversed); g_free (path_reversed);
} }
if (class_path && context->rc_sets_widget_class) if (class_path && context->rc_sets_widget_class)
{ {
gchar *path;
gchar *path_reversed; gchar *path_reversed;
guint path_length; guint path_length;
path = g_strdup (class_path);
path_length = strlen (class_path); path_length = strlen (class_path);
path_reversed = g_strdup (class_path); path_reversed = g_strdup (class_path);
g_strreverse (path_reversed); g_strreverse (path_reversed);
rc_styles = gtk_rc_styles_match (rc_styles, context->rc_sets_widget_class, path_length, class_path, path_reversed); rc_styles = gtk_rc_styles_match (rc_styles, context->rc_sets_widget_class, path_length, path, path_reversed);
g_free (path);
g_free (path_reversed); g_free (path_reversed);
} }
...@@ -1860,16 +1886,17 @@ gtk_rc_get_style_by_paths (GtkSettings *settings, ...@@ -1860,16 +1886,17 @@ gtk_rc_get_style_by_paths (GtkSettings *settings,
{ {
while (type) while (type)
{ {
const gchar *path; gchar *path;
gchar *path_reversed; gchar *path_reversed;
guint path_length; guint path_length;
path = g_type_name (type); path = g_strdup (g_type_name (type));
path_length = strlen (path); path_length = strlen (path);
path_reversed = g_strdup (path); path_reversed = g_strdup (path);
g_strreverse (path_reversed); g_strreverse (path_reversed);
rc_styles = gtk_rc_styles_match (rc_styles, context->rc_sets_class, path_length, path, path_reversed); rc_styles = gtk_rc_styles_match (rc_styles, context->rc_sets_class, path_length, path, path_reversed);
g_free (path);
g_free (path_reversed); g_free (path_reversed);
type = g_type_parent (type); type = g_type_parent (type);
...@@ -1887,7 +1914,8 @@ gtk_rc_get_style_by_paths (GtkSettings *settings, ...@@ -1887,7 +1914,8 @@ gtk_rc_get_style_by_paths (GtkSettings *settings,
static GSList * static GSList *
gtk_rc_add_rc_sets (GSList *slist, gtk_rc_add_rc_sets (GSList *slist,
GtkRcStyle *rc_style, GtkRcStyle *rc_style,
const gchar *pattern) const gchar *pattern,
GtkPathType path_type)
{ {
GtkRcStyle *new_style; GtkRcStyle *new_style;
GtkRcSet *rc_set; GtkRcSet *rc_set;
...@@ -1903,7 +1931,19 @@ gtk_rc_add_rc_sets (GSList *slist, ...@@ -1903,7 +1931,19 @@ gtk_rc_add_rc_sets (GSList *slist,
new_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]); new_style->bg_pixmap_name[i] = g_strdup (rc_style->bg_pixmap_name[i]);
rc_set = g_new (GtkRcSet, 1); rc_set = g_new (GtkRcSet, 1);
rc_set->pspec = g_pattern_spec_new (pattern); rc_set->type = path_type;
if (path_type == GTK_PATH_WIDGET_CLASS)
{
rc_set->pspec = NULL;
rc_set->path = _gtk_rc_parse_widget_class_path (pattern);
}
else
{
rc_set->pspec = g_pattern_spec_new (pattern);
rc_set->path = NULL;
}
rc_set->rc_style = rc_style; rc_set->rc_style = rc_style;
return g_slist_prepend (slist, rc_set); return g_slist_prepend (slist, rc_set);
...@@ -1920,7 +1960,7 @@ gtk_rc_add_widget_name_style (GtkRcStyle *rc_style, ...@@ -1920,7 +1960,7 @@ gtk_rc_add_widget_name_style (GtkRcStyle *rc_style,
context = gtk_rc_context_get (gtk_settings_get_default ()); context = gtk_rc_context_get (gtk_settings_get_default ());
context->rc_sets_widget = gtk_rc_add_rc_sets (context->rc_sets_widget, rc_style, pattern); context->rc_sets_widget = gtk_rc_add_rc_sets (context->rc_sets_widget, rc_style, pattern, GTK_PATH_WIDGET);
} }
void void
...@@ -1934,7 +1974,7 @@ gtk_rc_add_widget_class_style (GtkRcStyle *rc_style, ...@@ -1934,7 +1974,7 @@ gtk_rc_add_widget_class_style (GtkRcStyle *rc_style,
context = gtk_rc_context_get (gtk_settings_get_default ()); context = gtk_rc_context_get (gtk_settings_get_default ());
context->rc_sets_widget_class = gtk_rc_add_rc_sets (context->rc_sets_widget_class, rc_style, pattern); context->rc_sets_widget_class = gtk_rc_add_rc_sets (context->rc_sets_widget_class, rc_style, pattern, GTK_PATH_WIDGET_CLASS);
} }
void void
...@@ -1948,7 +1988,7 @@ gtk_rc_add_class_style (GtkRcStyle *rc_style, ...@@ -1948,7 +1988,7 @@ gtk_rc_add_class_style (GtkRcStyle *rc_style,
context = gtk_rc_context_get (gtk_settings_get_default ()); context = gtk_rc_context_get (gtk_settings_get_default ());
context->rc_sets_class = gtk_rc_add_rc_sets (context->rc_sets_class, rc_style, pattern); context->rc_sets_class = gtk_rc_add_rc_sets (context->rc_sets_class, rc_style, pattern, GTK_PATH_CLASS);
} }
GScanner* GScanner*
...@@ -3870,7 +3910,19 @@ gtk_rc_parse_path_pattern (GtkRcContext *context, ...@@ -3870,7 +3910,19 @@ gtk_rc_parse_path_pattern (GtkRcContext *context,
} }
rc_set = g_new (GtkRcSet, 1); rc_set = g_new (GtkRcSet, 1);
rc_set->pspec = g_pattern_spec_new (pattern); rc_set->type = path_type;
if (path_type == GTK_PATH_WIDGET_CLASS)
{
rc_set->pspec = NULL;
rc_set->path = _gtk_rc_parse_widget_class_path (pattern);
}
else
{
rc_set->pspec = g_pattern_spec_new (pattern);
rc_set->path = NULL;
}
rc_set->rc_style = rc_style; rc_set->rc_style = rc_style;
rc_set->priority = priority; rc_set->priority = priority;
...@@ -4215,6 +4267,286 @@ gtk_rc_parse_logical_color (GScanner *scanner, ...@@ -4215,6 +4267,286 @@ gtk_rc_parse_logical_color (GScanner *scanner,
return G_TOKEN_NONE; return G_TOKEN_NONE;
} }
GSList *
_gtk_rc_parse_widget_class_path (const gchar *pattern)
{
GSList *result;
PathElt *path_elt;
const gchar *current;
const gchar *class_start;
const gchar *class_end;
const gchar *pattern_end;
const gchar *pattern_start;
gchar *sub_pattern;
result = NULL;
current = pattern;
while ((class_start = strchr (current, '<')) &&
(class_end = strchr (class_start, '>')))
{
/* Add patterns, but ignore single dots */
if (!(class_start == current ||
(class_start == current + 1 && current[0] == '.')))
{
pattern_end = class_start - 1;
pattern_start = current;