Re: widget colors/fonts
- From: Owen Taylor <otaylor redhat com>
- To: gtk-devel-list gnome org
- Subject: Re: widget colors/fonts
- Date: 21 Aug 2000 23:04:32 -0400
Havoc Pennington <hp@redhat.com> writes:
> Hi,
>
> I think we have discussed convenience routines for modifying widget
> styles, but never proposed an API. So here is a proposal:
>
> void gtk_widget_set_color (GtkWidget *widget,
> GtkRcFlags component,
> GtkStateType state,
> GdkColor *color);
>
> void gtk_widget_set_font (GtkWidget *widget,
> PangoFontDescription *desc);
>
> These both modify a GtkRcStyle which is stored on the widget as object
> data. If it's the same GtkRcStyle stored by gtk_widget_modify_style()
> then the fact that that GtkRcStyle gets modified is slightly
> surprising; on the other hand, if it isn't the same GtkRcStyle then
> combining the above calls with modify_style could result in surprising
> behavior as well. To me it seems cleanest to modify the "gtk-rc-style"
> style, or maybe have gtk_widget_modify_style() copy the passed-in
> style instead of just ref'ing it.
>
> I am not a huge fan of using GtkRcFlags here, mostly because
> GtkRcFlags isn't a good name for the enum in this context.
> If I could think of a good name in this context I'd advocate creating
> another enum for this purpose.
>
> The color arg is of course an unallocated color.
>
> Sample usage:
>
> gtk_widget_set_color (label, GTK_RC_FG, GTK_STATE_NORMAL, color);
> gtk_widget_set_font (label, &desc);
>
> So, suggestions on enhancing the API welcome.
I've gone ahead and implemented functions like this:
- I've called the functions gtk_widget_modify_fg, gtk_widet_modify_font,
etc, to indicate their close connection to gtk_widget_modify_style().
(I haven't added modify_bg_pixmap() or modify_[xy]_thickness,
so modify_style() is still needed in a few less common cases.)
- I think using a flags type for an enum value is a poor idea -
for one thing, it will end up mapped wrong by language bindings.
And I think having flags fields and enum values is inviting
disaster (GTK_WIDGET_TOPLEVEL vs. GTK_TOPLEVEL), so I've
added separate gtk_widget_modify_{fg,bg,text,base}.
- As Havoc suggested, I've made modify_style() copy, not ref
the style, since it doesn't make sense to ref a passed in value,
then change it later. (The one exception is that if you retrieve
the style, then call modify_style() with that result, it won't
make a fresh copy - it simply causes the displayed style to
be recomputed. I think this is convenient and not confusing.)
The interesting part of patch follows. (I.e., not including the
ugliness demonstration for testgtk.)
Regards,
Owen
Index: gtk/gtkrc.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkrc.c,v
retrieving revision 1.62
diff -u -r1.62 gtkrc.c
--- gtk/gtkrc.c 2000/07/26 11:32:45 1.62
+++ gtk/gtkrc.c 2000/08/22 03:01:17
@@ -871,6 +871,29 @@
return style;
}
+/**
+ * gtk_rc_style_copy:
+ * @orig: the style to copy
+ *
+ * Make a copy of the specified #GtkRcStyle. This function
+ * will correctly copy an rc style that is a member of a class
+ * derived from #GtkRcStyle.
+ *
+ * Return value: the resulting #GtkRcStyle
+ **/
+GtkRcStyle *
+gtk_rc_style_copy (GtkRcStyle *orig)
+{
+ GtkRcStyle *style;
+
+ g_return_if_fail (GTK_IS_RC_STYLE (orig));
+
+ style = GTK_RC_STYLE_GET_CLASS (orig)->clone (orig);
+ GTK_RC_STYLE_GET_CLASS (style)->merge (style, orig);
+
+ return style;
+}
+
void
gtk_rc_style_ref (GtkRcStyle *rc_style)
{
Index: gtk/gtkwidget.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwidget.c,v
retrieving revision 1.172
diff -u -r1.172 gtkwidget.c
--- gtk/gtkwidget.c 2000/07/26 11:32:59 1.172
+++ gtk/gtkwidget.c 2000/08/22 03:01:17
@@ -3035,27 +3035,239 @@
return widget->style;
}
+/**
+ * gtk_widget_modify_style:
+ * @widget: a #GtkWidget
+ * @style: the #GtkRcStyle holding the style modifications
+ *
+ * Modify style values on the widget. Modifications made using this
+ * technique take precendence over style values set via an RC file,
+ * however, they will be overriden if a style is explicitely set on
+ * the widget using gtk_widget_set_style(). The #GtkRcStyle structure
+ * is designed so each field can either be set or unset, so it is
+ * possible, using this function, to modify some style values and
+ * leave the others unchanged.
+ *
+ * Note that modifications made with this function are not cumulative
+ * with previous calls to gtk_widget_modify_style() or with such
+ * functions as gtk_widget_modify_fg(). If you wish to retain
+ * previous values, you must first call gtk_widget_get_modifier_style(),
+ * make your modifications to the returned style, then call
+ * gtk_widget_modify_style() with that style. On the other hand,
+ * if you first call gtk_widget_modify_style(), subsequent calls
+ * to such functions gtk_widget_modify_fg() will be have a cumulative
+ * effect with the inital modifications.
+ **/
void
gtk_widget_modify_style (GtkWidget *widget,
GtkRcStyle *style)
{
GtkRcStyle *old_style;
+
+ g_return_if_fail (GTK_IS_RC_STYLE (style));
if (!rc_style_key_id)
rc_style_key_id = g_quark_from_static_string (rc_style_key);
- old_style = gtk_object_get_data_by_id (GTK_OBJECT (widget), rc_style_key_id);
+ old_style = gtk_object_get_data_by_id (GTK_OBJECT (widget),
+ rc_style_key_id);
if (style != old_style)
+ gtk_object_set_data_by_id_full (GTK_OBJECT (widget),
+ rc_style_key_id,
+ gtk_rc_style_copy (style),
+ (GtkDestroyNotify)gtk_rc_style_unref);
+
+ if (GTK_WIDGET_RC_STYLE (widget))
+ gtk_widget_set_rc_style (widget);
+}
+
+/**
+ * gtk_widget_get_modifier_style:
+ * @widget: a #GtkWidget
+ *
+ * Return the current modifier style for the widget. (As set by
+ * gtk_widget_modify_style().) If no style has previously set, a new
+ * #GtkRcStyle will be created with all values unset, and set as the
+ * modifier style for the widget. If you make changes to this rc
+ * style, you must call gtk_widget_modify_style(), passing in the
+ * returned rc style, to make sure that your changes take effect.
+ *
+ * Return value: the modifier style for the widget. This rc style is
+ * owned by the widget. If you want to keep a pointer to value this
+ * around, you must add a refcount using gtk_rc_style_ref().
+ **/
+GtkRcStyle *
+gtk_widget_get_modifier_style (GtkWidget *widget)
+{
+ GtkRcStyle *rc_style;
+
+ if (!rc_style_key_id)
+ rc_style_key_id = g_quark_from_static_string (rc_style_key);
+
+ rc_style = gtk_object_get_data_by_id (GTK_OBJECT (widget),
+ rc_style_key_id);
+
+ if (!rc_style)
{
- gtk_rc_style_ref (style);
-
+ rc_style = gtk_rc_style_new();
gtk_object_set_data_by_id_full (GTK_OBJECT (widget),
rc_style_key_id,
- style,
+ rc_style,
(GtkDestroyNotify)gtk_rc_style_unref);
}
+ return rc_style;
+}
+
+static void
+gtk_widget_modify_color_component (GtkWidget *widget,
+ GtkRcFlags component,
+ GtkStateType state,
+ GdkColor *color)
+{
+ GtkRcStyle *rc_style = gtk_widget_get_modifier_style (widget);
+
+ switch (component)
+ {
+ case GTK_RC_FG:
+ rc_style->fg[state] = *color;
+ break;
+ case GTK_RC_BG:
+ rc_style->bg[state] = *color;
+ break;
+ case GTK_RC_TEXT:
+ rc_style->text[state] = *color;
+ break;
+ case GTK_RC_BASE:
+ rc_style->base[state] = *color;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ rc_style->color_flags[state] |= component;
+
+ if (GTK_WIDGET_RC_STYLE (widget))
+ gtk_widget_set_rc_style (widget);
+}
+
+/**
+ * gtk_widget_modify_fg:
+ * @widget: a #GtkWidget
+ * @state: the state for which to set the foreground color.
+ * @color: the color to assign (does not need to be allocated)
+ *
+ * Set the foreground color for a widget in a particular state. All
+ * other style values are left untouched. See also
+ * gtk_widget_modify_style().
+ **/
+void
+gtk_widget_modify_fg (GtkWidget *widget,
+ GtkStateType state,
+ GdkColor *color)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+ g_return_if_fail (state >= GTK_STATE_NORMAL && state <= GTK_STATE_INSENSITIVE);
+ g_return_if_fail (color != NULL);
+
+ gtk_widget_modify_color_component (widget, GTK_RC_FG, state, color);
+}
+
+/**
+ * gtk_widget_modify_bg:
+ * @widget: a #GtkWidget
+ * @state: the state for which to set the foreground color.
+ * @color: the color to assign (does not need to be allocated)
+ *
+ * Set the background color for a widget in a particular state. All
+ * other style values are left untouched. See also
+ * gtk_widget_modify_style().
+ **/
+void
+gtk_widget_modify_bg (GtkWidget *widget,
+ GtkStateType state,
+ GdkColor *color)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+ g_return_if_fail (state >= GTK_STATE_NORMAL && state <= GTK_STATE_INSENSITIVE);
+ g_return_if_fail (color != NULL);
+
+ gtk_widget_modify_color_component (widget, GTK_RC_BG, state, color);
+}
+
+/**
+ * gtk_widget_modify_base:
+ * @widget: a #GtkWidget
+ * @state: the state for which to set the foreground color.
+ * @color: the color to assign (does not need to be allocated)
+ *
+ * Set the text color for a widget in a particular state. All other
+ * style values are left untouched. The text color is the foreground
+ * color used along with the base color (see gtk_widget_modify_base)
+ * for widgets such as #GtkEntry and #GtkTextView. See also
+ * gtk_widget_modify_style().
+ **/
+void
+gtk_widget_modify_text (GtkWidget *widget,
+ GtkStateType state,
+ GdkColor *color)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+ g_return_if_fail (state >= GTK_STATE_NORMAL && state <= GTK_STATE_INSENSITIVE);
+ g_return_if_fail (color != NULL);
+
+ gtk_widget_modify_color_component (widget, GTK_RC_TEXT, state, color);
+}
+
+/**
+ * gtk_widget_modify_base:
+ * @widget: a #GtkWidget
+ * @state: the state for which to set the foreground color.
+ * @color: the color to assign (does not need to be allocated)
+ *
+ * Set the text color for a widget in a particular state.
+ * All other style values are left untouched. The base color
+ * is the background color used along with the text color
+ * (see gtk_widget_modify_text) for widgets such as #GtkEntry
+ * and #GtkTextView. See also gtk_widget_modify_style().
+ **/
+void
+gtk_widget_modify_base (GtkWidget *widget,
+ GtkStateType state,
+ GdkColor *color)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+ g_return_if_fail (state >= GTK_STATE_NORMAL && state <= GTK_STATE_INSENSITIVE);
+ g_return_if_fail (color != NULL);
+
+ gtk_widget_modify_color_component (widget, GTK_RC_BASE, state, color);
+}
+
+/**
+ * gtk_widget_modify_font:
+ * @widget: a #GtkWidget
+ * @font: the font description to use
+ *
+ * Set the font to use for a widget. All other style values are left
+ * untouched. See also gtk_widget_modify_style().
+ **/
+void
+gtk_widget_modify_font (GtkWidget *widget,
+ PangoFontDescription *font_desc)
+{
+ GtkRcStyle *rc_style;
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+ g_return_if_fail (font_desc != NULL);
+
+ rc_style = gtk_widget_get_modifier_style (widget);
+
+ if (rc_style->font_desc)
+ pango_font_description_free (rc_style->font_desc);
+
+ rc_style->font_desc = pango_font_description_copy (font_desc);
+
if (GTK_WIDGET_RC_STYLE (widget))
gtk_widget_set_rc_style (widget);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]