Gtk.StyleContext

GtkStyleContext is an object that stores styling information affecting a widget defined by GtkWidgetPath. In order to construct the final style information, GtkStyleContext queries information from all attached GtkStyleProviders. Style providers can be either attached explicitly to the context through gtk_style_context_add_provider(), or to the screen through gtk_style_context_add_provider_for_screen(). The resulting style is a combination of all providers' information in priority order. For GTK+ widgets, any GtkStyleContext returned by gtk_widget_get_style_context() will already have a GtkWidgetPath, a GdkScreen and RTL/LTR information set. The style context will be also updated automatically if any of these settings change on the widget. If you are using the theming layer standalone, you will need to set a widget path and a screen yourself to the created style context through gtk_style_context_set_path() and gtk_style_context_set_screen(), as well as updating the context yourself using gtk_style_context_invalidate() whenever any of the conditions change, such as a change in the GtkSettings:gtk-theme-name setting or a hierarchy change in the rendered widget. <refsect2 id="gtkstylecontext-animations"> <title>Transition animations</title> <para> GtkStyleContext has built-in support for state change transitions. Note that these animations respect the GtkSettings:gtk-enable-animations setting. </para> <para> For simple widgets where state changes affect the whole widget area, calling gtk_style_context_notify_state_change() with a %NULL region is sufficient to trigger the transition animation. And GTK+ already does that when gtk_widget_set_state() or gtk_widget_set_state_flags() are called. </para> <para> If a widget needs to declare several animatable regions (i.e. not affecting the whole widget area), its GtkWidget::draw signal handler needs to wrap the render operations for the different regions with calls to gtk_style_context_push_animatable_region() and gtk_style_context_pop_animatable_region(). These functions take an identifier for the region which must be unique within the style context. For simple widgets with a fixed set of animatable regions, using an enumeration works well: </para> <example> <title>Using an enumeration to identify animatable regions</title> <programlisting> enum { REGION_ENTRY, REGION_BUTTON_UP, REGION_BUTTON_DOWN }; ... gboolean spin_button_draw (GtkWidget *widget, cairo_t *cr) { GtkStyleContext *context; context = gtk_widget_get_style_context (widget); gtk_style_context_push_animatable_region (context, GUINT_TO_POINTER (REGION_ENTRY)); gtk_render_background (cr, 0, 0, 100, 30); gtk_render_frame (cr, 0, 0, 100, 30); gtk_style_context_pop_animatable_region (context); ... } </programlisting> </example> <para> For complex widgets with an arbitrary number of animatable regions, it is up to the implementation to come up with a way to uniquely identify each animatable region. Using pointers to internal structs is one way to achieve this: </para> <example> <title>Using struct pointers to identify animatable regions</title> <programlisting> void notebook_draw_tab (GtkWidget *widget, NotebookPage *page, cairo_t *cr) { gtk_style_context_push_animatable_region (context, page); gtk_render_extension (cr, page->x, page->y, page->width, page->height); gtk_style_context_pop_animatable_region (context); } </programlisting> </example> <para> The widget also needs to notify the style context about a state change for a given animatable region so the animation is triggered. </para> <example> <title>Triggering a state change animation on a region</title> <programlisting> gboolean notebook_motion_notify (GtkWidget *widget, GdkEventMotion *event) { GtkStyleContext *context; NotebookPage *page; context = gtk_widget_get_style_context (widget); page = find_page_under_pointer (widget, event); gtk_style_context_notify_state_change (context, gtk_widget_get_window (widget), page, GTK_STATE_PRELIGHT, TRUE); ... } </programlisting> </example> <para> gtk_style_context_notify_state_change() accepts %NULL region IDs as a special value, in this case, the whole widget area will be updated by the animation. </para> </refsect2> <refsect2 id="gtkstylecontext-classes"> <title>Style classes and regions</title> <para> Widgets can add style classes to their context, which can be used to associate different styles by class (see <xref linkend="gtkcssprovider-selectors"/>). Theme engines can also use style classes to vary their rendering. GTK+ has a number of predefined style classes: GTK_STYLE_CLASS_CELL, GTK_STYLE_CLASS_ENTRY, GTK_STYLE_CLASS_BUTTON, GTK_STYLE_CLASS_COMBOBOX_ENTRY, GTK_STYLE_CLASS_CALENDAR, GTK_STYLE_CLASS_SLIDER, GTK_STYLE_CLASS_BACKGROUND, GTK_STYLE_CLASS_RUBBERBAND, GTK_STYLE_CLASS_TOOLTIP, GTK_STYLE_CLASS_MENU, GTK_STYLE_CLASS_MENUBAR, GTK_STYLE_CLASS_MENUITEM, GTK_STYLE_CLASS_TOOLBAR, GTK_STYLE_CLASS_PRIMARY_TOOLBAR, GTK_STYLE_CLASS_INLINE_TOOLBAR, GTK_STYLE_CLASS_RADIO, GTK_STYLE_CLASS_CHECK, GTK_STYLE_CLASS_TROUGH, GTK_STYLE_CLASS_SCROLLBAR, GTK_STYLE_CLASS_SCALE, GTK_STYLE_CLASS_SCALE_HAS_MARKS_ABOVE, GTK_STYLE_CLASS_SCALE_HAS_MARKS_BELOW, GTK_STYLE_CLASS_HEADER, GTK_STYLE_CLASS_ACCELERATOR, GTK_STYLE_CLASS_GRIP, GTK_STYLE_CLASS_DOCK, GTK_STYLE_CLASS_PROGRESSBAR, GTK_STYLE_CLASS_SPINNER, GTK_STYLE_CLASS_EXPANDER, GTK_STYLE_CLASS_SPINBUTTON, GTK_STYLE_CLASS_NOTEBOOK, GTK_STYLE_CLASS_VIEW, GTK_STYLE_CLASS_SIDEBAR, GTK_STYLE_CLASS_IMAGE, GTK_STYLE_CLASS_HIGHLIGHT, GTK_STYLE_CLASS_FRAME, GTK_STYLE_CLASS_DND, GTK_STYLE_CLASS_PANE_SEPARATOR, GTK_STYLE_CLASS_SEPARATOR, GTK_STYLE_CLASS_INFO, GTK_STYLE_CLASS_WARNING, GTK_STYLE_CLASS_QUESTION, GTK_STYLE_CLASS_ERROR, GTK_STYLE_CLASS_HORIZONTAL, GTK_STYLE_CLASS_VERTICAL. </para> <para> Widgets can also add regions with flags to their context. The regions used by GTK+ widgets are: <informaltable> <tgroup cols="4"> <thead> <row> <entry>Region</entry> <entry>Flags</entry> <entry>Macro</entry> <entry>Used by</entry> </row> </thead> <tbody> <row> <entry>row</entry> <entry>even, odd</entry> <entry>GTK_STYLE_REGION_ROW</entry> <entry>GtkTreeView</entry> </row> <row> <entry>column</entry> <entry>first, last, sorted</entry> <entry>GTK_STYLE_REGION_COLUMN</entry> <entry>GtkTreeView</entry> </row> <row> <entry>column-header</entry> <entry></entry> <entry>GTK_STYLE_REGION_COLUMN_HEADER</entry> <entry></entry> </row> <row> <entry>tab</entry> <entry>even, odd, first, last</entry> <entry>GTK_STYLE_REGION_TAB</entry> <entry>GtkNotebook</entry> </row> </tbody> </tgroup> </informaltable> </para> </refsect2> <refsect2 id="gtkstylecontext-custom-styling"> <title>Custom styling in UI libraries and applications</title> <para> If you are developing a library with custom GtkWidget<!-- -->s that render differently than standard components, you may need to add a GtkStyleProvider yourself with the %GTK_STYLE_PROVIDER_PRIORITY_FALLBACK priority, either a GtkCssProvider or a custom object implementing the GtkStyleProvider interface. This way theming engines may still attempt to style your UI elements in a different way if needed so. </para> <para> If you are using custom styling on an applications, you probably want then to make your style information prevail to the theme's, so you must use a GtkStyleProvider with the %GTK_STYLE_PROVIDER_PRIORITY_APPLICATION priority, keep in mind that the user settings in <filename><replaceable>XDG_CONFIG_HOME</replaceable>/gtk-3.0/gtk.css</filename> will still take precedence over your changes, as it uses the %GTK_STYLE_PROVIDER_PRIORITY_USER priority. </para> <para> If a custom theming engine is needed, you probably want to implement a GtkStyleProvider yourself so it points to your GtkThemingEngine implementation, as GtkCssProvider uses gtk_theming_engine_load() which loads the theming engine module from the standard paths. </para> </refsect2>

Hierarchy

  • GObject.Object