Compare commits
24 Commits
matthiasc/
...
wip/actor
Author | SHA1 | Date | |
---|---|---|---|
|
77a059162b | ||
|
3bbe53689a | ||
|
0d60250917 | ||
|
cb31648aa3 | ||
|
2081d36e88 | ||
|
37fa22c608 | ||
|
a137e66648 | ||
|
8c8a0e1bd6 | ||
|
fe956e983c | ||
|
17cb423a71 | ||
|
49a6d85310 | ||
|
2f691d4097 | ||
|
46570d6a76 | ||
|
f7ef7c11d3 | ||
|
e84af768f9 | ||
|
e6f5e4e448 | ||
|
bbe48d8144 | ||
|
ce2c4b2de0 | ||
|
cc86c700eb | ||
|
ec4516264b | ||
|
d85dacd40c | ||
|
99e9dc83fa | ||
|
55f3ad0bf3 | ||
|
38df4155b7 |
@@ -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
|
||||
|
@@ -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
82
gtk/actors/Makefile.am
Normal 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
2521
gtk/actors/gtkactor.c
Normal file
File diff suppressed because it is too large
Load Diff
176
gtk/actors/gtkactorprivate.h
Normal file
176
gtk/actors/gtkactorprivate.h
Normal 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
230
gtk/actors/gtkbinlayout.c
Normal 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));
|
||||
}
|
87
gtk/actors/gtkbinlayoutprivate.h
Normal file
87
gtk/actors/gtkbinlayoutprivate.h
Normal 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
362
gtk/actors/gtkcssactor.c
Normal 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, >k_css_actor_source, actor);
|
||||
}
|
||||
|
63
gtk/actors/gtkcssactorprivate.h
Normal file
63
gtk/actors/gtkcssactorprivate.h
Normal 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
689
gtk/actors/gtkcssbox.c
Normal 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;
|
||||
}
|
72
gtk/actors/gtkcssboxprivate.h
Normal file
72
gtk/actors/gtkcssboxprivate.h
Normal 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
516
gtk/actors/gtkcsstext.c
Normal 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));
|
||||
}
|
||||
|
67
gtk/actors/gtkcsstextprivate.h
Normal file
67
gtk/actors/gtkcsstextprivate.h
Normal 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__ */
|
498
gtk/actors/gtklayoutmanager.c
Normal file
498
gtk/actors/gtklayoutmanager.c
Normal 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;
|
||||
*
|
||||
* /* retrieve the layout meta-object */
|
||||
* meta = _gtk_layout_manager_get_child_meta (manager,
|
||||
* container,
|
||||
* child);
|
||||
* my_meta = MY_LAYOUT_META (meta);
|
||||
*
|
||||
* /* compute the desired allocation for the child */
|
||||
* compute_allocation (self, my_meta, child,
|
||||
* allocation, flags,
|
||||
* &child_box);
|
||||
*
|
||||
* /* this is the additional code that deals with the animation
|
||||
* * of the layout manager
|
||||
* */
|
||||
* if (!self->is_animating)
|
||||
* {
|
||||
* /* store the last stable allocation for later use */
|
||||
* my_meta->last_alloc = _gtk_actor_box_copy (&child_box);
|
||||
* }
|
||||
* else
|
||||
* {
|
||||
* GtkActorBox end = { 0, };
|
||||
* gdouble p;
|
||||
*
|
||||
* /* get the progress of the animation */
|
||||
* p = _gtk_layout_manager_get_animation_progress (manager);
|
||||
*
|
||||
* if (my_meta->last_alloc != NULL)
|
||||
* {
|
||||
* /* copy the desired allocation as the final state */
|
||||
* end = child_box;
|
||||
*
|
||||
* /* then interpolate the initial and final state
|
||||
* * depending on the progress of the animation,
|
||||
* * and put the result inside the box we will use
|
||||
* * to allocate the child
|
||||
* */
|
||||
* _gtk_actor_box_interpolate (my_meta->last_alloc,
|
||||
* &end,
|
||||
* p,
|
||||
* &child_box);
|
||||
* }
|
||||
* else
|
||||
* {
|
||||
* /* if there is no stable allocation then the child was
|
||||
* * added while animating; one possible course of action
|
||||
* * is to just bail out and fall through to the allocation
|
||||
* * to position the child directly at its final state
|
||||
* */
|
||||
* my_meta->last_alloc =
|
||||
* _gtk_actor_box_copy (&child_box);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* /* allocate the child */
|
||||
* _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;
|
||||
}
|
134
gtk/actors/gtklayoutmanagerprivate.h
Normal file
134
gtk/actors/gtklayoutmanagerprivate.h
Normal 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
225
gtk/actors/gtkwidgetactor.c
Normal 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);
|
||||
}
|
||||
}
|
76
gtk/actors/gtkwidgetactorprivate.h
Normal file
76
gtk/actors/gtkwidgetactorprivate.h
Normal 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__ */
|
@@ -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 = >K_CSS_MATCHER_ACTOR;
|
||||
matcher->actor.actor = GTK_ACTOR (box);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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,
|
||||
|
@@ -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,
|
||||
|
@@ -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));
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
|
321
gtk/gtkwidget.c
321
gtk/gtkwidget.c
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user