Compare commits

...

24 Commits

Author SHA1 Message Date
Benjamin Otte
77a059162b xxx: progressbar 2013-01-05 20:19:10 +01:00
Benjamin Otte
3bbe53689a widget: Marshal size allocation to actor 2013-01-05 20:19:09 +01:00
Benjamin Otte
0d60250917 widget: Make size-request vfuncs call into actor code 2013-01-05 20:19:09 +01:00
Benjamin Otte
cb31648aa3 cssmatcher: Redo the fallback detection
We need to do the fallback detection when we initialize the matcher, not
when we first decide what matcher to create. This is necessary to be
able to switch from actor matching to widget path matching for
submatchers.
2013-01-05 20:19:09 +01:00
Benjamin Otte
2081d36e88 widget: Use the actor's style context. 2013-01-05 20:19:09 +01:00
Benjamin Otte
37fa22c608 widget: Add a private accessor for the widget's actor
This is necessary to port widgets to actors.
2013-01-05 20:15:17 +01:00
Benjamin Otte
a137e66648 actor: Add a screen_changed vfunc
... and call it from GtkWidgetActor, when the screen changes.
2013-01-05 20:15:17 +01:00
Benjamin Otte
8c8a0e1bd6 widget: Put the widget's name into the actor
Use GtkCssBox::id instead of keeping a copy in the GtkWidgetPrivate.
2013-01-05 20:15:17 +01:00
Benjamin Otte
fe956e983c widget: Add a base actor
Use that actor for tracking the realized, visible and mapped states.
2013-01-05 20:15:17 +01:00
Benjamin Otte
17cb423a71 actors: Add a custom subclass for the base widget actor
This custom class needs to do all the hacks that are necessary because
of the interaction with GtkWidget. The class should be removed with GTK
4.
2013-01-05 20:15:16 +01:00
Benjamin Otte
49a6d85310 binlayout: Add API needed for progressbars
We need the ability to set size and position with more granularity than
align and expand flags give us for things like:
(1) sliders
(2) progress indicators
(3) panes
(4) dragged actors (like the switch slider)

... and until we have a good way to do that, this should suffice.
2013-01-05 20:15:16 +01:00
Benjamin Otte
2f691d4097 widget: Get rid of direct struct access
... to visible, realized and mapped members and replace it with the
function calls doing the same thing.
2013-01-05 20:15:16 +01:00
Benjamin Otte
46570d6a76 actors: Make GtkCssActor a style context source
... and add a style_updated signal.
2013-01-05 20:15:16 +01:00
Benjamin Otte
f7ef7c11d3 css: Add a matcher for actors. 2013-01-05 20:15:16 +01:00
Benjamin Otte
e84af768f9 stylecontext: Change css matcher initialization
2 changes:
(1) Add an optional css_matcher_init vfunc
(2) Allow create_query_path vfunc to fail

Both of these are required for the actors work.
2013-01-05 20:15:16 +01:00
Benjamin Otte
e6f5e4e448 actors: Add GtkCssText
An actor for displaying text. Essentiall it's a PangoLayout moving
around on screen.
2013-01-05 20:15:16 +01:00
Benjamin Otte
bbe48d8144 actors: Add GtkCssBox
GtkCssBox is an actor that does 2 things:
(1) It manages the styles
(2) It implements the CSS box model and provides for margin, padding and
    border

And with this, GtkCssBox will be pretty much the most important layout
element when creating widgets.
2013-01-05 20:15:15 +01:00
Benjamin Otte
ce2c4b2de0 actors: Add GtkCssActor
GtkCssActor is an actor maintaining a reference to a style context. It
is not owning the style context though.

The actor owning a style context is GtkCssBox, which is now a subclass
of GtkCssActor.
2013-01-05 20:15:15 +01:00
Benjamin Otte
cc86c700eb actors: Add GtkBinLayout
Also mostly copied from Clutter - at least in name and function.
2013-01-05 20:15:15 +01:00
Benjamin Otte
ec4516264b actors: First batch of ClutterActor copy/paste
This is the first set of stuff needed for an actor implementation. It
implements size request and allocate, positioning, drawing, the usual
show/realize/map cycle and layout managers
2013-01-05 20:15:15 +01:00
Benjamin Otte
d85dacd40c actors: Add skeleton build logic for actors directory
Copyright is added from ClutterActor, as that's where I intend to grab a
bunch of code from.
2013-01-04 13:09:48 +01:00
Benjamin Otte
99e9dc83fa css: Add min/max-width/height CSS properties
Nothing is using them yet.
2013-01-04 13:09:47 +01:00
Benjamin Otte
55f3ad0bf3 sizerequestcache: Store floats instead of ints
This is in preparation for the GtkActor work.
2013-01-04 13:09:47 +01:00
Benjamin Otte
38df4155b7 stylecontext: Make the source provide a vtable
This way, the code looks a bit cleaner (and way more like C++, ahem).
But most of all, this prepares for GtkActor, which will be yet another
source.
2013-01-04 13:09:47 +01:00
29 changed files with 6605 additions and 825 deletions

View File

@@ -1787,6 +1787,7 @@ gtk/makefile.msc
gtk/gtkversion.h
gtk/gtk-win32.rc
gtk/a11y/Makefile
gtk/actors/Makefile
gtk/tests/Makefile
libgail-util/Makefile
modules/Makefile

View File

@@ -16,7 +16,7 @@ else
GTK_PRINT_PREVIEW_COMMAND="evince --unlink-tempfile --preview --print-settings %s %f"
endif
SUBDIRS = a11y . tests
SUBDIRS = a11y actors . tests
if HAVE_PAPI_CUPS
GTK_PRINT_BACKENDS=file,papi,cups
@@ -108,11 +108,13 @@ libgtkincludedir = $(includedir)/gtk-3.0/gtk
libadd = \
$(top_builddir)/gdk/libgdk-3.la \
$(top_builddir)/gtk/a11y/libgtka11y.la \
$(top_builddir)/gtk/actors/libgtkactors.la \
$(GMODULE_LIBS) \
$(GTK_DEP_LIBS)
deps = \
$(top_builddir)/gdk/libgdk-3.la \
$(top_builddir)/gtk/a11y/libgtka11y.la
$(top_builddir)/gtk/a11y/libgtka11y.la \
$(top_builddir)/gtk/actors/libgtkactors.la
# libtool stuff: set version and export symbols for resolving
# since automake doesn't support conditionalized libsomething_la_LDFLAGS

82
gtk/actors/Makefile.am Normal file
View File

@@ -0,0 +1,82 @@
include $(top_srcdir)/Makefile.decl
noinst_LTLIBRARIES = libgtkactors.la
gtkactors_c_sources = \
gtkactor.c \
gtkbinlayout.c \
gtkcssactor.c \
gtkcssbox.c \
gtkcsstext.c \
gtklayoutmanager.c \
gtkwidgetactor.c
gtkactors_private_h_sources = \
gtkactorprivate.h \
gtkbinlayoutprivate.h \
gtkcssactorprivate.h \
gtkcssboxprivate.h \
gtkcsstextprivate.h \
gtklayoutmanagerprivate.h \
gtkwidgetactorprivate.h
libgtkactors_la_SOURCES = \
$(gtkactors_c_sources) \
$(gtkactors_private_h_sources)
libgtkactors_la_CPPFLAGS = \
-I$(top_srcdir) \
-I$(top_srcdir)/gdk \
-I$(top_builddir)/gdk \
-I$(top_srcdir)/gtk \
-I$(top_builddir)/gtk \
-DGTK_VERSION=\"$(GTK_VERSION)\"\
-DGTK_COMPILATION \
$(AM_CPPFLAGS)
libgtkactors_la_CFLAGS = \
$(GTK_DEP_CFLAGS) \
$(GTK_DEBUG_FLAGS) \
$(AM_CFLAGS)
libgtkactors_la_LIBADD = \
$(GTK_DEP_LIBS) \
$(INTLLIBS)
libgtkactors_la_LDFLAGS = \
$(LDFLAGS)
dist-hook: ../../build/win32/vs9/libgtkactors.vcproj ../../build/win32/vs10/libgtkactors.vcxproj ../../build/win32/vs10/libgtkactors.vcxproj.filters
../../build/win32/vs9/libgtkactors.vcproj: ../../build/win32/vs9/libgtkactors.vcprojin
for F in $(libgtkactors_la_SOURCES); do \
case $$F in \
*.c) echo ' <File RelativePath="..\..\..\gtk\a11y\'$$F'" />' \
;; \
esac; \
done >libgtkactors.sourcefiles
$(CPP) -P - <$(top_srcdir)/build/win32/vs9/libgtkactors.vcprojin >$@
rm libgtkactors.sourcefiles
../../build/win32/vs10/libgtkactors.vcxproj: ../../build/win32/vs10/libgtkactors.vcxprojin
for F in $(libgtkactors_la_SOURCES); do \
case $$F in \
*.c) echo ' <ClCompile Include="..\..\..\gtk\a11y\'$$F'" />' \
;; \
esac; \
done >libgtkactors.vs10.sourcefiles
$(CPP) -P - <$(top_srcdir)/build/win32/vs10/libgtkactors.vcxprojin >$@
rm libgtkactors.vs10.sourcefiles
../../build/win32/vs10/libgtkactors.vcxproj.filters: ../../build/win32/vs10/libgtkactors.vcxproj.filtersin
for F in $(libgtkactors_la_SOURCES); do \
case $$F in \
*.c) echo ' <ClCompile Include="..\..\..\gtk\a11y\'$$F'"><Filter>Source Files</Filter></ClCompile>' \
;; \
esac; \
done >libgtkactors.vs10.sourcefiles.filters
$(CPP) -P - <$(top_srcdir)/build/win32/vs10/libgtkactors.vcxproj.filtersin >$@
rm libgtkactors.vs10.sourcefiles.filters
-include $(top_srcdir)/git.mk

2521
gtk/actors/gtkactor.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,176 @@
/*
* Copyright © 2006, 2007, 2008 OpenedHand Ltd
* Copyright © 2009, 2010 Intel Corp
* Copyright © 2012 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#ifndef __GTK_ACTOR_PRIVATE_H__
#define __GTK_ACTOR_PRIVATE_H__
#include <cairo.h>
#include <gdk/gdk.h>
#include <gtk/gtkenums.h>
#include <gtk/gtktypes.h>
G_BEGIN_DECLS
#define GTK_TYPE_ACTOR (_gtk_actor_get_type ())
#define GTK_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_ACTOR, GtkActor))
#define GTK_ACTOR_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_ACTOR, GtkActorClass))
#define GTK_IS_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_ACTOR))
#define GTK_IS_ACTOR_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_ACTOR))
#define GTK_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_ACTOR, GtkActorClass))
/* forward declarations go here */
typedef struct _GtkLayoutManager GtkLayoutManager;
typedef struct _GtkActor GtkActor;
typedef struct _GtkActorPrivate GtkActorPrivate;
typedef struct _GtkActorClass GtkActorClass;
struct _GtkActor
{
GInitiallyUnowned parent;
GtkActorPrivate *priv;
};
struct _GtkActorClass
{
GInitiallyUnownedClass parent_class;
void (* show) (GtkActor *self);
void (* hide) (GtkActor *self);
void (* realize) (GtkActor *self);
void (* unrealize) (GtkActor *self);
void (* map) (GtkActor *self);
void (* unmap) (GtkActor *self);
void (* draw) (GtkActor *self,
cairo_t *cr);
void (* parent_set) (GtkActor *self,
GtkActor *old_parent);
void (* queue_relayout) (GtkActor *self);
void (* queue_redraw) (GtkActor *self,
const cairo_rectangle_t *box);
/* size negotiation */
GtkSizeRequestMode (* get_request_mode) (GtkActor *self);
void (* get_preferred_size) (GtkActor *self,
GtkOrientation orientation,
gfloat for_size,
gfloat *min_size_p,
gfloat *natural_size_p);
void (* position) (GtkActor *self,
const cairo_matrix_t *transform);
void (* allocate) (GtkActor *self,
const cairo_matrix_t *position,
gfloat width,
gfloat height);
void (* screen_changed) (GtkActor *self,
GdkScreen *new_screen,
GdkScreen *old_screen);
/* signals */
void (* actor_added) (GtkActor *self,
GtkActor *child);
void (* actor_removed) (GtkActor *self,
GtkActor *child);
};
GType _gtk_actor_get_type (void) G_GNUC_CONST;
void _gtk_actor_show (GtkActor *self);
void _gtk_actor_hide (GtkActor *self);
void _gtk_actor_realize (GtkActor *self);
void _gtk_actor_unrealize (GtkActor *self);
void _gtk_actor_map (GtkActor *self);
void _gtk_actor_unmap (GtkActor *self);
void _gtk_actor_draw (GtkActor *self,
cairo_t *cr);
void _gtk_actor_queue_redraw (GtkActor *self);
void _gtk_actor_queue_redraw_area (GtkActor *self,
const cairo_rectangle_t *box);
void _gtk_actor_queue_relayout (GtkActor *self);
void _gtk_actor_set_visible (GtkActor *self,
gboolean visible);
gboolean _gtk_actor_get_visible (GtkActor *self);
gboolean _gtk_actor_get_mapped (GtkActor *self);
gboolean _gtk_actor_get_realized (GtkActor *self);
/* Size negotiation */
GtkSizeRequestMode _gtk_actor_get_request_mode (GtkActor *self);
void _gtk_actor_get_preferred_size (GtkActor *self,
GtkOrientation orientation,
gfloat for_size,
gfloat *min_size_p,
gfloat *natural_size_p);
gfloat _gtk_actor_get_width (GtkActor *self);
gfloat _gtk_actor_get_height (GtkActor *self);
void _gtk_actor_allocate (GtkActor *self,
const cairo_matrix_t *position,
gfloat width,
gfloat height);
const cairo_matrix_t * _gtk_actor_get_position (GtkActor *actor);
void _gtk_actor_position (GtkActor *actor,
const cairo_matrix_t *position);
void _gtk_actor_set_layout_manager (GtkActor *actor,
GtkLayoutManager *layout_manager);
GtkLayoutManager * _gtk_actor_get_layout_manager (GtkActor *actor);
void _gtk_actor_layout_manager_changed (GtkActor *self);
/* Text */
void _gtk_actor_set_text_direction (GtkActor *self,
GtkTextDirection text_dir);
GtkTextDirection _gtk_actor_get_text_direction (GtkActor *self);
/* GDK integration */
GdkScreen * _gtk_actor_get_screen (GtkActor *self);
GtkWidget * _gtk_actor_get_widget (GtkActor *self);
/* Actor hierarchy */
void _gtk_actor_add_child (GtkActor *self,
GtkActor *child);
void _gtk_actor_insert_child_at_index (GtkActor *self,
GtkActor *child,
gint index_);
void _gtk_actor_insert_child_above (GtkActor *self,
GtkActor *child,
GtkActor *sibling);
void _gtk_actor_insert_child_below (GtkActor *self,
GtkActor *child,
GtkActor *sibling);
void _gtk_actor_remove_child (GtkActor *self,
GtkActor *child);
void _gtk_actor_remove_all_children (GtkActor *self);
gint _gtk_actor_get_n_children (GtkActor *self);
GtkActor * _gtk_actor_get_child_at_index (GtkActor *self,
gint index_);
GtkActor * _gtk_actor_get_previous_sibling (GtkActor *self);
GtkActor * _gtk_actor_get_next_sibling (GtkActor *self);
GtkActor * _gtk_actor_get_first_child (GtkActor *self);
GtkActor * _gtk_actor_get_last_child (GtkActor *self);
GtkActor * _gtk_actor_get_parent (GtkActor *self);
gboolean _gtk_actor_contains (GtkActor *self,
GtkActor *descendant);
gboolean _gtk_actor_is_toplevel (GtkActor *actor);
G_END_DECLS
#endif /* __GTK_ACTOR_PRIVATE_H__ */

230
gtk/actors/gtkbinlayout.c Normal file
View File

@@ -0,0 +1,230 @@
/*
* Gtk.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright (C) 2009 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author:
* Emmanuele Bassi <ebassi@linux.intel.com>
*/
/**
* SECTION:_gtk-bin-layout
* @short_description: A simple layout manager
*
* #GtkBinLayout is a layout manager which implements the following
* policy:
*
* <itemizedlist>
* <listitem><simpara>the preferred size is the maximum preferred size
* between all the children of the container using the
* layout;</simpara></listitem>
* <listitem><simpara>each child is allocated in "layers", on on top
* of the other;</simpara></listitem>
* </itemizedlist>
*
* <figure id="bin-layout">
* <title>Bin layout</title>
* <para>The image shows a #GtkBinLayout with three layers:
* a background #GtkCairoTexture, set to fill on both the X
* and Y axis; a #GtkTexture, set to center on both the X and
* Y axis; and a #GtkRectangle, set to %GTK_BIN_ALIGNMENT_END
* on both the X and Y axis.</para>
* <graphic fileref="bin-layout.png" format="PNG"/>
* </figure>
*
* <example id="example-_gtk-bin-layout">
* <title>How to pack actors inside a BinLayout</title>
* <programlisting>
* <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../examples/bin-layout.c">
* <xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback>
* </xi:include>
* </programlisting>
* </example>
*
* #GtkBinLayout is available since Gtk 1.2
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "gtkbinlayoutprivate.h"
struct _GtkBinLayoutPrivate {
gint dummy;
};
G_DEFINE_TYPE (GtkBinLayout,
_gtk_bin_layout,
GTK_TYPE_LAYOUT_MANAGER);
/*
* GtkBinLayout
*/
static void
gtk_bin_layout_get_preferred_size (GtkLayoutManager *manager,
GtkOrientation orientation,
gfloat for_size,
gfloat *min_size_p,
gfloat *nat_size_p)
{
GtkActor *actor = _gtk_layout_manager_get_actor (manager);
GtkActor *child;
gfloat min_size, nat_size;
min_size = nat_size = 0.0;
for (child = _gtk_actor_get_first_child (actor);
child;
child = _gtk_actor_get_next_sibling (child))
{
gfloat minimum, natural;
_gtk_actor_get_preferred_size (child,
orientation,
for_size,
&minimum,
&natural);
min_size = MAX (min_size, minimum);
nat_size = MAX (nat_size, natural);
}
*min_size_p = min_size;
*nat_size_p = nat_size;
}
typedef struct _Alignment Alignment;
struct _Alignment {
gfloat xalign;
gfloat yalign;
gfloat xscale;
gfloat yscale;
};
static const Alignment *
get_alignment (GtkActor *actor)
{
return g_object_get_data (G_OBJECT (actor), "gtk-bin-layout-alignment");
}
static void
gtk_bin_layout_allocate (GtkLayoutManager *manager,
const cairo_matrix_t *transform,
gfloat width,
gfloat height)
{
GtkActor *actor, *child;
actor = _gtk_layout_manager_get_actor (manager);
for (child = _gtk_actor_get_first_child (actor);
child;
child = _gtk_actor_get_next_sibling (child))
{
const Alignment *alignment = get_alignment (child);
if (alignment == NULL)
{
_gtk_actor_allocate (child, transform, width, height);
}
else
{
gfloat min, nat, child_width, child_height;
cairo_matrix_t child_transform;
_gtk_actor_get_preferred_size (child, GTK_ORIENTATION_HORIZONTAL, -1, &min, &nat);
child_width = (width - min) * alignment->xscale + min;
_gtk_actor_get_preferred_size (child, GTK_ORIENTATION_VERTICAL, child_width, &min, &nat);
child_height = (height - min) * alignment->yscale + min;
cairo_matrix_init_translate (&child_transform,
(width - child_width) * alignment->xalign,
(height - child_height) * alignment->yalign);
cairo_matrix_multiply (&child_transform, transform, &child_transform);
_gtk_actor_allocate (child, &child_transform, child_width, child_height);
}
}
}
static void
_gtk_bin_layout_class_init (GtkBinLayoutClass *klass)
{
GtkLayoutManagerClass *layout_class = GTK_LAYOUT_MANAGER_CLASS (klass);
g_type_class_add_private (klass, sizeof (GtkBinLayoutPrivate));
layout_class->get_preferred_size = gtk_bin_layout_get_preferred_size;
layout_class->allocate = gtk_bin_layout_allocate;
}
static void
_gtk_bin_layout_init (GtkBinLayout *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
GTK_TYPE_BIN_LAYOUT,
GtkBinLayoutPrivate);
}
/**
* _gtk_bin_layout_new:
*
* Creates a new #GtkBinLayout layout manager
*
* Return value: the newly created layout manager
*
* Since: 1.2
*/
GtkLayoutManager *
_gtk_bin_layout_new (void)
{
return g_object_new (GTK_TYPE_BIN_LAYOUT, NULL);
}
void
_gtk_bin_layout_set_child_alignment (GtkBinLayout *layout,
GtkActor *child,
gfloat xalign,
gfloat yalign,
gfloat xscale,
gfloat yscale)
{
Alignment *alignment;
g_return_if_fail (GTK_IS_BIN_LAYOUT (layout));
g_return_if_fail (GTK_IS_ACTOR (child));
g_return_if_fail (xalign >= 0.0 && xalign <= 1.0);
g_return_if_fail (yalign >= 0.0 && yalign <= 1.0);
g_return_if_fail (xscale >= 0.0 && xscale <= 1.0);
g_return_if_fail (yscale >= 0.0 && yscale <= 1.0);
alignment = g_new (Alignment, 1);
alignment->xalign = xalign;
alignment->yalign = yalign;
alignment->xscale = xscale;
alignment->yscale = yscale;
g_object_set_data_full (G_OBJECT (child),
"gtk-bin-layout-alignment",
alignment,
g_free);
_gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER (layout));
}

View File

@@ -0,0 +1,87 @@
/*
* Gtk.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright (C) 2009 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author:
* Emmanuele Bassi <ebassi@linux.intel.com>
*/
#ifndef __GTK_BIN_LAYOUT_PRIVATE_H__
#define __GTK_BIN_LAYOUT_PRIVATE_H__
#include <gtk/actors/gtklayoutmanagerprivate.h>
G_BEGIN_DECLS
#define GTK_TYPE_BIN_LAYOUT (_gtk_bin_layout_get_type ())
#define GTK_BIN_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_BIN_LAYOUT, GtkBinLayout))
#define GTK_IS_BIN_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_BIN_LAYOUT))
#define GTK_BIN_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_BIN_LAYOUT, GtkBinLayoutClass))
#define GTK_IS_BIN_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_BIN_LAYOUT))
#define GTK_BIN_LAYOUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_BIN_LAYOUT, GtkBinLayoutClass))
typedef struct _GtkBinLayout GtkBinLayout;
typedef struct _GtkBinLayoutPrivate GtkBinLayoutPrivate;
typedef struct _GtkBinLayoutClass GtkBinLayoutClass;
/**
* GtkBinLayout:
*
* The #GtkBinLayout structure contains only private data
* and should be accessed using the provided API
*
* Since: 1.2
*/
struct _GtkBinLayout
{
/*< private >*/
GtkLayoutManager parent_instance;
GtkBinLayoutPrivate *priv;
};
/**
* GtkBinLayoutClass:
*
* The #GtkBinLayoutClass structure contains only private
* data and should be accessed using the provided API
*
* Since: 1.2
*/
struct _GtkBinLayoutClass
{
/*< private >*/
GtkLayoutManagerClass parent_class;
};
GType _gtk_bin_layout_get_type (void) G_GNUC_CONST;
GtkLayoutManager * _gtk_bin_layout_new (void);
void _gtk_bin_layout_set_child_alignment (GtkBinLayout *layout,
GtkActor *child,
gfloat xalign,
gfloat yalign,
gfloat xscale,
gfloat yscale);
G_END_DECLS
#endif /* __GTK_BIN_LAYOUT_H__ */

362
gtk/actors/gtkcssactor.c Normal file
View File

@@ -0,0 +1,362 @@
/*
* Copyright © 2012 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#include "config.h"
#include "gtkcssactorprivate.h"
#include "gtkcontainer.h"
#include "gtkcontainerprivate.h"
#include "gtkcssboxprivate.h"
#include "gtkcssmatcherprivate.h"
#include "gtkdebug.h"
#include "gtkintl.h"
#include "gtkprivate.h"
#include "gtkstylecontext.h"
#include "gtkstylecontextprivate.h"
#include "gtktypebuiltins.h"
#include "gtkwidgetactorprivate.h"
#include "gtkwidgetprivate.h"
struct _GtkCssActorPrivate {
GtkStyleContext *context;
};
enum
{
PROP_0,
PROP_STYLE_CONTEXT,
PROP_LAST
};
static GParamSpec *obj_props[PROP_LAST];
G_DEFINE_TYPE (GtkCssActor, _gtk_css_actor, GTK_TYPE_ACTOR)
static gboolean
gtk_css_actor_owns_context (GtkCssActor *actor)
{
return GTK_IS_CSS_BOX (actor);
}
static void
gtk_css_actor_finalize (GObject *object)
{
GtkCssActor *self = GTK_CSS_ACTOR (object);
GtkCssActorPrivate *priv = self->priv;
if (priv->context)
{
if (gtk_css_actor_owns_context (self))
_gtk_style_context_set_source (priv->context, NULL, NULL);
g_object_unref (priv->context);
priv->context = NULL;
}
G_OBJECT_CLASS (_gtk_css_actor_parent_class)->finalize (object);
}
static void
gtk_css_actor_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
//GtkCssActor *css_actor = GTK_CSS_ACTOR (object);
switch (prop_id)
{
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_css_actor_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkCssActor *css_actor = GTK_CSS_ACTOR (object);
switch (prop_id)
{
case PROP_STYLE_CONTEXT:
g_value_set_object (value, _gtk_css_actor_get_style_context (css_actor));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_css_actor_set_style_context (GtkCssActor *self,
GtkStyleContext *context)
{
GtkCssActorPrivate *priv;
GtkActor *iter;
g_return_if_fail (GTK_IS_CSS_ACTOR (self));
g_return_if_fail (context == NULL || GTK_IS_STYLE_CONTEXT (context));
/* XXX: Use a default context for NULL? */
priv = self->priv;
if (priv->context == context)
return;
if (priv->context)
g_object_unref (priv->context);
if (context)
g_object_ref (context);
priv->context = context;
for (iter = _gtk_actor_get_first_child (GTK_ACTOR (self));
iter != NULL;
iter = _gtk_actor_get_next_sibling (iter))
{
GtkCssActor *css_actor;
if (!GTK_IS_CSS_ACTOR (iter))
continue;
css_actor = GTK_CSS_ACTOR (iter);
if (gtk_css_actor_owns_context (css_actor))
continue;
gtk_css_actor_set_style_context (css_actor, context);
}
g_object_notify (G_OBJECT (self), "style-context");
}
static void
gtk_css_actor_real_parent_set (GtkActor *actor,
GtkActor *old_parent)
{
GtkCssActor *self = GTK_CSS_ACTOR (actor);
GtkActor *parent;
parent = _gtk_actor_get_parent (actor);
if (parent != NULL)
{
g_warn_if_fail (GTK_IS_CSS_ACTOR (parent));
}
GTK_ACTOR_CLASS (_gtk_css_actor_parent_class)->parent_set (actor, old_parent);
if (!gtk_css_actor_owns_context (self))
{
if (parent)
gtk_css_actor_set_style_context (self, _gtk_css_actor_get_style_context (GTK_CSS_ACTOR (parent)));
else
gtk_css_actor_set_style_context (self, NULL);
}
}
static void
gtk_css_actor_real_style_updated (GtkCssActor *actor,
const GtkBitmask *changed)
{
}
static void
_gtk_css_actor_class_init (GtkCssActorClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkActorClass *actor_class = GTK_ACTOR_CLASS (klass);
object_class->finalize = gtk_css_actor_finalize;
object_class->set_property = gtk_css_actor_set_property;
object_class->get_property = gtk_css_actor_get_property;
actor_class->parent_set = gtk_css_actor_real_parent_set;
klass->style_updated = gtk_css_actor_real_style_updated;
/**
* GtkCssActor:style-context:
*
* The style context in use by the actor.
*
* FIXME: Do we want to replace this with a GtkCssComputedValues?
*/
obj_props[PROP_STYLE_CONTEXT] =
g_param_spec_object ("style-context",
P_("Style Context"),
P_("Style context used by this actor"),
GTK_TYPE_STYLE_CONTEXT,
GTK_PARAM_READABLE);
g_object_class_install_properties (object_class, PROP_LAST, obj_props);
g_type_class_add_private (klass, sizeof (GtkCssActorPrivate));
}
static void
_gtk_css_actor_init (GtkCssActor *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
GTK_TYPE_CSS_ACTOR,
GtkCssActorPrivate);
}
GtkStyleContext *
_gtk_css_actor_get_style_context (GtkCssActor *actor)
{
g_return_val_if_fail (GTK_IS_CSS_ACTOR (actor), NULL);
return actor->priv->context;
}
static gboolean
gtk_css_actor_source_init_css_matcher (GtkCssMatcher *matcher,
gpointer actor)
{
return _gtk_css_matcher_actor_init (matcher, actor);
}
static GtkWidgetPath *
gtk_css_actor_source_create_query_path (gpointer actor)
{
GtkWidget *widget;
widget = _gtk_actor_get_widget (actor);
if (widget == NULL)
return NULL;
return _gtk_widget_create_path (widget);
}
static const GtkWidgetPath *
gtk_css_actor_source_get_path (gpointer actor)
{
GtkWidget *widget;
widget = _gtk_actor_get_widget (actor);
if (widget == NULL)
return NULL;
return gtk_widget_get_path (widget);
}
static void
gtk_css_actor_source_invalidate (gpointer actor)
{
GtkStyleContext *context;
GtkActor *iter;
context = GTK_CSS_ACTOR (actor)->priv->context;
GTK_CSS_ACTOR_GET_CLASS (actor)->style_updated (actor, _gtk_style_context_get_changes (context));
for (iter = _gtk_actor_get_first_child (actor);
iter != NULL;
iter = _gtk_actor_get_next_sibling (iter))
{
if (!GTK_IS_CSS_ACTOR (iter))
continue;
if (gtk_css_actor_owns_context (GTK_CSS_ACTOR (iter)))
continue;
gtk_css_actor_source_invalidate (iter);
}
}
static void
gtk_css_actor_source_queue_invalidate (gpointer actor)
{
GtkWidget *widget;
widget = _gtk_actor_get_widget (actor);
if (GTK_IS_RESIZE_CONTAINER (widget))
_gtk_container_queue_restyle (GTK_CONTAINER (widget));
}
static gboolean
gtk_css_actor_source_should_animate (gpointer actor)
{
if (!_gtk_actor_get_mapped (actor))
return FALSE;
#if 0
gboolean animate;
g_object_get (gtk_widget_get_settings (widget),
"gtk-enable-animations", &animate,
NULL);
return animate;
#endif
return TRUE;
}
static GType
gtk_css_actor_source_get_widget_type (gpointer actor)
{
GtkWidget *widget;
widget = _gtk_actor_get_widget (actor);
if (widget == NULL)
return G_TYPE_INVALID;
return G_OBJECT_TYPE (widget);
}
static void
gtk_css_actor_source_destroy (gpointer actor)
{
}
static const GtkStyleContextSource gtk_css_actor_source = {
TRUE,
FALSE,
gtk_css_actor_source_init_css_matcher,
gtk_css_actor_source_create_query_path,
gtk_css_actor_source_get_path,
gtk_css_actor_source_invalidate,
gtk_css_actor_source_queue_invalidate,
gtk_css_actor_source_should_animate,
gtk_css_actor_source_get_widget_type,
gtk_css_actor_source_destroy
};
void
_gtk_css_actor_init_box (GtkCssActor *self)
{
GtkActor *actor = GTK_ACTOR (self);
GtkCssActorPrivate *priv = self->priv;
priv->context = gtk_style_context_new ();
gtk_style_context_set_screen (priv->context, _gtk_actor_get_screen (actor));
_gtk_style_context_set_source (priv->context, &gtk_css_actor_source, actor);
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright © 2012 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#ifndef __GTK_CSS_ACTOR_PRIVATE_H__
#define __GTK_CSS_ACTOR_PRIVATE_H__
#include <gtk/actors/gtkactorprivate.h>
#include <gtk/gtkbitmaskprivate.h>
#include <gtk/gtkstylecontext.h>
G_BEGIN_DECLS
#define GTK_TYPE_CSS_ACTOR (_gtk_css_actor_get_type ())
#define GTK_CSS_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_ACTOR, GtkCssActor))
#define GTK_CSS_ACTOR_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_ACTOR, GtkCssActorClass))
#define GTK_IS_CSS_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_ACTOR))
#define GTK_IS_CSS_ACTOR_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_ACTOR))
#define GTK_CSS_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_ACTOR, GtkCssActorClass))
typedef struct _GtkCssActor GtkCssActor;
typedef struct _GtkCssActorPrivate GtkCssActorPrivate;
typedef struct _GtkCssActorClass GtkCssActorClass;
typedef struct _GtkCssActorIter GtkCssActorIter;
struct _GtkCssActor
{
GtkActor parent;
GtkCssActorPrivate *priv;
};
struct _GtkCssActorClass
{
GtkActorClass parent_class;
void (* style_updated) (GtkCssActor *actor,
const GtkBitmask *changed);
};
GType _gtk_css_actor_get_type (void) G_GNUC_CONST;
GtkStyleContext * _gtk_css_actor_get_style_context (GtkCssActor *actor);
void _gtk_css_actor_init_box (GtkCssActor *actor);
G_END_DECLS
#endif /* __GTK_CSS_ACTOR_PRIVATE_H__ */

689
gtk/actors/gtkcssbox.c Normal file
View File

@@ -0,0 +1,689 @@
/*
* Copyright © 2012 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#include "config.h"
#include "gtkcssboxprivate.h"
#include "gtkcssenumvalueprivate.h"
#include "gtkcssnumbervalueprivate.h"
#include "gtkcssstylepropertyprivate.h"
#include "gtkcsstypesprivate.h"
#include "gtkdebug.h"
#include "gtkintl.h"
#include "gtklayoutmanagerprivate.h"
#include "gtkprivate.h"
#include "gtkstylecontext.h"
#include "gtkstylecontextprivate.h"
#include "gtktypebuiltins.h"
/* state flags that when set will automatically be set on all parents */
#define GTK_STATE_FLAGS_PROPAGATE_TO_PARENT (GTK_STATE_FLAG_PRELIGHT)
/* state flags that when set will automatically propagate to all children */
#define GTK_STATE_FLAGS_PROPAGATE_TO_CHILDREN (GTK_STATE_FLAG_INSENSITIVE | GTK_STATE_FLAG_BACKDROP)
G_STATIC_ASSERT((GTK_STATE_FLAGS_PROPAGATE_TO_PARENT & GTK_STATE_FLAGS_PROPAGATE_TO_CHILDREN) == 0);
#define GTK_STATE_FLAGS_NO_PROPAGATE (~(GTK_STATE_FLAGS_PROPAGATE_TO_PARENT | GTK_STATE_FLAGS_PROPAGATE_TO_CHILDREN))
struct _GtkCssBoxPrivate {
GtkStateFlags state;
char * id;
};
enum
{
PROP_0,
PROP_EFFECTIVE_STATE,
PROP_STATE,
PROP_ID,
PROP_LAST
};
static GParamSpec *obj_props[PROP_LAST];
G_DEFINE_TYPE (GtkCssBox, _gtk_css_box, GTK_TYPE_CSS_ACTOR)
static void
gtk_css_box_set_effective_state (GtkCssBox *box,
GtkStateFlags state)
{
gtk_style_context_set_state (_gtk_css_actor_get_style_context (GTK_CSS_ACTOR (box)), state);
g_object_notify_by_pspec (G_OBJECT (box), obj_props[PROP_EFFECTIVE_STATE]);
}
GtkStateFlags
_gtk_css_box_get_effective_state (GtkCssBox *self)
{
g_return_val_if_fail (GTK_IS_CSS_BOX (self), 0);
return gtk_style_context_get_state (_gtk_css_actor_get_style_context (GTK_CSS_ACTOR (self)));
}
static void
gtk_css_box_update_state_on_parent (GtkCssBox *box,
GtkStateFlags state_to_set,
GtkStateFlags state_to_unset)
{
GtkStateFlags effective;
GtkActor *iter, *parent;
effective = _gtk_css_box_get_effective_state (box);
state_to_set = ~effective & state_to_set;
state_to_unset = effective & state_to_unset;
for (iter = _gtk_actor_get_first_child (GTK_ACTOR (box));
iter && state_to_unset != 0;
iter = _gtk_actor_get_next_sibling (iter))
{
if (!GTK_IS_CSS_BOX (iter))
continue;
state_to_unset &= ~_gtk_css_box_get_effective_state (GTK_CSS_BOX (iter));
}
if (state_to_set == 0 && state_to_unset == 0)
return;
gtk_css_box_set_effective_state (box, (effective | state_to_set) & ~state_to_unset);
parent = _gtk_actor_get_parent (GTK_ACTOR (box));
if (GTK_IS_CSS_BOX (parent))
gtk_css_box_update_state_on_parent (GTK_CSS_BOX (parent), state_to_set, state_to_unset);
}
static void
gtk_css_box_update_state_on_children (GtkCssBox *box,
GtkStateFlags state_to_set,
GtkStateFlags state_to_unset)
{
GtkStateFlags effective;
GtkActor *iter;
effective = _gtk_css_box_get_effective_state (box);
state_to_set = ~effective & state_to_set;
state_to_unset = effective & state_to_unset;
gtk_css_box_set_effective_state (box, (effective | state_to_set) & ~state_to_unset);
if (state_to_set == 0 && state_to_unset == 0)
return;
for (iter = _gtk_actor_get_first_child (GTK_ACTOR (box));
iter;
iter = _gtk_actor_get_next_sibling (iter))
{
if (!GTK_IS_CSS_BOX (iter))
continue;
gtk_css_box_update_state_on_children (GTK_CSS_BOX (iter), state_to_set, state_to_unset);
}
}
static void
gtk_css_box_finalize (GObject *object)
{
GtkCssBox *self = GTK_CSS_BOX (object);
GtkCssBoxPrivate *priv = self->priv;
g_free (priv->id);
G_OBJECT_CLASS (_gtk_css_box_parent_class)->finalize (object);
}
static void
gtk_css_box_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkCssBox *css_box = GTK_CSS_BOX (object);
switch (prop_id)
{
case PROP_STATE:
_gtk_css_box_set_state (css_box, g_value_get_enum (value));
break;
case PROP_ID:
_gtk_css_box_set_id (css_box, g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_css_box_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkCssBox *css_box = GTK_CSS_BOX (object);
switch (prop_id)
{
case PROP_EFFECTIVE_STATE:
g_value_set_enum (value, _gtk_css_box_get_effective_state (css_box));
break;
case PROP_STATE:
g_value_set_enum (value, _gtk_css_box_get_state (css_box));
break;
case PROP_ID:
g_value_set_string (value, _gtk_css_box_get_id (css_box));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_css_box_queue_restyle (GtkCssBox *self,
GtkCssChange change)
{
_gtk_style_context_queue_invalidate (_gtk_css_actor_get_style_context (GTK_CSS_ACTOR (self)), change);
}
static void
gtk_css_box_queue_restyle_siblings (GtkCssBox *self,
GtkCssChange change)
{
GtkActor *iter;
for (iter = _gtk_actor_get_previous_sibling (GTK_ACTOR (self));
iter;
iter = _gtk_actor_get_previous_sibling (iter))
{
if (GTK_IS_CSS_BOX (iter))
gtk_css_box_queue_restyle (GTK_CSS_BOX (iter), change);
}
for (iter = _gtk_actor_get_next_sibling (GTK_ACTOR (self));
iter;
iter = _gtk_actor_get_next_sibling (iter))
{
if (GTK_IS_CSS_BOX (iter))
gtk_css_box_queue_restyle (GTK_CSS_BOX (iter), change);
}
}
static void
gtk_css_box_real_show (GtkActor *self)
{
GtkCssBox *box = GTK_CSS_BOX (self);
GTK_ACTOR_CLASS (_gtk_css_box_parent_class)->show (self);
gtk_css_box_queue_restyle_siblings (box, GTK_CSS_CHANGE_ANY_SIBLING);
}
static void
gtk_css_box_real_hide (GtkActor *self)
{
GtkCssBox *box = GTK_CSS_BOX (self);
gtk_css_box_queue_restyle_siblings (box, GTK_CSS_CHANGE_ANY_SIBLING);
GTK_ACTOR_CLASS (_gtk_css_box_parent_class)->hide (self);
}
static void
gtk_css_box_real_map (GtkActor *self)
{
GTK_ACTOR_CLASS (_gtk_css_box_parent_class)->map (self);
_gtk_style_context_update_animating (_gtk_css_actor_get_style_context (GTK_CSS_ACTOR (self)));
}
static void
gtk_css_box_real_unmap (GtkActor *self)
{
GTK_ACTOR_CLASS (_gtk_css_box_parent_class)->unmap (self);
_gtk_style_context_update_animating (_gtk_css_actor_get_style_context (GTK_CSS_ACTOR (self)));
}
static void
gtk_css_box_real_parent_set (GtkActor *self,
GtkActor *old_parent)
{
GtkCssBox *box = GTK_CSS_BOX (self);
GtkActor *parent;
parent = _gtk_actor_get_parent (self);
if (old_parent == NULL)
{
g_warn_if_fail (GTK_IS_CSS_BOX (parent));
}
GTK_ACTOR_CLASS (_gtk_css_box_parent_class)->parent_set (self, old_parent);
gtk_style_context_set_parent (_gtk_css_actor_get_style_context (GTK_CSS_ACTOR (self)),
parent ? _gtk_css_actor_get_style_context (GTK_CSS_ACTOR (parent)) : NULL);
if (parent)
{
gtk_css_box_update_state_on_children (box,
_gtk_css_box_get_effective_state (GTK_CSS_BOX (parent)) & GTK_STATE_FLAGS_PROPAGATE_TO_CHILDREN,
0);
gtk_css_box_update_state_on_parent (GTK_CSS_BOX (parent),
_gtk_css_box_get_effective_state (box) & GTK_STATE_FLAGS_PROPAGATE_TO_PARENT,
0);
}
else
{
gtk_css_box_update_state_on_children (box,
0,
_gtk_css_box_get_effective_state (GTK_CSS_BOX (old_parent)) & GTK_STATE_FLAGS_PROPAGATE_TO_CHILDREN);
gtk_css_box_update_state_on_parent (GTK_CSS_BOX (old_parent),
0,
_gtk_css_box_get_effective_state (box) & GTK_STATE_FLAGS_PROPAGATE_TO_PARENT);
}
}
static double
gtk_css_box_get_edge (GtkCssBox *self,
GtkCssSide side)
{
const struct {
guint margin;
guint border;
guint border_style;
guint padding;
} properties[] = {
/* [GTK_CSS_TOP] = */ { GTK_CSS_PROPERTY_MARGIN_TOP,
GTK_CSS_PROPERTY_BORDER_TOP_WIDTH,
GTK_CSS_PROPERTY_BORDER_TOP_STYLE,
GTK_CSS_PROPERTY_PADDING_TOP },
/* [GTK_CSS_RIGHT] = */ { GTK_CSS_PROPERTY_MARGIN_RIGHT,
GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH,
GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE,
GTK_CSS_PROPERTY_PADDING_RIGHT },
/* [GTK_CSS_BOTTOM] = */ { GTK_CSS_PROPERTY_MARGIN_BOTTOM,
GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH,
GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE,
GTK_CSS_PROPERTY_PADDING_BOTTOM },
/* [GTK_CSS_LEFT] = */ { GTK_CSS_PROPERTY_MARGIN_LEFT,
GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH,
GTK_CSS_PROPERTY_BORDER_LEFT_STYLE,
GTK_CSS_PROPERTY_PADDING_LEFT }
};
GtkStyleContext *context;
GtkBorderStyle border_style;
double result;
context = _gtk_css_actor_get_style_context (GTK_CSS_ACTOR (self));
result = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, properties[side].margin), 100)
+ _gtk_css_number_value_get (_gtk_style_context_peek_property (context, properties[side].padding), 100);
border_style = _gtk_css_border_style_value_get (_gtk_style_context_peek_property (context, properties[side].border_style));
if (border_style != GTK_BORDER_STYLE_NONE && border_style != GTK_BORDER_STYLE_HIDDEN)
result += _gtk_css_number_value_get (_gtk_style_context_peek_property (context, properties[side].border), 100);
return result;
}
static void
adjust_size_for_css (GtkCssBox *self,
GtkOrientation orientation,
gfloat *min_size_p,
gfloat *nat_size_p)
{
GtkStyleContext *context;
gfloat min_css, nat_css;
context = _gtk_css_actor_get_style_context (GTK_CSS_ACTOR (self));
min_css = _gtk_css_number_value_get (
_gtk_style_context_peek_property (context,
orientation == GTK_ORIENTATION_HORIZONTAL ? GTK_CSS_PROPERTY_MIN_WIDTH
: GTK_CSS_PROPERTY_MIN_HEIGHT), 0);
nat_css = _gtk_css_number_value_get (
_gtk_style_context_peek_property (context,
orientation == GTK_ORIENTATION_HORIZONTAL ? GTK_CSS_PROPERTY_MAX_WIDTH
: GTK_CSS_PROPERTY_MAX_HEIGHT), 0);
*min_size_p = MAX (min_css, *min_size_p);
*nat_size_p = MIN (nat_css, *nat_size_p);
*nat_size_p = MAX (*min_size_p, *nat_size_p);
}
static void
gtk_css_box_real_get_preferred_size (GtkActor *self,
GtkOrientation orientation,
gfloat for_size,
gfloat *min_size_p,
gfloat *nat_size_p)
{
GtkCssBox *box = GTK_CSS_BOX (self);
float extra_size;
if (for_size >= 0)
{
if (orientation == GTK_ORIENTATION_VERTICAL)
extra_size = gtk_css_box_get_edge (box, GTK_CSS_LEFT) + gtk_css_box_get_edge (box, GTK_CSS_RIGHT);
else
extra_size = gtk_css_box_get_edge (box, GTK_CSS_TOP) + gtk_css_box_get_edge (box, GTK_CSS_BOTTOM);
for_size = MAX (0, for_size - extra_size);
}
GTK_ACTOR_CLASS (_gtk_css_box_parent_class)->get_preferred_size (self, orientation, for_size, min_size_p, nat_size_p);
adjust_size_for_css (box, orientation, min_size_p, nat_size_p);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
extra_size = gtk_css_box_get_edge (box, GTK_CSS_LEFT) + gtk_css_box_get_edge (box, GTK_CSS_RIGHT);
else
extra_size = gtk_css_box_get_edge (box, GTK_CSS_TOP) + gtk_css_box_get_edge (box, GTK_CSS_BOTTOM);
*min_size_p = MAX (0, *min_size_p + extra_size);
*nat_size_p = MAX (0, *nat_size_p + extra_size);
}
static void
gtk_css_box_real_allocate (GtkActor *actor,
const cairo_matrix_t *position,
gfloat width,
gfloat height)
{
GtkCssBox *self = GTK_CSS_BOX (actor);
GtkLayoutManager *layout_manager;
layout_manager = _gtk_actor_get_layout_manager (actor);
if (layout_manager)
{
cairo_matrix_t transform;
double top, left, bottom, right;
top = gtk_css_box_get_edge (self, GTK_CSS_TOP);
left = gtk_css_box_get_edge (self, GTK_CSS_LEFT);
bottom = gtk_css_box_get_edge (self, GTK_CSS_BOTTOM);
right = gtk_css_box_get_edge (self, GTK_CSS_RIGHT);
cairo_matrix_init_translate (&transform, left, top);
_gtk_layout_manager_allocate (layout_manager,
&transform,
width - left - right,
height - top - bottom);
}
GTK_ACTOR_CLASS (_gtk_css_box_parent_class)->allocate (actor, position, width, height);
}
static void
gtk_css_box_real_draw (GtkActor *actor,
cairo_t *cr)
{
GtkCssBox *self = GTK_CSS_BOX (actor);
GtkStyleContext *context;
double width, height;
double top, left, bottom, right;
context = _gtk_css_actor_get_style_context (GTK_CSS_ACTOR (actor));
top = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_MARGIN_TOP), 100);
right = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_MARGIN_RIGHT), 100);
bottom = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_MARGIN_BOTTOM), 100);
left = _gtk_css_number_value_get (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_MARGIN_LEFT), 100);
width = _gtk_actor_get_width (actor) - left - right;
height = _gtk_actor_get_height (actor) - bottom - top;
gtk_render_background (context,
cr,
left, top,
width, height);
gtk_render_frame (context,
cr,
left, top,
width, height);
cairo_translate (cr,
gtk_css_box_get_edge (self, GTK_CSS_LEFT),
gtk_css_box_get_edge (self, GTK_CSS_TOP));
GTK_ACTOR_CLASS (_gtk_css_box_parent_class)->draw (actor, cr);
}
static void
gtk_css_box_real_screen_changed (GtkActor *actor,
GdkScreen *new_screen,
GdkScreen *old_screen)
{
GtkStyleContext *context;
context = _gtk_css_actor_get_style_context (GTK_CSS_ACTOR (actor));
gtk_style_context_set_screen (context, new_screen);
}
static void
gtk_css_box_real_style_updated (GtkCssActor *actor,
const GtkBitmask *changes)
{
if (_gtk_css_style_property_changes_affect_size (changes))
_gtk_actor_queue_relayout (GTK_ACTOR (actor));
else
_gtk_actor_queue_redraw (GTK_ACTOR (actor));
}
static void
_gtk_css_box_class_init (GtkCssBoxClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkActorClass *actor_class = GTK_ACTOR_CLASS (klass);
GtkCssActorClass *css_actor_class = GTK_CSS_ACTOR_CLASS (klass);
object_class->finalize = gtk_css_box_finalize;
object_class->set_property = gtk_css_box_set_property;
object_class->get_property = gtk_css_box_get_property;
actor_class->show = gtk_css_box_real_show;
actor_class->hide = gtk_css_box_real_hide;
actor_class->map = gtk_css_box_real_map;
actor_class->unmap = gtk_css_box_real_unmap;
actor_class->draw = gtk_css_box_real_draw;
actor_class->parent_set = gtk_css_box_real_parent_set;
actor_class->get_preferred_size = gtk_css_box_real_get_preferred_size;
actor_class->allocate = gtk_css_box_real_allocate;
actor_class->screen_changed = gtk_css_box_real_screen_changed;
css_actor_class->style_updated = gtk_css_box_real_style_updated;
/**
* GtkCssBox:state:
*
* The state flags explicitly set on the box.
*
* See also GtkCssBox:effective-state.
*/
obj_props[PROP_STATE] =
g_param_spec_flags ("state",
P_("State"),
P_("State flags set on the box"),
GTK_TYPE_STATE_FLAGS,
0,
GTK_PARAM_READWRITE);
/**
* GtkCssBox:effective-state:
*
* The state flags explicitly set on the box. These are the flags cpomputed
* from the box's own state and propagated state from parent or children boxes.
*
* See also GtkCssBox:state.
*/
obj_props[PROP_EFFECTIVE_STATE] =
g_param_spec_flags ("effective-state",
P_("Effective State"),
P_("Effective state computed for the box"),
GTK_TYPE_STATE_FLAGS,
0,
GTK_PARAM_READWRITE);
/**
* GtkCssBox:id:
*
* The ID given to this box or %NULL if the box does not have an ID. This is the
* default.
*
* The ID is used for matching in CSS and is supposed to be unique for an actor tree.
* Currently this is not enforced, but it might be in the future.
*/
obj_props[PROP_ID] =
g_param_spec_string ("id",
P_("ID"),
P_("ID given to this actor"),
NULL,
GTK_PARAM_READWRITE);
g_type_class_add_private (klass, sizeof (GtkCssBoxPrivate));
}
static void
_gtk_css_box_init (GtkCssBox *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
GTK_TYPE_CSS_BOX,
GtkCssBoxPrivate);
_gtk_css_actor_init_box (GTK_CSS_ACTOR (self));
}
GtkActor *
_gtk_css_box_new (void)
{
return g_object_new (GTK_TYPE_CSS_BOX, NULL);
}
void
_gtk_css_box_set_state (GtkCssBox *self,
GtkStateFlags state)
{
GtkCssBoxPrivate *priv;
GtkStateFlags changed;
g_return_if_fail (GTK_IS_CSS_BOX (self));
priv = self->priv;
if (priv->state == state)
return;
g_object_freeze_notify (G_OBJECT (self));
changed = priv->state ^ state;
priv->state = state;
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_STATE]);
if (changed & GTK_STATE_FLAGS_PROPAGATE_TO_PARENT)
gtk_css_box_update_state_on_parent (self,
state & changed & GTK_STATE_FLAGS_PROPAGATE_TO_PARENT,
~state & changed & GTK_STATE_FLAGS_PROPAGATE_TO_PARENT);
if (changed & GTK_STATE_FLAGS_PROPAGATE_TO_CHILDREN)
gtk_css_box_update_state_on_children (self,
state & changed & GTK_STATE_FLAGS_PROPAGATE_TO_CHILDREN,
~state & changed & GTK_STATE_FLAGS_PROPAGATE_TO_CHILDREN);
gtk_css_box_set_effective_state (self,
(_gtk_css_box_get_effective_state (self) & GTK_STATE_FLAGS_NO_PROPAGATE)
| (state & ~GTK_STATE_FLAGS_NO_PROPAGATE));
g_object_thaw_notify (G_OBJECT (self));
}
GtkStateFlags
_gtk_css_box_get_state (GtkCssBox *self)
{
g_return_val_if_fail (GTK_IS_CSS_BOX (self), 0);
return self->priv->state;
}
void
_gtk_css_box_add_class (GtkCssBox *self,
const gchar *class_name)
{
g_return_if_fail (GTK_IS_CSS_BOX (self));
g_return_if_fail (class_name != NULL);
gtk_style_context_add_class (_gtk_css_actor_get_style_context (GTK_CSS_ACTOR (self)), class_name);
}
void
_gtk_css_box_remove_class (GtkCssBox *self,
const gchar *class_name)
{
g_return_if_fail (GTK_IS_CSS_BOX (self));
g_return_if_fail (class_name != NULL);
gtk_style_context_remove_class (_gtk_css_actor_get_style_context (GTK_CSS_ACTOR (self)), class_name);
}
gboolean
_gtk_css_box_has_class (GtkCssBox *self,
const gchar *class_name)
{
g_return_val_if_fail (GTK_IS_CSS_BOX (self), FALSE);
g_return_val_if_fail (class_name != NULL, FALSE);
return gtk_style_context_has_class (_gtk_css_actor_get_style_context (GTK_CSS_ACTOR (self)), class_name);
}
void
_gtk_css_box_set_id (GtkCssBox *self,
const char *id)
{
GtkCssBoxPrivate *priv;
g_return_if_fail (GTK_IS_CSS_BOX (self));
priv = self->priv;
if (g_strcmp0 (priv->id, id) == 0)
return;
g_free (priv->id);
priv->id = g_strdup (id);
gtk_css_box_queue_restyle (self, GTK_CSS_CHANGE_NAME);
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ID]);
}
const char *
_gtk_css_box_get_id (GtkCssBox *self)
{
g_return_val_if_fail (GTK_IS_CSS_BOX (self), NULL);
return self->priv->id;
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright © 2012 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#ifndef __GTK_CSS_BOX_PRIVATE_H__
#define __GTK_CSS_BOX_PRIVATE_H__
#include <gtk/actors/gtkcssactorprivate.h>
G_BEGIN_DECLS
#define GTK_TYPE_CSS_BOX (_gtk_css_box_get_type ())
#define GTK_CSS_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_BOX, GtkCssBox))
#define GTK_CSS_BOX_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_BOX, GtkCssBoxClass))
#define GTK_IS_CSS_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_BOX))
#define GTK_IS_CSS_BOX_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_BOX))
#define GTK_CSS_BOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_BOX, GtkCssBoxClass))
typedef struct _GtkCssBox GtkCssBox;
typedef struct _GtkCssBoxPrivate GtkCssBoxPrivate;
typedef struct _GtkCssBoxClass GtkCssBoxClass;
typedef struct _GtkCssBoxIter GtkCssBoxIter;
struct _GtkCssBox
{
GtkCssActor parent;
GtkCssBoxPrivate *priv;
};
struct _GtkCssBoxClass
{
GtkCssActorClass parent_class;
};
GType _gtk_css_box_get_type (void) G_GNUC_CONST;
GtkActor * _gtk_css_box_new (void);
void _gtk_css_box_set_state (GtkCssBox *self,
GtkStateFlags state);
GtkStateFlags _gtk_css_box_get_state (GtkCssBox *self);
GtkStateFlags _gtk_css_box_get_effective_state (GtkCssBox *self);
void _gtk_css_box_set_id (GtkCssBox *self,
const char *id);
const char * _gtk_css_box_get_id (GtkCssBox *self);
void _gtk_css_box_add_class (GtkCssBox *self,
const gchar *class_name);
void _gtk_css_box_remove_class (GtkCssBox *self,
const gchar *class_name);
gboolean _gtk_css_box_has_class (GtkCssBox *self,
const gchar *class_name);
G_END_DECLS
#endif /* __GTK_CSS_BOX_PRIVATE_H__ */

516
gtk/actors/gtkcsstext.c Normal file
View File

@@ -0,0 +1,516 @@
/*
* Copyright © 2012 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#include "config.h"
#include "gtkcsstextprivate.h"
#include "gtkdebug.h"
#include "gtkintl.h"
#include "gtkmain.h"
#include "gtkprivate.h"
#include "gtkstylecontext.h"
#include "gtktypebuiltins.h"
struct _GtkCssTextPrivate {
PangoLayout *layout;
gint width_chars;
gint max_width_chars;
guint wrap :1;
};
enum
{
PROP_0,
PROP_ELLIPSIZE,
PROP_TEXT,
PROP_TEXT_ALIGNMENT,
PROP_LAST
};
static GParamSpec *obj_props[PROP_LAST];
G_DEFINE_TYPE (GtkCssText, _gtk_css_text, GTK_TYPE_CSS_ACTOR)
static void
gtk_css_text_finalize (GObject *object)
{
GtkCssText *self = GTK_CSS_TEXT (object);
GtkCssTextPrivate *priv = self->priv;
g_object_unref (priv->layout);
G_OBJECT_CLASS (_gtk_css_text_parent_class)->finalize (object);
}
static void
gtk_css_text_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkCssText *self = GTK_CSS_TEXT (object);
switch (prop_id)
{
case PROP_ELLIPSIZE:
_gtk_css_text_set_ellipsize (self, g_value_get_enum (value));
break;
case PROP_TEXT:
_gtk_css_text_set_text (self, g_value_get_string (value));
break;
case PROP_TEXT_ALIGNMENT:
_gtk_css_text_set_text_alignment (self, g_value_get_enum (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_css_text_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkCssText *self = GTK_CSS_TEXT (object);
switch (prop_id)
{
case PROP_ELLIPSIZE:
g_value_set_enum (value, _gtk_css_text_get_ellipsize (self));
break;
case PROP_TEXT:
g_value_set_string (value, _gtk_css_text_get_text (self));
break;
case PROP_TEXT_ALIGNMENT:
g_value_set_enum (value, _gtk_css_text_get_text_alignment (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
/**
* gtk_css_text_get_measuring_layout:
* @self: the #GtkCssText
* @existing_layout: %NULL or an existing layout already in use.
* @width: the width to measure with in pango units, or -1 for infinite
*
* Gets a layout that can be used for measuring sizes. The returned
* layout will be identical to the label's layout except for the
* layout's width, which will be set to @width. Do not modify the returned
* layout.
*
* Returns: a new reference to a pango layout
**/
static PangoLayout *
gtk_css_text_get_measuring_layout (GtkCssText *self,
PangoLayout *existing_layout,
int width)
{
GtkCssTextPrivate *priv = self->priv;
PangoRectangle rect;
PangoLayout *copy;
if (existing_layout != NULL)
{
if (existing_layout != priv->layout)
{
pango_layout_set_width (existing_layout, width);
return existing_layout;
}
g_object_unref (existing_layout);
}
if (pango_layout_get_width (priv->layout) == width)
{
g_object_ref (priv->layout);
return priv->layout;
}
/* We can use the label's own layout if we're not allocated a size yet,
* because we don't need it to be properly setup at that point.
* This way we can make use of caching upon the label's creation.
*/
if (_gtk_actor_get_width (GTK_ACTOR (self)) <= 1)
{
g_object_ref (priv->layout);
pango_layout_set_width (priv->layout, width);
return priv->layout;
}
/* oftentimes we want to measure a width that is far wider than the current width,
* even though the layout would not change if we made it wider. In that case, we
* can just return the current layout, because for measuring purposes, it will be
* identical.
*/
pango_layout_get_extents (priv->layout, NULL, &rect);
if ((width == -1 || rect.width <= width) &&
!pango_layout_is_wrapped (priv->layout) &&
!pango_layout_is_ellipsized (priv->layout))
{
g_object_ref (priv->layout);
return priv->layout;
}
copy = pango_layout_copy (priv->layout);
pango_layout_set_width (copy, width);
return copy;
}
static GtkSizeRequestMode
gtk_css_text_real_get_request_mode (GtkActor *actor)
{
/* XXX: Return CONSTANT_SIZE when wrapping is disabled */
return GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
}
static gint
get_char_pixels (GtkWidget *self,
PangoLayout *layout)
{
PangoContext *context;
PangoFontMetrics *metrics;
gint char_width, digit_width;
context = pango_layout_get_context (layout);
metrics = pango_context_get_metrics (context,
pango_context_get_font_description (context),
pango_context_get_language (context));
char_width = pango_font_metrics_get_approximate_char_width (metrics);
digit_width = pango_font_metrics_get_approximate_digit_width (metrics);
pango_font_metrics_unref (metrics);
return MAX (char_width, digit_width);;
}
static void
gtk_css_text_get_preferred_layout_size (GtkCssText *self,
PangoRectangle *smallest,
PangoRectangle *widest)
{
GtkCssTextPrivate *priv = self->priv;
PangoLayout *layout;
gint char_pixels;
/* "width-chars" Hard-coded minimum width:
* - minimum size should be MAX (width-chars, strlen ("..."));
* - natural size should be MAX (width-chars, strlen (priv->text));
*
* "max-width-chars" User specified maximum size requisition
* - minimum size should be MAX (width-chars, 0)
* - natural size should be MIN (max-width-chars, strlen (priv->text))
*
* For ellipsizing selfs; if max-width-chars is specified: either it is used as
* a minimum size or the self text as a minimum size (natural size still overflows).
*
* For wrapping selfs; A reasonable minimum size is useful to naturally layout
* interfaces automatically. In this case if no "width-chars" is specified, the minimum
* width will default to the wrap guess that gtk_css_text_ensure_layout() does.
*/
/* Start off with the pixel extents of an as-wide-as-possible layout */
layout = gtk_css_text_get_measuring_layout (self, NULL, -1);
if (priv->width_chars > -1 || priv->max_width_chars > -1)
char_pixels = get_char_pixels (GTK_WIDGET (self), layout);
else
char_pixels = 0;
pango_layout_get_extents (layout, NULL, widest);
widest->width = MAX (widest->width, char_pixels * priv->width_chars);
widest->x = widest->y = 0;
if (pango_layout_get_ellipsize (priv->layout) != PANGO_ELLIPSIZE_NONE || priv->wrap)
{
/* a layout with width 0 will be as small as humanly possible */
layout = gtk_css_text_get_measuring_layout (self,
layout,
priv->width_chars > -1 ? char_pixels * priv->width_chars
: 0);
pango_layout_get_extents (layout, NULL, smallest);
smallest->width = MAX (smallest->width, char_pixels * priv->width_chars);
smallest->x = smallest->y = 0;
if (priv->max_width_chars > -1 && widest->width > char_pixels * priv->max_width_chars)
{
layout = gtk_css_text_get_measuring_layout (self,
layout,
MAX (smallest->width, char_pixels * priv->max_width_chars));
pango_layout_get_extents (layout, NULL, widest);
widest->width = MAX (widest->width, char_pixels * priv->width_chars);
widest->x = widest->y = 0;
}
}
else
{
*smallest = *widest;
}
if (widest->width < smallest->width)
*smallest = *widest;
g_object_unref (layout);
}
static void
gtk_css_text_real_get_preferred_size (GtkActor *actor,
GtkOrientation orientation,
gfloat for_size,
gfloat *min_size_p,
gfloat *nat_size_p)
{
GtkCssText *self = GTK_CSS_TEXT (actor);
if (for_size < 0)
{
PangoRectangle smallest_rect, widest_rect;
gtk_css_text_get_preferred_layout_size (self, &smallest_rect, &widest_rect);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
*min_size_p = (double) smallest_rect.width / PANGO_SCALE;
*nat_size_p = (double) widest_rect.width / PANGO_SCALE;
}
else
{
*min_size_p = (double) widest_rect.height / PANGO_SCALE;
*nat_size_p = (double) smallest_rect.height / PANGO_SCALE;
}
}
else
{
PangoLayout *layout;
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
/* XXX */
return gtk_css_text_real_get_preferred_size (actor , orientation, -1, min_size_p, nat_size_p);
}
else
{
gint text_height;
layout = gtk_css_text_get_measuring_layout (self, NULL, for_size * PANGO_SCALE);
pango_layout_get_size (layout, NULL, &text_height);
*min_size_p = (double) text_height / PANGO_SCALE;
*nat_size_p = (double) text_height / PANGO_SCALE;
g_object_unref (layout);
}
}
}
static void
gtk_css_text_real_allocate (GtkActor *actor,
const cairo_matrix_t *position,
gfloat width,
gfloat height)
{
GtkCssText *self = GTK_CSS_TEXT (actor);
GtkCssTextPrivate *priv = self->priv;
GTK_ACTOR_CLASS (_gtk_css_text_parent_class)->allocate (actor, position, width, height);
pango_layout_set_width (priv->layout, width * PANGO_SCALE);
}
static void
gtk_css_text_real_draw (GtkActor *actor,
cairo_t *cr)
{
GtkCssText *self = GTK_CSS_TEXT (actor);
GtkCssTextPrivate *priv = self->priv;
GtkStyleContext *context;
context = _gtk_css_actor_get_style_context (GTK_CSS_ACTOR (actor));
GTK_ACTOR_CLASS (_gtk_css_text_parent_class)->draw (actor, cr);
gtk_render_layout (context,
cr,
0, 0,
priv->layout);
}
static void
_gtk_css_text_class_init (GtkCssTextClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkActorClass *actor_class = GTK_ACTOR_CLASS (klass);
object_class->finalize = gtk_css_text_finalize;
object_class->set_property = gtk_css_text_set_property;
object_class->get_property = gtk_css_text_get_property;
actor_class->draw = gtk_css_text_real_draw;
actor_class->get_request_mode = gtk_css_text_real_get_request_mode;
actor_class->get_preferred_size = gtk_css_text_real_get_preferred_size;
actor_class->allocate = gtk_css_text_real_allocate;
/**
* GtkCssText:ellipsize:
*
* The ellipsize mode to use.
*
* See also GtkCssText:wrap.
*/
obj_props[PROP_ELLIPSIZE] =
g_param_spec_enum ("ellipsize",
P_("Ellipsize"),
P_("Ellipsize mode to use"),
PANGO_TYPE_ELLIPSIZE_MODE,
PANGO_ELLIPSIZE_NONE,
GTK_PARAM_READWRITE);
/**
* GtkCssText:text:
*
* The text to display.
*/
obj_props[PROP_TEXT] =
g_param_spec_string ("text",
P_("Text"),
P_("Text to display"),
NULL,
GTK_PARAM_READWRITE);
/**
* GtkCssText:text-alignment:
*
* The alignment of the text.
*
* See also GtkActor:halign for aligning the text box.
*/
obj_props[PROP_ELLIPSIZE] =
g_param_spec_enum ("text-alignment",
P_("Text alignment"),
P_("ow to align the rows of text"),
PANGO_TYPE_ALIGNMENT,
PANGO_ALIGN_LEFT,
GTK_PARAM_READWRITE);
g_object_class_install_properties (object_class, PROP_LAST, obj_props);
g_type_class_add_private (klass, sizeof (GtkCssTextPrivate));
}
static void
_gtk_css_text_init (GtkCssText *self)
{
GtkCssTextPrivate *priv;
PangoContext *context;
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
GTK_TYPE_CSS_TEXT,
GtkCssTextPrivate);
priv = self->priv;
context = gdk_pango_context_get_for_screen (_gtk_actor_get_screen (GTK_ACTOR (self)));
g_warning ("set proper font on context");
pango_context_set_language (context, gtk_get_default_language ());
priv->layout = pango_layout_new (context);
g_object_unref (context);
priv->max_width_chars = -1;
priv->width_chars = -1;
}
GtkActor *
_gtk_css_text_new (void)
{
return g_object_new (GTK_TYPE_CSS_TEXT, NULL);
}
const char *
_gtk_css_text_get_text (GtkCssText *self)
{
g_return_val_if_fail (GTK_IS_CSS_TEXT (self), NULL);
return pango_layout_get_text (self->priv->layout);
}
void
_gtk_css_text_set_text (GtkCssText *self,
const char *text)
{
g_return_if_fail (GTK_IS_CSS_TEXT (self));
pango_layout_set_text (self->priv->layout, text, -1);
_gtk_actor_queue_relayout (GTK_ACTOR (self));
}
PangoEllipsizeMode
_gtk_css_text_get_ellipsize (GtkCssText *self)
{
g_return_val_if_fail (GTK_IS_CSS_TEXT (self), PANGO_ELLIPSIZE_NONE);
return pango_layout_get_ellipsize (self->priv->layout);
}
void
_gtk_css_text_set_ellipsize (GtkCssText *self,
PangoEllipsizeMode ellipsize)
{
g_return_if_fail (GTK_IS_CSS_TEXT (self));
pango_layout_set_ellipsize (self->priv->layout, ellipsize);
_gtk_actor_queue_relayout (GTK_ACTOR (self));
}
PangoAlignment
_gtk_css_text_get_text_alignment (GtkCssText *self)
{
g_return_val_if_fail (GTK_IS_CSS_TEXT (self), PANGO_ALIGN_LEFT);
return pango_layout_get_alignment (self->priv->layout);
}
void
_gtk_css_text_set_text_alignment (GtkCssText *self,
PangoAlignment alignment)
{
g_return_if_fail (GTK_IS_CSS_TEXT (self));
pango_layout_set_alignment (self->priv->layout, alignment);
_gtk_actor_queue_redraw (GTK_ACTOR (self));
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright © 2012 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#ifndef __GTK_CSS_TEXT_PRIVATE_H__
#define __GTK_CSS_TEXT_PRIVATE_H__
#include <gtk/actors/gtkcssactorprivate.h>
G_BEGIN_DECLS
#define GTK_TYPE_CSS_TEXT (_gtk_css_text_get_type ())
#define GTK_CSS_TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_TEXT, GtkCssText))
#define GTK_CSS_TEXT_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_TEXT, GtkCssTextClass))
#define GTK_IS_CSS_TEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_TEXT))
#define GTK_IS_CSS_TEXT_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_TEXT))
#define GTK_CSS_TEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_TEXT, GtkCssTextClass))
typedef struct _GtkCssText GtkCssText;
typedef struct _GtkCssTextPrivate GtkCssTextPrivate;
typedef struct _GtkCssTextClass GtkCssTextClass;
typedef struct _GtkCssTextIter GtkCssTextIter;
struct _GtkCssText
{
GtkCssActor parent;
GtkCssTextPrivate *priv;
};
struct _GtkCssTextClass
{
GtkCssActorClass parent_class;
};
GType _gtk_css_text_get_type (void) G_GNUC_CONST;
GtkActor * _gtk_css_text_new (void);
const char * _gtk_css_text_get_text (GtkCssText *self);
void _gtk_css_text_set_text (GtkCssText *self,
const char *text);
PangoEllipsizeMode _gtk_css_text_get_ellipsize (GtkCssText *self);
void _gtk_css_text_set_ellipsize (GtkCssText *self,
PangoEllipsizeMode ellipsize);
PangoAlignment _gtk_css_text_get_text_alignment (GtkCssText *self);
void _gtk_css_text_set_text_alignment (GtkCssText *self,
PangoAlignment alignment);
G_END_DECLS
#endif /* __GTK_CSS_TEXT_PRIVATE_H__ */

View File

@@ -0,0 +1,498 @@
/*
* Gtk.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright (C) 2009 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author:
* Emmanuele Bassi <ebassi@linux.intel.com>
*/
/**
* SECTION:_gtk-layout-manager
* @short_description: Layout managers base class
*
* #GtkLayoutManager is a base abstract class for layout managers. A
* layout manager implements the layouting policy for a composite or a
* container actor: it controls the preferred size of the actor to which
* it has been paired, and it controls the allocation of its children.
*
* Any composite or container #GtkActor subclass can delegate the
* layouting of its children to a #GtkLayoutManager.
*
* Gtk provides some simple #GtkLayoutManager sub-classes, like
* #GtkBoxLayout and #GtkBinLayout.
*
* <refsect2 id="GtkLayoutManager-use-in-Actor">
* <title>Using a Layout Manager inside an Actor</title>
* <para>In order to use a #GtkLayoutManager inside a #GtkActor
* sub-class you should invoke _gtk_layout_manager_get_preferred_size()
* inside the #GtkActorClass.get_preferred_size() virtual function and
* _gtk_layout_manager_get_preferred_height() inside the
* #GtkActorClass.get_preferred_height() virtual functions implementation.
* You should also call _gtk_layout_manager_allocate() inside the
* implementation of the #GtkActorClass.allocate() virtual function.</para>
* <para>In order to receive notifications for changes in the layout
* manager policies you should also connect to the
* #GtkLayoutManager::layout-changed signal and queue a relayout
* on your actor. The following code should be enough if the actor
* does not need to perform specific operations whenever a layout
* manager changes:</para>
* <informalexample><programlisting>
* g_signal_connect_swapped (layout_manager,
* "layout-changed",
* G_CALLBACK (_gtk_actor_queue_relayout),
* actor);
* </programlisting></informalexample>
* </refsect2>
*
* <refsect2 id="GtkLayoutManager-implementation">
* <title>Implementing a GtkLayoutManager</title>
* <para>The implementation of a layout manager does not differ from
* the implementation of the size requisition and allocation bits of
* #GtkActor, so you should read the relative documentation
* <link linkend="_gtk-subclassing-GtkActor">for subclassing
* GtkActor</link>.</para>
* <para>The layout manager implementation can hold a back pointer
* to the #GtkContainer by implementing the
* <function>set_container()</function> virtual function. The layout manager
* should not hold a real reference (i.e. call g_object_ref()) on the
* container actor, to avoid reference cycles.</para>
* <para>If a layout manager has properties affecting the layout
* policies then it should emit the #GtkLayoutManager::layout-changed
* signal on itself by using the _gtk_layout_manager_layout_changed()
* function whenever one of these properties changes.</para>
* </refsect2>
*
* <refsect2 id="GtkLayoutManager-animation">
* <title>Animating a GtkLayoutManager</title>
* <para>A layout manager is used to let a #GtkContainer take complete
* ownership over the layout (that is: the position and sizing) of its
* children; this means that using the Gtk animation API, like
* _gtk_actor_animate(), to animate the position and sizing of a child of
* a layout manager it is not going to work properly, as the animation will
* automatically override any setting done by the layout manager
* itself.</para>
* <para>It is possible for a #GtkLayoutManager sub-class to animate its
* children layout by using the base class animation support. The
* #GtkLayoutManager animation support consists of three virtual
* functions: #GtkLayoutManagerClass.begin_animation(),
* #GtkLayoutManagerClass.get_animation_progress(), and
* #GtkLayoutManagerClass.end_animation().</para>
* <variablelist>
* <varlistentry>
* <term><function>begin_animation (duration, easing)</function></term>
* <listitem><para>This virtual function is invoked when the layout
* manager should begin an animation. The implementation should set up
* the state for the animation and create the ancillary objects for
* animating the layout. The default implementation creates a
* #GtkTimeline for the given duration and a #GtkAlpha binding
* the timeline to the given easing mode. This function returns a
* #GtkAlpha which should be used to control the animation from
* the caller perspective.</para></listitem>
* </varlistentry>
* <varlistentry>
* <term><function>get_animation_progress()</function></term>
* <listitem><para>This virtual function should be invoked when animating
* a layout manager. It returns the progress of the animation, using the
* same semantics as the #GtkAlpha:alpha value.</para></listitem>
* </varlistentry>
* <varlistentry>
* <term><function>end_animation()</function></term>
* <listitem><para>This virtual function is invoked when the animation of
* a layout manager ends, and it is meant to be used for bookkeeping the
* objects created in the <function>begin_animation()</function>
* function. The default implementation will call it implicitly when the
* timeline is complete.</para></listitem>
* </varlistentry>
* </variablelist>
* <para>The simplest way to animate a layout is to create a #GtkTimeline
* inside the <function>begin_animation()</function> virtual function, along
* with a #GtkAlpha, and for each #GtkTimeline::new-frame signal
* emission call _gtk_layout_manager_layout_changed(), which will cause a
* relayout. The #GtkTimeline::completed signal emission should cause
* _gtk_layout_manager_end_animation() to be called. The default
* implementation provided internally by #GtkLayoutManager does exactly
* this, so most sub-classes should either not override any animation-related
* virtual function or simply override #GtkLayoutManagerClass.begin_animation()
* and #GtkLayoutManagerClass.end_animation() to set up ad hoc state, and then
* chain up to the parent's implementation.</para>
* <example id="example-GtkLayoutManager-animation">
* <title>Animation of a Layout Manager</title>
* <para>The code below shows how a #GtkLayoutManager sub-class should
* provide animating the allocation of its children from within the
* #GtkLayoutManagerClass.allocate() virtual function implementation. The
* animation is computed between the last stable allocation performed
* before the animation started and the desired final allocation.</para>
* <para>The <varname>is_animating</varname> variable is stored inside the
* #GtkLayoutManager sub-class and it is updated by overriding the
* #GtkLayoutManagerClass.begin_animation() and the
* #GtkLayoutManagerClass.end_animation() virtual functions and chaining up
* to the base class implementation.</para>
* <para>The last stable allocation is stored within a #GtkLayoutMeta
* sub-class used by the implementation.</para>
* <programlisting>
* static void
* my_layout_manager_allocate (GtkLayoutManager *manager,
* GtkContainer *container,
* const GtkActorBox *allocation,
* GtkAllocationFlags flags)
* {
* MyLayoutManager *self = MY_LAYOUT_MANAGER (manager);
* GtkActor *child;
*
* for (child = _gtk_actor_get_first_child (GTK_ACTOR (container));
* child != NULL;
* child = _gtk_actor_get_next_sibling (child))
* {
* GtkLayoutMeta *meta;
* MyLayoutMeta *my_meta;
*
* /&ast; retrieve the layout meta-object &ast;/
* meta = _gtk_layout_manager_get_child_meta (manager,
* container,
* child);
* my_meta = MY_LAYOUT_META (meta);
*
* /&ast; compute the desired allocation for the child &ast;/
* compute_allocation (self, my_meta, child,
* allocation, flags,
* &amp;child_box);
*
* /&ast; this is the additional code that deals with the animation
* &ast; of the layout manager
* &ast;/
* if (!self-&gt;is_animating)
* {
* /&ast; store the last stable allocation for later use &ast;/
* my_meta-&gt;last_alloc = _gtk_actor_box_copy (&amp;child_box);
* }
* else
* {
* GtkActorBox end = { 0, };
* gdouble p;
*
* /&ast; get the progress of the animation &ast;/
* p = _gtk_layout_manager_get_animation_progress (manager);
*
* if (my_meta-&gt;last_alloc != NULL)
* {
* /&ast; copy the desired allocation as the final state &ast;/
* end = child_box;
*
* /&ast; then interpolate the initial and final state
* &ast; depending on the progress of the animation,
* &ast; and put the result inside the box we will use
* &ast; to allocate the child
* &ast;/
* _gtk_actor_box_interpolate (my_meta-&gt;last_alloc,
* &amp;end,
* p,
* &amp;child_box);
* }
* else
* {
* /&ast; if there is no stable allocation then the child was
* &ast; added while animating; one possible course of action
* &ast; is to just bail out and fall through to the allocation
* &ast; to position the child directly at its final state
* &ast;/
* my_meta-&gt;last_alloc =
* _gtk_actor_box_copy (&amp;child_box);
* }
* }
*
* /&ast; allocate the child &ast;/
* _gtk_actor_allocate (child, &child_box, flags);
* }
* }
* </programlisting>
* </example>
* <para>Sub-classes of #GtkLayoutManager that support animations of the
* layout changes should call _gtk_layout_manager_begin_animation()
* whenever a layout property changes value, e.g.:</para>
* <informalexample>
* <programlisting>
* if (self->orientation != new_orientation)
* {
* GtkLayoutManager *manager;
*
* self->orientation = new_orientation;
*
* manager = GTK_LAYOUT_MANAGER (self);
* _gtk_layout_manager_layout_changed (manager);
* _gtk_layout_manager_begin_animation (manager, 500, GTK_LINEAR);
*
* g_object_notify (G_OBJECT (self), "orientation");
* }
* </programlisting>
* </informalexample>
* <para>The code above will animate a change in the
* <varname>orientation</varname> layout property of a layout manager.</para>
* </refsect2>
*
* <refsect2 id="_gtk-layout-properties">
* <title>Layout Properties</title>
* <para>If a layout manager has layout properties, that is properties that
* should exist only as the result of the presence of a specific (layout
* manager, container actor, child actor) combination, and it wishes to store
* those properties inside a #GtkLayoutMeta, then it should override the
* #GtkLayoutManagerClass.get_child_meta_type() virtual function to return
* the #GType of the #GtkLayoutMeta sub-class used to store the layout
* properties; optionally, the #GtkLayoutManager sub-class might also
* override the #GtkLayoutManagerClass.create_child_meta() virtual function
* to control how the #GtkLayoutMeta instance is created, otherwise the
* default implementation will be equivalent to:</para>
* <informalexample><programlisting>
* GtkLayoutManagerClass *klass;
* GType meta_type;
*
* klass = GTK_LAYOUT_MANAGER_GET_CLASS (manager);
* meta_type = klass->get_child_meta_type (manager);
*
* return g_object_new (meta_type,
* "manager", manager,
* "container", container,
* "actor", actor,
* NULL);
* </programlisting></informalexample>
* <para>Where <varname>manager</varname> is the #GtkLayoutManager,
* <varname>container</varname> is the #GtkContainer using the
* #GtkLayoutManager and <varname>actor</varname> is the #GtkActor
* child of the #GtkContainer.</para>
* </refsect2>
*
* <refsect2 id="_gtk-layout-script">
* <title>Using GtkLayoutManager with GtkScript</title>
* <para>#GtkLayoutManager instance can be created in the same way
* as other objects in #GtkScript; properties can be set using the
* common syntax.</para>
* <para>Layout properties can be set on children of a container with
* a #GtkLayoutManager using the <emphasis>layout::</emphasis>
* modifier on the property name, for instance:</para>
* <informalexample><programlisting>
* {
* "type" : "GtkBox",
* "layout-manager" : { "type" : "GtkTableLayout" },
* "children" : [
* {
* "type" : "GtkTexture",
* "filename" : "image-00.png",
*
* "layout::row" : 0,
* "layout::column" : 0,
* "layout::x-align" : "left",
* "layout::y-align" : "center",
* "layout::x-expand" : true,
* "layout::y-expand" : true
* },
* {
* "type" : "GtkTexture",
* "filename" : "image-01.png",
*
* "layout::row" : 0,
* "layout::column" : 1,
* "layout::x-align" : "right",
* "layout::y-align" : "center",
* "layout::x-expand" : true,
* "layout::y-expand" : true
* }
* ]
* }
* </programlisting></informalexample>
* </refsect2>
*
* #GtkLayoutManager is available since Gtk 1.2
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "gtklayoutmanagerprivate.h"
#define LAYOUT_MANAGER_WARN_NOT_IMPLEMENTED(m,method) G_STMT_START { \
GObject *_obj = G_OBJECT (m); \
g_warning ("Layout managers of type %s do not implement " \
"the GtkLayoutManager::%s method", \
G_OBJECT_TYPE_NAME (_obj), \
(method)); } G_STMT_END
struct _GtkLayoutManagerPrivate
{
GtkActor *actor;
};
G_DEFINE_ABSTRACT_TYPE (GtkLayoutManager,
_gtk_layout_manager,
G_TYPE_INITIALLY_UNOWNED);
static void
layout_manager_real_get_preferred_size (GtkLayoutManager *manager,
GtkOrientation orientation,
gfloat for_size,
gfloat *min_size_p,
gfloat *nat_size_p)
{
LAYOUT_MANAGER_WARN_NOT_IMPLEMENTED (manager, "get_preferred_size");
*min_size_p = 0.0;
*nat_size_p = 0.0;
}
static void
layout_manager_real_allocate (GtkLayoutManager *manager,
const cairo_matrix_t *transform,
gfloat width,
gfloat height)
{
LAYOUT_MANAGER_WARN_NOT_IMPLEMENTED (manager, "allocate");
}
static void
_gtk_layout_manager_class_init (GtkLayoutManagerClass *klass)
{
g_type_class_add_private (klass, sizeof (GtkLayoutManagerPrivate));
klass->get_preferred_size = layout_manager_real_get_preferred_size;
klass->allocate = layout_manager_real_allocate;
}
static void
_gtk_layout_manager_init (GtkLayoutManager *manager)
{
manager->priv =
G_TYPE_INSTANCE_GET_PRIVATE (manager, GTK_TYPE_LAYOUT_MANAGER,
GtkLayoutManagerPrivate);
}
/**
* _gtk_layout_manager_get_preferred_size:
* @manager: a #GtkLayoutManager
* @orientation: orientation to query size for
* @for_size: the size in the opposite direction, or -1
* @min_width_p: (out) (allow-none): return location for the minimum width
* of the layout, or %NULL
* @nat_width_p: (out) (allow-none): return location for the natural width
* of the layout, or %NULL
*
* Computes the minimum and natural widths of the @container according
* to @manager.
*
* See also _gtk_actor_get_preferred_size()
*
* Since: 1.2
*/
void
_gtk_layout_manager_get_preferred_size (GtkLayoutManager *manager,
GtkOrientation orientation,
gfloat for_size,
gfloat *min_size_p,
gfloat *nat_size_p)
{
GtkLayoutManagerClass *klass;
gfloat ignore;
g_return_if_fail (GTK_IS_LAYOUT_MANAGER (manager));
if (min_size_p == NULL)
min_size_p = &ignore;
if (nat_size_p == NULL)
nat_size_p = &ignore;
klass = GTK_LAYOUT_MANAGER_GET_CLASS (manager);
klass->get_preferred_size (manager,
orientation,
for_size,
min_size_p,
nat_size_p);
}
/**
* _gtk_layout_manager_allocate:
* @manager: a #GtkLayoutManager
* @transform: transformation to apply to all children
* @width: width of allocation area
* @height: height of allocation area
*
* Allocates the children to the area given with @width and @height.
*
* See also _gtk_actor_allocate()
*
* Since: 1.2
*/
void
_gtk_layout_manager_allocate (GtkLayoutManager *manager,
const cairo_matrix_t *transform,
gfloat width,
gfloat height)
{
GtkLayoutManagerClass *klass;
g_return_if_fail (GTK_IS_LAYOUT_MANAGER (manager));
g_return_if_fail (transform != NULL);
g_return_if_fail (width >= 0.0);
g_return_if_fail (height >= 0.0);
klass = GTK_LAYOUT_MANAGER_GET_CLASS (manager);
klass->allocate (manager, transform, width, height);
}
/**
* _gtk_layout_manager_layout_changed:
* @manager: a #GtkLayoutManager
*
* Signals Emits the #GtkLayoutManager::layout-changed signal on @manager
*
* This function should only be called by implementations of the
* #GtkLayoutManager class
*
* Since: 1.2
*/
void
_gtk_layout_manager_layout_changed (GtkLayoutManager *manager)
{
GtkLayoutManagerPrivate *priv;
g_return_if_fail (GTK_IS_LAYOUT_MANAGER (manager));
priv = manager->priv;
if (priv->actor)
_gtk_actor_layout_manager_changed (priv->actor);
}
/*<private>
* Called from GtkActor when the layout manager is set.
*/
void
_gtk_layout_manager_set_actor (GtkLayoutManager *manager,
GtkActor *actor)
{
g_return_if_fail (GTK_IS_LAYOUT_MANAGER (manager));
g_return_if_fail (actor == NULL || GTK_IS_ACTOR (actor));
manager->priv->actor = actor;
}
GtkActor *
_gtk_layout_manager_get_actor (GtkLayoutManager *manager)
{
g_return_val_if_fail (GTK_IS_LAYOUT_MANAGER (manager), NULL);
return manager->priv->actor;
}

View File

@@ -0,0 +1,134 @@
/*
* Gtk.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright (C) 2009 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author:
* Emmanuele Bassi <ebassi@linux.intel.com>
*/
#ifndef __GTK_LAYOUT_MANAGER_PRIVATE_H__
#define __GTK_LAYOUT_MANAGER_PRIVATE_H__
#include <gtk/actors/gtkactorprivate.h>
G_BEGIN_DECLS
#define GTK_TYPE_LAYOUT_MANAGER (_gtk_layout_manager_get_type ())
#define GTK_LAYOUT_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_LAYOUT_MANAGER, GtkLayoutManager))
#define GTK_IS_LAYOUT_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_LAYOUT_MANAGER))
#define GTK_LAYOUT_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_LAYOUT_MANAGER, GtkLayoutManagerClass))
#define GTK_IS_LAYOUT_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_LAYOUT_MANAGER))
#define GTK_LAYOUT_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_LAYOUT_MANAGER, GtkLayoutManagerClass))
typedef struct _GtkLayoutManagerPrivate GtkLayoutManagerPrivate;
typedef struct _GtkLayoutManagerClass GtkLayoutManagerClass;
/**
* GtkLayoutManager:
*
* The #GtkLayoutManager structure contains only private data
* and should be accessed using the provided API
*
* Since: 1.2
*/
struct _GtkLayoutManager
{
/*< private >*/
GInitiallyUnowned parent_instance;
GtkLayoutManagerPrivate *priv;
};
/**
* GtkLayoutManagerClass:
* @get_preferred_width: virtual function; override to provide a preferred
* width for the layout manager. See also the get_preferred_width()
* virtual function in #GtkActor
* @get_preferred_height: virtual function; override to provide a preferred
* height for the layout manager. See also the get_preferred_height()
* virtual function in #GtkActor
* @allocate: virtual function; override to allocate the children of the
* layout manager. See also the allocate() virtual function in
* #GtkActor
* @set_container: virtual function; override to set a back pointer
* on the #GtkContainer using the layout manager. The implementation
* should not take a reference on the container, but just take a weak
* reference, to avoid potential leaks due to reference cycles
* @get_child_meta_type: virtual function; override to return the #GType
* of the #GtkLayoutMeta sub-class used by the #GtkLayoutManager
* @create_child_meta: virtual function; override to create a
* #GtkLayoutMeta instance associated to a #GtkContainer and a
* child #GtkActor, used to maintain layout manager specific properties
* @begin_animation: virtual function; override to control the animation
* of a #GtkLayoutManager with the given duration and easing mode.
* This virtual function is deprecated, and it should not be overridden
* in newly written code.
* @end_animation: virtual function; override to end an animation started
* by _gtk_layout_manager_begin_animation(). This virtual function is
* deprecated, and it should not be overriden in newly written code.
* @get_animation_progress: virtual function; override to control the
* progress of the animation of a #GtkLayoutManager. This virtual
* function is deprecated, and it should not be overridden in newly written
* code.
* @layout_changed: class handler for the #GtkLayoutManager::layout-changed
* signal
*
* The #GtkLayoutManagerClass structure contains only private
* data and should be accessed using the provided API
*
* Since: 1.2
*/
struct _GtkLayoutManagerClass
{
/*< private >*/
GInitiallyUnownedClass parent_class;
/*< public >*/
void (* get_preferred_size) (GtkLayoutManager *manager,
GtkOrientation orientation,
gfloat for_size,
gfloat *min_size_p,
gfloat *nat_size_p);
void (* allocate) (GtkLayoutManager *manager,
const cairo_matrix_t *transform,
gfloat width,
gfloat height);
};
GType _gtk_layout_manager_get_type (void) G_GNUC_CONST;
void _gtk_layout_manager_get_preferred_size (GtkLayoutManager *manager,
GtkOrientation orientation,
gfloat for_size,
gfloat *min_size_p,
gfloat *nat_size_p);
void _gtk_layout_manager_allocate (GtkLayoutManager *manager,
const cairo_matrix_t *transform,
gfloat width,
gfloat height);
void _gtk_layout_manager_set_actor (GtkLayoutManager *manager,
GtkActor *actor);
GtkActor * _gtk_layout_manager_get_actor (GtkLayoutManager *manager);
void _gtk_layout_manager_layout_changed (GtkLayoutManager *manager);
G_END_DECLS
#endif /* __GTK_LAYOUT_MANAGER_PRIVATE_H__ */

225
gtk/actors/gtkwidgetactor.c Normal file
View File

@@ -0,0 +1,225 @@
/*
* Copyright © 2012 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#include "config.h"
#include "gtkwidgetactorprivate.h"
#include "gtkwidgetprivate.h"
#include <math.h>
struct _GtkWidgetActorPrivate {
gpointer dummy;
};
G_DEFINE_TYPE (GtkWidgetActor, _gtk_widget_actor, GTK_TYPE_CSS_BOX)
static void
gtk_widget_actor_real_queue_redraw (GtkActor *actor,
const cairo_rectangle_t *box)
{
GtkWidget *widget;
int x, y, w, h;
if (_gtk_actor_get_parent (actor))
{
GTK_ACTOR_CLASS (_gtk_widget_actor_parent_class)->queue_redraw (actor, box);
return;
}
widget = _gtk_actor_get_widget (actor);
x = floor (box->x);
y = floor (box->y);
w = ceil (box->x + box->width) - x;
h = ceil (box->y + box->height) - y;
if (!gtk_widget_get_has_window (widget))
{
GtkAllocation allocation;
gtk_widget_get_allocation (widget, &allocation);
x += allocation.x;
y += allocation.y;
}
gtk_widget_queue_draw_area (widget, x, y, w, h);
}
static void
gtk_widget_actor_real_style_updated (GtkCssActor *actor,
const GtkBitmask *changed)
{
_gtk_widget_emit_style_updated (_gtk_actor_get_widget (GTK_ACTOR (actor)));
GTK_CSS_ACTOR_CLASS (_gtk_widget_actor_parent_class)->style_updated (actor, changed);
}
static void
_gtk_widget_actor_class_init (GtkWidgetActorClass *klass)
{
GtkActorClass *actor_class = GTK_ACTOR_CLASS (klass);
GtkCssActorClass *css_actor_class = GTK_CSS_ACTOR_CLASS (klass);
#if 0
GObjectClass *object_class = G_OBJECT_CLASS (klass);
actor_class->parent_set = gtk_widget_actor_real_parent_set;
actor_class->show = gtk_css_box_real_show;
actor_class->hide = gtk_css_box_real_hide;
actor_class->map = gtk_css_box_real_map;
actor_class->unmap = gtk_css_box_real_unmap;
actor_class->draw = gtk_css_box_real_draw;
actor_class->parent_set = gtk_css_box_real_parent_set;
actor_class->get_preferred_size = gtk_css_box_real_get_preferred_size;
actor_class->allocate = gtk_css_box_real_allocate;
#endif
actor_class->queue_redraw = gtk_widget_actor_real_queue_redraw;
css_actor_class->style_updated = gtk_widget_actor_real_style_updated;
g_type_class_add_private (klass, sizeof (GtkWidgetActorPrivate));
}
static void
_gtk_widget_actor_init (GtkWidgetActor *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
GTK_TYPE_WIDGET_ACTOR,
GtkWidgetActorPrivate);
}
void
_gtk_widget_actor_show (GtkActor *actor)
{
g_return_if_fail (GTK_IS_WIDGET_ACTOR (actor));
GTK_ACTOR_CLASS (_gtk_widget_actor_parent_class)->show (actor);
}
void
_gtk_widget_actor_hide (GtkActor *actor)
{
g_return_if_fail (GTK_IS_WIDGET_ACTOR (actor));
GTK_ACTOR_CLASS (_gtk_widget_actor_parent_class)->hide (actor);
}
void
_gtk_widget_actor_map (GtkActor *actor)
{
g_return_if_fail (GTK_IS_WIDGET_ACTOR (actor));
GTK_ACTOR_CLASS (_gtk_widget_actor_parent_class)->map (actor);
}
void
_gtk_widget_actor_unmap (GtkActor *actor)
{
g_return_if_fail (GTK_IS_WIDGET_ACTOR (actor));
GTK_ACTOR_CLASS (_gtk_widget_actor_parent_class)->unmap (actor);
}
void
_gtk_widget_actor_realize (GtkActor *actor)
{
g_return_if_fail (GTK_IS_WIDGET_ACTOR (actor));
GTK_ACTOR_CLASS (_gtk_widget_actor_parent_class)->realize (actor);
}
void
_gtk_widget_actor_unrealize (GtkActor *actor)
{
g_return_if_fail (GTK_IS_WIDGET_ACTOR (actor));
GTK_ACTOR_CLASS (_gtk_widget_actor_parent_class)->unrealize (actor);
}
GtkSizeRequestMode
_gtk_widget_actor_get_request_mode (GtkActor *actor)
{
g_return_val_if_fail (GTK_IS_WIDGET_ACTOR (actor), GTK_SIZE_REQUEST_CONSTANT_SIZE);
return GTK_ACTOR_CLASS (_gtk_widget_actor_parent_class)->get_request_mode (actor);
}
void
_gtk_widget_actor_get_preferred_size (GtkActor *actor,
GtkOrientation orientation,
gfloat for_size,
gfloat *min_size_p,
gfloat *natural_size_p)
{
g_return_if_fail (GTK_IS_WIDGET_ACTOR (actor));
GTK_ACTOR_CLASS (_gtk_widget_actor_parent_class)->get_preferred_size (actor,
orientation,
for_size,
min_size_p,
natural_size_p);
}
void
_gtk_widget_actor_allocate (GtkActor *actor,
double x,
double y,
double width,
double height)
{
cairo_matrix_t position;
g_return_if_fail (GTK_IS_WIDGET_ACTOR (actor));
cairo_matrix_init_translate (&position, x, y);
GTK_ACTOR_CLASS (_gtk_widget_actor_parent_class)->allocate (actor,
&position,
width, height);
}
void
_gtk_widget_actor_screen_changed (GtkActor *actor,
GdkScreen *new_screen,
GdkScreen *old_screen)
{
g_return_if_fail (GTK_IS_WIDGET_ACTOR (actor));
g_return_if_fail (new_screen == NULL || GDK_IS_SCREEN (new_screen));
g_return_if_fail (old_screen == NULL || GDK_IS_SCREEN (old_screen));
if (new_screen == NULL)
new_screen = gdk_screen_get_default ();
if (old_screen == NULL)
old_screen = gdk_screen_get_default ();
if (new_screen == old_screen)
return;
GTK_ACTOR_GET_CLASS (actor)->screen_changed (actor, new_screen, old_screen);
for (actor = _gtk_actor_get_first_child (actor);
actor != NULL;
actor = _gtk_actor_get_next_sibling (actor))
{
if (GTK_IS_WIDGET_ACTOR (actor))
continue;
_gtk_widget_actor_screen_changed (actor, new_screen, old_screen);
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright © 2012 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Authors: Benjamin Otte <otte@gnome.org>
*/
#ifndef __GTK_WIDGET_ACTOR_PRIVATE_H__
#define __GTK_WIDGET_ACTOR_PRIVATE_H__
#include <gtk/actors/gtkcssboxprivate.h>
G_BEGIN_DECLS
#define GTK_TYPE_WIDGET_ACTOR (_gtk_widget_actor_get_type ())
#define GTK_WIDGET_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_WIDGET_ACTOR, GtkWidgetActor))
#define GTK_WIDGET_ACTOR_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_WIDGET_ACTOR, GtkWidgetActorClass))
#define GTK_IS_WIDGET_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_WIDGET_ACTOR))
#define GTK_IS_WIDGET_ACTOR_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_WIDGET_ACTOR))
#define GTK_WIDGET_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_WIDGET_ACTOR, GtkWidgetActorClass))
typedef struct _GtkWidgetActor GtkWidgetActor;
typedef struct _GtkWidgetActorPrivate GtkWidgetActorPrivate;
typedef struct _GtkWidgetActorClass GtkWidgetActorClass;
struct _GtkWidgetActor
{
GtkCssBox parent;
GtkWidgetActorPrivate *priv;
};
struct _GtkWidgetActorClass
{
GtkCssBoxClass parent_class;
};
GType _gtk_widget_actor_get_type (void) G_GNUC_CONST;
void _gtk_widget_actor_show (GtkActor *actor);
void _gtk_widget_actor_hide (GtkActor *actor);
void _gtk_widget_actor_map (GtkActor *actor);
void _gtk_widget_actor_unmap (GtkActor *actor);
void _gtk_widget_actor_realize (GtkActor *actor);
void _gtk_widget_actor_unrealize (GtkActor *actor);
GtkSizeRequestMode _gtk_widget_actor_get_request_mode (GtkActor *self);
void _gtk_widget_actor_get_preferred_size (GtkActor *self,
GtkOrientation orientation,
gfloat for_size,
gfloat *min_size_p,
gfloat *natural_size_p);
void _gtk_widget_actor_allocate (GtkActor *actor,
double x,
double y,
double width,
double height);
void _gtk_widget_actor_screen_changed (GtkActor *actor,
GdkScreen *new_screen,
GdkScreen *old_screen);
G_END_DECLS
#endif /* __GTK_WIDGET_ACTOR_PRIVATE_H__ */

View File

@@ -19,7 +19,10 @@
#include "gtkcssmatcherprivate.h"
#include "gtkcontainer.h"
#include "gtkwidget.h"
#include "gtkwidgetpath.h"
#include "actors/gtkwidgetactorprivate.h"
/* GTK_CSS_MATCHER_WIDGET_PATH */
@@ -422,3 +425,204 @@ _gtk_css_matcher_superset_init (GtkCssMatcher *matcher,
matcher->superset.relevant = relevant;
}
/* GTK_CSS_MATCHER_WIDGET_ACTOR */
static gboolean
gtk_css_matcher_actor_get_parent (GtkCssMatcher *matcher,
const GtkCssMatcher *child)
{
GtkActor *parent;
for (parent = _gtk_actor_get_parent (child->actor.actor);
parent != NULL;
parent = _gtk_actor_get_parent (parent))
{
if (GTK_IS_CSS_BOX (parent))
{
if (_gtk_css_matcher_actor_init (matcher, GTK_CSS_BOX (parent)))
return TRUE;
if (_gtk_css_matcher_init (matcher,
gtk_widget_get_path (_gtk_actor_get_widget (parent)),
0))
return TRUE;
return FALSE;
}
}
return FALSE;
}
static gboolean
gtk_css_matcher_actor_get_previous (GtkCssMatcher *matcher,
const GtkCssMatcher *next)
{
GtkActor *prev;
for (prev = _gtk_actor_get_previous_sibling (next->actor.actor);
prev != NULL;
prev = _gtk_actor_get_previous_sibling (prev))
{
if (GTK_IS_CSS_BOX (prev))
{
if (_gtk_css_matcher_actor_init (matcher, GTK_CSS_BOX (prev)))
return TRUE;
if (_gtk_css_matcher_init (matcher,
gtk_widget_get_path (_gtk_actor_get_widget (prev)),
0))
return TRUE;
return FALSE;
}
}
return FALSE;
}
static GtkStateFlags
gtk_css_matcher_actor_get_state (const GtkCssMatcher *matcher)
{
return _gtk_css_box_get_effective_state (GTK_CSS_BOX (matcher->actor.actor));
}
static gboolean
gtk_css_matcher_actor_has_type (const GtkCssMatcher *matcher,
GType type)
{
GtkWidget *widget;
widget = _gtk_actor_get_widget (matcher->actor.actor);
if (widget == NULL)
return FALSE;
return g_type_is_a (G_OBJECT_TYPE (widget), type);
}
static gboolean
gtk_css_matcher_actor_has_class (const GtkCssMatcher *matcher,
GQuark class_name)
{
return _gtk_css_box_has_class (GTK_CSS_BOX (matcher->actor.actor), g_quark_to_string (class_name));
}
static gboolean
gtk_css_matcher_actor_has_id (const GtkCssMatcher *matcher,
const char *id)
{
const char *box_id;
box_id = _gtk_css_box_get_id (GTK_CSS_BOX (matcher->actor.actor));
if (box_id == NULL)
return FALSE;
return g_ascii_strcasecmp (box_id, id) == 0;
}
static gboolean
gtk_css_matcher_actor_has_regions (const GtkCssMatcher *matcher)
{
return FALSE;
}
static gboolean
gtk_css_matcher_actor_has_region (const GtkCssMatcher *matcher,
const char *region,
GtkRegionFlags flags)
{
return FALSE;
}
static gboolean
gtk_css_matcher_actor_has_position (const GtkCssMatcher *matcher,
gboolean forward,
int a,
int b)
{
GtkActor *actor;
int x;
x = 0;
if (forward)
{
for (actor = matcher->actor.actor;
actor;
actor = _gtk_actor_get_previous_sibling (actor))
{
if (GTK_IS_CSS_BOX (actor))
x++;
}
}
else
{
for (actor = matcher->actor.actor;
actor;
actor = _gtk_actor_get_next_sibling (actor))
{
if (GTK_IS_CSS_BOX (actor))
x++;
}
}
x -= b;
if (a == 0)
return x == 0;
if (x % a)
return FALSE;
return x / a > 0;
}
static const GtkCssMatcherClass GTK_CSS_MATCHER_ACTOR = {
gtk_css_matcher_actor_get_parent,
gtk_css_matcher_actor_get_previous,
gtk_css_matcher_actor_get_state,
gtk_css_matcher_actor_has_type,
gtk_css_matcher_actor_has_class,
gtk_css_matcher_actor_has_id,
gtk_css_matcher_actor_has_regions,
gtk_css_matcher_actor_has_region,
gtk_css_matcher_actor_has_position,
FALSE
};
static gboolean
actor_needs_to_use_widget_path (GtkActor *actor)
{
GtkWidget *widget, *parent;
if (!GTK_IS_WIDGET_ACTOR (actor))
return FALSE;
widget = _gtk_actor_get_widget (actor);
if (widget == NULL)
return FALSE;
parent = gtk_widget_get_parent (widget);
if (parent == NULL)
return FALSE;
if (GTK_CONTAINER_GET_CLASS (parent)->get_path_for_child ==
GTK_CONTAINER_CLASS(g_type_class_peek (GTK_TYPE_CONTAINER))->get_path_for_child)
return FALSE;
return TRUE;
}
gboolean
_gtk_css_matcher_actor_init (GtkCssMatcher *matcher,
GtkCssBox *box)
{
g_return_val_if_fail (matcher != NULL, FALSE);
g_return_val_if_fail (GTK_IS_CSS_BOX (box), FALSE);
if (actor_needs_to_use_widget_path (GTK_ACTOR (box)))
return FALSE;
matcher->actor.klass = &GTK_CSS_MATCHER_ACTOR;
matcher->actor.actor = GTK_ACTOR (box);
return TRUE;
}

View File

@@ -21,10 +21,12 @@
#include <gtk/gtkenums.h>
#include <gtk/gtktypes.h>
#include "gtk/gtkcsstypesprivate.h"
#include "gtk/actors/gtkcssboxprivate.h"
G_BEGIN_DECLS
typedef union _GtkCssMatcher GtkCssMatcher;
typedef struct _GtkCssMatcherActor GtkCssMatcherActor;
typedef struct _GtkCssMatcherSuperset GtkCssMatcherSuperset;
typedef struct _GtkCssMatcherWidgetPath GtkCssMatcherWidgetPath;
typedef struct _GtkCssMatcherClass GtkCssMatcherClass;
@@ -67,10 +69,16 @@ struct _GtkCssMatcherSuperset {
GtkCssChange relevant;
};
struct _GtkCssMatcherActor {
const GtkCssMatcherClass *klass;
GtkActor *actor;
};
union _GtkCssMatcher {
const GtkCssMatcherClass *klass;
GtkCssMatcherWidgetPath path;
GtkCssMatcherSuperset superset;
GtkCssMatcherActor actor;
};
gboolean _gtk_css_matcher_init (GtkCssMatcher *matcher,
@@ -80,6 +88,8 @@ void _gtk_css_matcher_any_init (GtkCssMatcher *match
void _gtk_css_matcher_superset_init (GtkCssMatcher *matcher,
const GtkCssMatcher *subset,
GtkCssChange relevant);
gboolean _gtk_css_matcher_actor_init (GtkCssMatcher *matcher,
GtkCssBox *box) G_GNUC_WARN_UNUSED_RESULT;
static inline gboolean

View File

@@ -712,6 +712,15 @@ border_image_width_parse (GtkCssStyleProperty *property,
FALSE);
}
static GtkCssValue *
minmax_parse (GtkCssStyleProperty *property,
GtkCssParser *parser)
{
return _gtk_css_number_value_parse (parser,
GTK_CSS_PARSE_LENGTH
| GTK_CSS_POSITIVE_ONLY);
}
static GtkCssValue *
transition_property_parse_one (GtkCssParser *parser)
{
@@ -1283,6 +1292,41 @@ _gtk_css_style_property_init_properties (void)
_gtk_css_number_value_new (1, GTK_CSS_NUMBER),
_gtk_css_number_value_new (1, GTK_CSS_NUMBER)));
gtk_css_style_property_register ("min-width",
GTK_CSS_PROPERTY_MIN_WIDTH,
G_TYPE_NONE,
GTK_STYLE_PROPERTY_ANIMATED,
minmax_parse,
NULL,
NULL,
_gtk_css_number_value_new (0, GTK_CSS_PX));
gtk_css_style_property_register ("max-width",
GTK_CSS_PROPERTY_MAX_WIDTH,
G_TYPE_NONE,
GTK_STYLE_PROPERTY_ANIMATED,
minmax_parse,
NULL,
NULL,
/* XXX: Should be 'none' */
_gtk_css_number_value_new (G_MAXDOUBLE, GTK_CSS_PX));
gtk_css_style_property_register ("min-height",
GTK_CSS_PROPERTY_MIN_HEIGHT,
G_TYPE_NONE,
GTK_STYLE_PROPERTY_ANIMATED,
minmax_parse,
NULL,
NULL,
_gtk_css_number_value_new (0, GTK_CSS_PX));
gtk_css_style_property_register ("max-height",
GTK_CSS_PROPERTY_MAX_HEIGHT,
G_TYPE_NONE,
GTK_STYLE_PROPERTY_ANIMATED,
minmax_parse,
NULL,
NULL,
/* XXX: Should be 'none' */
_gtk_css_number_value_new (G_MAXDOUBLE, GTK_CSS_PX));
gtk_css_style_property_register ("transition-property",
GTK_CSS_PROPERTY_TRANSITION_PROPERTY,
G_TYPE_NONE,

View File

@@ -120,6 +120,10 @@ enum { /*< skip >*/
GTK_CSS_PROPERTY_BORDER_IMAGE_REPEAT,
GTK_CSS_PROPERTY_BORDER_IMAGE_SLICE,
GTK_CSS_PROPERTY_BORDER_IMAGE_WIDTH,
GTK_CSS_PROPERTY_MIN_WIDTH,
GTK_CSS_PROPERTY_MAX_WIDTH,
GTK_CSS_PROPERTY_MIN_HEIGHT,
GTK_CSS_PROPERTY_MAX_HEIGHT,
GTK_CSS_PROPERTY_TRANSITION_PROPERTY,
GTK_CSS_PROPERTY_TRANSITION_DURATION,
GTK_CSS_PROPERTY_TRANSITION_TIMING_FUNCTION,

View File

@@ -24,15 +24,21 @@
#include "config.h"
#include <math.h>
#include <string.h>
#include "gtkprogressbar.h"
#include "gtkorientableprivate.h"
#include "gtkprivate.h"
#include "gtkintl.h"
#include "gtkwidgetprivate.h"
#include "a11y/gtkprogressbaraccessible.h"
#include "actors/gtkbinlayoutprivate.h"
#include "actors/gtkcssboxprivate.h"
#include "actors/gtkcsstextprivate.h"
/**
* SECTION:gtkprogressbar
* @Short_description: A widget which indicates progress visually
@@ -70,7 +76,8 @@
struct _GtkProgressBarPrivate
{
gchar *text;
GtkActor *slider;
GtkActor *text;
gdouble fraction;
gdouble pulse_fraction;
@@ -82,9 +89,8 @@ struct _GtkProgressBarPrivate
guint activity_dir : 1;
guint activity_mode : 1;
guint ellipsize : 3;
guint show_text : 1;
guint inverted : 1;
guint autotext : 1;
};
enum {
@@ -106,18 +112,11 @@ static void gtk_progress_bar_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void gtk_progress_bar_get_preferred_width (GtkWidget *widget,
gint *minimum,
gint *natural);
static void gtk_progress_bar_get_preferred_height (GtkWidget *widget,
gint *minimum,
gint *natural);
static void gtk_progress_bar_real_update (GtkProgressBar *progress);
static gboolean gtk_progress_bar_draw (GtkWidget *widget,
cairo_t *cr);
static void gtk_progress_bar_act_mode_enter (GtkProgressBar *progress);
static void gtk_progress_bar_finalize (GObject *object);
static void gtk_progress_bar_set_orientation (GtkProgressBar *progress,
GtkOrientation orientation);
@@ -135,11 +134,8 @@ gtk_progress_bar_class_init (GtkProgressBarClass *class)
gobject_class->set_property = gtk_progress_bar_set_property;
gobject_class->get_property = gtk_progress_bar_get_property;
gobject_class->finalize = gtk_progress_bar_finalize;
widget_class->draw = gtk_progress_bar_draw;
widget_class->get_preferred_width = gtk_progress_bar_get_preferred_width;
widget_class->get_preferred_height = gtk_progress_bar_get_preferred_height;
g_object_class_override_property (gobject_class, PROP_ORIENTATION, "orientation");
@@ -295,6 +291,7 @@ static void
gtk_progress_bar_init (GtkProgressBar *pbar)
{
GtkProgressBarPrivate *priv;
GtkActor *trough;
pbar->priv = G_TYPE_INSTANCE_GET_PRIVATE (pbar,
GTK_TYPE_PROGRESS_BAR,
@@ -307,13 +304,22 @@ gtk_progress_bar_init (GtkProgressBar *pbar)
priv->activity_pos = 0;
priv->activity_dir = 1;
priv->activity_blocks = 5;
priv->ellipsize = PANGO_ELLIPSIZE_NONE;
priv->show_text = FALSE;
priv->text = NULL;
priv->fraction = 0.0;
gtk_widget_set_has_window (GTK_WIDGET (pbar), FALSE);
trough = _gtk_widget_get_actor (GTK_WIDGET (pbar));
_gtk_actor_set_layout_manager (trough, _gtk_bin_layout_new ());
_gtk_css_box_add_class (GTK_CSS_BOX (trough), GTK_STYLE_CLASS_TROUGH);
_gtk_css_box_add_class (GTK_CSS_BOX (trough), GTK_STYLE_CLASS_HORIZONTAL);
priv->slider = _gtk_css_box_new ();
_gtk_css_box_add_class (GTK_CSS_BOX (priv->slider), GTK_STYLE_CLASS_PROGRESSBAR);
_gtk_actor_add_child (trough, priv->slider);
priv->text = _gtk_css_text_new ();
_gtk_css_text_set_text_alignment (GTK_CSS_TEXT (priv->text), PANGO_ALIGN_CENTER);
_gtk_actor_hide (priv->text);
_gtk_actor_add_child (trough, priv->text);
}
static void
@@ -379,13 +385,13 @@ gtk_progress_bar_get_property (GObject *object,
g_value_set_double (value, priv->pulse_fraction);
break;
case PROP_TEXT:
g_value_set_string (value, priv->text);
g_value_set_string (value, _gtk_css_text_get_text (GTK_CSS_TEXT (priv->text)));
break;
case PROP_SHOW_TEXT:
g_value_set_boolean (value, priv->show_text);
g_value_set_boolean (value, _gtk_actor_get_visible (priv->text));
break;
case PROP_ELLIPSIZE:
g_value_set_enum (value, priv->ellipsize);
g_value_set_enum (value, _gtk_css_text_get_ellipsize (GTK_CSS_TEXT (priv->text)));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -410,16 +416,75 @@ gtk_progress_bar_new (void)
return pbar;
}
static void
gtk_progress_bar_update_position (GtkProgressBar *pbar)
{
GtkProgressBarPrivate *priv;
GtkLayoutManager *layout;
double scale, align;
gboolean inverted;
priv = pbar->priv;
layout = _gtk_actor_get_layout_manager (_gtk_widget_get_actor (GTK_WIDGET (pbar)));
inverted = priv->inverted;
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL &&
gtk_widget_get_direction (GTK_WIDGET (pbar)) == GTK_TEXT_DIR_RTL)
inverted = !inverted;
if (priv->activity_mode)
{
align = priv->activity_pos;
scale = 1.0 / priv->activity_blocks;
}
else
{
align = inverted ? 1.0 : 0.0;
scale = priv->fraction;
}
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
{
_gtk_bin_layout_set_child_alignment (GTK_BIN_LAYOUT (layout),
priv->slider,
align,
0.0,
scale,
1.0);
}
else
{
_gtk_bin_layout_set_child_alignment (GTK_BIN_LAYOUT (layout),
priv->slider,
0.0,
align,
1.0,
scale);
}
}
static void
gtk_progress_bar_update_text (GtkProgressBar *pbar)
{
GtkProgressBarPrivate *priv = pbar->priv;
char *s;
if (!priv->autotext)
return;
s = g_strdup_printf ("%.0f %%", priv->fraction * 100.0);
_gtk_css_text_set_text (GTK_CSS_TEXT (priv->text), s);
g_free (s);
}
static void
gtk_progress_bar_real_update (GtkProgressBar *pbar)
{
GtkProgressBarPrivate *priv;
GtkWidget *widget;
g_return_if_fail (GTK_IS_PROGRESS_BAR (pbar));
priv = pbar->priv;
widget = GTK_WIDGET (pbar);
if (priv->activity_mode)
{
@@ -443,178 +508,18 @@ gtk_progress_bar_real_update (GtkProgressBar *pbar)
}
}
}
gtk_widget_queue_draw (widget);
}
static void
gtk_progress_bar_finalize (GObject *object)
{
GtkProgressBar *pbar = GTK_PROGRESS_BAR (object);
GtkProgressBarPrivate *priv = pbar->priv;
g_free (priv->text);
G_OBJECT_CLASS (gtk_progress_bar_parent_class)->finalize (object);
}
static gchar *
get_current_text (GtkProgressBar *pbar)
{
GtkProgressBarPrivate *priv = pbar->priv;
if (priv->text)
return g_strdup (priv->text);
else
return g_strdup_printf ("%.0f %%", priv->fraction * 100.0);
}
static void
gtk_progress_bar_get_preferred_width (GtkWidget *widget,
gint *minimum,
gint *natural)
{
GtkProgressBar *pbar;
GtkProgressBarPrivate *priv;
GtkStyleContext *style_context;
GtkStateFlags state;
GtkBorder padding;
gchar *buf;
PangoRectangle logical_rect;
PangoLayout *layout;
gint width;
gint xspacing;
gint min_width;
g_return_if_fail (GTK_IS_PROGRESS_BAR (widget));
style_context = gtk_widget_get_style_context (widget);
state = gtk_widget_get_state_flags (widget);
gtk_style_context_get_padding (style_context, state, &padding);
gtk_widget_style_get (widget,
"xspacing", &xspacing,
NULL);
pbar = GTK_PROGRESS_BAR (widget);
priv = pbar->priv;
width = padding.left + padding.right + xspacing;
if (priv->show_text)
{
buf = get_current_text (pbar);
layout = gtk_widget_create_pango_layout (widget, buf);
pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
if (priv->ellipsize)
{
PangoContext *context;
PangoFontMetrics *metrics;
gint char_width;
/* The minimum size for ellipsized text is ~ 3 chars */
context = pango_layout_get_context (layout);
metrics = pango_context_get_metrics (context,
pango_context_get_font_description (context),
pango_context_get_language (context));
char_width = pango_font_metrics_get_approximate_char_width (metrics);
pango_font_metrics_unref (metrics);
width += PANGO_PIXELS (char_width) * 3;
}
else
width += logical_rect.width;
g_object_unref (layout);
g_free (buf);
}
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
gtk_widget_style_get (widget,
"min-horizontal-bar-width", &min_width,
NULL);
else
gtk_widget_style_get (widget,
"min-vertical-bar-width", &min_width,
NULL);
*minimum = *natural = MAX (min_width, width);
}
static void
gtk_progress_bar_get_preferred_height (GtkWidget *widget,
gint *minimum,
gint *natural)
{
GtkProgressBar *pbar;
GtkProgressBarPrivate *priv;
GtkStyleContext *context;
GtkStateFlags state;
GtkBorder padding;
gchar *buf;
PangoRectangle logical_rect;
PangoLayout *layout;
gint height;
gint yspacing;
gint min_height;
g_return_if_fail (GTK_IS_PROGRESS_BAR (widget));
context = gtk_widget_get_style_context (widget);
state = gtk_widget_get_state_flags (widget);
gtk_style_context_get_padding (context, state, &padding);
gtk_widget_style_get (widget,
"yspacing", &yspacing,
NULL);
pbar = GTK_PROGRESS_BAR (widget);
priv = pbar->priv;
height = padding.top + padding.bottom + yspacing;
if (priv->show_text)
{
buf = get_current_text (pbar);
layout = gtk_widget_create_pango_layout (widget, buf);
pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
height += logical_rect.height;
g_object_unref (layout);
g_free (buf);
}
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
gtk_widget_style_get (widget,
"min-horizontal-bar-height", &min_height,
NULL);
else
gtk_widget_style_get (widget,
"min-vertical-bar-height", &min_height,
NULL);
*minimum = *natural = MAX (min_height, height);
gtk_progress_bar_update_position (pbar);
}
static void
gtk_progress_bar_act_mode_enter (GtkProgressBar *pbar)
{
GtkProgressBarPrivate *priv = pbar->priv;
GtkStyleContext *context;
GtkStateFlags state;
GtkBorder padding;
GtkWidget *widget = GTK_WIDGET (pbar);
GtkOrientation orientation;
gboolean inverted;
context = gtk_widget_get_style_context (widget);
state = gtk_widget_get_state_flags (widget);
gtk_style_context_get_padding (context, state, &padding);
orientation = priv->orientation;
inverted = priv->inverted;
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
@@ -653,337 +558,12 @@ gtk_progress_bar_act_mode_enter (GtkProgressBar *pbar)
}
}
static void
gtk_progress_bar_get_activity (GtkProgressBar *pbar,
GtkOrientation orientation,
gint *offset,
gint *amount)
{
GtkProgressBarPrivate *priv = pbar->priv;
GtkWidget *widget = GTK_WIDGET (pbar);
GtkStyleContext *context;
GtkAllocation allocation;
GtkStateFlags state;
GtkBorder padding;
int size;
context = gtk_widget_get_style_context (widget);
state = gtk_style_context_get_state (context);
gtk_widget_get_allocation (widget, &allocation);
gtk_style_context_get_padding (context, state, &padding);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
size = allocation.width - padding.left - padding.top;
else
size = allocation.height - padding.left - padding.top;
*amount = MAX (2, size / priv->activity_blocks);
*offset = priv->activity_pos * (size - *amount);
}
static void
gtk_progress_bar_paint_activity (GtkProgressBar *pbar,
cairo_t *cr,
GtkOrientation orientation,
gboolean inverted,
int width,
int height)
{
GtkStyleContext *context;
GtkStateFlags state;
GtkBorder padding;
GtkWidget *widget = GTK_WIDGET (pbar);
GdkRectangle area;
context = gtk_widget_get_style_context (widget);
state = gtk_widget_get_state_flags (widget);
gtk_style_context_get_padding (context, state, &padding);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
gtk_progress_bar_get_activity (pbar, orientation, &area.x, &area.width);
area.y = padding.top;
area.height = height - padding.top - padding.bottom;
}
else
{
gtk_progress_bar_get_activity (pbar, orientation, &area.y, &area.height);
area.x = padding.left;
area.width = width - padding.left - padding.right;
}
gtk_style_context_save (context);
gtk_style_context_add_class (context, GTK_STYLE_CLASS_PROGRESSBAR);
gtk_style_context_add_class (context, GTK_STYLE_CLASS_PULSE);
gtk_render_activity (context, cr, area.x, area.y, area.width, area.height);
gtk_style_context_restore (context);
}
static void
gtk_progress_bar_paint_continuous (GtkProgressBar *pbar,
cairo_t *cr,
gint amount,
GtkOrientation orientation,
gboolean inverted,
int width,
int height)
{
GtkStyleContext *context;
GtkStateFlags state;
GtkBorder padding;
GtkWidget *widget = GTK_WIDGET (pbar);
GdkRectangle area;
if (amount <= 0)
return;
context = gtk_widget_get_style_context (widget);
state = gtk_widget_get_state_flags (widget);
gtk_style_context_get_padding (context, state, &padding);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
area.width = amount;
area.height = height - padding.top - padding.bottom;
area.y = padding.top;
if (!inverted)
area.x = padding.left;
else
area.x = width - amount - padding.right;
}
else
{
area.width = width - padding.left - padding.right;
area.height = amount;
area.x = padding.left;
if (!inverted)
area.y = padding.top;
else
area.y = height - amount - padding.bottom;
}
gtk_style_context_save (context);
gtk_style_context_add_class (context, GTK_STYLE_CLASS_PROGRESSBAR);
gtk_render_activity (context, cr, area.x, area.y, area.width, area.height);
gtk_style_context_restore (context);
}
static void
gtk_progress_bar_paint_text (GtkProgressBar *pbar,
cairo_t *cr,
gint offset,
gint amount,
GtkOrientation orientation,
gboolean inverted,
int width,
int height)
{
GtkProgressBarPrivate *priv = pbar->priv;
GtkStyleContext *context;
GtkStateFlags state;
GtkBorder padding;
GtkWidget *widget = GTK_WIDGET (pbar);
gint x;
gint y;
gchar *buf;
GdkRectangle rect;
PangoLayout *layout;
PangoRectangle logical_rect;
GdkRectangle prelight_clip, start_clip, end_clip;
gfloat text_xalign = 0.5;
gfloat text_yalign = 0.5;
context = gtk_widget_get_style_context (widget);
state = gtk_widget_get_state_flags (widget);
gtk_style_context_get_padding (context, state, &padding);
if (gtk_widget_get_direction (widget) != GTK_TEXT_DIR_LTR)
text_xalign = 1.0 - text_xalign;
buf = get_current_text (pbar);
layout = gtk_widget_create_pango_layout (widget, buf);
pango_layout_set_ellipsize (layout, priv->ellipsize);
if (priv->ellipsize)
pango_layout_set_width (layout, width * PANGO_SCALE);
pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
x = padding.left + 1 + text_xalign * (width - padding.left - padding.right - 2 - logical_rect.width);
y = padding.top + 1 + text_yalign * (height - padding.top - padding.bottom - 2 - logical_rect.height);
rect.x = padding.left;
rect.y = padding.top;
rect.width = width - padding.left - padding.right;
rect.height = height - padding.top - padding.bottom;
prelight_clip = start_clip = end_clip = rect;
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
if (!inverted)
{
if (offset != -1)
prelight_clip.x = offset;
prelight_clip.width = amount;
start_clip.width = prelight_clip.x - start_clip.x;
end_clip.x = start_clip.x + start_clip.width + prelight_clip.width;
end_clip.width -= prelight_clip.width + start_clip.width;
}
else
{
if (offset != -1)
prelight_clip.x = offset;
else
prelight_clip.x = rect.x + rect.width - amount;
prelight_clip.width = amount;
start_clip.width = prelight_clip.x - start_clip.x;
end_clip.x = start_clip.x + start_clip.width + prelight_clip.width;
end_clip.width -= prelight_clip.width + start_clip.width;
}
}
else
{
if (!inverted)
{
if (offset != -1)
prelight_clip.y = offset;
prelight_clip.height = amount;
start_clip.height = prelight_clip.y - start_clip.y;
end_clip.y = start_clip.y + start_clip.height + prelight_clip.height;
end_clip.height -= prelight_clip.height + start_clip.height;
}
else
{
if (offset != -1)
prelight_clip.y = offset;
else
prelight_clip.y = rect.y + rect.height - amount;
prelight_clip.height = amount;
start_clip.height = prelight_clip.y - start_clip.y;
end_clip.y = start_clip.y + start_clip.height + prelight_clip.height;
end_clip.height -= prelight_clip.height + start_clip.height;
}
}
gtk_style_context_save (context);
gtk_style_context_add_class (context, GTK_STYLE_CLASS_TROUGH);
if (start_clip.width > 0 && start_clip.height > 0)
{
cairo_save (cr);
gdk_cairo_rectangle (cr, &start_clip);
cairo_clip (cr);
gtk_render_layout (context, cr, x, y, layout);
cairo_restore (cr);
}
if (end_clip.width > 0 && end_clip.height > 0)
{
cairo_save (cr);
gdk_cairo_rectangle (cr, &end_clip);
cairo_clip (cr);
gtk_render_layout (context, cr, x, y, layout);
cairo_restore (cr);
}
gtk_style_context_restore (context);
cairo_save (cr);
gdk_cairo_rectangle (cr, &prelight_clip);
cairo_clip (cr);
gtk_style_context_save (context);
gtk_style_context_add_class (context, GTK_STYLE_CLASS_PROGRESSBAR);
gtk_render_layout (context, cr, x, y, layout);
gtk_style_context_restore (context);
cairo_restore (cr);
g_object_unref (layout);
g_free (buf);
}
static gboolean
gtk_progress_bar_draw (GtkWidget *widget,
cairo_t *cr)
{
GtkProgressBar *pbar = GTK_PROGRESS_BAR (widget);
GtkProgressBarPrivate *priv = pbar->priv;
GtkOrientation orientation;
gboolean inverted;
GtkStyleContext *context;
GtkStateFlags state;
GtkBorder padding;
int width, height;
context = gtk_widget_get_style_context (widget);
state = gtk_widget_get_state_flags (widget);
gtk_style_context_get_padding (context, state, &padding);
orientation = priv->orientation;
inverted = priv->inverted;
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
{
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
inverted = !inverted;
}
width = gtk_widget_get_allocated_width (widget);
height = gtk_widget_get_allocated_height (widget);
gtk_style_context_save (context);
gtk_style_context_add_class (context, GTK_STYLE_CLASS_TROUGH);
gtk_render_background (context, cr, 0, 0, width, height);
gtk_render_frame (context, cr, 0, 0, width, height);
gtk_style_context_restore (context);
if (priv->activity_mode)
{
gtk_progress_bar_paint_activity (pbar, cr,
orientation, inverted,
width, height);
if (priv->show_text)
{
gint offset;
gint amount;
gtk_progress_bar_get_activity (pbar, orientation, &offset, &amount);
gtk_progress_bar_paint_text (pbar, cr,
offset, amount,
orientation, inverted,
width, height);
}
}
else
{
gint amount;
gint space;
if (orientation == GTK_ORIENTATION_HORIZONTAL)
space = width - padding.left - padding.right;
else
space = height - padding.top - padding.bottom;
amount = space * gtk_progress_bar_get_fraction (pbar);
gtk_progress_bar_paint_continuous (pbar, cr, amount, orientation, inverted, width, height);
if (priv->show_text)
gtk_progress_bar_paint_text (pbar, cr, -1, amount, orientation, inverted, width, height);
}
cairo_reset_clip (cr);
_gtk_actor_draw (_gtk_widget_get_actor (widget), cr);
return FALSE;
}
@@ -1002,7 +582,7 @@ gtk_progress_bar_set_activity_mode (GtkProgressBar *pbar,
if (priv->activity_mode)
gtk_progress_bar_act_mode_enter (pbar);
gtk_widget_queue_resize (GTK_WIDGET (pbar));
gtk_progress_bar_update_position (pbar);
}
}
@@ -1027,7 +607,8 @@ gtk_progress_bar_set_fraction (GtkProgressBar *pbar,
priv->fraction = CLAMP(fraction, 0.0, 1.0);
gtk_progress_bar_set_activity_mode (pbar, FALSE);
gtk_progress_bar_real_update (pbar);
gtk_progress_bar_update_text (pbar);
gtk_progress_bar_update_position (pbar);
g_object_notify (G_OBJECT (pbar), "fraction");
}
@@ -1077,13 +658,19 @@ gtk_progress_bar_set_text (GtkProgressBar *pbar,
priv = pbar->priv;
/* Don't notify again if nothing's changed. */
if (g_strcmp0 (priv->text, text) == 0)
if (g_strcmp0 (_gtk_css_text_get_text (GTK_CSS_TEXT (priv->text)), text) == 0)
return;
g_free (priv->text);
priv->text = g_strdup (text);
gtk_widget_queue_resize (GTK_WIDGET (pbar));
if (text)
{
_gtk_css_text_set_text (GTK_CSS_TEXT (priv->text), text);
priv->autotext = FALSE;
}
else
{
priv->autotext = TRUE;
gtk_progress_bar_update_text (pbar);
}
g_object_notify (G_OBJECT (pbar), "text");
}
@@ -1116,11 +703,9 @@ gtk_progress_bar_set_show_text (GtkProgressBar *pbar,
show_text = !!show_text;
if (priv->show_text != show_text)
if (_gtk_actor_get_visible (priv->text) != show_text)
{
priv->show_text = show_text;
gtk_widget_queue_resize (GTK_WIDGET (pbar));
_gtk_actor_set_visible (priv->text, show_text);
g_object_notify (G_OBJECT (pbar), "show-text");
}
@@ -1142,7 +727,7 @@ gtk_progress_bar_get_show_text (GtkProgressBar *pbar)
{
g_return_val_if_fail (GTK_IS_PROGRESS_BAR (pbar), FALSE);
return pbar->priv->show_text;
return _gtk_actor_get_visible (pbar->priv->text);
}
/**
@@ -1176,8 +761,20 @@ gtk_progress_bar_set_orientation (GtkProgressBar *pbar,
if (priv->orientation != orientation)
{
GtkActor *actor = _gtk_widget_get_actor (GTK_WIDGET (pbar));
priv->orientation = orientation;
_gtk_orientable_set_style_classes (GTK_ORIENTABLE (pbar));
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
_gtk_css_box_add_class (GTK_CSS_BOX (actor), GTK_STYLE_CLASS_HORIZONTAL);
_gtk_css_box_remove_class (GTK_CSS_BOX (actor), GTK_STYLE_CLASS_VERTICAL);
}
else
{
_gtk_css_box_add_class (GTK_CSS_BOX (actor), GTK_STYLE_CLASS_VERTICAL);
_gtk_css_box_remove_class (GTK_CSS_BOX (actor), GTK_STYLE_CLASS_HORIZONTAL);
}
gtk_widget_queue_resize (GTK_WIDGET (pbar));
}
@@ -1205,7 +802,7 @@ gtk_progress_bar_set_inverted (GtkProgressBar *pbar,
{
priv->inverted = inverted;
gtk_widget_queue_resize (GTK_WIDGET (pbar));
gtk_progress_bar_update_position (pbar);
g_object_notify (G_OBJECT (pbar), "inverted");
}
@@ -1228,7 +825,7 @@ gtk_progress_bar_get_text (GtkProgressBar *pbar)
{
g_return_val_if_fail (GTK_IS_PROGRESS_BAR (pbar), NULL);
return pbar->priv->text;
return _gtk_css_text_get_text (GTK_CSS_TEXT (pbar->priv->text));
}
/**
@@ -1301,12 +898,11 @@ gtk_progress_bar_set_ellipsize (GtkProgressBar *pbar,
priv = pbar->priv;
if ((PangoEllipsizeMode)priv->ellipsize != mode)
if (_gtk_css_text_get_ellipsize (GTK_CSS_TEXT (priv->text)) != mode)
{
priv->ellipsize = mode;
_gtk_css_text_set_ellipsize (GTK_CSS_TEXT (priv->text), mode);
g_object_notify (G_OBJECT (pbar), "ellipsize");
gtk_widget_queue_resize (GTK_WIDGET (pbar));
}
}
@@ -1326,5 +922,5 @@ gtk_progress_bar_get_ellipsize (GtkProgressBar *pbar)
{
g_return_val_if_fail (GTK_IS_PROGRESS_BAR (pbar), PANGO_ELLIPSIZE_NONE);
return pbar->priv->ellipsize;
return _gtk_css_text_get_ellipsize (GTK_CSS_TEXT (pbar->priv->text));
}

View File

@@ -103,6 +103,7 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
SizeRequestCache *cache;
gint min_size = 0;
gint nat_size = 0;
gfloat min_float, nat_float;
gboolean found_in_cache;
if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_CONSTANT_SIZE)
@@ -112,8 +113,8 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
found_in_cache = _gtk_size_request_cache_lookup (cache,
orientation,
for_size,
&min_size,
&nat_size);
&min_float,
&nat_float);
if (!found_in_cache)
{
@@ -233,6 +234,11 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
min_size,
nat_size);
}
else
{
min_size = min_float;
nat_size = nat_float;
}
if (minimum_size)
*minimum_size = min_size;

View File

@@ -54,6 +54,16 @@ _gtk_size_request_cache_free (SizeRequestCache *cache)
}
}
gboolean
_gtk_size_request_cache_is_empty (SizeRequestCache *cache)
{
return !cache->request_mode_valid
&& !cache->flags[0].cached_size_valid
&& !cache->flags[0].n_cached_requests
&& !cache->flags[1].cached_size_valid
&& !cache->flags[1].n_cached_requests;
}
void
_gtk_size_request_cache_clear (SizeRequestCache *cache)
@@ -65,9 +75,9 @@ _gtk_size_request_cache_clear (SizeRequestCache *cache)
void
_gtk_size_request_cache_commit (SizeRequestCache *cache,
GtkOrientation orientation,
gint for_size,
gint minimum_size,
gint natural_size)
gfloat for_size,
gfloat minimum_size,
gfloat natural_size)
{
SizeRequest **cached_sizes;
SizeRequest *cached_size;
@@ -135,9 +145,9 @@ _gtk_size_request_cache_commit (SizeRequestCache *cache,
gboolean
_gtk_size_request_cache_lookup (SizeRequestCache *cache,
GtkOrientation orientation,
gint for_size,
gint *minimum,
gint *natural)
gfloat for_size,
gfloat *minimum,
gfloat *natural)
{
CachedSize *result = NULL;

View File

@@ -39,14 +39,14 @@ G_BEGIN_DECLS
#define GTK_SIZE_REQUEST_CACHED_SIZES (5)
typedef struct {
gint minimum_size;
gint natural_size;
gfloat minimum_size;
gfloat natural_size;
} CachedSize;
typedef struct
{
gint lower_for_size; /* The minimum for_size with the same result */
gint upper_for_size; /* The maximum for_size with the same result */
gfloat lower_for_size; /* The minimum for_size with the same result */
gfloat upper_for_size; /* The maximum for_size with the same result */
CachedSize cached_size;
} SizeRequest;
@@ -67,17 +67,18 @@ typedef struct {
void _gtk_size_request_cache_init (SizeRequestCache *cache);
void _gtk_size_request_cache_free (SizeRequestCache *cache);
gboolean _gtk_size_request_cache_is_empty (SizeRequestCache *cache);
void _gtk_size_request_cache_clear (SizeRequestCache *cache);
void _gtk_size_request_cache_commit (SizeRequestCache *cache,
GtkOrientation orientation,
gint for_size,
gint minimum_size,
gint natural_size);
gfloat for_size,
gfloat minimum_size,
gfloat natural_size);
gboolean _gtk_size_request_cache_lookup (SizeRequestCache *cache,
GtkOrientation orientation,
gint for_size,
gint *minimum,
gint *natural);
gfloat for_size,
gfloat *minimum,
gfloat *natural);
G_END_DECLS

View File

@@ -363,8 +363,8 @@ struct _GtkStyleContextPrivate
GtkStyleContext *parent;
GSList *children;
GtkWidget *widget;
GtkWidgetPath *widget_path;
const GtkStyleContextSource *source;
gpointer source_data;
GHashTable *style_data;
GtkStyleInfo *info;
@@ -411,8 +411,7 @@ gtk_style_context_real_changed (GtkStyleContext *context)
{
GtkStyleContextPrivate *priv = context->priv;
if (priv->widget)
_gtk_widget_style_context_invalidated (priv->widget);
priv->source->invalidate (priv->source_data);
}
static void
@@ -699,6 +698,62 @@ gtk_style_context_set_cascade (GtkStyleContext *context,
gtk_style_context_cascade_changed (cascade, context);
}
static gboolean
default_init_css_matcher (GtkCssMatcher *matcher,
gpointer data)
{
return FALSE;
}
static GtkWidgetPath *
default_create_query_path (gpointer data)
{
return NULL;
}
static const GtkWidgetPath *
default_get_path (gpointer data)
{
return NULL;
}
static void
default_do_nothing (gpointer data)
{
/* Hi mom */
}
static gboolean
default_should_animate (gpointer data)
{
return FALSE;
}
static GType
default_get_widget_type (gpointer data)
{
return G_TYPE_INVALID;
}
static const GtkStyleContextSource default_source = {
FALSE,
TRUE,
default_init_css_matcher,
default_create_query_path,
default_get_path,
default_do_nothing,
default_do_nothing,
default_should_animate,
default_get_widget_type,
default_do_nothing
};
static gboolean
gtk_style_context_has_valid_source (GtkStyleContext *context)
{
return context->priv->source != &default_source;
}
static void
gtk_style_context_init (GtkStyleContext *style_context)
{
@@ -715,6 +770,7 @@ gtk_style_context_init (GtkStyleContext *style_context)
priv->screen = gdk_screen_get_default ();
priv->relevant_changes = GTK_CSS_CHANGE_ANY;
priv->source = &default_source;
/* Create default info store */
priv->info = style_info_new ();
@@ -805,25 +861,17 @@ gtk_style_context_should_animate (GtkStyleContext *context)
{
GtkStyleContextPrivate *priv;
StyleData *data;
gboolean animate;
priv = context->priv;
if (priv->widget == NULL)
return FALSE;
if (!gtk_widget_get_mapped (priv->widget))
if (!priv->source->should_animate (priv->source_data))
return FALSE;
data = style_data_lookup (context);
if (!style_data_is_animating (data))
return FALSE;
g_object_get (gtk_widget_get_settings (context->priv->widget),
"gtk-enable-animations", &animate,
NULL);
return animate;
return TRUE;
}
void
@@ -853,8 +901,7 @@ gtk_style_context_finalize (GObject *object)
gtk_style_context_set_cascade (style_context, NULL);
if (priv->widget_path)
gtk_widget_path_free (priv->widget_path);
_gtk_style_context_set_source (style_context, NULL, NULL);
g_hash_table_destroy (priv->style_data);
@@ -936,7 +983,10 @@ create_query_path (GtkStyleContext *context,
guint i, pos;
priv = context->priv;
path = priv->widget ? _gtk_widget_create_path (priv->widget) : gtk_widget_path_copy (priv->widget_path);
path = priv->source->create_query_path (priv->source_data);
if (path == NULL)
return NULL;
pos = gtk_widget_path_length (path) - 1;
/* Set widget regions */
@@ -976,13 +1026,28 @@ build_properties (GtkStyleContext *context,
priv = context->priv;
path = create_query_path (context, info);
lookup = _gtk_css_lookup_new (relevant_changes);
if (info->next == NULL &&
priv->source->css_matcher_init (&matcher, priv->source_data))
{
_gtk_style_provider_private_lookup (GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
&matcher,
lookup);
}
else
{
path = create_query_path (context, info);
if (_gtk_css_matcher_init (&matcher, path, info->state_flags))
_gtk_style_provider_private_lookup (GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
&matcher,
lookup);
if (path)
{
if (_gtk_css_matcher_init (&matcher, path, info->state_flags))
_gtk_style_provider_private_lookup (GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
&matcher,
lookup);
gtk_widget_path_free (path);
}
}
_gtk_css_lookup_resolve (lookup,
GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
@@ -990,7 +1055,6 @@ build_properties (GtkStyleContext *context,
priv->parent ? style_data_lookup (priv->parent)->store : NULL);
_gtk_css_lookup_free (lookup);
gtk_widget_path_free (path);
}
static StyleData *
@@ -1007,7 +1071,7 @@ style_data_lookup (GtkStyleContext *context)
if (info->data)
return info->data;
g_assert (priv->widget != NULL || priv->widget_path != NULL);
g_assert (gtk_style_context_has_valid_source (context));
data = g_hash_table_lookup (priv->style_data, info);
if (data)
@@ -1062,8 +1126,8 @@ gtk_style_context_set_invalid (GtkStyleContext *context,
{
if (priv->parent)
gtk_style_context_set_invalid (priv->parent, TRUE);
else if (GTK_IS_RESIZE_CONTAINER (priv->widget))
_gtk_container_queue_restyle (GTK_CONTAINER (priv->widget));
else
priv->source->queue_invalidate (priv->source_data);
}
}
@@ -1119,17 +1183,28 @@ gtk_style_context_new (void)
}
void
_gtk_style_context_set_widget (GtkStyleContext *context,
GtkWidget *widget)
_gtk_style_context_set_source (GtkStyleContext *context,
const GtkStyleContextSource *source,
gpointer data)
{
GtkStyleContextPrivate *priv;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
context->priv->widget = widget;
if (source == NULL)
source = &default_source;
_gtk_style_context_update_animating (context);
priv = context->priv;
_gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_ANY_SELF);
priv->source->destroy (priv->source_data);
priv->source = source;
priv->source_data = data;
_gtk_style_context_queue_invalidate (context,
GTK_CSS_CHANGE_ANY_SELF
| GTK_CSS_CHANGE_ANY_SIBLING
| GTK_CSS_CHANGE_ANY_PARENT);
}
/**
@@ -1326,15 +1401,12 @@ GtkCssSection *
gtk_style_context_get_section (GtkStyleContext *context,
const gchar *property)
{
GtkStyleContextPrivate *priv;
GtkStyleProperty *prop;
StyleData *data;
g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
g_return_val_if_fail (property != NULL, NULL);
priv = context->priv;
g_return_val_if_fail (priv->widget != NULL || priv->widget_path != NULL, NULL);
g_return_val_if_fail (gtk_style_context_has_valid_source (context), NULL);
prop = _gtk_style_property_lookup (property);
if (!GTK_IS_CSS_STYLE_PROPERTY (prop))
@@ -1371,16 +1443,13 @@ gtk_style_context_get_property (GtkStyleContext *context,
GtkStateFlags state,
GValue *value)
{
GtkStyleContextPrivate *priv;
GtkStyleProperty *prop;
StyleData *data;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (property != NULL);
g_return_if_fail (value != NULL);
priv = context->priv;
g_return_if_fail (priv->widget != NULL || priv->widget_path != NULL);
g_return_if_fail (gtk_style_context_has_valid_source (context));
prop = _gtk_style_property_lookup (property);
if (prop == NULL)
@@ -1547,6 +1616,37 @@ gtk_style_context_state_is_running (GtkStyleContext *context,
return FALSE;
}
static GtkWidgetPath *
widget_path_create_query_path (gpointer data)
{
return gtk_widget_path_copy (data);
}
static const GtkWidgetPath *
widget_path_get_path (gpointer data)
{
return data;
}
static GType
widget_path_get_widget_type (gpointer data)
{
return gtk_widget_path_get_object_type (data);
}
static const GtkStyleContextSource widget_path_source = {
FALSE,
TRUE,
default_init_css_matcher,
widget_path_create_query_path,
widget_path_get_path,
default_do_nothing,
default_do_nothing,
default_should_animate,
widget_path_get_widget_type,
(GDestroyNotify) gtk_widget_path_free
};
/**
* gtk_style_context_set_path:
* @context: a #GtkStyleContext
@@ -1566,24 +1666,13 @@ void
gtk_style_context_set_path (GtkStyleContext *context,
GtkWidgetPath *path)
{
GtkStyleContextPrivate *priv;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (path != NULL);
g_return_if_fail (!context->priv->source->internal_to_gtk);
priv = context->priv;
g_return_if_fail (priv->widget == NULL);
if (priv->widget_path)
{
gtk_widget_path_free (priv->widget_path);
priv->widget_path = NULL;
}
if (path)
priv->widget_path = gtk_widget_path_copy (path);
_gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_ANY);
_gtk_style_context_set_source (context,
&widget_path_source,
gtk_widget_path_copy (path));
}
/**
@@ -1602,10 +1691,8 @@ gtk_style_context_get_path (GtkStyleContext *context)
GtkStyleContextPrivate *priv;
priv = context->priv;
if (priv->widget)
return gtk_widget_get_path (priv->widget);
else
return priv->widget_path;
return priv->source->get_path (priv->source_data);
}
/**
@@ -2276,11 +2363,12 @@ _gtk_style_context_peek_style_property (GtkStyleContext *context,
g_param_spec_ref (pcache->pspec);
g_value_init (&pcache->value, G_PARAM_SPEC_VALUE_TYPE (pspec));
if (priv->widget || priv->widget_path)
if (gtk_style_context_has_valid_source (context))
{
GtkWidgetPath *widget_path = priv->widget ? _gtk_widget_create_path (priv->widget) : priv->widget_path;
GtkWidgetPath *widget_path = priv->source->create_query_path (priv->source_data);
if (gtk_style_provider_get_style_property (GTK_STYLE_PROVIDER (priv->cascade),
if (widget_path &&
gtk_style_provider_get_style_property (GTK_STYLE_PROVIDER (priv->cascade),
widget_path,
state, pspec, &pcache->value))
{
@@ -2324,13 +2412,12 @@ _gtk_style_context_peek_style_property (GtkStyleContext *context,
G_GNUC_END_IGNORE_DEPRECATIONS;
if (priv->widget)
gtk_widget_path_free (widget_path);
gtk_widget_path_free (widget_path);
return &pcache->value;
}
if (priv->widget)
if (widget_path)
gtk_widget_path_free (widget_path);
}
@@ -2368,25 +2455,16 @@ gtk_style_context_get_style_property (GtkStyleContext *context,
g_return_if_fail (value != NULL);
priv = context->priv;
widget_type = priv->source->get_widget_type (priv->source_data);
if (widget_type == G_TYPE_INVALID)
return;
if (priv->widget)
if (!g_type_is_a (widget_type, GTK_TYPE_WIDGET))
{
widget_type = G_OBJECT_TYPE (priv->widget);
}
else
{
if (!priv->widget_path)
return;
widget_type = gtk_widget_path_get_object_type (priv->widget_path);
if (!g_type_is_a (widget_type, GTK_TYPE_WIDGET))
{
g_warning ("%s: can't get style properties for non-widget class `%s'",
G_STRLOC,
g_type_name (widget_type));
return;
}
g_warning ("%s: can't get style properties for non-widget class `%s'",
G_STRLOC,
g_type_name (widget_type));
return;
}
widget_class = g_type_class_ref (widget_type);
@@ -2441,24 +2519,16 @@ gtk_style_context_get_style_valist (GtkStyleContext *context,
prop_name = va_arg (args, const gchar *);
priv = context->priv;
if (priv->widget)
{
widget_type = G_OBJECT_TYPE (priv->widget);
}
else
{
if (!priv->widget_path)
return;
widget_type = priv->source->get_widget_type (priv->source_data);
if (widget_type == G_TYPE_INVALID)
return;
widget_type = gtk_widget_path_get_object_type (priv->widget_path);
if (!g_type_is_a (widget_type, GTK_TYPE_WIDGET))
{
g_warning ("%s: can't get style properties for non-widget class `%s'",
G_STRLOC,
g_type_name (widget_type));
return;
}
if (!g_type_is_a (widget_type, GTK_TYPE_WIDGET))
{
g_warning ("%s: can't get style properties for non-widget class `%s'",
G_STRLOC,
g_type_name (widget_type));
return;
}
state = gtk_style_context_get_state (context);
@@ -2541,13 +2611,9 @@ GtkIconSet *
gtk_style_context_lookup_icon_set (GtkStyleContext *context,
const gchar *stock_id)
{
GtkStyleContextPrivate *priv;
g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
g_return_val_if_fail (stock_id != NULL, NULL);
priv = context->priv;
g_return_val_if_fail (priv->widget != NULL || priv->widget_path != NULL, NULL);
g_return_val_if_fail (gtk_style_context_has_valid_source (context), NULL);
return gtk_icon_factory_lookup_default (stock_id);
}
@@ -2854,7 +2920,7 @@ gtk_style_context_notify_state_change (GtkStyleContext *context,
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (state > GTK_STATE_NORMAL && state <= GTK_STATE_FOCUSED);
g_return_if_fail (context->priv->widget != NULL || context->priv->widget_path != NULL);
g_return_if_fail (gtk_style_context_has_valid_source (context));
}
/**
@@ -3009,6 +3075,9 @@ gtk_style_context_do_invalidate (GtkStyleContext *context,
priv = context->priv;
if (!gtk_style_context_has_valid_source (context))
return;
/* Avoid reentrancy */
if (priv->invalidating_context)
return;
@@ -3081,22 +3150,9 @@ gtk_style_context_needs_full_revalidate (GtkStyleContext *context,
static gboolean
gtk_style_context_should_create_transitions (GtkStyleContext *context)
{
GtkStyleContextPrivate *priv;
gboolean animate;
GtkStyleContextPrivate *priv = context->priv;
priv = context->priv;
if (priv->widget == NULL)
return FALSE;
if (!gtk_widget_get_mapped (priv->widget))
return FALSE;
g_object_get (gtk_widget_get_settings (context->priv->widget),
"gtk-enable-animations", &animate,
NULL);
return animate;
return priv->source->should_animate (priv->source_data);
}
void
@@ -3229,15 +3285,15 @@ _gtk_style_context_queue_invalidate (GtkStyleContext *context,
priv = context->priv;
if (priv->widget != NULL)
if (priv->source->instant_invalidate)
{
gtk_style_context_invalidate (context);
}
else
{
priv->pending_changes |= change;
gtk_style_context_set_invalid (context, TRUE);
}
else if (priv->widget_path == NULL)
{
gtk_style_context_invalidate (context);
}
}
/**
@@ -3535,14 +3591,11 @@ const PangoFontDescription *
gtk_style_context_get_font (GtkStyleContext *context,
GtkStateFlags state)
{
GtkStyleContextPrivate *priv;
StyleData *data;
PangoFontDescription *description;
g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
priv = context->priv;
g_return_val_if_fail (priv->widget != NULL || priv->widget_path != NULL, NULL);
g_return_val_if_fail (gtk_style_context_has_valid_source (context), NULL);
data = style_data_lookup_for_state (context, state);

View File

@@ -25,8 +25,26 @@
G_BEGIN_DECLS
void _gtk_style_context_set_widget (GtkStyleContext *context,
GtkWidget *widget);
typedef struct _GtkStyleContextSource GtkStyleContextSource;
struct _GtkStyleContextSource {
guint internal_to_gtk :1;
guint instant_invalidate :1;
gboolean (* css_matcher_init) (GtkCssMatcher *matcher,
gpointer data);
GtkWidgetPath * (* create_query_path) (gpointer data);
const GtkWidgetPath * (* get_path) (gpointer data);
void (* invalidate) (gpointer data);
void (* queue_invalidate) (gpointer data);
gboolean (* should_animate) (gpointer data);
GType (* get_widget_type) (gpointer data);
void (* destroy) (gpointer data);
};
void _gtk_style_context_set_source (GtkStyleContext *context,
const GtkStyleContextSource *source,
gpointer data);
const GtkBitmask *
_gtk_style_context_get_changes (GtkStyleContext *context);

View File

@@ -63,6 +63,7 @@
#include "gtkplug.h"
#include "gtktypebuiltins.h"
#include "a11y/gtkwidgetaccessible.h"
#include "actors/gtkwidgetactorprivate.h"
/**
* SECTION:gtkwidget
@@ -321,9 +322,6 @@ struct _GtkWidgetPrivate
guint anchored : 1;
guint composite_child : 1;
guint no_window : 1;
guint realized : 1;
guint mapped : 1;
guint visible : 1;
guint sensitive : 1;
guint can_focus : 1;
guint has_focus : 1;
@@ -357,13 +355,8 @@ struct _GtkWidgetPrivate
/* SizeGroup related flags */
guint have_size_groups : 1;
/* The widget's name. If the widget does not have a name
* (the name is NULL), then its name (as returned by
* "gtk_widget_get_name") is its class's name.
* Among other things, the widget name is used to determine
* the style to use for a widget.
*/
gchar *name;
/* The base actor for the widget. */
GtkActor *actor;
/* The list of attached windows to this widget.
* We keep a list in order to call reset_style to all of them,
@@ -376,7 +369,6 @@ struct _GtkWidgetPrivate
* the font to use for text.
*/
GtkStyle *style;
GtkStyleContext *context;
/* Widget's path for styling */
GtkWidgetPath *path;
@@ -3503,8 +3495,8 @@ gtk_widget_get_property (GObject *object,
gpointer *eventp;
case PROP_NAME:
if (priv->name)
g_value_set_string (value, priv->name);
if (_gtk_css_box_get_id (GTK_CSS_BOX (priv->actor)))
g_value_set_string (value, _gtk_css_box_get_id (GTK_CSS_BOX (priv->actor)));
else
g_value_set_static_string (value, "");
break;
@@ -3655,8 +3647,11 @@ gtk_widget_init (GtkWidget *widget)
GtkWidgetPrivate);
priv = widget->priv;
priv->actor = g_object_new (GTK_TYPE_WIDGET_ACTOR,
"widget", widget,
"visible", FALSE, NULL);
priv->child_visible = TRUE;
priv->name = NULL;
priv->allocation.x = -1;
priv->allocation.y = -1;
priv->allocation.width = 1;
@@ -3926,8 +3921,7 @@ gtk_widget_unparent (GtkWidget *widget)
/* Unset BACKDROP since we are no longer inside a toplevel window */
gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_BACKDROP);
if (priv->context)
gtk_style_context_set_parent (priv->context, NULL);
gtk_style_context_set_parent (_gtk_css_actor_get_style_context (GTK_CSS_ACTOR (priv->actor)), NULL);
_gtk_widget_update_parent_muxer (widget);
@@ -4064,7 +4058,7 @@ gtk_widget_real_show (GtkWidget *widget)
if (!gtk_widget_get_visible (widget))
{
priv->visible = TRUE;
_gtk_widget_set_visible_flag (widget, TRUE);
if (priv->parent &&
gtk_widget_get_mapped (priv->parent) &&
@@ -4162,7 +4156,7 @@ gtk_widget_real_hide (GtkWidget *widget)
{
if (gtk_widget_get_visible (widget))
{
widget->priv->visible = FALSE;
_gtk_widget_set_visible_flag (widget, FALSE);
if (gtk_widget_get_mapped (widget))
gtk_widget_unmap (widget);
@@ -4246,9 +4240,6 @@ gtk_widget_map (GtkWidget *widget)
if (!gtk_widget_get_has_window (widget))
gdk_window_invalidate_rect (priv->window, &priv->allocation, FALSE);
if (widget->priv->context)
_gtk_style_context_update_animating (widget->priv->context);
gtk_widget_pop_verify_invariants (widget);
}
}
@@ -4277,9 +4268,6 @@ gtk_widget_unmap (GtkWidget *widget)
gdk_window_invalidate_rect (priv->window, &priv->allocation, FALSE);
_gtk_tooltip_hide (widget);
if (widget->priv->context)
_gtk_style_context_update_animating (widget->priv->context);
g_signal_emit (widget, widget_signals[UNMAP], 0);
gtk_widget_pop_verify_invariants (widget);
@@ -4522,11 +4510,11 @@ gtk_widget_unrealize (GtkWidget *widget)
{
g_object_ref (widget);
if (widget->priv->mapped)
if (gtk_widget_get_mapped (widget))
gtk_widget_unmap (widget);
g_signal_emit (widget, widget_signals[UNREALIZE], 0);
g_assert (!widget->priv->mapped);
g_assert (!gtk_widget_get_mapped (widget));
gtk_widget_set_realized (widget, FALSE);
g_object_unref (widget);
@@ -5163,7 +5151,7 @@ gtk_widget_real_size_allocate (GtkWidget *widget,
{
GtkWidgetPrivate *priv = widget->priv;
priv->allocation = *allocation;
gtk_widget_set_allocation (widget, allocation);
if (gtk_widget_get_realized (widget) &&
gtk_widget_get_has_window (widget))
@@ -6711,6 +6699,7 @@ static void
gtk_widget_real_style_updated (GtkWidget *widget)
{
GtkWidgetPrivate *priv = widget->priv;
const GtkBitmask *changes;
gtk_widget_update_pango_context (widget);
@@ -6726,28 +6715,20 @@ gtk_widget_real_style_updated (GtkWidget *widget)
widget->priv->style);
}
if (widget->priv->context)
{
const GtkBitmask *changes = _gtk_style_context_get_changes (widget->priv->context);
changes = _gtk_style_context_get_changes (gtk_widget_get_style_context (widget));
if (gtk_widget_get_realized (widget) &&
gtk_widget_get_has_window (widget) &&
!gtk_widget_get_app_paintable (widget))
gtk_style_context_set_background (widget->priv->context,
widget->priv->window);
if (gtk_widget_get_realized (widget) &&
gtk_widget_get_has_window (widget) &&
!gtk_widget_get_app_paintable (widget))
gtk_style_context_set_background (gtk_widget_get_style_context (widget),
widget->priv->window);
if (widget->priv->anchored)
{
if (changes && _gtk_css_style_property_changes_affect_size (changes))
gtk_widget_queue_resize (widget);
else
gtk_widget_queue_draw (widget);
}
}
else
if (widget->priv->anchored)
{
if (widget->priv->anchored)
if (changes && _gtk_css_style_property_changes_affect_size (changes))
gtk_widget_queue_resize (widget);
else
gtk_widget_queue_draw (widget);
}
}
@@ -7219,15 +7200,12 @@ gtk_widget_set_name (GtkWidget *widget,
const gchar *name)
{
GtkWidgetPrivate *priv;
gchar *new_name;
g_return_if_fail (GTK_IS_WIDGET (widget));
priv = widget->priv;
new_name = g_strdup (name);
g_free (priv->name);
priv->name = new_name;
_gtk_css_box_set_id (GTK_CSS_BOX (priv->actor), name);
_gtk_widget_invalidate_style_context (widget, GTK_CSS_CHANGE_NAME);
@@ -7247,14 +7225,14 @@ gtk_widget_set_name (GtkWidget *widget,
const gchar*
gtk_widget_get_name (GtkWidget *widget)
{
GtkWidgetPrivate *priv;
const char *name;
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
priv = widget->priv;
name = _gtk_css_box_get_id (GTK_CSS_BOX (widget->priv->actor));
if (priv->name)
return priv->name;
if (name)
return name;
return G_OBJECT_TYPE_NAME (widget);
}
@@ -7494,7 +7472,17 @@ void
_gtk_widget_set_visible_flag (GtkWidget *widget,
gboolean visible)
{
widget->priv->visible = visible;
gboolean was_mapped = gtk_widget_get_mapped (widget);
gboolean was_realized = gtk_widget_get_realized (widget);
if (visible)
_gtk_widget_actor_show (widget->priv->actor);
else
_gtk_widget_actor_hide (widget->priv->actor);
g_assert (_gtk_actor_get_visible (widget->priv->actor) == visible);
g_assert (was_mapped == gtk_widget_get_mapped (widget));
g_assert (was_realized == gtk_widget_get_realized (widget));
}
/**
@@ -7518,7 +7506,7 @@ gtk_widget_get_visible (GtkWidget *widget)
{
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
return widget->priv->visible;
return _gtk_actor_get_visible (widget->priv->actor);
}
/**
@@ -7543,12 +7531,10 @@ gtk_widget_is_visible (GtkWidget *widget)
while (widget)
{
GtkWidgetPrivate *priv = widget->priv;
if (!priv->visible)
if (!gtk_widget_get_visible (widget))
return FALSE;
widget = priv->parent;
widget = gtk_widget_get_parent (widget);
}
return TRUE;
@@ -7664,7 +7650,7 @@ gtk_widget_get_realized (GtkWidget *widget)
{
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
return widget->priv->realized;
return _gtk_actor_get_realized (widget->priv->actor);
}
/**
@@ -7683,9 +7669,21 @@ void
gtk_widget_set_realized (GtkWidget *widget,
gboolean realized)
{
gboolean was_visible, was_mapped;
g_return_if_fail (GTK_IS_WIDGET (widget));
widget->priv->realized = realized;
was_visible = gtk_widget_get_visible (widget);
was_mapped = gtk_widget_get_mapped (widget);
if (realized)
_gtk_widget_actor_realize (widget->priv->actor);
else
_gtk_widget_actor_unrealize (widget->priv->actor);
g_assert (_gtk_actor_get_realized (widget->priv->actor) == realized);
g_assert (was_visible == gtk_widget_get_visible (widget));
g_assert (was_mapped == gtk_widget_get_mapped (widget));
}
/**
@@ -7703,7 +7701,7 @@ gtk_widget_get_mapped (GtkWidget *widget)
{
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
return widget->priv->mapped;
return _gtk_actor_get_mapped (widget->priv->actor);
}
/**
@@ -7722,9 +7720,21 @@ void
gtk_widget_set_mapped (GtkWidget *widget,
gboolean mapped)
{
gboolean was_visible, was_realized;
g_return_if_fail (GTK_IS_WIDGET (widget));
widget->priv->mapped = mapped;
was_visible = gtk_widget_get_visible (widget);
was_realized = gtk_widget_get_realized (widget);
if (mapped)
_gtk_widget_actor_map (widget->priv->actor);
else
_gtk_widget_actor_unmap (widget->priv->actor);
g_assert (_gtk_actor_get_mapped (widget->priv->actor) == mapped);
g_assert (was_visible == gtk_widget_get_visible (widget));
g_assert (was_realized == gtk_widget_get_realized (widget));
}
/**
@@ -8021,9 +8031,8 @@ gtk_widget_set_parent (GtkWidget *widget,
data.flags_to_unset = 0;
gtk_widget_propagate_state (widget, &data);
if (priv->context)
gtk_style_context_set_parent (priv->context,
gtk_widget_get_style_context (parent));
gtk_style_context_set_parent (_gtk_css_actor_get_style_context (GTK_CSS_ACTOR (priv->actor)),
gtk_widget_get_style_context (parent));
_gtk_widget_update_parent_muxer (widget);
@@ -8323,8 +8332,7 @@ do_screen_change (GtkWidget *widget,
_gtk_tooltip_hide (widget);
if (new_screen && priv->context)
gtk_style_context_set_screen (priv->context, new_screen);
_gtk_widget_actor_screen_changed (priv->actor, new_screen, old_screen);
g_signal_emit (widget, widget_signals[SCREEN_CHANGED], 0, old_screen);
}
@@ -8539,15 +8547,15 @@ gtk_widget_verify_invariants (GtkWidget *widget)
parent = widget->priv->parent;
if (widget->priv->mapped)
if (gtk_widget_get_mapped (widget))
{
/* Mapped implies ... */
if (!widget->priv->realized)
if (!gtk_widget_get_realized (widget))
g_warning ("%s %p is mapped but not realized",
G_OBJECT_TYPE_NAME (widget), widget);
if (!widget->priv->visible)
if (!gtk_widget_get_visible (widget))
g_warning ("%s %p is mapped but not visible",
G_OBJECT_TYPE_NAME (widget), widget);
@@ -8583,7 +8591,7 @@ gtk_widget_verify_invariants (GtkWidget *widget)
if (parent == NULL || parent->priv->verifying_invariants_count == 0)
{
if (parent &&
parent->priv->realized)
gtk_widget_get_realized (parent))
{
/* Parent realized implies... */
@@ -8603,20 +8611,20 @@ gtk_widget_verify_invariants (GtkWidget *widget)
{
/* No parent or parent not realized on non-toplevel implies... */
if (widget->priv->realized && !widget->priv->in_reparent)
if (gtk_widget_get_realized (widget) && !widget->priv->in_reparent)
g_warning ("%s %p is not realized but child %s %p is realized",
parent ? G_OBJECT_TYPE_NAME (parent) : "no parent", parent,
G_OBJECT_TYPE_NAME (widget), widget);
}
if (parent &&
parent->priv->mapped &&
widget->priv->visible &&
gtk_widget_get_mapped (parent) &&
gtk_widget_get_visible (widget) &&
widget->priv->child_visible)
{
/* Parent mapped and we are visible implies... */
if (!widget->priv->mapped)
if (!gtk_widget_get_mapped (widget))
g_warning ("%s %p is mapped but visible child %s %p is not mapped",
G_OBJECT_TYPE_NAME (parent), parent,
G_OBJECT_TYPE_NAME (widget), widget);
@@ -8625,17 +8633,17 @@ gtk_widget_verify_invariants (GtkWidget *widget)
{
/* No parent or parent not mapped on non-toplevel implies... */
if (widget->priv->mapped && !widget->priv->in_reparent)
if (gtk_widget_get_mapped (widget) && !widget->priv->in_reparent)
g_warning ("%s %p is mapped but visible=%d child_visible=%d parent %s %p mapped=%d",
G_OBJECT_TYPE_NAME (widget), widget,
widget->priv->visible,
gtk_widget_get_visible (widget),
widget->priv->child_visible,
parent ? G_OBJECT_TYPE_NAME (parent) : "no parent", parent,
parent ? parent->priv->mapped : FALSE);
parent ? gtk_widget_get_mapped (parent) : FALSE);
}
}
if (!widget->priv->realized)
if (!gtk_widget_get_realized (widget))
{
/* Not realized implies... */
@@ -10331,7 +10339,7 @@ gtk_widget_dispose (GObject *object)
else if (gtk_widget_get_visible (widget))
gtk_widget_hide (widget);
priv->visible = FALSE;
_gtk_widget_actor_hide (priv->actor);
if (gtk_widget_get_realized (widget))
gtk_widget_unrealize (widget);
@@ -10390,11 +10398,12 @@ gtk_widget_finalize (GObject *object)
gtk_grab_remove (widget);
g_object_unref (priv->actor);
priv->actor = NULL;
g_object_unref (priv->style);
priv->style = NULL;
g_free (priv->name);
aux_info = gtk_widget_get_aux_info (widget, FALSE);
if (aux_info)
gtk_widget_aux_info_destroy (aux_info);
@@ -10406,12 +10415,6 @@ gtk_widget_finalize (GObject *object)
if (priv->path)
gtk_widget_path_free (priv->path);
if (priv->context)
{
_gtk_style_context_set_widget (priv->context, NULL);
g_object_unref (priv->context);
}
_gtk_size_request_cache_free (&priv->requests);
if (g_object_is_floating (object))
@@ -10505,7 +10508,7 @@ gtk_widget_real_unrealize (GtkWidget *widget)
{
GtkWidgetPrivate *priv = widget->priv;
g_assert (!widget->priv->mapped);
g_assert (!gtk_widget_get_mapped (widget));
/* printf ("unrealizing %s\n", g_type_name (G_TYPE_FROM_INSTANCE (widget)));
*/
@@ -10958,7 +10961,7 @@ gtk_widget_propagate_state (GtkWidget *widget,
if (!gtk_widget_is_sensitive (widget) && gtk_widget_has_grab (widget))
gtk_grab_remove (widget);
gtk_style_context_set_state (gtk_widget_get_style_context (widget), new_flags);
_gtk_css_box_set_state (GTK_CSS_BOX (priv->actor), new_flags);
g_signal_emit (widget, widget_signals[STATE_CHANGED], 0, old_state);
g_signal_emit (widget, widget_signals[STATE_FLAGS_CHANGED], 0, old_flags);
@@ -12681,8 +12684,7 @@ gtk_widget_buildable_custom_finished (GtkBuildable *buildable,
static GtkSizeRequestMode
gtk_widget_real_get_request_mode (GtkWidget *widget)
{
/* By default widgets dont trade size at all. */
return GTK_SIZE_REQUEST_CONSTANT_SIZE;
return _gtk_widget_actor_get_request_mode (widget->priv->actor);
}
static void
@@ -12690,11 +12692,17 @@ gtk_widget_real_get_width (GtkWidget *widget,
gint *minimum_size,
gint *natural_size)
{
gfloat min, nat;
_gtk_widget_actor_get_preferred_size (widget->priv->actor,
GTK_ORIENTATION_HORIZONTAL,
-1,
&min, &nat);
if (minimum_size)
*minimum_size = 0;
*minimum_size = min;
if (natural_size)
*natural_size = 0;
*natural_size = nat;
}
static void
@@ -12702,11 +12710,17 @@ gtk_widget_real_get_height (GtkWidget *widget,
gint *minimum_size,
gint *natural_size)
{
gfloat min, nat;
_gtk_widget_actor_get_preferred_size (widget->priv->actor,
GTK_ORIENTATION_VERTICAL,
-1,
&min, &nat);
if (minimum_size)
*minimum_size = 0;
*minimum_size = min;
if (natural_size)
*natural_size = 0;
*natural_size = nat;
}
static void
@@ -12715,7 +12729,24 @@ gtk_widget_real_get_height_for_width (GtkWidget *widget,
gint *minimum_height,
gint *natural_height)
{
GTK_WIDGET_GET_CLASS (widget)->get_preferred_height (widget, minimum_height, natural_height);
if (GTK_WIDGET_GET_CLASS (widget)->get_preferred_height == gtk_widget_real_get_height)
{
gfloat min, nat;
_gtk_widget_actor_get_preferred_size (widget->priv->actor,
GTK_ORIENTATION_VERTICAL,
width,
&min, &nat);
if (minimum_height)
*minimum_height = min;
if (natural_height)
*natural_height = nat;
}
else
{
GTK_WIDGET_GET_CLASS (widget)->get_preferred_height (widget, minimum_height, natural_height);
}
}
static void
@@ -12724,7 +12755,24 @@ gtk_widget_real_get_width_for_height (GtkWidget *widget,
gint *minimum_width,
gint *natural_width)
{
GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget, minimum_width, natural_width);
if (GTK_WIDGET_GET_CLASS (widget)->get_preferred_width == gtk_widget_real_get_width)
{
gfloat min, nat;
_gtk_widget_actor_get_preferred_size (widget->priv->actor,
GTK_ORIENTATION_HORIZONTAL,
height,
&min, &nat);
if (minimum_width)
*minimum_width = min;
if (natural_width)
*natural_width = nat;
}
else
{
GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget, minimum_width, natural_width);
}
}
/**
@@ -13518,6 +13566,10 @@ gtk_widget_set_allocation (GtkWidget *widget,
priv = widget->priv;
priv->allocation = *allocation;
_gtk_widget_actor_allocate (priv->actor,
allocation->x, allocation->y,
allocation->width, allocation->height);
}
/**
@@ -13888,6 +13940,8 @@ gint
gtk_widget_path_append_for_widget (GtkWidgetPath *path,
GtkWidget *widget)
{
GList *classes, *l;
const char *name;
gint pos;
g_return_val_if_fail (path != NULL, 0);
@@ -13895,23 +13949,19 @@ gtk_widget_path_append_for_widget (GtkWidgetPath *path,
pos = gtk_widget_path_append_type (path, G_OBJECT_TYPE (widget));
if (widget->priv->name)
gtk_widget_path_iter_set_name (path, pos, widget->priv->name);
name = _gtk_css_box_get_id (GTK_CSS_BOX (widget->priv->actor));
if (name)
gtk_widget_path_iter_set_name (path, pos, name);
if (widget->priv->context)
{
GList *classes, *l;
/* Also add any persistent classes in
* the style context the widget path
*/
classes = gtk_style_context_list_classes (gtk_widget_get_style_context (widget));
/* Also add any persistent classes in
* the style context the widget path
*/
classes = gtk_style_context_list_classes (widget->priv->context);
for (l = classes; l; l = l->next)
gtk_widget_path_iter_add_class (path, pos, l->data);
for (l = classes; l; l = l->next)
gtk_widget_path_iter_add_class (path, pos, l->data);
g_list_free (classes);
}
g_list_free (classes);
return pos;
}
@@ -13971,7 +14021,7 @@ gtk_widget_get_path (GtkWidget *widget)
}
void
_gtk_widget_style_context_invalidated (GtkWidget *widget)
_gtk_widget_emit_style_updated (GtkWidget *widget)
{
if (widget->priv->path)
{
@@ -13990,6 +14040,15 @@ _gtk_widget_style_context_invalidated (GtkWidget *widget)
}
}
/* actor is guaranteed to be a GtkCssBox */
GtkActor *
_gtk_widget_get_actor (GtkWidget *widget)
{
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
return widget->priv->actor;
}
/**
* gtk_widget_get_style_context:
* @widget: a #GtkWidget
@@ -14002,46 +14061,16 @@ _gtk_widget_style_context_invalidated (GtkWidget *widget)
GtkStyleContext *
gtk_widget_get_style_context (GtkWidget *widget)
{
GtkWidgetPrivate *priv;
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
priv = widget->priv;
if (G_UNLIKELY (priv->context == NULL))
{
GdkScreen *screen;
priv->context = gtk_style_context_new ();
gtk_style_context_set_state (priv->context, priv->state_flags);
screen = gtk_widget_get_screen (widget);
if (screen)
gtk_style_context_set_screen (priv->context, screen);
if (priv->parent)
gtk_style_context_set_parent (priv->context,
gtk_widget_get_style_context (priv->parent));
_gtk_style_context_set_widget (priv->context, widget);
}
return widget->priv->context;
return _gtk_css_actor_get_style_context (GTK_CSS_ACTOR (widget->priv->actor));
}
void
_gtk_widget_invalidate_style_context (GtkWidget *widget,
GtkCssChange change)
{
GtkWidgetPrivate *priv;
priv = widget->priv;
if (priv->context == NULL)
return;
_gtk_style_context_queue_invalidate (priv->context, change);
_gtk_style_context_queue_invalidate (gtk_widget_get_style_context (widget), change);
}
/**

View File

@@ -28,6 +28,7 @@
#include "gtkcsstypesprivate.h"
#include "gtkwidget.h"
#include "gactionmuxer.h"
#include "actors/gtkactorprivate.h"
G_BEGIN_DECLS
@@ -131,10 +132,13 @@ void _gtk_widget_set_captured_event_handler (GtkWidget
gboolean _gtk_widget_captured_event (GtkWidget *widget,
GdkEvent *event);
GtkActor * _gtk_widget_get_actor (GtkWidget *widget);
void _gtk_widget_emit_style_updated (GtkWidget *widget);
GtkWidgetPath * _gtk_widget_create_path (GtkWidget *widget);
void _gtk_widget_invalidate_style_context (GtkWidget *widget,
GtkCssChange change);
void _gtk_widget_style_context_invalidated (GtkWidget *widget);
void _gtk_widget_update_parent_muxer (GtkWidget *widget);
GActionMuxer * _gtk_widget_get_action_muxer (GtkWidget *widget);