Compare commits

...

22 Commits

Author SHA1 Message Date
Benjamin Otte
1c44454854 image: Only redraw changed parts of the picture, not the full picture 2011-02-14 19:33:05 +01:00
Benjamin Otte
fe3b6ffc7a gtk: Make region argument to gtk_widget_queue_Draw_region() const 2011-02-14 19:33:04 +01:00
Benjamin Otte
1be6566272 gtk: Rewrite GtkImage to only use pictures
The code now creates pictures of the correct type if you use
gtk_image_set_from_whatever(). This hugely simplifies the generic code
of GtkImage.
2011-02-14 19:33:04 +01:00
Benjamin Otte
403260b18b testpicture: Add an animation demo 2011-02-14 19:33:04 +01:00
Benjamin Otte
db3d517c22 gdk: Add GdkPixbufAnimationPicture
Does nothing but display a GdkPixbufAnimation. :)
2011-02-14 19:33:04 +01:00
Benjamin Otte
d8d33bfa0c testpicture: Add icon theme examples 2011-02-14 19:33:04 +01:00
Benjamin Otte
4c7c292a04 testpicture: Add scribble area
Requires a custom picture subclass. And all the code in 180 lines,
woohoo!
2011-02-14 19:33:04 +01:00
Benjamin Otte
9223264b7a gtk: Add GtkNamedPicture
Supposed to be used for named icons. See gtk_image_set_icon_name() for
what it replaces.
2011-02-14 19:33:04 +01:00
Benjamin Otte
67e2fec6e1 gtk: Add GtkIconPicture
It' supposed to be used to get a picture for a GIcon
2011-02-14 19:33:04 +01:00
Benjamin Otte
3770c98f6e gtk: Add GtkIconThemePicture
This is the abstract base class for icons from icon themes. It will be
used by subclasses for GIcon and icon names.
2011-02-14 19:33:04 +01:00
Benjamin Otte
f9257fba91 tests: Handle invalidations properly in rotating drawingarea 2011-02-14 19:33:04 +01:00
Benjamin Otte
b32c135abb tests: Add testpicture test
Needs more fun, but I can add that later.
2011-02-14 19:33:04 +01:00
Benjamin Otte
9ef7ae541b gtk: Add GtkIconSetPicture
Does what it says.
2011-02-14 19:33:03 +01:00
Benjamin Otte
0df9f21109 gtk: Add GtkStockPicture
It's a GdkPicture displaying a stock icon.
2011-02-14 19:33:03 +01:00
Benjamin Otte
d6dcd5e51c gtk: Add GtkIconPicture
It's a GdkPicture for an icon from an icontheme.
2011-02-14 19:33:03 +01:00
Benjamin Otte
5f230589bb gtk: Add a private GtkStyledPicture
It's supposed to handle our use cases for styling. And it's better to
write this code only once after all.
2011-02-14 19:33:03 +01:00
Benjamin Otte
1d927e872e gdk: Add GdkPictureLoader
It loads pictures, surprise!
2011-02-14 19:33:03 +01:00
Benjamin Otte
252ccb129f gtk: Add the ability to set a GdkPicture on a GtkImage 2011-02-14 19:33:03 +01:00
Benjamin Otte
9668dcba7d gtk: Add GtkStylablePicture
This interface allows adding styling information to GdkPicture
subclasses that can be used by widgets to draw them.
2011-02-14 19:33:03 +01:00
Benjamin Otte
e56f013698 gdk: Add GdkPixbufPicture
This allows an easy transition from pixbufs to pictures.
I probably went a bit overboard with the keep-pixbuf and keep-surface
settings, but oh well...

xxx: pixbufpicture
2011-02-14 19:32:59 +01:00
Benjamin Otte
ad7ab0f781 gdk: Make creating a surface from a pixbuf an intenral function 2011-02-14 19:24:02 +01:00
Benjamin Otte
edb1cb5569 gdk: Introduce GdkPicture
It's an API that's intended to replace GdkPixbuf.
2011-02-14 19:24:02 +01:00
37 changed files with 5781 additions and 878 deletions

View File

@@ -79,7 +79,11 @@ gdk_public_h_sources = \
gdkkeysyms-compat.h \
gdkmain.h \
gdkpango.h \
gdkpicture.h \
gdkpictureloader.h \
gdkpixbuf.h \
gdkpixbufpicture.h \
gdkpixbufanimationpicture.h \
gdkprivate.h \
gdkproperty.h \
gdkrectangle.h \
@@ -128,7 +132,11 @@ gdk_c_sources = \
gdkkeyuni.c \
gdkoffscreenwindow.c \
gdkpango.c \
gdkpicture.c \
gdkpictureloader.c \
gdkpixbuf-drawable.c \
gdkpixbufanimationpicture.c \
gdkpixbufpicture.c \
gdkrectangle.c \
gdkrgba.c \
gdkscreen.c \

View File

@@ -45,7 +45,11 @@
#include <gdk/gdkkeysyms.h>
#include <gdk/gdkmain.h>
#include <gdk/gdkpango.h>
#include <gdk/gdkpicture.h>
#include <gdk/gdkpictureloader.h>
#include <gdk/gdkpixbuf.h>
#include <gdk/gdkpixbufpicture.h>
#include <gdk/gdkpixbufanimationpicture.h>
#include <gdk/gdkproperty.h>
#include <gdk/gdkrectangle.h>
#include <gdk/gdkrgba.h>

View File

@@ -231,6 +231,25 @@ gdk_pango_context_get_for_screen
gdk_pango_layout_get_clip_region
gdk_pango_layout_line_get_clip_region
gdk_parse_args
gdk_picture_changed
gdk_picture_changed_rect
gdk_picture_changed_region
gdk_picture_draw
gdk_picture_get_height
gdk_picture_get_type
gdk_picture_get_width
gdk_picture_loader_get_error
gdk_picture_loader_get_picture
gdk_picture_loader_get_type G_GNUC_CONST
gdk_picture_loader_load_from_stream
gdk_picture_loader_load_from_stream_async
gdk_picture_loader_load_from_file
gdk_picture_loader_load_from_file_async
gdk_picture_loader_load_from_filename
gdk_picture_loader_load_from_filename_async
gdk_picture_loader_new
gdk_picture_ref_surface
gdk_picture_resized
gdk_pixbuf_get_from_surface
gdk_pixbuf_get_from_window
gdk_pointer_grab

View File

@@ -194,6 +194,16 @@ gdk_cairo_set_source_pixbuf (cairo_t *cr,
const GdkPixbuf *pixbuf,
gdouble pixbuf_x,
gdouble pixbuf_y)
{
cairo_surface_t *surface;
surface = _gdk_cairo_create_surface_for_pixbuf (pixbuf);
cairo_set_source_surface (cr, surface, pixbuf_x, pixbuf_y);
cairo_surface_destroy (surface);
}
cairo_surface_t *
_gdk_cairo_create_surface_for_pixbuf (const GdkPixbuf *pixbuf)
{
gint width = gdk_pixbuf_get_width (pixbuf);
gint height = gdk_pixbuf_get_height (pixbuf);
@@ -277,8 +287,7 @@ gdk_cairo_set_source_pixbuf (cairo_t *cr,
cairo_pixels += cairo_stride;
}
cairo_set_source_surface (cr, surface, pixbuf_x, pixbuf_y);
cairo_surface_destroy (surface);
return surface;
}
/**

View File

@@ -285,6 +285,8 @@ void gdk_synthesize_window_state (GdkWindow *window,
gboolean _gdk_cairo_surface_extents (cairo_surface_t *surface,
GdkRectangle *extents);
cairo_surface_t *_gdk_cairo_create_surface_for_pixbuf (const GdkPixbuf *pixbuf);
/*************************************
* Interfaces used by windowing code *
*************************************/

371
gdk/gdkpicture.c Normal file
View File

@@ -0,0 +1,371 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 2010 Benjamin Otte <otte@gnome.org>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include "gdkpicture.h"
#include <cairo-gobject.h>
#include "gdkintl.h"
struct _GdkPicturePrivate {
int width;
int height;
};
G_DEFINE_ABSTRACT_TYPE (GdkPicture, gdk_picture, G_TYPE_OBJECT)
enum {
PROP_0,
PROP_WIDTH,
PROP_HEIGHT
};
enum {
RESIZED,
CHANGED,
LAST_SIGNAL
};
static guint signals [LAST_SIGNAL] = { 0 };
/**
* SECTION:gdkpicture
* @Short_description: pixel areas to display
* @Title: GdkPicture
* @See_also: #GdkMotionPicture
*
* A #GdkPicture is used to represent a pixel area of a specific size.
* Its main job is being the interface between applications that want
* to display pictures without a lot of work and people that want to
* provide pictures that can be rendered.
*
* Pictures can resize themselves and change their contents over time.
* If you need to react to updates, you should connect to the
* GdkPicture::resized and GdkPicture::changed signals.
*
* A lot of #GdkPicture subclasses require a running main loop, so if
* you want to use #GdkPicture without a main loop, you need to make
* sure that it actually works.
*
* #GdkPicture is meant to replace #GdkPixbuf.
*/
static void
gdk_picture_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GdkPicture *picture = GDK_PICTURE (object);
GdkPicturePrivate *priv = picture->priv;
switch (prop_id)
{
case PROP_WIDTH:
g_value_set_int (value, priv->width);
break;
case PROP_HEIGHT:
g_value_set_int (value, priv->height);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static cairo_surface_t *
gdk_picture_fallback_ref_surface (GdkPicture *picture)
{
GdkPicturePrivate *priv = picture->priv;
cairo_surface_t *surface;
cairo_t *cr;
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
priv->width,
priv->height);
cr = cairo_create (surface);
gdk_picture_draw (picture, cr);
cairo_destroy (cr);
return surface;
}
static void
gdk_picture_fallback_draw (GdkPicture *picture,
cairo_t *cr)
{
cairo_surface_t *surface;
surface = gdk_picture_ref_surface (picture);
cairo_set_source_surface (cr, surface, 0, 0);
cairo_surface_destroy (surface);
cairo_paint (cr);
}
static void
gdk_picture_class_init (GdkPictureClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->get_property = gdk_picture_get_property;
klass->ref_surface = gdk_picture_fallback_ref_surface;
klass->draw = gdk_picture_fallback_draw;
/**
* GdkPicture:width:
*
* Number of pixels in the x direction.
*
* Since: 3.2
*/
g_object_class_install_property (object_class,
PROP_WIDTH,
g_param_spec_int ("width",
P_("width"),
P_("Number of pixels in x direction"),
0, G_MAXINT, 0,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
/**
* GdkPicture:height:
*
* Number of pixels in the y direction.
*
* Since: 3.2
*/
g_object_class_install_property (object_class,
PROP_HEIGHT,
g_param_spec_int ("height",
P_("height"),
P_("Number of pixels in y direction"),
0, G_MAXINT, 0,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
/**
* GdkPicture::changed:
* @picture: the #GdkPicture that changed.
* @region: the region that was changed
*
* The ::changed signal is emitted when the contents of a @picture
* have changed and a redraw of parts of the @picture are necessary.
* The given @region specifies the area that has changed.
*/
signals[CHANGED] =
g_signal_new (g_intern_static_string ("changed"),
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
g_cclosure_marshal_VOID__BOXED,
G_TYPE_NONE, 1, CAIRO_GOBJECT_TYPE_REGION);
/**
* GdkPicture::resized:
* @picture: the #GdkPicture that changed size
*
* The ::resize signal is emitted when the width or height of a
* @picture has changed. This and a redraw of parts of the
* @picture are necessary.
* After the emission of this signal, a #GdkPicture::changed
* signal will be emitted, so it might not be necessary to connect
* to both signals.
*/
signals[RESIZED] =
g_signal_new (g_intern_static_string ("resized"),
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
g_type_class_add_private (klass, sizeof (GdkPicturePrivate));
}
static void
gdk_picture_init (GdkPicture *picture)
{
picture->priv = G_TYPE_INSTANCE_GET_PRIVATE (picture,
GDK_TYPE_PICTURE,
GdkPicturePrivate);
}
/**
* gdk_picture_get_width:
* @picture: the picture
*
* Gets the width of the @picture. That is the number of pixels in the
* X direction. Note that the width may be 0 in certain cases, like
* when a picture hasn't finished loading from a file yet.
*
* Returns: The width of @picture
**/
int
gdk_picture_get_width (GdkPicture *picture)
{
g_return_val_if_fail (GDK_IS_PICTURE (picture), 0);
return picture->priv->width;
}
/**
* gdk_picture_get_height:
* @picture: the picture
*
* Gets the height of the @picture. That is the number of pixels in the
* Y direction. Note that the width may be 0 in certain cases, like
* when a picture hasn't finished loading from a file yet.
*
* Returns: The height of @picture
**/
int
gdk_picture_get_height (GdkPicture *picture)
{
g_return_val_if_fail (GDK_IS_PICTURE (picture), 0);
return picture->priv->height;
}
/**
* gdk_picture_ref_surface:
* @picture: the picture to get the surface from
*
* Gets a #cairo_surface_t representing the @picture. This function is
* useful when you don't just want to draw @picture, but do more
* sophisticated things, like use it in a cairo_mask() call. You must not
* modify the returned surface.
* If you just want to draw the @picture, calling gdk_picture_draw() is
*
* Returns: (transfer full): A surface representing @picture. The surface
* remains a valid representation of @picture's contents until the next
* time the GdkPicture::changed signal is emitted. Use
* cairo_surface_destroy() to free the returned surface.
**/
cairo_surface_t *
gdk_picture_ref_surface (GdkPicture *picture)
{
GdkPictureClass *picture_class;
g_return_val_if_fail (GDK_IS_PICTURE (picture), NULL);
picture_class = GDK_PICTURE_GET_CLASS (picture);
return picture_class->ref_surface (picture);
}
/**
* gdk_picture_draw:
* @picture: the picture to draw
* @cr: the cairo context to draw to
*
* Draws the given @picture to the given cairo context. The cairo context
* should be set to default values for everything but the source and the
* matrix. Otherwise the results are undefined.
**/
void
gdk_picture_draw (GdkPicture *picture,
cairo_t *cr)
{
GdkPictureClass *picture_class;
g_return_if_fail (GDK_IS_PICTURE (picture));
picture_class = GDK_PICTURE_GET_CLASS (picture);
cairo_save (cr);
picture_class->draw (picture, cr);
cairo_restore (cr);
}
void
gdk_picture_resized (GdkPicture *picture,
int new_width,
int new_height)
{
GObject *object;
GdkPicturePrivate *priv;
g_return_if_fail (GDK_IS_PICTURE (picture));
g_return_if_fail (new_width >= 0);
g_return_if_fail (new_height >= 0);
object = G_OBJECT (picture);
priv = picture->priv;
g_object_freeze_notify (object);
priv->width = new_width;
g_object_notify (object, "width");
priv->height = new_height;
g_object_notify (object, "height");
g_object_thaw_notify (object);
g_signal_emit (picture, signals[RESIZED], 0);
gdk_picture_changed (picture);
}
void
gdk_picture_changed (GdkPicture *picture)
{
GdkPicturePrivate *priv;
cairo_rectangle_int_t rect;
g_return_if_fail (GDK_IS_PICTURE (picture));
priv = picture->priv;
rect.x = 0;
rect.y = 0;
rect.width = priv->width;
rect.height = priv->height;
gdk_picture_changed_rect (picture, &rect);
}
void
gdk_picture_changed_rect (GdkPicture *picture,
const cairo_rectangle_int_t *rect)
{
cairo_region_t *region;
g_return_if_fail (GDK_IS_PICTURE (picture));
region = cairo_region_create_rectangle (rect);
gdk_picture_changed_region (picture, region);
cairo_region_destroy (region);
}
void
gdk_picture_changed_region (GdkPicture *picture,
const cairo_region_t *region)
{
g_return_if_fail (GDK_IS_PICTURE (picture));
g_signal_emit (picture, signals[CHANGED], 0, region);
}

80
gdk/gdkpicture.h Normal file
View File

@@ -0,0 +1,80 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 2010 Benjamin Otte <otte@gnome.org>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION)
#error "Only <gdk/gdk.h> can be included directly."
#endif
#ifndef __GDK_PICTURE_H__
#define __GDK_PICTURE_H__
#include <glib-object.h>
#include <cairo.h>
G_BEGIN_DECLS
#define GDK_TYPE_PICTURE (gdk_picture_get_type ())
#define GDK_PICTURE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_PICTURE, GdkPicture))
#define GDK_PICTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_PICTURE, GdkPictureClass))
#define GDK_IS_PICTURE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_PICTURE))
#define GDK_IS_PICTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_PICTURE))
#define GDK_PICTURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_PICTURE, GdkPictureClass))
typedef struct _GdkPicture GdkPicture;
typedef struct _GdkPicturePrivate GdkPicturePrivate;
typedef struct _GdkPictureClass GdkPictureClass;
struct _GdkPicture {
GObject parent_object;
GdkPicturePrivate *priv;
};
struct _GdkPictureClass {
GObjectClass parent_class;
/* need to implement one of these */
cairo_surface_t * (* ref_surface) (GdkPicture *picture);
void (* draw) (GdkPicture *picture,
cairo_t *cr);
};
GType gdk_picture_get_type (void);
int gdk_picture_get_width (GdkPicture *picture);
int gdk_picture_get_height (GdkPicture *picture);
cairo_surface_t * gdk_picture_ref_surface (GdkPicture *picture);
void gdk_picture_draw (GdkPicture *picture,
cairo_t *cr);
/* for implementing subclasses only */
void gdk_picture_resized (GdkPicture *picture,
int new_width,
int new_height);
void gdk_picture_changed (GdkPicture *picture);
void gdk_picture_changed_rect (GdkPicture *picture,
const cairo_rectangle_int_t *rect);
void gdk_picture_changed_region (GdkPicture *picture,
const cairo_region_t *region);
G_END_DECLS
#endif /* __GDK_PICTURE_H__ */

677
gdk/gdkpictureloader.c Normal file
View File

@@ -0,0 +1,677 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 2010 Benjamin Otte <otte@gnome.org>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include "gdkpictureloader.h"
#include "gdkintl.h"
#include "gdkinternals.h"
#include "gdkpixbuf.h"
typedef struct _GdkPictureAsyncLoad GdkPictureAsyncLoad;
struct _GdkPictureLoaderPrivate {
GdkPictureAsyncLoad *load;
GdkPicture *picture;
GError *error;
};
struct _GdkPictureAsyncLoad {
GdkPictureLoader *loader;
GdkPixbufLoader *pixbuf_loader;
guchar buffer[4096];
int io_priority;
GCancellable *cancellable;
GAsyncReadyCallback callback;
gpointer user_data;
};
G_DEFINE_TYPE (GdkPictureLoader, gdk_picture_loader, GDK_TYPE_PICTURE)
enum {
PROP_0,
PROP_PICTURE,
PROP_ERROR,
};
/**
* SECTION:gdkpictureloader
* @Short_description: Loading images into Pictures
* @Title: GdkPictureLoader
* @See_also: #GdkPicture
*
* A #GdkPictureLoader is an implementation of #GdkPicture that can load
* images from a stream. It takes care of figuring out the format,
* decoding the image and error handling.
*/
static void
gdk_picture_loader_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GdkPictureLoader *loader = GDK_PICTURE_LOADER (object);
GdkPictureLoaderPrivate *priv = loader->priv;
switch (prop_id)
{
case PROP_PICTURE:
g_value_set_object (value, priv->picture);
break;
case PROP_ERROR:
g_value_set_boxed (value, priv->error);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gdk_picture_loader_draw (GdkPicture *picture,
cairo_t *cr)
{
GdkPictureLoader *loader = GDK_PICTURE_LOADER (picture);
GdkPictureLoaderPrivate *priv = loader->priv;
if (priv->error)
{
/* FIXME: Draw broken image icon */
cairo_set_source_rgb (cr, 1, 0, 0);
cairo_rectangle (cr, 0, 0,
gdk_picture_get_width (picture),
gdk_picture_get_height (picture));
cairo_fill (cr);
return;
}
if (priv->picture)
{
gdk_picture_draw (priv->picture, cr);
return;
}
if (priv->load)
{
/* FIXME: Draw loading icon */
cairo_set_source_rgb (cr, 0, 0, 1);
cairo_rectangle (cr, 0, 0,
gdk_picture_get_width (picture),
gdk_picture_get_height (picture));
cairo_fill (cr);
return;
}
/* no load happening, size should be empty */
g_assert (gdk_picture_get_width (picture) == 0);
g_assert (gdk_picture_get_height (picture) == 0);
return;
}
static void
gdk_picture_loader_class_init (GdkPictureLoaderClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdkPictureClass *picture_class = GDK_PICTURE_CLASS (klass);
object_class->get_property = gdk_picture_loader_get_property;
picture_class->draw = gdk_picture_loader_draw;
/**
* GdkPictureLoader:picture:
*
* The picture that is loading or %NULL if loading hasn't processed
* enough or no the loader is in an error.
*
* Since: 3.2
*/
g_object_class_install_property (object_class,
PROP_PICTURE,
g_param_spec_object ("picture",
P_("picture"),
P_("the loading picture"),
GDK_TYPE_PICTURE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
/**
* GdkPictureLoader:error:
*
* The error that happened during loading or %NULL if no error happened yet.
*
* Since: 3.2
*/
g_object_class_install_property (object_class,
PROP_ERROR,
g_param_spec_boxed ("error",
P_("error"),
P_("error that happened during load"),
G_TYPE_ERROR,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
g_type_class_add_private (klass, sizeof (GdkPictureLoaderPrivate));
}
static void
gdk_picture_loader_init (GdkPictureLoader *loader)
{
loader->priv = G_TYPE_INSTANCE_GET_PRIVATE (loader,
GDK_TYPE_PICTURE_LOADER,
GdkPictureLoaderPrivate);
}
/**
* gdk_picture_loader_new:
*
* Creates a new #GdkPictureLoader for loading images.
*
* Returns: a new picture
**/
GdkPicture *
gdk_picture_loader_new (void)
{
return g_object_new (GDK_TYPE_PICTURE_LOADER, NULL);
}
/**
* gdk_picture_loader_get_error:
* @loader: the loader to check
*
* If there was an error while loading the image, it can be queried
* with this function. Otherwise, %NULL is returned.
*
* Returns: The error that @loader is in or %NULL if none
**/
const GError *
gdk_picture_loader_get_error (GdkPictureLoader *loader)
{
g_return_val_if_fail (GDK_IS_PICTURE_LOADER (loader), NULL);
return loader->priv->error;
}
/**
* gdk_picture_loader_get_picture:
* @loader: the loader to get the picture from
*
* Gets the picture that is currently loading or has been loaded. If
* there is an error or the load has not progressed enough
*
* Returns: (transfer none) (allow-none): a %GdkPicture or %NULL.
**/
GdkPicture *
gdk_picture_loader_get_picture (GdkPictureLoader *loader)
{
g_return_val_if_fail (GDK_IS_PICTURE_LOADER (loader), NULL);
return loader->priv->picture;
}
static void
gdk_picture_loader_reset (GdkPictureLoader *loader)
{
GdkPictureLoaderPrivate *priv = loader->priv;
if (priv->load) {
if (priv->load->loader)
g_object_unref (priv->load->loader);
priv->load->loader = NULL;
priv->load = NULL;
}
if (priv->error) {
g_error_free (priv->error);
priv->error = NULL;
g_object_notify (G_OBJECT (loader), "error");
}
if (priv->picture) {
g_object_unref (priv->picture);
priv->picture = NULL;
g_object_notify (G_OBJECT (loader), "picture");
}
gdk_picture_resized (GDK_PICTURE (loader), 0, 0);
}
static void
gdk_picture_loader_handle_error (GdkPictureLoader *loader,
GError ** error)
{
GdkPictureLoaderPrivate *priv = loader->priv;
g_assert (priv->error);
if (error)
*error = g_error_copy (priv->error);
g_object_notify (G_OBJECT (loader), "error");
}
static void
gdk_picture_loader_size_prepared (GdkPixbufLoader *loader,
int width,
int height,
GdkPictureLoader *picture)
{
gdk_picture_resized (GDK_PICTURE (picture), width, height);
}
static void
gdk_picture_loader_area_prepared (GdkPixbufLoader *loader,
GdkPictureLoader *picture)
{
GdkPictureLoaderPrivate *priv = picture->priv;
priv->picture = gdk_pixbuf_picture_new (gdk_pixbuf_loader_get_pixbuf (loader));
g_assert (gdk_picture_get_width (priv->picture) == gdk_picture_get_width (GDK_PICTURE (picture)));
g_assert (gdk_picture_get_height (priv->picture) == gdk_picture_get_height (GDK_PICTURE (picture)));
g_object_notify (G_OBJECT (picture), "picture");
}
static void
gdk_picture_loader_area_updated (GdkPixbufLoader *loader,
int x,
int y,
int width,
int height,
GdkPictureLoader *picture)
{
cairo_rectangle_int_t rect = { x, y, width, height };
gdk_picture_changed_rect (picture->priv->picture, &rect);
gdk_picture_changed_rect (GDK_PICTURE (picture), &rect);
}
static GdkPixbufLoader *
gdk_picture_loader_create_loader (GdkPictureLoader *loader)
{
GdkPixbufLoader *pixbuf_loader;
pixbuf_loader = gdk_pixbuf_loader_new ();
g_signal_connect (pixbuf_loader,
"size-prepared",
G_CALLBACK (gdk_picture_loader_size_prepared),
loader);
g_signal_connect (pixbuf_loader,
"area-prepared",
G_CALLBACK (gdk_picture_loader_area_prepared),
loader);
g_signal_connect (pixbuf_loader,
"area-updated",
G_CALLBACK (gdk_picture_loader_area_updated),
loader);
return pixbuf_loader;
}
void
gdk_picture_loader_load_from_stream (GdkPictureLoader *loader,
GInputStream * stream,
GCancellable * cancellable,
GError ** error)
{
GdkPictureLoaderPrivate *priv;
GdkPixbufLoader *pixbuf_loader;
guchar buffer[4096];
gssize bytes_read;
g_return_if_fail (GDK_IS_PICTURE_LOADER (loader));
g_return_if_fail (G_IS_INPUT_STREAM (stream));
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
priv = loader->priv;
pixbuf_loader = gdk_picture_loader_create_loader (loader);
do
{
bytes_read = g_input_stream_read (stream,
buffer,
sizeof (buffer),
cancellable,
&priv->error);
if (bytes_read > 0)
{
if (!gdk_pixbuf_loader_write (pixbuf_loader,
buffer,
bytes_read,
&priv->error))
bytes_read = -1;
}
else if (bytes_read == 0)
{
if (!gdk_pixbuf_loader_close (pixbuf_loader,
&priv->error))
bytes_read = -1;
}
if (bytes_read < 0)
gdk_picture_loader_handle_error (loader, error);
}
while (bytes_read > 0);
g_object_unref (pixbuf_loader);
}
void
gdk_picture_loader_load_from_file (GdkPictureLoader *loader,
GFile * file,
GCancellable * cancellable,
GError ** error)
{
GdkPictureLoaderPrivate *priv;
GFileInputStream *stream;
g_return_if_fail (GDK_IS_PICTURE_LOADER (loader));
g_return_if_fail (G_IS_FILE (file));
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
priv = loader->priv;
gdk_picture_loader_reset (loader);
stream = g_file_read (file, cancellable, &priv->error);
if (stream == NULL)
{
gdk_picture_loader_handle_error (loader, error);
return;
}
gdk_picture_loader_load_from_stream (loader,
G_INPUT_STREAM (stream),
cancellable,
error);
g_object_unref (stream);
}
void
gdk_picture_loader_load_from_filename (GdkPictureLoader *loader,
const char * filename,
GCancellable * cancellable,
GError ** error)
{
GFile *file;
g_return_if_fail (GDK_IS_PICTURE_LOADER (loader));
g_return_if_fail (filename != NULL);
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
file = g_file_new_for_path (filename);
gdk_picture_loader_load_from_file (loader, file, cancellable, error);
g_object_unref (file);
}
static GdkPictureAsyncLoad *
gdk_picture_async_load_new (GdkPictureLoader * loader,
int io_priority,
GCancellable * cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GdkPictureAsyncLoad *data = g_slice_new0 (GdkPictureAsyncLoad);
data->loader = g_object_ref (loader);
data->io_priority = io_priority;
data->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
data->callback = callback;
data->user_data = user_data;
data->pixbuf_loader = gdk_picture_loader_create_loader (loader);
loader->priv->load = data;
return data;
}
static void
gdk_picture_async_load_destroy (GdkPictureAsyncLoad *data)
{
if (data->loader && data->loader->priv->load == data)
data->loader->priv->load = NULL;
if (data->callback)
data->callback (G_OBJECT (data->loader), NULL, data->user_data);
g_object_unref (data->loader);
if (data->cancellable)
g_object_unref (data->cancellable);
g_object_unref (data->pixbuf_loader);
g_slice_free (GdkPictureAsyncLoad, data);
}
static void
gdk_picture_async_load_handle_error (GdkPictureAsyncLoad *data)
{
gdk_picture_loader_handle_error (data->loader, NULL);
gdk_picture_async_load_destroy (data);
}
static gboolean
gdk_picture_load_check_active (GdkPictureAsyncLoad *data)
{
return data != NULL && data->loader != NULL;
}
static void
gdk_picture_loader_close_callback (GObject * object,
GAsyncResult *res,
gpointer user_data)
{
GInputStream *stream = G_INPUT_STREAM (object);
GdkPictureAsyncLoad *data = user_data;
GdkPictureLoaderPrivate *priv;
/* Do we need to call this? */
if (!gdk_picture_load_check_active (data))
{
g_input_stream_close_finish (stream, res, NULL);
return;
}
priv = data->loader->priv;
if (!g_input_stream_close_finish (stream, res, &priv->error))
{
gdk_picture_async_load_handle_error (data);
return;
}
gdk_picture_async_load_destroy (data);
}
static void
gdk_picture_loader_read_callback (GObject * object,
GAsyncResult *res,
gpointer user_data)
{
GdkPictureAsyncLoad *data = user_data;
GInputStream *stream = G_INPUT_STREAM (object);
if (gdk_picture_load_check_active (data))
{
GdkPictureLoaderPrivate *priv = data->loader->priv;
gssize bytes_read;
bytes_read = g_input_stream_read_finish (stream, res, &priv->error);
if (bytes_read > 0)
{
if (gdk_pixbuf_loader_write (data->pixbuf_loader,
data->buffer,
bytes_read,
&priv->error))
{
g_input_stream_read_async (stream,
data->buffer,
sizeof (data->buffer),
data->io_priority,
data->cancellable,
gdk_picture_loader_read_callback,
data);
return;
}
bytes_read = -1;
}
else if (bytes_read == 0)
{
if (!gdk_pixbuf_loader_close (data->pixbuf_loader,
&priv->error))
bytes_read = -1;
}
if (bytes_read < 0)
{
g_input_stream_close_async (stream,
data->io_priority,
data->cancellable,
gdk_picture_loader_close_callback,
NULL);
gdk_picture_async_load_handle_error (data);
return;
}
}
g_input_stream_close_async (stream,
data->io_priority,
data->cancellable,
gdk_picture_loader_close_callback,
data);
}
static void
gdk_picture_async_load_start (GdkPictureAsyncLoad *data,
GInputStream *stream)
{
g_input_stream_read_async (stream,
data->buffer,
sizeof (data->buffer),
data->io_priority,
data->cancellable,
gdk_picture_loader_read_callback,
data);
}
void
gdk_picture_loader_load_from_stream_async (GdkPictureLoader * loader,
GInputStream * stream,
int io_priority,
GCancellable * cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GdkPictureAsyncLoad *data;
GdkPictureLoaderPrivate *priv;
g_return_if_fail (GDK_IS_PICTURE_LOADER (loader));
g_return_if_fail (G_IS_INPUT_STREAM (stream));
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
priv = loader->priv;
gdk_picture_loader_reset (loader);
data = gdk_picture_async_load_new (loader,
io_priority,
cancellable,
callback,
user_data);
gdk_picture_async_load_start (data, stream);
}
static void
gdk_picture_loader_file_read_callback (GObject * object,
GAsyncResult *res,
gpointer user_data)
{
GdkPictureAsyncLoad *data = user_data;
GFile *file = G_FILE (object);
GdkPictureLoaderPrivate *priv = data->loader->priv;
GInputStream *stream;
stream = G_INPUT_STREAM (g_file_read_finish (file, res, &priv->error));
if (stream == NULL)
{
gdk_picture_async_load_handle_error (data);
return;
}
if (gdk_picture_load_check_active (data))
gdk_picture_async_load_start (data, stream);
g_object_unref (stream);
}
void
gdk_picture_loader_load_from_file_async (GdkPictureLoader * loader,
GFile * file,
int io_priority,
GCancellable * cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GdkPictureAsyncLoad *load;
GdkPictureLoaderPrivate *priv;
g_return_if_fail (GDK_IS_PICTURE_LOADER (loader));
g_return_if_fail (G_IS_FILE (file));
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
priv = loader->priv;
gdk_picture_loader_reset (loader);
load = gdk_picture_async_load_new (loader,
io_priority,
cancellable,
callback,
user_data);
g_file_read_async (file,
io_priority,
cancellable,
gdk_picture_loader_file_read_callback,
load);
}
void
gdk_picture_loader_load_from_filename_async (GdkPictureLoader * loader,
const char * filename,
int io_priority,
GCancellable * cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GFile *file;
g_return_if_fail (GDK_IS_PICTURE_LOADER (loader));
g_return_if_fail (filename != NULL);
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
file = g_file_new_for_path (filename);
gdk_picture_loader_load_from_file_async (loader,
file,
io_priority,
cancellable,
callback,
user_data);
g_object_unref (file);
}

96
gdk/gdkpictureloader.h Normal file
View File

@@ -0,0 +1,96 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 2010 Benjamin Otte <otte@gnome.org>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION)
#error "Only <gdk/gdk.h> can be included directly."
#endif
#ifndef __GDK_PICTURE_LOADER_H__
#define __GDK_PICTURE_LOADER_H__
#include <gdk/gdkpicture.h>
#include <gio/gio.h>
G_BEGIN_DECLS
#define GDK_TYPE_PICTURE_LOADER (gdk_picture_loader_get_type ())
#define GDK_PICTURE_LOADER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_PICTURE_LOADER, GdkPictureLoader))
#define GDK_PICTURE_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_PICTURE_LOADER, GdkPictureLoaderClass))
#define GDK_IS_PICTURE_LOADER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_PICTURE_LOADER))
#define GDK_IS_PICTURE_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_PICTURE_LOADER))
#define GDK_PICTURE_LOADER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_PICTURE_LOADER, GdkPictureLoaderClass))
typedef struct _GdkPictureLoader GdkPictureLoader;
typedef struct _GdkPictureLoaderPrivate GdkPictureLoaderPrivate;
typedef struct _GdkPictureLoaderClass GdkPictureLoaderClass;
struct _GdkPictureLoader {
GdkPicture parent_picture;
GdkPictureLoaderPrivate *priv;
};
struct _GdkPictureLoaderClass {
GdkPictureClass parent_class;
};
GType gdk_picture_loader_get_type (void);
GdkPicture * gdk_picture_loader_new (void);
const GError * gdk_picture_loader_get_error (GdkPictureLoader * loader);
GdkPicture * gdk_picture_loader_get_picture (GdkPictureLoader * loader);
void gdk_picture_loader_load_from_stream (GdkPictureLoader * loader,
GInputStream * stream,
GCancellable * cancellable,
GError ** error);
void gdk_picture_loader_load_from_file (GdkPictureLoader * loader,
GFile * file,
GCancellable * cancellable,
GError ** error);
void gdk_picture_loader_load_from_filename (GdkPictureLoader * loader,
const char * filename,
GCancellable * cancellable,
GError ** error);
void gdk_picture_loader_load_from_stream_async(GdkPictureLoader * loader,
GInputStream * stream,
int io_priority,
GCancellable * cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
void gdk_picture_loader_load_from_file_async (GdkPictureLoader * loader,
GFile * file,
int io_priority,
GCancellable * cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
void gdk_picture_loader_load_from_filename_async (GdkPictureLoader *loader,
const char * filename,
int io_priority,
GCancellable * cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
G_END_DECLS
#endif /* __GDK_PICTURE_LOADER_H__ */

View File

@@ -0,0 +1,277 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 2010 Benjamin Otte <otte@gnome.org>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include "gdkpixbufanimationpicture.h"
#include <cairo-gobject.h>
#include "gdkintl.h"
#include "gdkinternals.h"
struct _GdkPixbufAnimationPicturePrivate {
GdkPixbufAnimation *animation;
GdkPixbufAnimationIter *iter;
guint timeout_id;
};
G_DEFINE_TYPE (GdkPixbufAnimationPicture, gdk_pixbuf_animation_picture, GDK_TYPE_PICTURE)
enum {
PROP_0,
PROP_ANIMATION,
};
/**
* SECTION:gdkpixbufanimationpicture
* @Short_description: Pictures for pixbuf animations
* @Title: GdkPixbufAnimationPicture
* @See_also: #GdkPicture, #GdkPixbufAnimation
*
* A #GdkPixbufAnimationPicture is an implementation of #GdkPicture for a
* #GdkPixbufAnimation. It is meant to help in the porting of applications
* from #GdkPixbuf use to #GdkPicture use.
*
* You should try not to use it for newly written code.
*/
static void
gdk_pixbuf_animation_picture_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GdkPixbufAnimationPicture *picture = GDK_PIXBUF_ANIMATION_PICTURE (object);
GdkPixbufAnimationPicturePrivate *priv = picture->priv;
switch (prop_id)
{
case PROP_ANIMATION:
g_value_set_object (value, priv->animation);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gdk_pixbuf_animation_picture_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GdkPixbufAnimationPicture *picture = GDK_PIXBUF_ANIMATION_PICTURE (object);
switch (prop_id)
{
case PROP_ANIMATION:
gdk_pixbuf_animation_picture_set_animation (picture, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gdk_pixbuf_animation_picture_dispose (GObject *object)
{
GdkPixbufAnimationPicture *picture = GDK_PIXBUF_ANIMATION_PICTURE (object);
gdk_pixbuf_animation_picture_set_animation (picture, NULL);
G_OBJECT_CLASS (gdk_pixbuf_animation_picture_parent_class)->dispose (object);
}
static cairo_surface_t *
gdk_pixbuf_animation_picture_ref_surface (GdkPicture *picture)
{
GdkPixbufAnimationPicture *animation = GDK_PIXBUF_ANIMATION_PICTURE (picture);
GdkPixbufAnimationPicturePrivate *priv = animation->priv;
if (!priv->animation)
return cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0);
if (!priv->iter)
return _gdk_cairo_create_surface_for_pixbuf (gdk_pixbuf_animation_get_static_image (priv->animation));
return _gdk_cairo_create_surface_for_pixbuf (gdk_pixbuf_animation_iter_get_pixbuf (priv->iter));
}
static void
gdk_pixbuf_animation_picture_class_init (GdkPixbufAnimationPictureClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdkPictureClass *picture_class = GDK_PICTURE_CLASS (klass);
object_class->get_property = gdk_pixbuf_animation_picture_get_property;
object_class->set_property = gdk_pixbuf_animation_picture_set_property;
object_class->dispose = gdk_pixbuf_animation_picture_dispose;
picture_class->ref_surface = gdk_pixbuf_animation_picture_ref_surface;
/**
* GdkPixbufAnimationPicture:animation:
*
* The animation to be drawn or %NULL if none was set.
*
* Since: 3.2
*/
g_object_class_install_property (object_class,
PROP_ANIMATION,
g_param_spec_object ("animation",
P_("Animation"),
P_("the pixbuf animation to display"),
GDK_TYPE_PIXBUF_ANIMATION,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_type_class_add_private (klass, sizeof (GdkPixbufAnimationPicturePrivate));
}
static void
gdk_pixbuf_animation_picture_init (GdkPixbufAnimationPicture *picture)
{
GdkPixbufAnimationPicturePrivate *priv;
picture->priv = G_TYPE_INSTANCE_GET_PRIVATE (picture,
GDK_TYPE_PIXBUF_ANIMATION_PICTURE,
GdkPixbufAnimationPicturePrivate);
priv = picture->priv;
}
/**
* gdk_pixbuf_animation_picture_new:
* @animation: the pixbuf animation to create the picture with or %NULL
*
* Creates a new #GdkPixbufAnimationPicture displaying the given @pixbuf_animation.
*
* Returns: a new picture
**/
GdkPicture *
gdk_pixbuf_animation_picture_new (GdkPixbufAnimation *animation)
{
g_return_val_if_fail (animation == NULL || GDK_IS_PIXBUF_ANIMATION (animation), NULL);
return g_object_new (GDK_TYPE_PIXBUF_ANIMATION_PICTURE, "animation", animation, NULL);
}
static void
gdk_pixbuf_animation_iter_remove_timeout (GdkPixbufAnimationPicture *picture)
{
GdkPixbufAnimationPicturePrivate *priv = picture->priv;
if (priv->timeout_id == 0)
return;
g_source_remove (priv->timeout_id);
priv->timeout_id = 0;
}
static gboolean gdk_pixbuf_animation_iter_timeout_callback (gpointer data);
static void
gdk_pixbuf_animation_iter_add_timeout (GdkPixbufAnimationPicture *picture)
{
GdkPixbufAnimationPicturePrivate *priv = picture->priv;
guint delay;
g_assert (!priv->timeout_id);
delay = gdk_pixbuf_animation_iter_get_delay_time (priv->iter);
if (delay > 0)
priv->timeout_id = gdk_threads_add_timeout (delay,
gdk_pixbuf_animation_iter_timeout_callback,
picture);
}
static gboolean
gdk_pixbuf_animation_iter_timeout_callback (gpointer data)
{
GdkPixbufAnimationPicture *picture = data;
GdkPixbufAnimationPicturePrivate *priv = picture->priv;
priv->timeout_id = 0;
gdk_pixbuf_animation_iter_advance (priv->iter, NULL);
gdk_pixbuf_animation_iter_add_timeout (picture);
gdk_picture_changed (GDK_PICTURE (picture));
return FALSE;
}
void
gdk_pixbuf_animation_picture_set_animation (GdkPixbufAnimationPicture *picture,
GdkPixbufAnimation * animation)
{
GdkPixbufAnimationPicturePrivate *priv;
g_return_if_fail (GDK_IS_PIXBUF_ANIMATION_PICTURE (picture));
g_return_if_fail (animation == NULL || GDK_IS_PIXBUF_ANIMATION (animation));
priv = picture->priv;
if (animation)
g_object_ref (animation);
if (priv->iter)
{
gdk_pixbuf_animation_iter_remove_timeout (picture);
g_object_unref (priv->iter);
priv->iter = NULL;
}
if (priv->animation)
{
g_object_unref (priv->animation);
priv->animation = NULL;
}
priv->animation = animation;
if (animation)
{
GdkPixbuf *pixbuf;
if (!gdk_pixbuf_animation_is_static_image (animation))
{
priv->iter = gdk_pixbuf_animation_get_iter (animation, NULL);
gdk_pixbuf_animation_iter_add_timeout (picture);
}
pixbuf = gdk_pixbuf_animation_get_static_image (animation);
gdk_picture_resized (GDK_PICTURE (picture),
gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf));
}
else
gdk_picture_resized (GDK_PICTURE (picture), 0, 0);
g_object_notify (G_OBJECT (picture), "animation");
}
GdkPixbufAnimation *
gdk_pixbuf_animation_picture_get_animation (GdkPixbufAnimationPicture *picture)
{
g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION_PICTURE (picture), NULL);
return picture->priv->animation;
}

View File

@@ -0,0 +1,66 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 2010 Benjamin Otte <otte@gnome.org>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION)
#error "Only <gdk/gdk.h> can be included directly."
#endif
#ifndef __GDK_PIXBUF_ANIMATION_PICTURE_H__
#define __GDK_PIXBUF_ANIMATION_PICTURE_H__
#include <gdk/gdkpicture.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
G_BEGIN_DECLS
#define GDK_TYPE_PIXBUF_ANIMATION_PICTURE (gdk_pixbuf_animation_picture_get_type ())
#define GDK_PIXBUF_ANIMATION_PICTURE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_PIXBUF_ANIMATION_PICTURE, GdkPixbufAnimationPicture))
#define GDK_PIXBUF_ANIMATION_PICTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_PIXBUF_ANIMATION_PICTURE, GdkPixbufAnimationPictureClass))
#define GDK_IS_PIXBUF_ANIMATION_PICTURE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_PIXBUF_ANIMATION_PICTURE))
#define GDK_IS_PIXBUF_ANIMATION_PICTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_PIXBUF_ANIMATION_PICTURE))
#define GDK_PIXBUF_ANIMATION_PICTURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_PIXBUF_ANIMATION_PICTURE, GdkPixbufAnimationPictureClass))
typedef struct _GdkPixbufAnimationPicture GdkPixbufAnimationPicture;
typedef struct _GdkPixbufAnimationPicturePrivate GdkPixbufAnimationPicturePrivate;
typedef struct _GdkPixbufAnimationPictureClass GdkPixbufAnimationPictureClass;
struct _GdkPixbufAnimationPicture {
GdkPicture parent_picture;
GdkPixbufAnimationPicturePrivate *priv;
};
struct _GdkPixbufAnimationPictureClass {
GdkPictureClass parent_class;
};
GType gdk_pixbuf_animation_picture_get_type (void);
GdkPicture * gdk_pixbuf_animation_picture_new (GdkPixbufAnimation *animation);
void gdk_pixbuf_animation_picture_set_animation (GdkPixbufAnimationPicture *picture,
GdkPixbufAnimation * animation);
GdkPixbufAnimation *
gdk_pixbuf_animation_picture_get_animation (GdkPixbufAnimationPicture *picture);
G_END_DECLS
#endif /* __GDK_PIXBUF_ANIMATION_PICTURE_H__ */

363
gdk/gdkpixbufpicture.c Normal file
View File

@@ -0,0 +1,363 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 2010 Benjamin Otte <otte@gnome.org>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include "gdkpixbufpicture.h"
#include <cairo-gobject.h>
#include "gdkintl.h"
#include "gdkinternals.h"
struct _GdkPixbufPicturePrivate {
GdkPixbuf *pixbuf;
cairo_surface_t *surface;
guint keep_pixbuf : 1;
guint keep_surface : 1;
};
G_DEFINE_TYPE (GdkPixbufPicture, gdk_pixbuf_picture, GDK_TYPE_PICTURE)
enum {
PROP_0,
PROP_PIXBUF,
PROP_KEEP_PIXBUF,
PROP_KEEP_SURFACE
};
/**
* SECTION:gdkpixbufpicture
* @Short_description: Pictures for pixbufs
* @Title: GdkPixbufPicture
* @See_also: #GdkPicture
*
* A #GdkPixbufPicture is an implementation of #GdkPicture for a #GdkPixbuf.
* It is meant to help in the porting of applications from #GdkPixbuf use
* to #GdkPicture use.
*
* You should try not to use it for newly written code.
*/
static void
gdk_pixbuf_picture_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GdkPixbufPicture *picture = GDK_PIXBUF_PICTURE (object);
GdkPixbufPicturePrivate *priv = picture->priv;
switch (prop_id)
{
case PROP_PIXBUF:
g_value_set_object (value, gdk_pixbuf_picture_get_pixbuf (picture));
break;
case PROP_KEEP_PIXBUF:
g_value_set_boolean (value, priv->keep_pixbuf);
break;
case PROP_KEEP_SURFACE:
g_value_set_boolean (value, priv->keep_surface);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gdk_pixbuf_picture_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GdkPixbufPicture *picture = GDK_PIXBUF_PICTURE (object);
switch (prop_id)
{
case PROP_PIXBUF:
gdk_pixbuf_picture_set_pixbuf (picture, g_value_get_object (value));
break;
case PROP_KEEP_PIXBUF:
gdk_pixbuf_picture_set_keep_pixbuf (picture, g_value_get_boolean (value));
break;
case PROP_KEEP_SURFACE:
gdk_pixbuf_picture_set_keep_surface (picture, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gdk_pixbuf_picture_dispose (GObject *object)
{
GdkPixbufPicture *picture = GDK_PIXBUF_PICTURE (object);
gdk_pixbuf_picture_set_pixbuf (picture, NULL);
G_OBJECT_CLASS (gdk_pixbuf_picture_parent_class)->dispose (object);
}
static cairo_surface_t *
gdk_pixbuf_picture_ref_surface (GdkPicture *picture)
{
GdkPixbufPicture *pixbuf_picture = GDK_PIXBUF_PICTURE (picture);
GdkPixbufPicturePrivate *priv = pixbuf_picture->priv;
cairo_surface_t *surface;
if (priv->surface)
return cairo_surface_reference (priv->surface);
if (priv->pixbuf)
surface = _gdk_cairo_create_surface_for_pixbuf (priv->pixbuf);
else
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0);
if (priv->keep_surface)
priv->surface = cairo_surface_reference (surface);
return surface;
}
static void
gdk_pixbuf_picture_class_init (GdkPixbufPictureClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdkPictureClass *picture_class = GDK_PICTURE_CLASS (klass);
object_class->get_property = gdk_pixbuf_picture_get_property;
object_class->set_property = gdk_pixbuf_picture_set_property;
object_class->dispose = gdk_pixbuf_picture_dispose;
picture_class->ref_surface = gdk_pixbuf_picture_ref_surface;
/**
* GdkPixbufPicture:pixbuf:
*
* The pixbuf to be drawn or %NULL if none was set or GdkPixbufPicture:keep-pixbuf
* is %FALSE.
*
* Since: 3.2
*/
g_object_class_install_property (object_class,
PROP_PIXBUF,
g_param_spec_object ("pixbuf",
P_("pixbuf"),
P_("the pixbuf to display"),
GDK_TYPE_PIXBUF,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* GdkPixbufPicture:keep-pixbuf:
*
* Whether to cache the pixbuf internally or to convert it into a #cairo_surface_t immediately.
*
* Since: 3.2
*/
g_object_class_install_property (object_class,
PROP_KEEP_PIXBUF,
g_param_spec_boolean ("keep-pixbuf",
P_("keep pixbuf"),
P_("TRUE to keep the pixbuf around"),
TRUE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
* GdkPixbufPicture:keep-surface:
*
* Whether to keep the #cairo_surface_t internally that was created when drawing the picture.
*
* Since: 3.2
*/
g_object_class_install_property (object_class,
PROP_KEEP_SURFACE,
g_param_spec_boolean ("keep-surface",
P_("keep surface"),
P_("TRUE to keep the surface around"),
FALSE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_type_class_add_private (klass, sizeof (GdkPixbufPicturePrivate));
}
static void
gdk_pixbuf_picture_init (GdkPixbufPicture *picture)
{
GdkPixbufPicturePrivate *priv;
picture->priv = G_TYPE_INSTANCE_GET_PRIVATE (picture,
GDK_TYPE_PIXBUF_PICTURE,
GdkPixbufPicturePrivate);
priv = picture->priv;
priv->keep_pixbuf = TRUE;
}
/**
* gdk_pixbuf_picture_new:
* @pixbuf: the pixbuf to create the picture with or %NULL
*
* Creates a new #GdkPixbufPicture displaying the given @pixbuf.
*
* Returns: a new picture
**/
GdkPicture *
gdk_pixbuf_picture_new (GdkPixbuf *pixbuf)
{
g_return_val_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf), NULL);
return g_object_new (GDK_TYPE_PIXBUF_PICTURE, "pixbuf", pixbuf, NULL);
}
void
gdk_pixbuf_picture_set_pixbuf (GdkPixbufPicture *picture,
GdkPixbuf * pixbuf)
{
GdkPixbufPicturePrivate *priv;
g_return_if_fail (GDK_IS_PIXBUF_PICTURE (picture));
g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf));
priv = picture->priv;
if (pixbuf)
g_object_ref (pixbuf);
if (priv->surface)
{
cairo_surface_destroy (priv->surface);
priv->surface = NULL;
}
if (priv->pixbuf)
{
g_object_unref (priv->pixbuf);
priv->pixbuf = NULL;
}
if (priv->keep_pixbuf)
{
priv->pixbuf = pixbuf;
}
else
{
if (pixbuf)
priv->surface = _gdk_cairo_create_surface_for_pixbuf (pixbuf);
}
g_object_notify (G_OBJECT (picture), "pixbuf");
if (pixbuf)
{
gdk_picture_resized (GDK_PICTURE (picture),
gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf));
}
else
gdk_picture_resized (GDK_PICTURE (picture), 0, 0);
}
GdkPixbuf *
gdk_pixbuf_picture_get_pixbuf (GdkPixbufPicture *picture)
{
g_return_val_if_fail (GDK_IS_PIXBUF_PICTURE (picture), NULL);
return picture->priv->pixbuf;
}
void
gdk_pixbuf_picture_set_keep_pixbuf (GdkPixbufPicture *picture,
gboolean keep_pixbuf)
{
GdkPixbufPicturePrivate *priv;
g_return_if_fail (GDK_IS_PIXBUF_PICTURE (picture));
priv = picture->priv;
if (priv->keep_pixbuf == keep_pixbuf)
return;
priv->keep_pixbuf = keep_pixbuf;
if (keep_pixbuf)
{
/* This is equal to setting the pixbuf to NULL because
* there's no pixbuf we could keep now. */
gdk_pixbuf_picture_set_pixbuf (picture, NULL);
}
else
{
gdk_pixbuf_picture_set_keep_surface (picture, TRUE);
if (priv->pixbuf)
{
priv->surface = _gdk_cairo_create_surface_for_pixbuf (priv->pixbuf);
g_object_unref (priv->pixbuf);
priv->pixbuf = NULL;
}
}
g_object_notify (G_OBJECT (picture), "keep-pixbuf");
}
gboolean
gdk_pixbuf_picture_get_keep_pixbuf (GdkPixbufPicture *picture)
{
g_return_val_if_fail (GDK_IS_PIXBUF_PICTURE (picture), FALSE);
return picture->priv->keep_pixbuf;
}
void
gdk_pixbuf_picture_set_keep_surface (GdkPixbufPicture *picture,
gboolean keep_surface)
{
GdkPixbufPicturePrivate *priv;
g_return_if_fail (GDK_IS_PIXBUF_PICTURE (picture));
priv = picture->priv;
if (priv->keep_surface == keep_surface)
return;
priv->keep_surface = keep_surface;
if (!keep_surface)
{
if (priv->surface)
{
cairo_surface_destroy (priv->surface);
priv->surface = NULL;
}
gdk_pixbuf_picture_set_keep_pixbuf (picture, TRUE);
}
g_object_notify (G_OBJECT (picture), "keep-surface");
}
gboolean
gdk_pixbuf_picture_get_keep_surface (GdkPixbufPicture *picture)
{
g_return_val_if_fail (GDK_IS_PIXBUF_PICTURE (picture), FALSE);
return picture->priv->keep_surface;
}

71
gdk/gdkpixbufpicture.h Normal file
View File

@@ -0,0 +1,71 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 2010 Benjamin Otte <otte@gnome.org>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION)
#error "Only <gdk/gdk.h> can be included directly."
#endif
#ifndef __GDK_PIXBUF_PICTURE_H__
#define __GDK_PIXBUF_PICTURE_H__
#include <gdk/gdkpicture.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
G_BEGIN_DECLS
#define GDK_TYPE_PIXBUF_PICTURE (gdk_pixbuf_picture_get_type ())
#define GDK_PIXBUF_PICTURE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_PIXBUF_PICTURE, GdkPixbufPicture))
#define GDK_PIXBUF_PICTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_PIXBUF_PICTURE, GdkPixbufPictureClass))
#define GDK_IS_PIXBUF_PICTURE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_PIXBUF_PICTURE))
#define GDK_IS_PIXBUF_PICTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_PIXBUF_PICTURE))
#define GDK_PIXBUF_PICTURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_PIXBUF_PICTURE, GdkPixbufPictureClass))
typedef struct _GdkPixbufPicture GdkPixbufPicture;
typedef struct _GdkPixbufPicturePrivate GdkPixbufPicturePrivate;
typedef struct _GdkPixbufPictureClass GdkPixbufPictureClass;
struct _GdkPixbufPicture {
GdkPicture parent_picture;
GdkPixbufPicturePrivate *priv;
};
struct _GdkPixbufPictureClass {
GdkPictureClass parent_class;
};
GType gdk_pixbuf_picture_get_type (void);
GdkPicture * gdk_pixbuf_picture_new (GdkPixbuf *pixbuf);
void gdk_pixbuf_picture_set_pixbuf (GdkPixbufPicture *picture,
GdkPixbuf * pixbuf);
GdkPixbuf * gdk_pixbuf_picture_get_pixbuf (GdkPixbufPicture *picture);
void gdk_pixbuf_picture_set_keep_pixbuf (GdkPixbufPicture *picture,
gboolean keep_pixbuf);
gboolean gdk_pixbuf_picture_get_keep_pixbuf (GdkPixbufPicture *picture);
void gdk_pixbuf_picture_set_keep_surface (GdkPixbufPicture *picture,
gboolean keep_surface);
gboolean gdk_pixbuf_picture_get_keep_surface (GdkPixbufPicture *picture);
G_END_DECLS
#endif /* __GDK_PIXBUF_PICTURE_H__ */

View File

@@ -227,7 +227,10 @@ gtk_public_h_sources = \
gtkhseparator.h \
gtkhsv.h \
gtkiconfactory.h \
gtkiconpicture.h \
gtkiconsetpicture.h \
gtkicontheme.h \
gtkiconthemepicture.h \
gtkiconview.h \
gtkimage.h \
gtkimagemenuitem.h \
@@ -251,6 +254,7 @@ gtk_public_h_sources = \
gtkmisc.h \
gtkmodules.h \
gtkmountoperation.h \
gtknamedpicture.h \
gtknotebook.h \
gtknumerableicon.h \
gtkoffscreenwindow.h \
@@ -296,6 +300,8 @@ gtk_public_h_sources = \
gtkstatusbar.h \
gtkstatusicon.h \
gtkstock.h \
gtkstockpicture.h \
gtkstylablepicture.h \
gtkstylecontext.h \
gtkstyleproperties.h \
gtkstyleprovider.h \
@@ -427,6 +433,7 @@ gtk_private_h_sources = \
gtksizegroup-private.h \
gtksocketprivate.h \
gtkstylecontextprivate.h \
gtkstyledpicture.h \
gtktextbtree.h \
gtktextbufferserialize.h \
gtktextchildprivate.h \
@@ -545,7 +552,10 @@ gtk_base_c_sources = \
gtkiconcache.c \
gtkiconcachevalidator.c \
gtkiconfactory.c \
gtkiconpicture.c \
gtkiconsetpicture.c \
gtkicontheme.c \
gtkiconthemepicture.c \
gtkiconview.c \
gtkimage.c \
gtkimagemenuitem.c \
@@ -573,6 +583,7 @@ gtk_base_c_sources = \
gtkmodifierstyle.c \
gtkmodules.c \
gtkmountoperation.c \
gtknamedpicture.c \
gtknotebook.c \
gtknumerableicon.c \
gtkoffscreenwindow.c \
@@ -622,7 +633,10 @@ gtk_base_c_sources = \
gtkstatusbar.c \
gtkstatusicon.c \
gtkstock.c \
gtkstockpicture.c \
gtkstylablepicture.c \
gtkstylecontext.c \
gtkstyledpicture.c \
gtkstyleproperties.c \
gtkstyleprovider.c \
gtkstyle.c \

View File

@@ -113,7 +113,10 @@
#include <gtk/gtkhseparator.h>
#include <gtk/gtkhsv.h>
#include <gtk/gtkiconfactory.h>
#include <gtk/gtkiconpicture.h>
#include <gtk/gtkiconsetpicture.h>
#include <gtk/gtkicontheme.h>
#include <gtk/gtkiconthemepicture.h>
#include <gtk/gtkiconview.h>
#include <gtk/gtkimage.h>
#include <gtk/gtkimagemenuitem.h>
@@ -136,6 +139,7 @@
#include <gtk/gtkmisc.h>
#include <gtk/gtkmodules.h>
#include <gtk/gtkmountoperation.h>
#include <gtk/gtknamedpicture.h>
#include <gtk/gtknotebook.h>
#include <gtk/gtknumerableicon.h>
#include <gtk/gtkoffscreenwindow.h>
@@ -179,6 +183,8 @@
#include <gtk/gtkstatusbar.h>
#include <gtk/gtkstatusicon.h>
#include <gtk/gtkstock.h>
#include <gtk/gtkstockpicture.h>
#include <gtk/gtkstylablepicture.h>
#include <gtk/gtkstylecontext.h>
#include <gtk/gtkstyleproperties.h>
#include <gtk/gtkstyleprovider.h>

View File

@@ -1135,12 +1135,24 @@ gtk_icon_info_load_symbolic_for_style
gtk_icon_info_new_for_pixbuf
gtk_icon_info_set_raw_coordinates
gtk_icon_lookup_flags_get_type G_GNUC_CONST
gtk_icon_picture_get_name
gtk_icon_picture_get_size
gtk_icon_picture_get_type G_GNUC_CONST
gtk_icon_picture_new
gtk_icon_picture_set_name
gtk_icon_picture_set_size
gtk_icon_set_add_source
gtk_icon_set_copy
gtk_icon_set_get_sizes
gtk_icon_set_get_type G_GNUC_CONST
gtk_icon_set_new
gtk_icon_set_new_from_pixbuf
gtk_icon_set_picture_get_icon_set
gtk_icon_set_picture_get_size
gtk_icon_set_picture_get_type G_GNUC_CONST
gtk_icon_set_picture_new
gtk_icon_set_picture_set_icon_set
gtk_icon_set_picture_set_size
gtk_icon_set_ref
gtk_icon_set_render_icon
gtk_icon_set_render_icon_pixbuf

207
gtk/gtkiconpicture.c Normal file
View File

@@ -0,0 +1,207 @@
/* GTK - The GIMP Drawing Kit
* Copyright (C) 2010 Benjamin Otte <otte@gnome.org>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include "gtkiconpicture.h"
#include "gtkintl.h"
#include "gtkprivate.h"
struct _GtkIconPicturePrivate {
GIcon *icon;
};
enum {
PROP_0,
PROP_ICON
};
G_DEFINE_TYPE (GtkIconPicture, gtk_icon_picture, GTK_TYPE_ICON_THEME_PICTURE)
/**
* SECTION:gtkiconsetpicture
* @Short_description: Pictures for #GtkIcons
* @Title: GtkIconPicture
* @See_also: #GtkIcon
*
* A #GtkIconPicture is an implementation of #GdkPicture for icon sets.
*/
static void
gtk_icon_picture_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkIconPicture *picture = GTK_ICON_PICTURE (object);
GtkIconPicturePrivate *priv = picture->priv;
switch (prop_id)
{
case PROP_ICON:
g_value_set_object (value, priv->icon);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_icon_picture_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkIconPicture *picture = GTK_ICON_PICTURE (object);
switch (prop_id)
{
case PROP_ICON:
gtk_icon_picture_set_icon (picture, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_icon_picture_dispose (GObject *object)
{
GtkIconPicture *icon = GTK_ICON_PICTURE (object);
GtkIconPicturePrivate *priv = icon->priv;
if (priv->icon) {
g_object_unref (priv->icon);
priv->icon = NULL;
}
G_OBJECT_CLASS (gtk_icon_picture_parent_class)->dispose (object);
}
GtkIconInfo *
gtk_icon_picture_lookup (GtkIconThemePicture * picture,
GtkIconTheme * theme,
int size,
GtkIconLookupFlags flags)
{
GtkIconPicture *icon = GTK_ICON_PICTURE (picture);
GtkIconPicturePrivate *priv = icon->priv;
if (priv->icon == NULL)
return NULL;
return gtk_icon_theme_lookup_by_gicon (theme,
priv->icon,
size,
flags);
}
static void
gtk_icon_picture_class_init (GtkIconPictureClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkIconThemePictureClass *icon_theme_picture_class = GTK_ICON_THEME_PICTURE_CLASS (klass);
object_class->get_property = gtk_icon_picture_get_property;
object_class->set_property = gtk_icon_picture_set_property;
object_class->dispose = gtk_icon_picture_dispose;
icon_theme_picture_class->lookup = gtk_icon_picture_lookup;
/**
* GtkIconPicture:icon:
*
* The icon to display.
*
* Since: 3.2
*/
g_object_class_install_property (object_class,
PROP_ICON,
g_param_spec_object ("icon",
P_("Icon"),
P_("Icon to display"),
G_TYPE_ICON,
GTK_PARAM_READWRITE));
g_type_class_add_private (klass, sizeof (GtkIconPicturePrivate));
}
static void
gtk_icon_picture_init (GtkIconPicture *picture)
{
picture->priv = G_TYPE_INSTANCE_GET_PRIVATE (picture,
GTK_TYPE_ICON_PICTURE,
GtkIconPicturePrivate);
}
/**
* gtk_icon_picture_new:
* @icon_name: the name of the icon to display
* @size: The icon size to use or -1 for default
*
* Creates a new #GtkIconPicture displaying the given @icon.
*
* Returns: a new picture
**/
GdkPicture *
gtk_icon_picture_new (GIcon * icon,
GtkIconSize size)
{
return g_object_new (GTK_TYPE_ICON_PICTURE,
"icon", icon,
"size", size,
NULL);
}
GIcon *
gtk_icon_picture_get_icon (GtkIconPicture * picture)
{
g_return_val_if_fail (GTK_IS_ICON_PICTURE (picture), NULL);
return picture->priv->icon;
}
void
gtk_icon_picture_set_icon (GtkIconPicture *picture,
GIcon * icon)
{
GtkIconPicturePrivate *priv;
g_return_if_fail (GTK_IS_ICON_PICTURE (picture));
priv = picture->priv;
if (icon == priv->icon)
return;
if (icon)
g_object_ref (icon);
if (priv->icon)
g_object_unref (priv->icon);
priv->icon = icon;
gtk_icon_theme_picture_update (GTK_ICON_THEME_PICTURE (picture));
g_object_notify (G_OBJECT (picture), "icon");
}

64
gtk/gtkiconpicture.h Normal file
View File

@@ -0,0 +1,64 @@
/* GTK - The GIMP Drawing Kit
* Copyright (C) 2010 Benjamin Otte <otte@gnome.org>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk.h> can be included directly."
#endif
#ifndef __GTK_ICON_PICTURE_H__
#define __GTK_ICON_PICTURE_H__
#include <gtk/gtkiconthemepicture.h>
G_BEGIN_DECLS
#define GTK_TYPE_ICON_PICTURE (gtk_icon_picture_get_type ())
#define GTK_ICON_PICTURE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_ICON_PICTURE, GtkIconPicture))
#define GTK_ICON_PICTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_ICON_PICTURE, GtkIconPictureClass))
#define GTK_IS_ICON_PICTURE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GTK_TYPE_ICON_PICTURE))
#define GTK_IS_ICON_PICTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_ICON_PICTURE))
#define GTK_ICON_PICTURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_ICON_PICTURE, GtkIconPictureClass))
typedef struct _GtkIconPicture GtkIconPicture;
typedef struct _GtkIconPicturePrivate GtkIconPicturePrivate;
typedef struct _GtkIconPictureClass GtkIconPictureClass;
struct _GtkIconPicture {
GtkIconThemePicture parent_picture;
GtkIconPicturePrivate * priv;
};
struct _GtkIconPictureClass {
GtkIconThemePictureClass parent_class;
};
GType gtk_icon_picture_get_type (void) G_GNUC_CONST;
GdkPicture * gtk_icon_picture_new (GIcon * icon,
GtkIconSize size);
GIcon * gtk_icon_picture_get_icon (GtkIconPicture * picture);
void gtk_icon_picture_set_icon (GtkIconPicture * picture,
GIcon * icon);
G_END_DECLS
#endif /* __GTK_ICON_PICTURE_H__ */

372
gtk/gtkiconsetpicture.c Normal file
View File

@@ -0,0 +1,372 @@
/* GTK - The GIMP Drawing Kit
* Copyright (C) 2010 Benjamin Otte <otte@gnome.org>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include "gtkiconsetpicture.h"
#include <cairo-gobject.h>
#include "gtkintl.h"
#include "gtkprivate.h"
#include "gtkstyledpicture.h"
struct _GtkIconSetPicturePrivate {
GdkPicture *picture;
GtkIconSet *set;
GtkIconSize size;
};
enum {
PROP_0,
PROP_ICON_SET,
PROP_SIZE
};
static void
gtk_icon_set_picture_update_picture (GtkIconSetPicture *picture)
{
GtkIconSetPicturePrivate *priv = picture->priv;
GtkIconSet *icon_set;
GtkStyleContext *style;
GdkPixbuf *pixbuf;
GtkWidgetPath *path;
path = gtk_widget_path_new ();
style = gtk_style_context_new ();
gtk_style_context_set_path (style, path);
gtk_widget_path_free (path);
if (priv->set == NULL)
{
icon_set = gtk_style_context_lookup_icon_set (style, GTK_STOCK_MISSING_IMAGE);
g_assert (icon_set);
}
else
icon_set = priv->set;
pixbuf = gtk_icon_set_render_icon_pixbuf (icon_set, style, priv->size);
gdk_pixbuf_picture_set_pixbuf (GDK_PIXBUF_PICTURE (priv->picture), pixbuf);
g_object_unref (pixbuf);
g_object_unref (style);
}
static GdkPicture *
gtk_icon_set_picture_update_styled (GtkStyledPicture *styled,
GdkPicture *pixbuf_picture)
{
GdkPicture *icon = gtk_picture_get_unstyled (GDK_PICTURE (styled));
GtkWidget *widget = gtk_styled_picture_get_widget (styled);
GtkIconSetPicturePrivate *priv = GTK_ICON_SET_PICTURE (icon)->priv;
GtkIconSet *icon_set;
GtkStyleContext *style;
GdkPixbuf *pixbuf;
style = gtk_widget_get_style_context (widget);
gtk_style_context_save (style);
gtk_style_context_set_state (style, gtk_widget_get_state_flags (widget));
if (priv->set == NULL)
{
icon_set = gtk_style_context_lookup_icon_set (style, GTK_STOCK_MISSING_IMAGE);
g_assert (icon_set);
}
else
icon_set = priv->set;
pixbuf = gtk_icon_set_render_icon_pixbuf (icon_set, style, priv->size);
gdk_pixbuf_picture_set_pixbuf (GDK_PIXBUF_PICTURE (pixbuf_picture), pixbuf);
g_object_unref (pixbuf);
gtk_style_context_restore (style);
g_object_ref (pixbuf_picture);
return pixbuf_picture;
}
static GdkPicture *
gtk_icon_set_picture_attach (GdkPicture *picture,
GtkWidget *widget)
{
GdkPicture *styled;
GdkPicture *pixbuf_picture;
styled = gtk_styled_picture_new (picture, widget);
pixbuf_picture = gdk_pixbuf_picture_new (NULL);
g_signal_connect (styled, "update", G_CALLBACK (gtk_icon_set_picture_update_styled), pixbuf_picture);
gtk_styled_picture_update (GTK_STYLED_PICTURE (styled));
/* We can get rid of it here. styled will have a reference to it
* and keep that reference until it goes away. */
g_object_unref (pixbuf_picture);
return styled;
}
static void
gtk_icon_set_picture_stylable_picture_init (GtkStylablePictureInterface *iface)
{
iface->attach = gtk_icon_set_picture_attach;
}
G_DEFINE_TYPE_WITH_CODE (GtkIconSetPicture, gtk_icon_set_picture, GDK_TYPE_PICTURE,
G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLABLE_PICTURE,
gtk_icon_set_picture_stylable_picture_init))
/**
* SECTION:gtkiconsetpicture
* @Short_description: Pictures for #GtkIconSets
* @Title: GtkIconSetPicture
* @See_also: #GtkIconSet
*
* A #GtkIconSetPicture is an implementation of #GdkPicture for icon sets.
*/
static void
gtk_icon_set_picture_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkIconSetPicture *picture = GTK_ICON_SET_PICTURE (object);
GtkIconSetPicturePrivate *priv = picture->priv;
switch (prop_id)
{
case PROP_ICON_SET:
g_value_set_boxed (value, priv->set);
break;
case PROP_SIZE:
g_value_set_int (value, priv->size);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_icon_set_picture_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkIconSetPicture *picture = GTK_ICON_SET_PICTURE (object);
switch (prop_id)
{
case PROP_ICON_SET:
gtk_icon_set_picture_set_icon_set (picture, g_value_get_boxed (value));
break;
case PROP_SIZE:
gtk_icon_set_picture_set_size (picture, g_value_get_int (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_icon_set_picture_dispose (GObject *object)
{
GtkIconSetPicture *icon_set = GTK_ICON_SET_PICTURE (object);
GtkIconSetPicturePrivate *priv = icon_set->priv;
if (priv->set) {
gtk_icon_set_unref (priv->set);
priv->set = NULL;
}
G_OBJECT_CLASS (gtk_icon_set_picture_parent_class)->dispose (object);
}
static cairo_surface_t *
gtk_icon_set_picture_ref_surface (GdkPicture *picture)
{
GtkIconSetPicture *icon_set = GTK_ICON_SET_PICTURE (picture);
return gdk_picture_ref_surface (icon_set->priv->picture);
}
static void
gtk_icon_set_picture_draw (GdkPicture *picture,
cairo_t *cr)
{
GtkIconSetPicture *icon_set = GTK_ICON_SET_PICTURE (picture);
gdk_picture_draw (icon_set->priv->picture, cr);
}
static void
gtk_icon_set_picture_class_init (GtkIconSetPictureClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdkPictureClass *picture_class = GDK_PICTURE_CLASS (klass);
object_class->get_property = gtk_icon_set_picture_get_property;
object_class->set_property = gtk_icon_set_picture_set_property;
object_class->dispose = gtk_icon_set_picture_dispose;
picture_class->ref_surface = gtk_icon_set_picture_ref_surface;
picture_class->draw = gtk_icon_set_picture_draw;
/**
* GtkIconSetPicture:size:
*
* The #GtkIconSize to use to determine the actual image size.
*
* Since: 3.2
*/
g_object_class_install_property (object_class,
PROP_SIZE,
g_param_spec_int ("size",
P_("Size"),
P_("Symbolic size to use"),
G_MININT, G_MAXINT,
GTK_ICON_SIZE_BUTTON,
GTK_PARAM_READWRITE));
/**
* GtkIconSetPicture:icon-set:
*
* The icon set to display.
*
* Since: 3.2
*/
g_object_class_install_property (object_class,
PROP_ICON_SET,
g_param_spec_boxed ("icon-set",
P_("Icon set"),
P_("Icon set to display"),
GTK_TYPE_ICON_SET,
GTK_PARAM_READWRITE));
g_type_class_add_private (klass, sizeof (GtkIconSetPicturePrivate));
}
static void
gtk_icon_set_picture_resized_callback (GdkPicture * pixbuf,
GtkIconSetPicture *icon_set)
{
gdk_picture_resized (GDK_PICTURE (icon_set),
gdk_picture_get_width (pixbuf),
gdk_picture_get_height (pixbuf));
}
static void
gtk_icon_set_picture_init (GtkIconSetPicture *picture)
{
GtkIconSetPicturePrivate *priv;
picture->priv = G_TYPE_INSTANCE_GET_PRIVATE (picture,
GTK_TYPE_ICON_SET_PICTURE,
GtkIconSetPicturePrivate);
priv = picture->priv;
priv->size = GTK_ICON_SIZE_BUTTON;
priv->picture = gdk_pixbuf_picture_new (NULL);
g_signal_connect_swapped (priv->picture,
"changed",
G_CALLBACK (gdk_picture_changed_region),
picture);
g_signal_connect (priv->picture,
"resized",
G_CALLBACK (gtk_icon_set_picture_resized_callback),
picture);
gtk_icon_set_picture_update_picture (picture);
}
/**
* gtk_icon_set_picture_new:
* @icon_set_name: the name of the icon_set to display
* @size: The icon_set size to use or -1 for default
*
* Creates a new #GtkIconSetPicture displaying the given @icon_set.
*
* Returns: a new picture
**/
GdkPicture *
gtk_icon_set_picture_new (GtkIconSet *icon_set,
GtkIconSize size)
{
return g_object_new (GTK_TYPE_ICON_SET_PICTURE,
"icon-set", icon_set,
"size", size,
NULL);
}
GtkIconSize
gtk_icon_set_picture_get_size (GtkIconSetPicture *picture)
{
g_return_val_if_fail (GTK_IS_ICON_SET_PICTURE (picture), -1);
return picture->priv->size;
}
void
gtk_icon_set_picture_set_size (GtkIconSetPicture *picture,
GtkIconSize size)
{
GtkIconSetPicturePrivate *priv;
g_return_if_fail (GTK_IS_ICON_SET_PICTURE (picture));
priv = picture->priv;
if (priv->size == size)
return;
priv->size = size;
gtk_icon_set_picture_update_picture (picture);
g_object_notify (G_OBJECT (picture), "size");
}
GtkIconSet *
gtk_icon_set_picture_get_icon_set (GtkIconSetPicture * picture)
{
g_return_val_if_fail (GTK_IS_ICON_SET_PICTURE (picture), NULL);
return picture->priv->set;
}
void
gtk_icon_set_picture_set_icon_set (GtkIconSetPicture *picture,
GtkIconSet * icon_set)
{
GtkIconSetPicturePrivate *priv;
g_return_if_fail (GTK_IS_ICON_SET_PICTURE (picture));
priv = picture->priv;
if (icon_set)
gtk_icon_set_ref (icon_set);
if (priv->set)
gtk_icon_set_ref (priv->set);
priv->set = icon_set;
gtk_icon_set_picture_update_picture (picture);
g_object_notify (G_OBJECT (picture), "icon-set");
}

67
gtk/gtkiconsetpicture.h Normal file
View File

@@ -0,0 +1,67 @@
/* GTK - The GIMP Drawing Kit
* Copyright (C) 2010 Benjamin Otte <otte@gnome.org>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk.h> can be included directly."
#endif
#ifndef __GTK_ICON_SET_PICTURE_H__
#define __GTK_ICON_SET_PICTURE_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define GTK_TYPE_ICON_SET_PICTURE (gtk_icon_set_picture_get_type ())
#define GTK_ICON_SET_PICTURE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_ICON_SET_PICTURE, GtkIconSetPicture))
#define GTK_ICON_SET_PICTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_ICON_SET_PICTURE, GtkIconSetPictureClass))
#define GTK_IS_ICON_SET_PICTURE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GTK_TYPE_ICON_SET_PICTURE))
#define GTK_IS_ICON_SET_PICTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_ICON_SET_PICTURE))
#define GTK_ICON_SET_PICTURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_ICON_SET_PICTURE, GtkIconSetPictureClass))
typedef struct _GtkIconSetPicture GtkIconSetPicture;
typedef struct _GtkIconSetPicturePrivate GtkIconSetPicturePrivate;
typedef struct _GtkIconSetPictureClass GtkIconSetPictureClass;
struct _GtkIconSetPicture {
GdkPicture parent_picture;
GtkIconSetPicturePrivate *priv;
};
struct _GtkIconSetPictureClass {
GdkPictureClass parent_class;
};
GType gtk_icon_set_picture_get_type (void) G_GNUC_CONST;
GdkPicture * gtk_icon_set_picture_new (GtkIconSet * icon_set,
GtkIconSize size);
GtkIconSize gtk_icon_set_picture_get_size (GtkIconSetPicture * picture);
void gtk_icon_set_picture_set_size (GtkIconSetPicture * picture,
GtkIconSize size);
GtkIconSet * gtk_icon_set_picture_get_icon_set (GtkIconSetPicture * picture);
void gtk_icon_set_picture_set_icon_set (GtkIconSetPicture * picture,
GtkIconSet * set);
G_END_DECLS
#endif /* __GTK_ICON_SET_PICTURE_H__ */

508
gtk/gtkiconthemepicture.c Normal file
View File

@@ -0,0 +1,508 @@
/* GTK - The GIMP Drawing Kit
* Copyright (C) 2010 Benjamin Otte <otte@gnome.org>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include "gtkiconthemepicture.h"
#include <cairo-gobject.h>
#include "gtkintl.h"
#include "gtkprivate.h"
#include "gtkstyledpicture.h"
struct _GtkIconThemePicturePrivate {
GdkPicture *picture;
GtkIconTheme *theme;
GtkIconSize size;
int pixel_size;
gboolean use_fallback;
};
enum {
PROP_0,
PROP_ICON_THEME,
PROP_SIZE,
PROP_PIXEL_SIZE
};
static int
gtk_icon_theme_picture_lookup_size (GtkSettings *settings,
GtkIconSize icon_size)
{
int width, height;
if (gtk_icon_size_lookup_for_settings (settings,
icon_size,
&width, &height))
return MIN (width, height);
if (icon_size != -1)
{
g_warning ("Invalid icon size %d\n", icon_size);
return 24;
}
return 48;
}
static GdkPixbuf *
gtk_icon_theme_picture_get_pixbuf_for_widget (GtkIconThemePicture *picture,
GtkWidget * widget)
{
GtkIconThemePicturePrivate *priv = picture->priv;
GtkIconTheme *icon_theme;
GdkScreen *screen;
GtkSettings *settings;
gint size;
GtkIconInfo *info;
GtkIconLookupFlags flags;
GdkPixbuf *pixbuf;
screen = widget ? gtk_widget_get_screen (widget) : gdk_screen_get_default ();
icon_theme = priv->theme ? priv->theme : gtk_icon_theme_get_for_screen (screen);
settings = gtk_settings_get_for_screen (screen);
flags = GTK_ICON_LOOKUP_USE_BUILTIN;
if (priv->use_fallback)
flags |= GTK_ICON_LOOKUP_GENERIC_FALLBACK;
if (priv->pixel_size != -1)
{
size = priv->pixel_size;
flags |= GTK_ICON_LOOKUP_FORCE_SIZE;
}
else
size = gtk_icon_theme_picture_lookup_size (settings, priv->size);
info = GTK_ICON_THEME_PICTURE_GET_CLASS (picture)->lookup (picture,
icon_theme,
size,
flags);
if (info)
{
if (widget)
{
GtkStyleContext *context;
context = gtk_widget_get_style_context (widget);
gtk_style_context_save (context);
gtk_style_context_set_state (context, gtk_widget_get_state_flags (widget));
pixbuf = gtk_icon_info_load_symbolic_for_context (info,
context,
NULL, NULL);
gtk_style_context_restore (context);
}
else
{
static const GdkRGBA foreground = { 0.0, 0.0, 0.0, 1.0 };
static const GdkRGBA success_color = { 0.3, 0.6, 0.02, 1.0 };
static const GdkRGBA warning_color = { 0.96, 0.47, 0.24, 1.0 };
static const GdkRGBA error_color = { 0.8, 0.0, 0.0, 1.0 };
pixbuf = gtk_icon_info_load_symbolic (info,
&foreground,
&success_color,
&warning_color,
&error_color,
NULL, NULL);
}
gtk_icon_info_free (info);
}
else
pixbuf = NULL;
if (pixbuf == NULL && widget != NULL)
{
pixbuf = gtk_widget_render_icon_pixbuf (widget,
GTK_STOCK_MISSING_IMAGE,
priv->size);
}
return pixbuf;
}
void
gtk_icon_theme_picture_update (GtkIconThemePicture *picture)
{
GtkIconThemePicturePrivate *priv = picture->priv;
GdkPixbuf *pixbuf;
pixbuf = gtk_icon_theme_picture_get_pixbuf_for_widget (picture, NULL);
gdk_pixbuf_picture_set_pixbuf (GDK_PIXBUF_PICTURE (priv->picture), pixbuf);
if (pixbuf)
g_object_unref (pixbuf);
}
static GdkPicture *
gtk_icon_theme_picture_update_styled (GtkStyledPicture *styled,
GdkPicture *pixbuf_picture)
{
GdkPicture *icon = gtk_picture_get_unstyled (GDK_PICTURE (styled));
GtkWidget *widget = gtk_styled_picture_get_widget (styled);
GdkPixbuf *pixbuf;
pixbuf = gtk_icon_theme_picture_get_pixbuf_for_widget (GTK_ICON_THEME_PICTURE (icon),
widget);
gdk_pixbuf_picture_set_pixbuf (GDK_PIXBUF_PICTURE (pixbuf_picture), pixbuf);
if (pixbuf)
g_object_unref (pixbuf);
g_object_ref (pixbuf_picture);
return pixbuf_picture;
}
static GdkPicture *
gtk_icon_theme_picture_attach (GdkPicture *picture,
GtkWidget *widget)
{
GdkPicture *styled;
GdkPicture *pixbuf_picture;
styled = gtk_styled_picture_new (picture, widget);
pixbuf_picture = gdk_pixbuf_picture_new (NULL);
g_signal_connect (styled, "update", G_CALLBACK (gtk_icon_theme_picture_update_styled), pixbuf_picture);
gtk_styled_picture_update (GTK_STYLED_PICTURE (styled));
/* We can get rid of it here. styled will have a reference to it
* and keep that reference until it goes away. */
g_object_unref (pixbuf_picture);
return styled;
}
static void
gtk_icon_theme_picture_stylable_picture_init (GtkStylablePictureInterface *iface)
{
iface->attach = gtk_icon_theme_picture_attach;
}
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GtkIconThemePicture, gtk_icon_theme_picture, GDK_TYPE_PICTURE,
G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLABLE_PICTURE,
gtk_icon_theme_picture_stylable_picture_init))
/**
* SECTION:gtkiconthemepicture
* @Short_description: Pictures for a #GtkIconTheme
* @Title: GtkIconThemePicture
* @See_also: #GtkIconTheme
*
* A #GtkIconThemePicture is an implementation of #GdkPicture to display
* icons from a #GtkIconTheme.
*/
static void
gtk_icon_theme_picture_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkIconThemePicture *picture = GTK_ICON_THEME_PICTURE (object);
GtkIconThemePicturePrivate *priv = picture->priv;
switch (prop_id)
{
case PROP_ICON_THEME:
g_value_set_object (value, priv->theme);
break;
case PROP_SIZE:
g_value_set_int (value, priv->size);
break;
case PROP_PIXEL_SIZE:
g_value_set_int (value, priv->pixel_size);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_icon_theme_picture_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkIconThemePicture *picture = GTK_ICON_THEME_PICTURE (object);
switch (prop_id)
{
case PROP_ICON_THEME:
gtk_icon_theme_picture_set_icon_theme (picture, g_value_get_object (value));
break;
case PROP_SIZE:
gtk_icon_theme_picture_set_size (picture, g_value_get_int (value));
break;
case PROP_PIXEL_SIZE:
gtk_icon_theme_picture_set_pixel_size (picture, g_value_get_int (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_icon_theme_picture_dispose (GObject *object)
{
GtkIconThemePicture *picture = GTK_ICON_THEME_PICTURE (object);
gtk_icon_theme_picture_set_icon_theme (picture, NULL);
G_OBJECT_CLASS (gtk_icon_theme_picture_parent_class)->dispose (object);
}
static cairo_surface_t *
gtk_icon_theme_picture_ref_surface (GdkPicture *picture)
{
GtkIconThemePicture *icon_theme = GTK_ICON_THEME_PICTURE (picture);
return gdk_picture_ref_surface (icon_theme->priv->picture);
}
static void
gtk_icon_theme_picture_draw (GdkPicture *picture,
cairo_t *cr)
{
GtkIconThemePicture *icon_theme = GTK_ICON_THEME_PICTURE (picture);
gdk_picture_draw (icon_theme->priv->picture, cr);
}
static void
gtk_icon_theme_picture_class_init (GtkIconThemePictureClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdkPictureClass *picture_class = GDK_PICTURE_CLASS (klass);
object_class->get_property = gtk_icon_theme_picture_get_property;
object_class->set_property = gtk_icon_theme_picture_set_property;
object_class->dispose = gtk_icon_theme_picture_dispose;
picture_class->ref_surface = gtk_icon_theme_picture_ref_surface;
picture_class->draw = gtk_icon_theme_picture_draw;
/**
* GtkIconThemePicture:size:
*
* The #GtkIconSize to use to determine the actual image size.
* This will only be used if #GtkIconThemePicture:pixel-size is
* unset.
*
* Since: 3.2
*/
g_object_class_install_property (object_class,
PROP_SIZE,
g_param_spec_int ("size",
P_("Size"),
P_("Symbolic size to use"),
G_MININT, G_MAXINT,
GTK_ICON_SIZE_BUTTON,
GTK_PARAM_READWRITE));
/**
* GtkIconThemePicture:pixel-size:
*
* The "pixel-size" property can be used to specify a fixed size
* overriding the #GtkIconThemePicture:icon-size property.
*
* Since: 3.2
*/
g_object_class_install_property (object_class,
PROP_PIXEL_SIZE,
g_param_spec_int ("pixel-size",
P_("Pixel size"),
P_("Pixel size to override size"),
-1, G_MAXINT,
-1,
GTK_PARAM_READWRITE));
/**
* GtkIconThemePicture:icon-theme:
*
* The icon theme to use or %NULL to use the default theme.
*
* Since: 3.2
*/
g_object_class_install_property (object_class,
PROP_ICON_THEME,
g_param_spec_object ("icon-theme",
P_("Icon theme"),
P_("Icon theme to use"),
GTK_TYPE_ICON_THEME,
GTK_PARAM_READWRITE));
g_type_class_add_private (klass, sizeof (GtkIconThemePicturePrivate));
}
static void
gtk_icon_theme_picture_resized_callback (GdkPicture * pixbuf,
GtkIconThemePicture *icon_theme)
{
gdk_picture_resized (GDK_PICTURE (icon_theme),
gdk_picture_get_width (pixbuf),
gdk_picture_get_height (pixbuf));
}
static void
gtk_icon_theme_picture_init (GtkIconThemePicture *picture)
{
GtkIconThemePicturePrivate *priv;
picture->priv = G_TYPE_INSTANCE_GET_PRIVATE (picture,
GTK_TYPE_ICON_THEME_PICTURE,
GtkIconThemePicturePrivate);
priv = picture->priv;
priv->size = GTK_ICON_SIZE_BUTTON;
priv->pixel_size = -1;
priv->picture = gdk_pixbuf_picture_new (NULL);
g_signal_connect_swapped (priv->picture,
"changed",
G_CALLBACK (gdk_picture_changed_region),
picture);
g_signal_connect (priv->picture,
"resized",
G_CALLBACK (gtk_icon_theme_picture_resized_callback),
picture);
}
GtkIconSize
gtk_icon_theme_picture_get_size (GtkIconThemePicture *picture)
{
g_return_val_if_fail (GTK_IS_ICON_THEME_PICTURE (picture), -1);
return picture->priv->size;
}
void
gtk_icon_theme_picture_set_size (GtkIconThemePicture *picture,
GtkIconSize size)
{
GtkIconThemePicturePrivate *priv;
g_return_if_fail (GTK_IS_ICON_THEME_PICTURE (picture));
priv = picture->priv;
if (priv->size == size)
return;
priv->size = size;
gtk_icon_theme_picture_update (picture);
g_object_notify (G_OBJECT (picture), "size");
}
int
gtk_icon_theme_picture_get_pixel_size (GtkIconThemePicture *picture)
{
g_return_val_if_fail (GTK_IS_ICON_THEME_PICTURE (picture), -1);
return picture->priv->pixel_size;
}
void
gtk_icon_theme_picture_set_pixel_size (GtkIconThemePicture *picture,
int pixel_size)
{
GtkIconThemePicturePrivate *priv;
g_return_if_fail (GTK_IS_ICON_THEME_PICTURE (picture));
priv = picture->priv;
if (priv->pixel_size == pixel_size)
return;
priv->pixel_size = pixel_size;
gtk_icon_theme_picture_update (picture);
g_object_notify (G_OBJECT (picture), "pixel-size");
}
GtkIconTheme *
gtk_icon_theme_picture_get_icon_theme (GtkIconThemePicture * picture)
{
g_return_val_if_fail (GTK_IS_ICON_THEME_PICTURE (picture), NULL);
return picture->priv->theme;
}
void
gtk_icon_theme_picture_set_icon_theme (GtkIconThemePicture *picture,
GtkIconTheme * icon_theme)
{
GtkIconThemePicturePrivate *priv;
g_return_if_fail (GTK_IS_ICON_THEME_PICTURE (picture));
g_return_if_fail (icon_theme == NULL || GTK_IS_ICON_THEME (icon_theme));
priv = picture->priv;
if (icon_theme)
{
g_object_ref (icon_theme);
g_signal_connect_swapped (icon_theme,
"changed",
G_CALLBACK (gtk_icon_theme_picture_update),
picture);
}
if (priv->theme)
{
g_signal_handlers_disconnect_by_func (priv->theme,
gtk_icon_theme_picture_update,
picture);
g_object_unref (priv->theme);
}
priv->theme = icon_theme;
gtk_icon_theme_picture_update (picture);
g_object_notify (G_OBJECT (picture), "icon-theme");
}
gboolean
gtk_icon_theme_picture_get_use_fallback (GtkIconThemePicture * picture)
{
g_return_val_if_fail (GTK_IS_ICON_THEME_PICTURE (picture), FALSE);
return picture->priv->use_fallback;
}
void
gtk_icon_theme_picture_set_use_fallback (GtkIconThemePicture *picture,
gboolean use_fallback)
{
GtkIconThemePicturePrivate *priv;
g_return_if_fail (GTK_IS_ICON_THEME_PICTURE (picture));
priv = picture->priv;
if (priv->use_fallback == use_fallback)
return;
priv->use_fallback = use_fallback;
gtk_icon_theme_picture_update (picture);
g_object_notify (G_OBJECT (picture), "icon-theme");
}

79
gtk/gtkiconthemepicture.h Normal file
View File

@@ -0,0 +1,79 @@
/* GTK - The GIMP Drawing Kit
* Copyright (C) 2010 Benjamin Otte <otte@gnome.org>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk.h> can be included directly."
#endif
#ifndef __GTK_ICON_THEME_PICTURE_H__
#define __GTK_ICON_THEME_PICTURE_H__
#include <gdk/gdk.h>
#include <gtk/gtkicontheme.h>
G_BEGIN_DECLS
#define GTK_TYPE_ICON_THEME_PICTURE (gtk_icon_theme_picture_get_type ())
#define GTK_ICON_THEME_PICTURE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_ICON_THEME_PICTURE, GtkIconThemePicture))
#define GTK_ICON_THEME_PICTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_ICON_THEME_PICTURE, GtkIconThemePictureClass))
#define GTK_IS_ICON_THEME_PICTURE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GTK_TYPE_ICON_THEME_PICTURE))
#define GTK_IS_ICON_THEME_PICTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_ICON_THEME_PICTURE))
#define GTK_ICON_THEME_PICTURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_ICON_THEME_PICTURE, GtkIconThemePictureClass))
typedef struct _GtkIconThemePicture GtkIconThemePicture;
typedef struct _GtkIconThemePicturePrivate GtkIconThemePicturePrivate;
typedef struct _GtkIconThemePictureClass GtkIconThemePictureClass;
struct _GtkIconThemePicture {
GdkPicture parent_picture;
GtkIconThemePicturePrivate *priv;
};
struct _GtkIconThemePictureClass {
GdkPictureClass parent_class;
GtkIconInfo * (* lookup) (GtkIconThemePicture * picture,
GtkIconTheme * theme,
int size,
GtkIconLookupFlags flags);
};
GType gtk_icon_theme_picture_get_type (void) G_GNUC_CONST;
GtkIconSize gtk_icon_theme_picture_get_size (GtkIconThemePicture * picture);
void gtk_icon_theme_picture_set_size (GtkIconThemePicture * picture,
GtkIconSize size);
int gtk_icon_theme_picture_get_pixel_size (GtkIconThemePicture * picture);
void gtk_icon_theme_picture_set_pixel_size (GtkIconThemePicture * picture,
int pixel_size);
GtkIconTheme * gtk_icon_theme_picture_get_icon_theme (GtkIconThemePicture * picture);
void gtk_icon_theme_picture_set_icon_theme (GtkIconThemePicture * picture,
GtkIconTheme * theme);
gboolean gtk_icon_theme_picture_get_use_fallback (GtkIconThemePicture * picture);
void gtk_icon_theme_picture_set_use_fallback (GtkIconThemePicture * picture,
gboolean use_fallback);
/* for subclasses only */
void gtk_icon_theme_picture_update (GtkIconThemePicture * picture);
G_END_DECLS
#endif /* __GTK_ICON_THEME_PICTURE_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -62,6 +62,8 @@ typedef struct _GtkImageClass GtkImageClass;
* This image type was added in GTK+ 2.6
* @GTK_IMAGE_GICON: the widget contains a #GIcon.
* This image type was added in GTK+ 2.14
* @GTK_IMAGE_PICTURE: the widget contains a #GdkPicture.
* This image type was added in GTK+ 3.2
*
* Describes the image data representation used by a #GtkImage. If you
* want to get the image from the widget, you can only get the
@@ -79,7 +81,8 @@ typedef enum
GTK_IMAGE_ICON_SET,
GTK_IMAGE_ANIMATION,
GTK_IMAGE_ICON_NAME,
GTK_IMAGE_GICON
GTK_IMAGE_GICON,
GTK_IMAGE_PICTURE
} GtkImageType;
/**
@@ -111,6 +114,7 @@ GType gtk_image_get_type (void) G_GNUC_CONST;
GtkWidget* gtk_image_new (void);
GtkWidget* gtk_image_new_from_file (const gchar *filename);
GtkWidget* gtk_image_new_from_picture (GdkPicture *picture);
GtkWidget* gtk_image_new_from_pixbuf (GdkPixbuf *pixbuf);
GtkWidget* gtk_image_new_from_stock (const gchar *stock_id,
GtkIconSize size);
@@ -125,6 +129,8 @@ GtkWidget* gtk_image_new_from_gicon (GIcon *icon,
void gtk_image_clear (GtkImage *image);
void gtk_image_set_from_file (GtkImage *image,
const gchar *filename);
void gtk_image_set_from_picture (GtkImage *image,
GdkPicture *picture);
void gtk_image_set_from_pixbuf (GtkImage *image,
GdkPixbuf *pixbuf);
void gtk_image_set_from_stock (GtkImage *image,
@@ -147,6 +153,7 @@ void gtk_image_set_pixel_size (GtkImage *image,
GtkImageType gtk_image_get_storage_type (GtkImage *image);
GdkPixbuf* gtk_image_get_pixbuf (GtkImage *image);
GdkPicture*gtk_image_get_picture (GtkImage *image);
void gtk_image_get_stock (GtkImage *image,
gchar **stock_id,
GtkIconSize *size);

View File

@@ -34,6 +34,7 @@
G_BEGIN_DECLS
typedef struct _GtkImagePixbufData GtkImagePixbufData;
typedef struct _GtkImagePictureData GtkImagePictureData;
typedef struct _GtkImageStockData GtkImageStockData;
typedef struct _GtkImageIconSetData GtkImageIconSetData;
typedef struct _GtkImageAnimationData GtkImageAnimationData;
@@ -45,6 +46,11 @@ struct _GtkImagePixbufData
GdkPixbuf *pixbuf;
};
struct _GtkImagePictureData
{
GdkPicture *picture;
};
struct _GtkImageStockData
{
gchar *stock_id;

200
gtk/gtknamedpicture.c Normal file
View File

@@ -0,0 +1,200 @@
/* GTK - The GIMP Drawing Kit
* Copyright (C) 2010 Benjamin Otte <otte@gnome.org>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include "gtknamedpicture.h"
#include "gtkintl.h"
#include "gtkprivate.h"
struct _GtkNamedPicturePrivate {
char *name;
};
enum {
PROP_0,
PROP_NAME
};
G_DEFINE_TYPE (GtkNamedPicture, gtk_named_picture, GTK_TYPE_ICON_THEME_PICTURE)
/**
* SECTION:gtknamedpicture
* @Short_description: Pictures for named icons
* @Title: GtkNamedPicture
* @See_also: #GtkIconTheme
*
* A #GtkNamedPicture is an implementation of #GdkPicture for named icons.
*/
static void
gtk_named_picture_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkNamedPicture *picture = GTK_NAMED_PICTURE (object);
GtkNamedPicturePrivate *priv = picture->priv;
switch (prop_id)
{
case PROP_NAME:
g_value_set_string (value, priv->name);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_named_picture_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkNamedPicture *picture = GTK_NAMED_PICTURE (object);
switch (prop_id)
{
case PROP_NAME:
gtk_named_picture_set_name (picture, g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_named_picture_dispose (GObject *object)
{
GtkNamedPicture *named = GTK_NAMED_PICTURE (object);
GtkNamedPicturePrivate *priv = named->priv;
g_free (priv->name);
priv->name = NULL;
G_OBJECT_CLASS (gtk_named_picture_parent_class)->dispose (object);
}
GtkIconInfo *
gtk_named_picture_lookup (GtkIconThemePicture * picture,
GtkIconTheme * theme,
int size,
GtkIconLookupFlags flags)
{
GtkNamedPicture *icon = GTK_NAMED_PICTURE (picture);
GtkNamedPicturePrivate *priv = icon->priv;
if (priv->name == NULL)
return NULL;
return gtk_icon_theme_lookup_icon (theme,
priv->name,
size,
flags);
}
static void
gtk_named_picture_class_init (GtkNamedPictureClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkIconThemePictureClass *icon_theme_picture_class = GTK_ICON_THEME_PICTURE_CLASS (klass);
object_class->get_property = gtk_named_picture_get_property;
object_class->set_property = gtk_named_picture_set_property;
object_class->dispose = gtk_named_picture_dispose;
icon_theme_picture_class->lookup = gtk_named_picture_lookup;
/**
* GtkNamedPicture:name:
*
* Name of the icon to display.
*
* Since: 3.2
*/
g_object_class_install_property (object_class,
PROP_NAME,
g_param_spec_string ("name",
P_("Name"),
P_("Name of the icon to display"),
NULL,
GTK_PARAM_READWRITE));
g_type_class_add_private (klass, sizeof (GtkNamedPicturePrivate));
}
static void
gtk_named_picture_init (GtkNamedPicture *picture)
{
picture->priv = G_TYPE_INSTANCE_GET_PRIVATE (picture,
GTK_TYPE_NAMED_PICTURE,
GtkNamedPicturePrivate);
}
/**
* gtk_named_picture_new:
* @name: the name of the icon to display
* @size: The icon size
*
* Creates a new #GtkNamedPicture displaying the icon for the
* given @name.
*
* Returns: a new picture
**/
GdkPicture *
gtk_named_picture_new (const char *name,
GtkIconSize size)
{
g_return_val_if_fail (name != NULL, NULL);
return g_object_new (GTK_TYPE_NAMED_PICTURE,
"name", name,
"size", size,
NULL);
}
const char *
gtk_named_picture_get_name (GtkNamedPicture * picture)
{
g_return_val_if_fail (GTK_IS_NAMED_PICTURE (picture), NULL);
return picture->priv->name;
}
void
gtk_named_picture_set_name (GtkNamedPicture *picture,
const char * name)
{
GtkNamedPicturePrivate *priv;
g_return_if_fail (GTK_IS_NAMED_PICTURE (picture));
priv = picture->priv;
g_free (priv->name);
priv->name = g_strdup (name);
gtk_icon_theme_picture_update (GTK_ICON_THEME_PICTURE (picture));
g_object_notify (G_OBJECT (picture), "name");
}

64
gtk/gtknamedpicture.h Normal file
View File

@@ -0,0 +1,64 @@
/* GTK - The GIMP Drawing Kit
* Copyright (C) 2010 Benjamin Otte <otte@gnome.org>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk.h> can be included directly."
#endif
#ifndef __GTK_NAMED_PICTURE_H__
#define __GTK_NAMED_PICTURE_H__
#include <gtk/gtkiconthemepicture.h>
G_BEGIN_DECLS
#define GTK_TYPE_NAMED_PICTURE (gtk_named_picture_get_type ())
#define GTK_NAMED_PICTURE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_NAMED_PICTURE, GtkNamedPicture))
#define GTK_NAMED_PICTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_NAMED_PICTURE, GtkNamedPictureClass))
#define GTK_IS_NAMED_PICTURE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GTK_TYPE_NAMED_PICTURE))
#define GTK_IS_NAMED_PICTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_NAMED_PICTURE))
#define GTK_NAMED_PICTURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_NAMED_PICTURE, GtkNamedPictureClass))
typedef struct _GtkNamedPicture GtkNamedPicture;
typedef struct _GtkNamedPicturePrivate GtkNamedPicturePrivate;
typedef struct _GtkNamedPictureClass GtkNamedPictureClass;
struct _GtkNamedPicture {
GtkIconThemePicture parent_picture;
GtkNamedPicturePrivate * priv;
};
struct _GtkNamedPictureClass {
GtkIconThemePictureClass parent_class;
};
GType gtk_named_picture_get_type (void) G_GNUC_CONST;
GdkPicture * gtk_named_picture_new (const char * name,
GtkIconSize size);
const char * gtk_named_picture_get_name (GtkNamedPicture * picture);
void gtk_named_picture_set_name (GtkNamedPicture * picture,
const char * name);
G_END_DECLS
#endif /* __GTK_NAMED_PICTURE_H__ */

371
gtk/gtkstockpicture.c Normal file
View File

@@ -0,0 +1,371 @@
/* GTK - The GIMP Drawing Kit
* Copyright (C) 2010 Benjamin Otte <otte@gnome.org>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include "gtkstockpicture.h"
#include <cairo-gobject.h>
#include "gtkintl.h"
#include "gtkprivate.h"
#include "gtkstyledpicture.h"
struct _GtkStockPicturePrivate {
GdkPicture *picture;
char *stock_id;
GtkIconSize size;
};
enum {
PROP_0,
PROP_STOCK,
PROP_SIZE
};
static void
gtk_stock_picture_update_picture (GtkStockPicture *picture)
{
GtkStockPicturePrivate *priv = picture->priv;
GtkIconSet *icon_set;
GtkStyleContext *style;
GdkPixbuf *pixbuf;
GtkWidgetPath *path;
path = gtk_widget_path_new ();
style = gtk_style_context_new ();
gtk_style_context_set_path (style, path);
gtk_widget_path_free (path);
if (priv->stock_id)
icon_set = gtk_style_context_lookup_icon_set (style, priv->stock_id);
else
icon_set = NULL;
if (icon_set == NULL)
{
icon_set = gtk_style_context_lookup_icon_set (style, GTK_STOCK_MISSING_IMAGE);
g_assert (icon_set);
}
pixbuf = gtk_icon_set_render_icon_pixbuf (icon_set, style, priv->size);
gdk_pixbuf_picture_set_pixbuf (GDK_PIXBUF_PICTURE (priv->picture), pixbuf);
g_object_unref (pixbuf);
g_object_unref (style);
}
static GdkPicture *
gtk_stock_picture_update_styled (GtkStyledPicture *styled,
GdkPicture *pixbuf_picture)
{
GdkPicture *stock = gtk_picture_get_unstyled (GDK_PICTURE (styled));
GtkWidget *widget = gtk_styled_picture_get_widget (styled);
GtkStockPicturePrivate *priv = GTK_STOCK_PICTURE (stock)->priv;
GdkPixbuf *pixbuf;
if (priv->stock_id)
pixbuf = gtk_widget_render_icon_pixbuf (widget,
priv->stock_id,
priv->size);
else
pixbuf = NULL;
if (pixbuf == NULL)
{
pixbuf = gtk_widget_render_icon_pixbuf (widget,
GTK_STOCK_MISSING_IMAGE,
priv->size);
g_assert (pixbuf != NULL);
}
gdk_pixbuf_picture_set_pixbuf (GDK_PIXBUF_PICTURE (pixbuf_picture), pixbuf);
g_object_unref (pixbuf);
g_object_ref (pixbuf_picture);
return pixbuf_picture;
}
static GdkPicture *
gtk_stock_picture_attach (GdkPicture *picture,
GtkWidget *widget)
{
GdkPicture *styled;
GdkPicture *pixbuf_picture;
styled = gtk_styled_picture_new (picture, widget);
pixbuf_picture = gdk_pixbuf_picture_new (NULL);
g_signal_connect (styled, "update", G_CALLBACK (gtk_stock_picture_update_styled), pixbuf_picture);
gtk_styled_picture_update (GTK_STYLED_PICTURE (styled));
/* We can get rid of it here. styled will have a reference to it
* and keep that reference until it goes away. */
g_object_unref (pixbuf_picture);
return styled;
}
static void
gtk_stock_picture_stylable_picture_init (GtkStylablePictureInterface *iface)
{
iface->attach = gtk_stock_picture_attach;
}
G_DEFINE_TYPE_WITH_CODE (GtkStockPicture, gtk_stock_picture, GDK_TYPE_PICTURE,
G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLABLE_PICTURE,
gtk_stock_picture_stylable_picture_init))
/**
* SECTION:gtkstockpicture
* @Short_description: Pictures for stock icons
* @Title: GtkStockPicture
* @See_also: #GtkIconFactory
*
* A #GtkStockPicture is an implementation of #GdkPicture for stock icons.
*/
static void
gtk_stock_picture_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkStockPicture *picture = GTK_STOCK_PICTURE (object);
GtkStockPicturePrivate *priv = picture->priv;
switch (prop_id)
{
case PROP_STOCK:
g_value_set_string (value, priv->stock_id);
break;
case PROP_SIZE:
g_value_set_int (value, priv->size);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_stock_picture_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkStockPicture *picture = GTK_STOCK_PICTURE (object);
switch (prop_id)
{
case PROP_STOCK:
gtk_stock_picture_set_stock_id (picture, g_value_get_string (value));
break;
case PROP_SIZE:
gtk_stock_picture_set_size (picture, g_value_get_int (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_stock_picture_dispose (GObject *object)
{
GtkStockPicture *icon = GTK_STOCK_PICTURE (object);
GtkStockPicturePrivate *priv = icon->priv;
if (priv->picture)
{
g_object_unref (priv->picture);
priv->picture = NULL;
}
g_free (priv->stock_id);
priv->stock_id = NULL;
G_OBJECT_CLASS (gtk_stock_picture_parent_class)->dispose (object);
}
static cairo_surface_t *
gtk_stock_picture_ref_surface (GdkPicture *picture)
{
GtkStockPicture *icon = GTK_STOCK_PICTURE (picture);
return gdk_picture_ref_surface (icon->priv->picture);
}
static void
gtk_stock_picture_draw (GdkPicture *picture,
cairo_t *cr)
{
GtkStockPicture *icon = GTK_STOCK_PICTURE (picture);
gdk_picture_draw (icon->priv->picture, cr);
}
static void
gtk_stock_picture_class_init (GtkStockPictureClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdkPictureClass *picture_class = GDK_PICTURE_CLASS (klass);
object_class->get_property = gtk_stock_picture_get_property;
object_class->set_property = gtk_stock_picture_set_property;
object_class->dispose = gtk_stock_picture_dispose;
picture_class->ref_surface = gtk_stock_picture_ref_surface;
picture_class->draw = gtk_stock_picture_draw;
/**
* GtkStockPicture:size:
*
* The #GtkIconSize to use to determine the actual image size.
*
* Since: 3.2
*/
g_object_class_install_property (object_class,
PROP_SIZE,
g_param_spec_int ("size",
P_("Size"),
P_("Symbolic size to use"),
G_MININT, G_MAXINT,
GTK_ICON_SIZE_BUTTON,
GTK_PARAM_READWRITE));
/**
* GtkStockPicture:stock:
*
* The stock id of the icon to display.
*
* Since: 3.2
*/
g_object_class_install_property (object_class,
PROP_STOCK,
g_param_spec_string ("stock",
P_("Name"),
P_("The stock id of the icon from the icon theme"),
NULL,
GTK_PARAM_READWRITE));
g_type_class_add_private (klass, sizeof (GtkStockPicturePrivate));
}
static void
gtk_stock_picture_resized_callback (GdkPicture * pixbuf,
GtkStockPicture *icon)
{
gdk_picture_resized (GDK_PICTURE (icon),
gdk_picture_get_width (pixbuf),
gdk_picture_get_height (pixbuf));
}
static void
gtk_stock_picture_init (GtkStockPicture *picture)
{
GtkStockPicturePrivate *priv;
picture->priv = G_TYPE_INSTANCE_GET_PRIVATE (picture,
GTK_TYPE_STOCK_PICTURE,
GtkStockPicturePrivate);
priv = picture->priv;
priv->size = GTK_ICON_SIZE_BUTTON;
priv->picture = gdk_pixbuf_picture_new (NULL);
g_signal_connect_swapped (priv->picture,
"changed",
G_CALLBACK (gdk_picture_changed_region),
picture);
g_signal_connect (priv->picture,
"resized",
G_CALLBACK (gtk_stock_picture_resized_callback),
picture);
gtk_stock_picture_update_picture (picture);
}
/**
* gtk_stock_picture_new:
* @stock_id: the stock_id of the icon to display
* @size: The icon size to use or -1 for default
*
* Creates a new #GtkStockPicture displaying the given @icon.
*
* Returns: a new picture
**/
GdkPicture *
gtk_stock_picture_new (const char *stock_id,
GtkIconSize size)
{
return g_object_new (GTK_TYPE_STOCK_PICTURE,
"stock", stock_id,
"size", size,
NULL);
}
GtkIconSize
gtk_stock_picture_get_size (GtkStockPicture *picture)
{
g_return_val_if_fail (GTK_IS_STOCK_PICTURE (picture), -1);
return picture->priv->size;
}
void
gtk_stock_picture_set_size (GtkStockPicture *picture,
GtkIconSize size)
{
GtkStockPicturePrivate *priv;
g_return_if_fail (GTK_IS_STOCK_PICTURE (picture));
priv = picture->priv;
if (priv->size == size)
return;
priv->size = size;
gtk_stock_picture_update_picture (picture);
g_object_notify (G_OBJECT (picture), "size");
}
const char *
gtk_stock_picture_get_stock_id (GtkStockPicture * picture)
{
g_return_val_if_fail (GTK_IS_STOCK_PICTURE (picture), NULL);
return picture->priv->stock_id;
}
void
gtk_stock_picture_set_stock_id (GtkStockPicture *picture,
const char * stock_id)
{
GtkStockPicturePrivate *priv;
g_return_if_fail (GTK_IS_STOCK_PICTURE (picture));
priv = picture->priv;
g_free (priv->stock_id);
priv->stock_id = g_strdup (stock_id);
gtk_stock_picture_update_picture (picture);
g_object_notify (G_OBJECT (picture), "stock");
}

67
gtk/gtkstockpicture.h Normal file
View File

@@ -0,0 +1,67 @@
/* GTK - The GIMP Drawing Kit
* Copyright (C) 2010 Benjamin Otte <otte@gnome.org>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk.h> can be included directly."
#endif
#ifndef __GTK_STOCK_PICTURE_H__
#define __GTK_STOCK_PICTURE_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define GTK_TYPE_STOCK_PICTURE (gtk_stock_picture_get_type ())
#define GTK_STOCK_PICTURE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_STOCK_PICTURE, GtkStockPicture))
#define GTK_STOCK_PICTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_STOCK_PICTURE, GtkStockPictureClass))
#define GTK_IS_STOCK_PICTURE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GTK_TYPE_STOCK_PICTURE))
#define GTK_IS_STOCK_PICTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_STOCK_PICTURE))
#define GTK_STOCK_PICTURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_STOCK_PICTURE, GtkStockPictureClass))
typedef struct _GtkStockPicture GtkStockPicture;
typedef struct _GtkStockPicturePrivate GtkStockPicturePrivate;
typedef struct _GtkStockPictureClass GtkStockPictureClass;
struct _GtkStockPicture {
GdkPicture parent_picture;
GtkStockPicturePrivate *priv;
};
struct _GtkStockPictureClass {
GdkPictureClass parent_class;
};
GType gtk_stock_picture_get_type (void) G_GNUC_CONST;
GdkPicture * gtk_stock_picture_new (const char * stock_id,
GtkIconSize size);
GtkIconSize gtk_stock_picture_get_size (GtkStockPicture * picture);
void gtk_stock_picture_set_size (GtkStockPicture * picture,
GtkIconSize size);
const char * gtk_stock_picture_get_stock_id (GtkStockPicture * picture);
void gtk_stock_picture_set_stock_id (GtkStockPicture * picture,
const char * stock_id);
G_END_DECLS
#endif /* __GTK_STOCK_PICTURE_H__ */

78
gtk/gtkstylablepicture.c Normal file
View File

@@ -0,0 +1,78 @@
/* gtktreesortable.c
* Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include "gtkstylablepicture.h"
#include "gtkintl.h"
/**
* SECTION:gtkstylablepicture
* @Short_description: Pictures that can be styled when attached to widgets
* @Title: GtkStylablePicture
* @See_also:#GdkPicture, #GtkWidget
*
* #GtkStylablePicture is an interface to be implemented by pictures that can be
* styled according to a #GtkWidget's #GtkStyleContext.
*/
G_DEFINE_INTERFACE (GtkStylablePicture, gtk_stylable_picture, GDK_TYPE_PICTURE)
static void
gtk_stylable_picture_default_init (GtkStylablePictureInterface *iface)
{
}
GdkPicture *
gtk_widget_style_picture (GtkWidget *widget,
GdkPicture *picture)
{
GtkStylablePictureInterface *iface;
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
g_return_val_if_fail (GDK_IS_PICTURE (picture), NULL);
if (!GTK_IS_STYLABLE_PICTURE (picture))
return g_object_ref (picture);
iface = GTK_STYLABLE_PICTURE_GET_IFACE (picture);
if (iface->attach == NULL)
return g_object_ref (picture);
return (* iface->attach) (picture, widget);
}
GdkPicture *
gtk_picture_get_unstyled (GdkPicture *styled)
{
GtkStylablePictureInterface *iface;
g_return_val_if_fail (GDK_IS_PICTURE (styled), NULL);
if (!GTK_IS_STYLABLE_PICTURE (styled))
return styled;
iface = GTK_STYLABLE_PICTURE_GET_IFACE (styled);
if (iface->get_unstyled == NULL)
return styled;
return iface->get_unstyled (styled);
}

63
gtk/gtkstylablepicture.h Normal file
View File

@@ -0,0 +1,63 @@
/* gtktreesortable.h
* Copyright (C) 2001 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk.h> can be included directly."
#endif
#ifndef __GTK_STYLABLE_PICTURE_H__
#define __GTK_STYLABLE_PICTURE_H__
#include <gdk/gdk.h>
#include <gtk/gtkwidget.h>
G_BEGIN_DECLS
#define GTK_TYPE_STYLABLE_PICTURE (gtk_stylable_picture_get_type ())
#define GTK_STYLABLE_PICTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_STYLABLE_PICTURE, GtkStylablePicture))
#define GTK_STYLABLE_PICTURE_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GTK_TYPE_STYLABLE_PICTURE, GtkStylablePictureInterface))
#define GTK_IS_STYLABLE_PICTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_STYLABLE_PICTURE))
#define GTK_STYLABLE_PICTURE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GTK_TYPE_STYLABLE_PICTURE, GtkStylablePictureInterface))
typedef struct _GtkStylablePicture GtkStylablePicture; /* Dummy typedef */
typedef struct _GtkStylablePictureInterface GtkStylablePictureInterface;
struct _GtkStylablePictureInterface
{
GTypeInterface g_iface;
/* virtual table */
GdkPicture * (* attach) (GdkPicture *picture,
GtkWidget *widget);
GdkPicture * (* get_unstyled) (GdkPicture *picture);
};
GType gtk_stylable_picture_get_type (void) G_GNUC_CONST;
GdkPicture * gtk_widget_style_picture (GtkWidget *widget,
GdkPicture *picture);
GdkPicture * gtk_picture_get_unstyled (GdkPicture *styled);
G_END_DECLS
#endif /* __GTK_STYLABLE_PICTURE_H__ */

287
gtk/gtkstyledpicture.c Normal file
View File

@@ -0,0 +1,287 @@
/* GTK - The GIMP Drawing Kit
* Copyright (C) 2010 Benjamin Otte <otte@gnome.org>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include "gtkstyledpicture.h"
#include <cairo-gobject.h>
#include "gtkintl.h"
#include "gtkmarshalers.h"
#include "gtkprivate.h"
struct _GtkStyledPicturePrivate {
GdkPicture *styled;
GtkWidget *widget;
GdkPicture *unstyled;
};
enum {
UPDATE,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0, };
static GdkPicture *
gtk_styled_picture_attach (GdkPicture *picture,
GtkWidget *widget)
{
GtkStyledPicture *styled = GTK_STYLED_PICTURE (picture);
GtkStyledPicturePrivate *priv = styled->priv;
g_warning ("styled pictures should not be exposed to the world, did somebody not call gtk_picture_get_unstyled()?");
return gtk_styled_picture_new (priv->unstyled,
priv->widget);
}
static GdkPicture *
gtk_styled_picture_get_unstyled (GdkPicture *picture)
{
GtkStyledPicture *styled = GTK_STYLED_PICTURE (picture);
return styled->priv->unstyled;
}
static void
gtk_styled_picture_stylable_picture_init (GtkStylablePictureInterface *iface)
{
iface->attach = gtk_styled_picture_attach;
iface->get_unstyled = gtk_styled_picture_get_unstyled;
}
G_DEFINE_TYPE_WITH_CODE (GtkStyledPicture, gtk_styled_picture, GDK_TYPE_PICTURE,
G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLABLE_PICTURE,
gtk_styled_picture_stylable_picture_init))
static void
gdk_styled_picture_resized_callback (GdkPicture *picture,
GtkStyledPicture *styled)
{
gdk_picture_resized (GDK_PICTURE (styled),
gdk_picture_get_width (picture),
gdk_picture_get_height (picture));
}
static void
gtk_styled_picture_set_styled (GtkStyledPicture *styled,
GdkPicture * picture)
{
GtkStyledPicturePrivate *priv = styled->priv;
if (priv->styled == picture)
return;
if (picture)
{
g_object_ref (picture);
g_signal_connect_swapped (picture,
"changed",
G_CALLBACK (gdk_picture_changed_region),
styled);
g_signal_connect (picture,
"resized",
G_CALLBACK (gdk_styled_picture_resized_callback),
styled);
}
if (priv->styled)
{
g_signal_handlers_disconnect_matched (priv->styled,
G_SIGNAL_MATCH_DATA,
0, 0, NULL, NULL, styled);
g_object_unref (priv->styled);
}
priv->styled = picture;
if (priv->styled)
gdk_picture_resized (GDK_PICTURE (styled),
gdk_picture_get_width (priv->styled),
gdk_picture_get_height (priv->styled));
else
gdk_picture_resized (GDK_PICTURE (styled), 0, 0);
}
static void
gtk_styled_picture_dispose (GObject *object)
{
GtkStyledPicture *styled = GTK_STYLED_PICTURE (object);
GtkStyledPicturePrivate *priv = styled->priv;
gtk_styled_picture_set_styled (styled, NULL);
if (priv->unstyled)
{
g_signal_handlers_disconnect_by_func (priv->unstyled,
gtk_styled_picture_update,
styled);
g_object_unref (priv->unstyled);
priv->unstyled = NULL;
}
if (priv->widget)
{
g_signal_handlers_disconnect_by_func (priv->widget,
gtk_styled_picture_update,
styled);
g_object_remove_weak_pointer (G_OBJECT (priv->widget), (void **) &priv->widget);
priv->widget = NULL;
}
G_OBJECT_CLASS (gtk_styled_picture_parent_class)->dispose (object);
}
static cairo_surface_t *
gtk_styled_picture_ref_surface (GdkPicture *picture)
{
GtkStyledPicture *styled = GTK_STYLED_PICTURE (picture);
return gdk_picture_ref_surface (styled->priv->styled);
}
static void
gtk_styled_picture_draw (GdkPicture *picture,
cairo_t *cr)
{
GtkStyledPicture *styled = GTK_STYLED_PICTURE (picture);
gdk_picture_draw (styled->priv->styled, cr);
}
static gboolean
gtk_styled_picture_update_accumulator (GSignalInvocationHint *ihint,
GValue *return_accu,
const GValue *handler_return,
gpointer unused)
{
gboolean continue_emission;
GObject *object;
object = g_value_get_object (handler_return);
g_value_set_object (return_accu, object);
continue_emission = !object;
return continue_emission;
}
static void
gtk_styled_picture_class_init (GtkStyledPictureClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdkPictureClass *picture_class = GDK_PICTURE_CLASS (klass);
object_class->dispose = gtk_styled_picture_dispose;
picture_class->ref_surface = gtk_styled_picture_ref_surface;
picture_class->draw = gtk_styled_picture_draw;
signals[UPDATE] =
g_signal_new (I_("update"),
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkStyledPictureClass, update),
gtk_styled_picture_update_accumulator, NULL,
_gtk_marshal_OBJECT__VOID,
GDK_TYPE_PICTURE, 0);
g_type_class_add_private (klass, sizeof (GtkStyledPicturePrivate));
}
static void
gtk_styled_picture_init (GtkStyledPicture *picture)
{
picture->priv = G_TYPE_INSTANCE_GET_PRIVATE (picture,
GTK_TYPE_STYLED_PICTURE,
GtkStyledPicturePrivate);
}
/**
* gtk_styled_picture_new:
* @unstyled: The unstyled picture
* @widget: The widet to attach to
*
* Creates a new #GtkStyledPicture displaying the styled version of
* an @unstyled #GdkPicture
*
* Returns: a new picture
**/
GdkPicture *
gtk_styled_picture_new (GdkPicture *unstyled,
GtkWidget *widget)
{
GtkStyledPicturePrivate *priv;
GtkStyledPicture *styled;
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
g_return_val_if_fail (GDK_IS_PICTURE (unstyled), NULL);
styled = g_object_new (GTK_TYPE_STYLED_PICTURE, NULL);
priv = styled->priv;
priv->widget = widget;
g_object_add_weak_pointer (G_OBJECT (widget), (void **) &priv->widget);
g_signal_connect_swapped (widget,
"style-updated",
G_CALLBACK (gtk_styled_picture_update),
styled);
g_signal_connect_swapped (widget,
"state-flags-changed",
G_CALLBACK (gtk_styled_picture_update),
styled);
g_signal_connect_swapped (widget,
"direction-changed",
G_CALLBACK (gtk_styled_picture_update),
styled);
styled->priv->unstyled = g_object_ref (unstyled);
g_signal_connect_swapped (unstyled,
"notify",
G_CALLBACK (gtk_styled_picture_update),
styled);
gtk_styled_picture_update (styled);
return GDK_PICTURE (styled);
}
void
gtk_styled_picture_update (GtkStyledPicture *picture)
{
GdkPicture *new_picture = NULL;
g_signal_emit (picture, signals[UPDATE], 0, &new_picture);
gtk_styled_picture_set_styled (picture, new_picture);
if (new_picture)
g_object_unref (new_picture);
}
GtkWidget *
gtk_styled_picture_get_widget (GtkStyledPicture *picture)
{
g_return_val_if_fail (GTK_IS_STYLED_PICTURE (picture), NULL);
return picture->priv->widget;
}

65
gtk/gtkstyledpicture.h Normal file
View File

@@ -0,0 +1,65 @@
/* GTK - The GIMP Drawing Kit
* Copyright (C) 2010 Benjamin Otte <otte@gnome.org>
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk.h> can be included directly."
#endif
#ifndef __GTK_STYLED_PICTURE_H__
#define __GTK_STYLED_PICTURE_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define GTK_TYPE_STYLED_PICTURE (gtk_styled_picture_get_type ())
#define GTK_STYLED_PICTURE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_STYLED_PICTURE, GtkStyledPicture))
#define GTK_STYLED_PICTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_STYLED_PICTURE, GtkStyledPictureClass))
#define GTK_IS_STYLED_PICTURE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GTK_TYPE_STYLED_PICTURE))
#define GTK_IS_STYLED_PICTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_STYLED_PICTURE))
#define GTK_STYLED_PICTURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_STYLED_PICTURE, GtkStyledPictureClass))
typedef struct _GtkStyledPicture GtkStyledPicture;
typedef struct _GtkStyledPicturePrivate GtkStyledPicturePrivate;
typedef struct _GtkStyledPictureClass GtkStyledPictureClass;
struct _GtkStyledPicture {
GdkPicture parent_picture;
GtkStyledPicturePrivate *priv;
};
struct _GtkStyledPictureClass {
GdkPictureClass parent_class;
GdkPicture * ( *update) (GtkStyledPicture *picture);
};
GType gtk_styled_picture_get_type (void) G_GNUC_CONST;
GdkPicture * gtk_styled_picture_new (GdkPicture *unstyled,
GtkWidget *widget);
void gtk_styled_picture_update (GtkStyledPicture *picture);
GtkWidget * gtk_styled_picture_get_widget (GtkStyledPicture *picture);
G_END_DECLS
#endif /* __GTK_STYLED_PICTURE_H__ */

View File

@@ -4464,8 +4464,8 @@ gtk_widget_unrealize (GtkWidget *widget)
* Since: 3.0
**/
void
gtk_widget_queue_draw_region (GtkWidget *widget,
cairo_region_t *region)
gtk_widget_queue_draw_region (GtkWidget *widget,
const cairo_region_t *region)
{
GtkWidgetPrivate *priv;
GtkWidget *w;

View File

@@ -477,7 +477,7 @@ void gtk_widget_queue_draw_area (GtkWidget *widget,
gint width,
gint height);
void gtk_widget_queue_draw_region (GtkWidget *widget,
cairo_region_t *region);
const cairo_region_t*region);
void gtk_widget_queue_resize (GtkWidget *widget);
void gtk_widget_queue_resize_no_redraw (GtkWidget *widget);
#ifndef GTK_DISABLE_DEPRECATED

View File

@@ -67,6 +67,7 @@ noinst_PROGRAMS = $(TEST_PROGS) \
testoffscreen \
testoffscreenwindow \
testorientable \
testpicture \
testprint \
testrecentchooser \
testrecentchoosermenu \
@@ -167,6 +168,7 @@ testoffscreenwindow_DEPENDENCIES = $(TEST_DEPS)
testappchooser_DEPENDENCIES = $(TEST_DEPS)
testappchooserbutton_DEPENDENCIES = $(TEST_DEPS)
testorientable_DEPENDENCIES = $(TEST_DEPS)
testpicture_DEPENDENCIES = $(TEST_DEPS)
testprint_DEPENDENCIES = $(TEST_DEPS)
testrecentchooser_DEPENDENCIES = $(TEST_DEPS)
testrecentchoosermenu_DEPENDENCIES = $(TEST_DEPS)
@@ -249,6 +251,7 @@ testoffscreenwindow_LDADD = $(LDADDS)
testappchooser_LDADD = $(LDADDS)
testappchooserbutton_LDADD = $(LDADDS)
testorientable_LDADD = $(LDADDS)
testpicture_LDADD = $(LDADDS)
testprint_LDADD = $(LDADDS)
testrecentchooser_LDADD = $(LDADDS)
testrecentchoosermenu_LDADD = $(LDADDS)

784
tests/testpicture.c Normal file
View File

@@ -0,0 +1,784 @@
#include <gtk/gtk.h>
#include <math.h>
#include <string.h>
#define IMAGE_TYPE_PICTURE (image_picture_get_type ())
#define IMAGE_PICTURE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), IMAGE_TYPE_PICTURE, ImagePicture))
#define IMAGE_PICTURE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), IMAGE_TYPE_PICTURE, ImagePictureClass))
#define IMAGE_IS_PICTURE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), IMAGE_TYPE_PICTURE))
#define IMAGE_IS_PICTURE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), IMAGE_TYPE_PICTURE))
#define IMAGE_PICTURE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), IMAGE_TYPE_PICTURE, ImagePictureClass))
typedef struct _ImagePicture ImagePicture;
typedef GdkPictureClass ImagePictureClass;
struct _ImagePicture {
GdkPicture picture;
cairo_surface_t *surface;
};
G_DEFINE_TYPE (ImagePicture, image_picture, GDK_TYPE_PICTURE)
static void
image_picture_finalize (GObject *object)
{
cairo_surface_destroy (IMAGE_PICTURE (object)->surface);
G_OBJECT_CLASS (image_picture_parent_class)->finalize (object);
}
static cairo_surface_t *
image_picture_ref_surface (GdkPicture *picture)
{
return cairo_surface_reference (IMAGE_PICTURE (picture)->surface);
}
static void
image_picture_class_init (ImagePictureClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdkPictureClass *picture_class = GDK_PICTURE_CLASS (klass);
object_class->finalize = image_picture_finalize;
picture_class->ref_surface = image_picture_ref_surface;
}
static void
image_picture_init (ImagePicture *picture)
{
picture->surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 100, 100);
gdk_picture_resized (GDK_PICTURE (picture), 100, 100);
}
static GdkPicture *
image_picture_new (void)
{
return g_object_new (IMAGE_TYPE_PICTURE, NULL);
}
#define SLOW_TYPE_INPUT_STREAM (slow_input_stream_get_type ())
#define SLOW_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SLOW_TYPE_INPUT_STREAM, SlowInputStream))
#define SLOW_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), SLOW_TYPE_INPUT_STREAM, SlowInputStreamClass))
#define SLOW_IS_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SLOW_TYPE_INPUT_STREAM))
#define SLOW_IS_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SLOW_TYPE_INPUT_STREAM))
#define SLOW_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), SLOW_TYPE_INPUT_STREAM, SlowInputStreamClass))
typedef GFilterInputStream SlowInputStream;
typedef GFilterInputStreamClass SlowInputStreamClass;
G_DEFINE_TYPE (SlowInputStream, slow_input_stream, G_TYPE_FILTER_INPUT_STREAM)
static gssize
slow_input_stream_read (GInputStream *stream,
void *buffer,
gsize count,
GCancellable *cancellable,
GError **error)
{
gssize result;
count = MIN (count, 100);
result = g_input_stream_read (g_filter_input_stream_get_base_stream (G_FILTER_INPUT_STREAM (stream)),
buffer,
count,
cancellable,
error);
if (result > 0)
g_usleep (result * G_USEC_PER_SEC / 500);
return result;
}
static gboolean
slow_input_stream_close (GInputStream *stream,
GCancellable *cancellable,
GError **error)
{
g_usleep (5 * G_USEC_PER_SEC);
return g_input_stream_close (g_filter_input_stream_get_base_stream (G_FILTER_INPUT_STREAM (stream)),
cancellable,
error);
}
static void
slow_input_stream_class_init (SlowInputStreamClass *klass)
{
GInputStreamClass *input_stream_class = G_INPUT_STREAM_CLASS (klass);
input_stream_class->read_fn = slow_input_stream_read;
input_stream_class->close_fn = slow_input_stream_close;
}
static void
slow_input_stream_init (SlowInputStream *klass)
{
}
static GInputStream *
slow_input_stream_new (GInputStream *base_stream)
{
return g_object_new (slow_input_stream_get_type (), "base-stream", base_stream, NULL);
}
typedef struct _Demo Demo;
struct _Demo
{
const char *name;
void (* create) (Demo *demo);
GtkWidget *widget;
GdkPicture *picture;
GdkPicture *attached_picture;
};
static void
file_is_loaded_callback (GObject *object,
GAsyncResult *res,
gpointer user_data)
{
}
static void
slowly_load_file (Demo *demo, GFile *file)
{
GInputStream *file_stream, *load_stream;
file_stream = G_INPUT_STREAM (g_file_read (file, NULL, NULL));
if (file_stream == NULL)
return;
load_stream = slow_input_stream_new (file_stream);
gdk_picture_loader_load_from_stream_async (GDK_PICTURE_LOADER (demo->picture),
load_stream,
G_PRIORITY_DEFAULT,
NULL,
file_is_loaded_callback,
demo);
g_object_unref (file_stream);
g_object_unref (load_stream);
}
static void
file_set_callback (GtkFileChooser *button,
Demo *demo)
{
GFile *file = gtk_file_chooser_get_file (button);
if (file)
slowly_load_file (demo, file);
}
static void
create_slowly_loading_image (Demo *demo)
{
GtkWidget *button, *image;
GtkFileFilter *filter;
GFile *default_file;
demo->widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
demo->picture = gdk_picture_loader_new ();
button = gtk_file_chooser_button_new ("Select file to slowly load",
GTK_FILE_CHOOSER_ACTION_OPEN);
gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (button), FALSE);
filter = gtk_file_filter_new ();
gtk_file_filter_add_pixbuf_formats (filter);
gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (button), filter);
default_file = g_file_new_for_path ("apple-red.png");
gtk_file_chooser_set_file (GTK_FILE_CHOOSER (button),
default_file, NULL);
slowly_load_file (demo, default_file);
g_object_unref (default_file);
g_signal_connect (button,
"file-set",
G_CALLBACK (file_set_callback),
demo);
gtk_box_pack_start (GTK_BOX (demo->widget), button, TRUE, TRUE, 0);
image = gtk_image_new_from_picture (demo->picture);
gtk_box_pack_start (GTK_BOX (demo->widget), image, TRUE, TRUE, 0);
}
static void
create_animation (Demo *demo)
{
GdkPixbufAnimation *animation = gdk_pixbuf_animation_new_from_file ("1234.gif", NULL);
demo->widget = gtk_label_new ("bla");
demo->picture = gdk_pixbuf_animation_picture_new (animation);
g_object_unref (animation);
}
static void
create_stock_picture (Demo *demo)
{
demo->widget = gtk_image_new_from_stock (GTK_STOCK_GOTO_FIRST, GTK_ICON_SIZE_BUTTON);
gtk_widget_set_direction (demo->widget, GTK_TEXT_DIR_RTL);
demo->picture = gtk_stock_picture_new (GTK_STOCK_GOTO_FIRST, GTK_ICON_SIZE_BUTTON);
}
static void
create_icon_set_picture (Demo *demo)
{
struct {
const char *icon_name;
GtkStateType state;
} states[] = {
{ GTK_STOCK_HOME, GTK_STATE_NORMAL },
{ GTK_STOCK_APPLY, GTK_STATE_ACTIVE },
{ GTK_STOCK_YES, GTK_STATE_PRELIGHT },
{ GTK_STOCK_SELECT_ALL, GTK_STATE_SELECTED },
{ GTK_STOCK_HELP, GTK_STATE_INSENSITIVE },
{ GTK_STOCK_ABOUT, GTK_STATE_INCONSISTENT },
{ GTK_STOCK_OK, GTK_STATE_FOCUSED }
};
GtkIconSet *set;
GtkIconSource *source;
guint i;
set = gtk_icon_set_new ();
for (i = 0; i < G_N_ELEMENTS (states); i++)
{
source = gtk_icon_source_new ();
gtk_icon_source_set_state (source, states[i].state);
gtk_icon_source_set_state_wildcarded (source, FALSE);
gtk_icon_source_set_icon_name (source, states[i].icon_name);
gtk_icon_set_add_source (set, source);
gtk_icon_source_free (source);
}
demo->widget = gtk_label_new ("Shows a manually constructed icon set.\n"
"It displays random stock icons fordifferent states.");
demo->picture = gtk_icon_set_picture_new (set, GTK_ICON_SIZE_BUTTON);
gtk_icon_set_unref (set);
}
static void
change_icon_theme_callback (GtkWidget *combo, GtkIconThemePicture *picture)
{
const char *theme_name = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (combo));
if (theme_name == NULL || g_str_equal (theme_name, "") || g_str_equal (theme_name, "(default)"))
{
gtk_icon_theme_picture_set_icon_theme (picture, NULL);
}
else
{
GtkIconTheme *icon_theme = gtk_icon_theme_new ();
gtk_icon_theme_set_custom_theme (icon_theme, theme_name);
gtk_icon_theme_picture_set_icon_theme (picture, icon_theme);
g_object_unref (icon_theme);
}
}
static GtkWidget *
theme_selector_new (GdkPicture *picture)
{
GtkWidget *combo;
GList *names, *walk;
GtkIconTheme *icon_theme;
char **paths;
guint i;
icon_theme = gtk_icon_theme_new ();
gtk_icon_theme_get_search_path (icon_theme, &paths, NULL);
combo = gtk_combo_box_text_new_with_entry ();
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "(default)");
gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
g_signal_connect (combo, "changed", G_CALLBACK (change_icon_theme_callback), picture);
names = NULL;
for (i = 0; paths[i]; i++)
{
GDir *dir = g_dir_open (paths[i], 0, NULL);
const char *name;
if (dir == NULL)
continue;
while ((name = g_dir_read_name (dir)))
{
char *full = g_build_filename (paths[i], name, "index.theme", NULL);
if (g_file_test (full, G_FILE_TEST_EXISTS))
names = g_list_prepend (names, g_strdup (name));
g_free (full);
}
g_dir_close (dir);
}
names = g_list_sort (names, (GCompareFunc) strcmp);
for (walk = names; walk; walk = walk->next)
{
/* skip identical names */
while (walk->next && g_str_equal (walk->data, walk->next->data))
walk = walk->next;
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), walk->data);
}
g_list_free_full (names, g_free);
g_strfreev (paths);
g_object_unref (icon_theme);
return combo;
}
static void
create_gicon_picture (Demo *demo)
{
GIcon *icon = g_themed_icon_new ("folder");
demo->widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
demo->picture = gtk_icon_picture_new (icon, GTK_ICON_SIZE_BUTTON);
gtk_box_pack_start (GTK_BOX (demo->widget), gtk_label_new ("Theme:"), FALSE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (demo->widget), theme_selector_new (demo->picture), FALSE, TRUE, 0);
g_object_unref (icon);
}
static void
update_icon_names (GtkNamedPicture *picture, GParamSpec *pspec, GtkComboBoxText *combo)
{
GList *names, *walk;
GtkIconTheme *icon_theme;
char *current;
guint i;
icon_theme = gtk_icon_theme_picture_get_icon_theme (GTK_ICON_THEME_PICTURE (picture));
if (icon_theme == NULL)
icon_theme = gtk_icon_theme_get_default ();
names = gtk_icon_theme_list_icons (icon_theme, NULL);
names = g_list_sort (names, (GCompareFunc) strcmp);
current = g_strdup (gtk_named_picture_get_name (picture));
gtk_combo_box_text_remove_all (combo);
for (walk = names, i = 0; walk; walk = walk->next, i++)
{
gtk_combo_box_text_append_text (combo, walk->data);
if (current && g_str_equal (walk->data, current))
gtk_combo_box_set_active (GTK_COMBO_BOX (combo), i);
}
g_list_free_full (names, g_free);
g_free (current);
}
static void
change_icon_name_callback (GtkComboBoxText *combo, GtkNamedPicture *picture)
{
gtk_named_picture_set_name (picture, gtk_combo_box_text_get_active_text (combo));
}
static GtkWidget *
icon_name_selector_new (GdkPicture *picture)
{
GtkWidget *combo;
combo = gtk_combo_box_text_new_with_entry ();
g_signal_connect (combo, "changed", G_CALLBACK (change_icon_name_callback), picture);
g_signal_connect (picture, "notify::icon-theme", G_CALLBACK (update_icon_names), combo);
update_icon_names (GTK_NAMED_PICTURE (picture), NULL, GTK_COMBO_BOX_TEXT (combo));
return combo;
}
static void
create_icon_name_picture (Demo *demo)
{
demo->widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
demo->picture = gtk_named_picture_new ("window-new", GTK_ICON_SIZE_BUTTON);
gtk_box_pack_start (GTK_BOX (demo->widget), gtk_label_new ("Theme:"), FALSE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (demo->widget), theme_selector_new (demo->picture), FALSE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (demo->widget), gtk_label_new ("Icon:"), FALSE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (demo->widget), icon_name_selector_new (demo->picture), FALSE, TRUE, 0);
}
static GdkRGBA scribble_colors[2] =
{
{ 0.0, 0.0, 0.0, 1.0 },
{ 0.0, 0.0, 0.0, 0.0 }
};
/* Draw a rectangle onto the picture */
static void
scribble (ImagePicture * picture,
gdouble x,
gdouble y,
const GdkRGBA *color)
{
GdkRectangle update_rect;
cairo_t *cr;
update_rect.x = x - 3;
update_rect.y = y - 3;
update_rect.width = 6;
update_rect.height = 6;
/* Paint to the surface, where we store our state */
cr = cairo_create (picture->surface);
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
gdk_cairo_set_source_rgba (cr, color);
gdk_cairo_rectangle (cr, &update_rect);
cairo_fill (cr);
cairo_destroy (cr);
/* Now invalidate the affected region of the drawing area. */
gdk_picture_changed_rect (GDK_PICTURE (picture), &update_rect);
}
static gboolean
scribble_button_press_event (GtkWidget *widget,
GdkEventButton *event,
ImagePicture *picture)
{
if (event->button == 1)
scribble (picture, event->x, event->y, &scribble_colors[0]);
else if (event->button == 3)
scribble (picture, event->x, event->y, &scribble_colors[1]);
/* We've handled the event, stop processing */
return TRUE;
}
static gboolean
scribble_motion_notify_event (GtkWidget *widget,
GdkEventMotion *event,
ImagePicture *picture)
{
int x, y;
GdkModifierType state;
/* This call is very important; it requests the next motion event.
* If you don't call gdk_window_get_pointer() you'll only get
* a single motion event. The reason is that we specified
* GDK_POINTER_MOTION_HINT_MASK to gtk_widget_set_events().
* If we hadn't specified that, we could just use event->x, event->y
* as the pointer location. But we'd also get deluged in events.
* By requesting the next event as we handle the current one,
* we avoid getting a huge number of events faster than we
* can cope.
*/
gdk_window_get_pointer (event->window, &x, &y, &state);
if (state & GDK_BUTTON1_MASK)
scribble (picture, x, y, &scribble_colors[0]);
if (state & GDK_BUTTON3_MASK)
scribble (picture, x, y, &scribble_colors[1]);
/* We've handled it, stop processing */
return TRUE;
}
static void
create_scribble_area (Demo *demo)
{
GtkWidget *frame, *image, *eventbox;
demo->picture = image_picture_new ();
demo->widget = gtk_alignment_new (0.5, 0.5, 0, 0);
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
gtk_container_add (GTK_CONTAINER (demo->widget), frame);
eventbox = gtk_event_box_new ();
gtk_container_add (GTK_CONTAINER (frame), eventbox);
/* Event signals */
g_signal_connect (eventbox, "motion-notify-event",
G_CALLBACK (scribble_motion_notify_event), demo->picture);
g_signal_connect (eventbox, "button-press-event",
G_CALLBACK (scribble_button_press_event), demo->picture);
/* Ask to receive events the drawing area doesn't normally
* subscribe to
*/
gtk_widget_add_events (eventbox,
GDK_BUTTON_PRESS_MASK
| GDK_POINTER_MOTION_MASK
| GDK_POINTER_MOTION_HINT_MASK);
image = gtk_image_new_from_picture (demo->picture);
gtk_container_add (GTK_CONTAINER (eventbox), image);
}
Demo demos[] = {
{ "Slowly loading image", create_slowly_loading_image, NULL, NULL },
{ "Animation", create_animation, NULL, NULL },
{ "Named theme icons", create_stock_picture, NULL, NULL },
{ "Icon Set", create_icon_set_picture, NULL, NULL },
{ "GIcon", create_gicon_picture, NULL, NULL },
{ "Named Icon", create_icon_name_picture, NULL, NULL },
{ "Scribble Area", create_scribble_area, NULL, NULL }
};
static guint rotation = 0;
static guint rotation_source = 0;
static void
get_picture_offset (GtkWidget *widget,
guint i,
double *offset_x,
double *offset_y)
{
double rx, ry;
rx = (gtk_widget_get_allocated_width (widget) - gdk_picture_get_width (demos[i].attached_picture)) / 2.0;
ry = (gtk_widget_get_allocated_height (widget) - gdk_picture_get_height (demos[i].attached_picture)) / 2.0;
*offset_x = gtk_widget_get_allocated_width (widget) / 2.0
+ rx * sin (2 * G_PI * i / G_N_ELEMENTS (demos) + (2 * G_PI * rotation / 360))
- gdk_picture_get_width (demos[i].attached_picture) / 2.0;
*offset_y = gtk_widget_get_allocated_height (widget) / 2.0
+ ry * cos (2 * G_PI * i / G_N_ELEMENTS (demos) + (2 * G_PI * rotation / 360))
- gdk_picture_get_height (demos[i].attached_picture) / 2.0;
}
static gboolean
draw_callback (GtkWidget *area,
cairo_t *cr,
gpointer unused)
{
guint i;
for (i = 0; i < G_N_ELEMENTS (demos); i++)
{
double x, y;
get_picture_offset (area, i, &x, &y);
cairo_save (cr);
cairo_translate (cr, x, y);
gdk_picture_draw (demos[i].attached_picture, cr);
cairo_restore (cr);
}
return FALSE;
}
#define ROTATE_FPS 30
#define ROTATE_SECONDS 6
static void
area_invalidate_picture (GtkWidget *area, guint i, const cairo_region_t *region)
{
cairo_region_t *copy;
double x, y;
int dx, dy;
get_picture_offset (area, i, &x, &y);
if (region)
copy = cairo_region_copy (region);
else
{
cairo_rectangle_int_t rect = { 0, 0,
gdk_picture_get_width (demos[i].attached_picture),
gdk_picture_get_height (demos[i].attached_picture) };
copy = cairo_region_create_rectangle (&rect);
}
cairo_region_translate (copy, floor (x), floor (y));
gtk_widget_queue_draw_region (area, copy);
dx = (floor (x) != ceil (x)) ? 1 : 0;
dy = (floor (y) != ceil (y)) ? 1 : 0;
if (dx || dy)
{
cairo_region_translate (copy, dx, dy);
gtk_widget_queue_draw_region (area, copy);
}
cairo_region_destroy (copy);
}
static gboolean
rotate_area (gpointer area)
{
guint i;
for (i = 0; i < G_N_ELEMENTS (demos); i++)
area_invalidate_picture (area, i, NULL);
rotation += 360 / ROTATE_SECONDS / ROTATE_FPS;
rotation %= 360;
for (i = 0; i < G_N_ELEMENTS (demos); i++)
area_invalidate_picture (area, i, NULL);
return TRUE;
}
static void
rotation_toggled (GtkButton *button, GtkWidget *area)
{
if (rotation_source)
{
g_source_remove (rotation_source);
rotation_source = 0;
gtk_button_set_label (button, GTK_STOCK_MEDIA_PLAY);
}
else
{
rotation_source = gdk_threads_add_timeout (1000 / ROTATE_FPS, rotate_area, area);
gtk_button_set_label (button, GTK_STOCK_MEDIA_PAUSE);
}
}
static void
picture_changed (GdkPicture *picture, const cairo_region_t *region, GtkWidget *area)
{
guint i;
for (i = 0; i < G_N_ELEMENTS (demos); i++)
{
if (demos[i].attached_picture == picture)
break;
}
g_assert (i < G_N_ELEMENTS (demos));
area_invalidate_picture (area, i, region);
}
static void
toggled_flag (GtkWidget *check, gpointer area)
{
int flag = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (check), "flags"));
if (flag)
{
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check)))
gtk_widget_set_state_flags (area, flag, FALSE);
else
gtk_widget_unset_state_flags (area, flag);
}
else
gtk_widget_set_direction (area,
gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check)) ? GTK_TEXT_DIR_RTL :
GTK_TEXT_DIR_LTR);
}
GtkWidget *
create_optionsview (GtkWidget *area)
{
struct {
GtkStateFlags flags;
const char * text;
} options[] = {
{ 0, "right-to-left" },
{ GTK_STATE_FLAG_ACTIVE, "active" },
{ GTK_STATE_FLAG_PRELIGHT, "prelight" },
{ GTK_STATE_FLAG_SELECTED, "selected" },
{ GTK_STATE_FLAG_INSENSITIVE, "insensitive" },
{ GTK_STATE_FLAG_INCONSISTENT, "inconsistent" },
{ GTK_STATE_FLAG_FOCUSED, "focused" }
};
GtkWidget *box, *check;
guint i;
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
for (i = 0; i < G_N_ELEMENTS (options); i++)
{
check = gtk_check_button_new_with_label (options[i].text);
if (options[i].flags)
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check),
gtk_widget_get_state_flags (area) & options[i].flags);
else
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check),
gtk_widget_get_direction (area) == GTK_TEXT_DIR_RTL);
g_object_set_data (G_OBJECT (check), "flags", GINT_TO_POINTER (options[i].flags));
g_signal_connect (check, "toggled", G_CALLBACK (toggled_flag), area);
gtk_box_pack_start (GTK_BOX (box), check, TRUE, TRUE, 0);
}
return box;
}
int
main (int argc, char **argv)
{
GtkWidget *window, *vbox, *hbox, *area, *widget;
guint i;
gtk_init (&argc, &argv);
//gdk_window_set_debug_updates (TRUE);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Pictures");
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
gtk_container_add (GTK_CONTAINER (window), hbox);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
area = gtk_drawing_area_new ();
gtk_widget_set_size_request (area, 400, 400);
g_signal_connect (area, "draw", G_CALLBACK (draw_callback), NULL);
gtk_box_pack_start (GTK_BOX (vbox), area, TRUE, TRUE, 0);
widget = gtk_button_new_from_stock (GTK_STOCK_MEDIA_PAUSE);
g_signal_connect (widget, "clicked", G_CALLBACK (rotation_toggled), area);
rotation_toggled (GTK_BUTTON (widget), area);
gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, TRUE, 0);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, TRUE, 0);
widget = create_optionsview (area);
gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, TRUE, 0);
for (i = 0; i < G_N_ELEMENTS (demos); i++)
{
GtkWidget *expander;
demos[i].create (&demos[i]);
demos[i].attached_picture = gtk_widget_style_picture (area, demos[i].picture);
g_signal_connect (demos[i].attached_picture, "changed", G_CALLBACK (picture_changed), area);
expander = gtk_expander_new (demos[i].name);
gtk_container_add (GTK_CONTAINER (expander), demos[i].widget);
gtk_box_pack_start (GTK_BOX (vbox), expander, FALSE, TRUE, 0);
}
gtk_widget_show_all (window);
gtk_main ();
return 0;
}