[cairo-commit] goocanvas/src goocanvas.c, NONE,
1.1 goocanvasitemmodel.c, NONE, 1.1 goocanvasitemmodel.h, NONE,
1.1 goocanvasstyle.c, NONE, 1.1 goocanvasstyle.h, NONE,
1.1 goocanvaswidget.c, NONE, 1.1 goocanvaswidget.h, NONE, 1.1
Damon Chaplin
commit at pdx.freedesktop.org
Wed Nov 29 10:27:10 PST 2006
- Previous message: [cairo-commit] goocanvas/demo mv-demo-arrowhead.c, NONE,
1.1 mv-demo-events.c, NONE, 1.1 mv-demo-features.c, NONE,
1.1 mv-demo-fifteen.c, NONE, 1.1 mv-demo-focus.c, NONE,
1.1 mv-demo-grabs.c, NONE, 1.1 mv-demo-paths.c, NONE,
1.1 mv-demo-scalability.c, NONE, 1.1 mv-demo.c, NONE,
1.1 mv-simple-demo.c, NONE, 1.1 widgets-demo.c, NONE, 1.1
- Next message: [cairo-commit] goocanvas/src Makefile.am, 1.10, 1.11 goocanvas.h,
1.2, 1.3 goocanvasatk.c, 1.6, 1.7 goocanvasatk.h, 1.1,
1.2 goocanvasellipse.c, 1.6, 1.7 goocanvasellipse.h, 1.2,
1.3 goocanvasgroup.c, 1.13, 1.14 goocanvasgroup.h, 1.8,
1.9 goocanvasimage.c, 1.7, 1.8 goocanvasimage.h, 1.2,
1.3 goocanvasimageview.c, 1.16, NONE goocanvasimageview.h, 1.4,
NONE goocanvasitem.c, 1.10, 1.11 goocanvasitem.h, 1.7,
1.8 goocanvasitemsimple.c, 1.14, 1.15 goocanvasitemsimple.h,
1.10, 1.11 goocanvasitemview.c, 1.14, NONE goocanvasitemview.h,
1.12, NONE goocanvasitemviewsimple.c, 1.13,
NONE goocanvasitemviewsimple.h, 1.5, NONE goocanvasmodel.c,
1.3, NONE goocanvasmodel.h, 1.2, NONE goocanvasmodelsimple.c,
1.5, NONE goocanvasmodelsimple.h, 1.2, NONE goocanvaspath.c,
1.7, 1.8 goocanvaspath.h, 1.5, 1.6 goocanvaspathview.c, 1.11,
NONE goocanvaspathview.h, 1.4, NONE goocanvaspolyline.c, 1.6,
1.7 goocanvaspolyline.h, 1.4, 1.5 goocanvaspolylineview.c,
1.19, NONE goocanvaspolylineview.h, 1.5, NONE goocanvasrect.c,
1.6, 1.7 goocanvasrect.h, 1.2, 1.3 goocanvasrectview.c, 1.12,
NONE goocanvasrectview.h, 1.4, NONE goocanvastext.c, 1.6,
1.7 goocanvastext.h, 1.3, 1.4 goocanvastextview.c, 1.19,
NONE goocanvastextview.h, 1.5, NONE goocanvasview.c, 1.32,
NONE goocanvasview.h, 1.11, NONE
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Committed by: damon
Update of /cvs/cairo/goocanvas/src
In directory kemper:/tmp/cvs-serv29333/src
Added Files:
goocanvas.c goocanvasitemmodel.c goocanvasitemmodel.h
goocanvasstyle.c goocanvasstyle.h goocanvaswidget.c
goocanvaswidget.h
Log Message:
added bunch of new files, part of new model/view architecture
--- NEW FILE: goocanvas.c ---
/*
* GooCanvas. Copyright (C) 2005 Damon Chaplin.
* Released under the GNU LGPL license. See COPYING for details.
*
* goocanvas.c - the main canvas widget.
*/
/**
* SECTION: goocanvas
* @Title: GooCanvas
* @Short_Description: the main canvas widget.
*
* #GooCanvas is the main widget containing a number of canvas items.
*
*
* Here is a simple example:
*
* <informalexample><programlisting>
* #include <goocanvas.h>
[...3172 lines suppressed...]
{
GooCanvas *canvas;
GList *tmp_list;
GooCanvasWidget *witem;
g_return_if_fail (GOO_IS_CANVAS (container));
g_return_if_fail (callback != NULL);
canvas = GOO_CANVAS (container);
tmp_list = canvas->widget_items;
while (tmp_list)
{
witem = tmp_list->data;
tmp_list = tmp_list->next;
if (witem->widget)
(* callback) (witem->widget, callback_data);
}
}
--- NEW FILE: goocanvasitemmodel.c ---
/*
* GooCanvas. Copyright (C) 2005 Damon Chaplin.
* Released under the GNU LGPL license. See COPYING for details.
*
* goocanvasitem.c - interface for canvas items & groups.
*/
/**
* SECTION:goocanvasitemmodel
* @Title: GooCanvasItemModel
* @Short_Description: the interface for canvas item models.
*
* #GooCanvasItemModel defines the interface that models for canvas items must
* implement, and contains methods for operating on canvas item models.
*/
#include <config.h>
#include <math.h>
#include <glib/gi18n-lib.h>
#include <gtk/gtk.h>
#include "goocanvasprivate.h"
#include <goocanvasenumtypes.h>
#include "goocanvasitemmodel.h"
#include "goocanvasutils.h"
#include "goocanvasmarshal.h"
static const char *animation_key = "GooCanvasItemModelAnimation";
enum {
CHILD_ADDED,
CHILD_MOVED,
CHILD_REMOVED,
CHANGED,
LAST_SIGNAL
};
static guint item_model_signals[LAST_SIGNAL] = { 0 };
static void goo_canvas_item_model_base_init (gpointer g_class);
extern void _goo_canvas_style_init (void);
GType
goo_canvas_item_model_get_type (void)
{
static GType item_model_type = 0;
if (!item_model_type)
{
static const GTypeInfo item_model_info =
{
sizeof (GooCanvasItemModelIface), /* class_size */
goo_canvas_item_model_base_init, /* base_init */
NULL, /* base_finalize */
};
item_model_type = g_type_register_static (G_TYPE_INTERFACE,
"GooCanvasItemModel",
&item_model_info, 0);
g_type_interface_add_prerequisite (item_model_type, G_TYPE_OBJECT);
}
return item_model_type;
}
static void
goo_canvas_item_model_base_init (gpointer g_iface)
{
static gboolean initialized = FALSE;
if (!initialized)
{
GType iface_type = G_TYPE_FROM_INTERFACE (g_iface);
/**
* GooCanvasItemModel::child-added
* @model: the item that received the signal.
* @child_num: the index of the new child.
*
* Emitted when a child has been added to the container item.
*/
item_model_signals[CHILD_ADDED] =
g_signal_new ("child-added",
iface_type,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GooCanvasItemModelIface, child_added),
NULL, NULL,
goo_canvas_marshal_VOID__INT,
G_TYPE_NONE, 1,
G_TYPE_INT);
/**
* GooCanvasItemModel::child-moved
* @model: the item that received the signal.
* @old_child_num: the old index of the child.
* @new_child_num: the new index of the child.
*
* Emitted when a child has been moved in the stacking order of a
* container item.
*/
item_model_signals[CHILD_MOVED] =
g_signal_new ("child-moved",
iface_type,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GooCanvasItemModelIface, child_moved),
NULL, NULL,
goo_canvas_marshal_VOID__INT_INT,
G_TYPE_NONE, 2,
G_TYPE_INT, G_TYPE_INT);
/**
* GooCanvasItemModel::child-removed
* @model: the item that received the signal.
* @child_num: the index of the child that was removed.
*
* Emitted when a child has been removed from the container item.
*/
item_model_signals[CHILD_REMOVED] =
g_signal_new ("child-removed",
iface_type,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GooCanvasItemModelIface, child_removed),
NULL, NULL,
goo_canvas_marshal_VOID__INT,
G_TYPE_NONE, 1,
G_TYPE_INT);
/**
* GooCanvasItemModel::changed
* @model: the item that received the signal.
* @recompute_bounds: if the bounds of the item need to be recomputed.
*
* Emitted when the item has been changed.
*/
item_model_signals[CHANGED] =
g_signal_new ("changed",
iface_type,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GooCanvasItemModelIface, changed),
NULL, NULL,
goo_canvas_marshal_VOID__BOOLEAN,
G_TYPE_NONE, 1,
G_TYPE_BOOLEAN);
g_object_interface_install_property (g_iface,
g_param_spec_object ("parent",
_("Parent"),
_("The parent item"),
GOO_TYPE_CANVAS_ITEM,
G_PARAM_READWRITE));
g_object_interface_install_property (g_iface,
g_param_spec_enum ("visibility",
_("Visibility"),
_("When the canvas item is visible"),
GOO_TYPE_CANVAS_ITEM_VISIBILITY,
GOO_CANVAS_ITEM_VISIBLE,
G_PARAM_READWRITE));
g_object_interface_install_property (g_iface,
g_param_spec_double ("visibility-threshold",
_("Visibility Threshold"),
_("The scale threshold at which the item becomes visible"),
0.0,
G_MAXDOUBLE,
0.0,
G_PARAM_READWRITE));
g_object_interface_install_property (g_iface,
g_param_spec_boxed ("transform",
_("Transform"),
_("The transformation matrix of the item"),
GOO_TYPE_CAIRO_MATRIX,
G_PARAM_READWRITE));
g_object_interface_install_property (g_iface,
g_param_spec_flags ("pointer-events",
_("Pointer Events"),
_("Specifies when the item receives pointer events"),
GOO_TYPE_CANVAS_POINTER_EVENTS,
GOO_CANVAS_EVENTS_VISIBLE_PAINTED,
G_PARAM_READWRITE));
g_object_interface_install_property (g_iface,
g_param_spec_string ("title",
_("Title"),
_("A short context-rich description of the item for use by assistive technologies"),
NULL,
G_PARAM_READWRITE));
g_object_interface_install_property (g_iface,
g_param_spec_string ("description",
_("Description"),
_("A description of the item for use by assistive technologies"),
NULL,
G_PARAM_READWRITE));
g_object_interface_install_property (g_iface,
g_param_spec_boolean ("can-focus",
_("Can Focus"),
_("If the item can take the keyboard focus"),
FALSE,
G_PARAM_READWRITE));
_goo_canvas_style_init ();
initialized = TRUE;
}
}
/**
* goo_canvas_item_model_add_child:
* @model: the container to add the item to.
* @child: the item to add.
* @position: the position of the item, or -1 to place it last (at the top of
* the stacking order).
*
* Adds a child item to a container item at the given stack position.
**/
void
goo_canvas_item_model_add_child (GooCanvasItemModel *model,
GooCanvasItemModel *child,
gint position)
{
GooCanvasItemModelIface *iface = GOO_CANVAS_ITEM_MODEL_GET_IFACE (model);
g_return_if_fail (iface->add_child != NULL);
iface->add_child (model, child, position);
}
/**
* goo_canvas_item_model_move_child:
* @model: a container item.
* @old_position: the current position of the child item.
* @new_position: the new position of the child item.
*
* Moves a child item to a new stack position within the container.
**/
void
goo_canvas_item_model_move_child (GooCanvasItemModel *model,
gint old_position,
gint new_position)
{
GooCanvasItemModelIface *iface = GOO_CANVAS_ITEM_MODEL_GET_IFACE (model);
g_return_if_fail (iface->move_child != NULL);
iface->move_child (model, old_position, new_position);
}
/**
* goo_canvas_item_model_remove_child:
* @model: a container item.
* @child_num: the position of the child item to remove.
*
* Removes the child item at the given position.
**/
void
goo_canvas_item_model_remove_child (GooCanvasItemModel *model,
gint child_num)
{
GooCanvasItemModelIface *iface = GOO_CANVAS_ITEM_MODEL_GET_IFACE (model);
g_return_if_fail (iface->remove_child != NULL);
iface->remove_child (model, child_num);
}
/**
* goo_canvas_item_model_find_child:
* @model: a container item.
* @child: the child item to find.
*
* Attempts to find the given child item with the container's stack.
*
* Returns: the position of the given @child item, or -1 if it isn't found.
**/
gint
goo_canvas_item_model_find_child (GooCanvasItemModel *model,
GooCanvasItemModel *child)
{
GooCanvasItemModel *item;
int n_children, i;
/* Find the current position of item and above. */
n_children = goo_canvas_item_model_get_n_children (model);
for (i = 0; i < n_children; i++)
{
item = goo_canvas_item_model_get_child (model, i);
if (child == item)
return i;
}
return -1;
}
/**
* goo_canvas_item_model_is_container:
* @model: an item model.
*
* Tests to see if the given item is a container.
*
* Returns: %TRUE if the item is a container.
**/
gboolean
goo_canvas_item_model_is_container (GooCanvasItemModel *model)
{
GooCanvasItemModelIface *iface = GOO_CANVAS_ITEM_MODEL_GET_IFACE (model);
return iface->get_n_children ? TRUE : FALSE;
}
/**
* goo_canvas_item_model_get_n_children:
* @model: a container item.
*
* Gets the number of children of the container.
*
* Returns: the number of children.
**/
gint
goo_canvas_item_model_get_n_children (GooCanvasItemModel *model)
{
GooCanvasItemModelIface *iface = GOO_CANVAS_ITEM_MODEL_GET_IFACE (model);
return iface->get_n_children ? iface->get_n_children (model) : 0;
}
/**
* goo_canvas_item_model_get_child:
* @model: a container item.
* @child_num: the position of a child in the container's stack.
*
* Gets the child item at the given stack position.
*
* Returns: the child item at the given stack position.
**/
GooCanvasItemModel*
goo_canvas_item_model_get_child (GooCanvasItemModel *model,
gint child_num)
{
GooCanvasItemModelIface *iface = GOO_CANVAS_ITEM_MODEL_GET_IFACE (model);
return iface->get_child ? iface->get_child (model, child_num) : NULL;
}
/**
* goo_canvas_item_model_get_parent:
* @model: an item model.
*
* Gets the parent of the given item.
*
* Returns: the parent item, or %NULL if the item has no parent.
**/
GooCanvasItemModel*
goo_canvas_item_model_get_parent (GooCanvasItemModel *model)
{
return GOO_CANVAS_ITEM_MODEL_GET_IFACE (model)->get_parent (model);
}
/**
* goo_canvas_item_model_set_parent:
* @model: an item model.
* @parent: the new parent item.
*
* Sets the parent of the item.
**/
void
goo_canvas_item_model_set_parent (GooCanvasItemModel *model,
GooCanvasItemModel *parent)
{
GOO_CANVAS_ITEM_MODEL_GET_IFACE (model)->set_parent (model, parent);
}
/**
* goo_canvas_item_model_raise:
* @model: an item model.
* @above: the item to raise @model above, or %NULL to raise @model to the top
* of the stack.
*
* Raises an item in the stacking order.
**/
void
goo_canvas_item_model_raise (GooCanvasItemModel *model,
GooCanvasItemModel *above)
{
GooCanvasItemModel *parent, *child;
int n_children, i, model_pos = -1, above_pos = -1;
parent = goo_canvas_item_model_get_parent (model);
if (!parent || model == above)
return;
/* Find the current position of model and above. */
n_children = goo_canvas_item_model_get_n_children (parent);
for (i = 0; i < n_children; i++)
{
child = goo_canvas_item_model_get_child (parent, i);
if (child == model)
model_pos = i;
if (child == above)
above_pos = i;
}
/* If above is NULL we raise the model to the top of the stack. */
if (!above)
above_pos = n_children - 1;
g_return_if_fail (model_pos != -1);
g_return_if_fail (above_pos != -1);
/* Only move the model if the new position is higher in the stack. */
if (above_pos > model_pos)
goo_canvas_item_model_move_child (parent, model_pos, above_pos);
}
/**
* goo_canvas_item_model_lower:
* @model: an item model.
* @below: the item to lower @model below, or %NULL to lower @model to the
* bottom of the stack.
*
* Lowers an item in the stacking order.
**/
void
goo_canvas_item_model_lower (GooCanvasItemModel *model,
GooCanvasItemModel *below)
{
GooCanvasItemModel *parent, *child;
int n_children, i, model_pos = -1, below_pos = -1;
parent = goo_canvas_item_model_get_parent (model);
if (!parent || model == below)
return;
/* Find the current position of model and below. */
n_children = goo_canvas_item_model_get_n_children (parent);
for (i = 0; i < n_children; i++)
{
child = goo_canvas_item_model_get_child (parent, i);
if (child == model)
model_pos = i;
if (child == below)
below_pos = i;
}
/* If below is NULL we lower the model to the bottom of the stack. */
if (!below)
below_pos = 0;
g_return_if_fail (model_pos != -1);
g_return_if_fail (below_pos != -1);
/* Only move the model if the new position is lower in the stack. */
if (below_pos < model_pos)
goo_canvas_item_model_move_child (parent, model_pos, below_pos);
}
/**
* goo_canvas_item_model_get_transform:
* @model: an item model.
*
* Gets the transformation matrix of an item model.
*
* Returns: the item's transformation matrix.
**/
cairo_matrix_t*
goo_canvas_item_model_get_transform (GooCanvasItemModel *model)
{
GooCanvasItemModelIface *iface = GOO_CANVAS_ITEM_MODEL_GET_IFACE (model);
return iface->get_transform ? iface->get_transform (model) : NULL;
}
/**
* goo_canvas_item_model_set_transform:
* @model: an item model.
* @matrix: the new transformation matrix, or %NULL to reset the
* transformation to the identity matrix.
*
* Sets the transformation matrix of an item model.
**/
void
goo_canvas_item_model_set_transform (GooCanvasItemModel *model,
cairo_matrix_t *matrix)
{
GOO_CANVAS_ITEM_MODEL_GET_IFACE (model)->set_transform (model, matrix);
}
/**
* goo_canvas_item_model_translate:
* @model: an item model.
* @tx: the amount to move the origin in the horizontal direction.
* @ty: the amount to move the origin in the vertical direction.
*
* Translates the origin of the item's coordinate system by the given amounts.
**/
void
goo_canvas_item_model_translate (GooCanvasItemModel *model,
double tx,
double ty)
{
GooCanvasItemModelIface *iface = GOO_CANVAS_ITEM_MODEL_GET_IFACE (model);
cairo_matrix_t *matrix, new_matrix = { 1, 0, 0, 1, 0, 0 };
matrix = iface->get_transform (model);
if (matrix)
new_matrix = *matrix;
cairo_matrix_translate (&new_matrix, tx, ty);
iface->set_transform (model, &new_matrix);
}
/**
* goo_canvas_item_model_scale:
* @model: an item model.
* @sx: the amount to scale the horizontal axis.
* @sy: the amount to scale the vertical axis.
*
* Scales the item's coordinate system by the given amounts.
**/
void
goo_canvas_item_model_scale (GooCanvasItemModel *model,
double sx,
double sy)
{
GooCanvasItemModelIface *iface = GOO_CANVAS_ITEM_MODEL_GET_IFACE (model);
cairo_matrix_t *matrix, new_matrix = { 1, 0, 0, 1, 0, 0 };
matrix = iface->get_transform (model);
if (matrix)
new_matrix = *matrix;
cairo_matrix_scale (&new_matrix, sx, sy);
iface->set_transform (model, &new_matrix);
}
/**
* goo_canvas_item_model_rotate:
* @model: an item model.
* @degrees: the clockwise angle of rotation.
* @cx: the x coordinate of the origin of the rotation.
* @cy: the y coordinate of the origin of the rotation.
*
* Rotates the item's coordinate system by the given amount, about the given
* origin.
**/
void
goo_canvas_item_model_rotate (GooCanvasItemModel *model,
double degrees,
double cx,
double cy)
{
GooCanvasItemModelIface *iface = GOO_CANVAS_ITEM_MODEL_GET_IFACE (model);
cairo_matrix_t *matrix, new_matrix = { 1, 0, 0, 1, 0, 0 };
double radians = degrees * (M_PI / 180);
matrix = iface->get_transform (model);
if (matrix)
new_matrix = *matrix;
cairo_matrix_translate (&new_matrix, cx, cy);
cairo_matrix_rotate (&new_matrix, radians);
cairo_matrix_translate (&new_matrix, -cx, -cy);
iface->set_transform (model, &new_matrix);
}
/**
* goo_canvas_item_model_skew_x:
* @model: an item model.
* @degrees: the skew angle.
* @cx: the x coordinate of the origin of the skew transform.
* @cy: the y coordinate of the origin of the skew transform.
*
* Skews the item's coordinate system along the x axis by the given amount,
* about the given origin.
**/
void
goo_canvas_item_model_skew_x (GooCanvasItemModel *model,
double degrees,
double cx,
double cy)
{
GooCanvasItemModelIface *iface = GOO_CANVAS_ITEM_MODEL_GET_IFACE (model);
cairo_matrix_t *matrix, tmp, new_matrix = { 1, 0, 0, 1, 0, 0 };
double radians = degrees * (M_PI / 180);
matrix = iface->get_transform (model);
if (matrix)
new_matrix = *matrix;
cairo_matrix_translate (&new_matrix, cx, cy);
cairo_matrix_init (&tmp, 1, 0, tan (radians), 1, 0, 0);
cairo_matrix_multiply (&new_matrix, &tmp, &new_matrix);
cairo_matrix_translate (&new_matrix, -cx, -cy);
iface->set_transform (model, &new_matrix);
}
/**
* goo_canvas_item_model_skew_y:
* @model: an item model.
* @degrees: the skew angle.
* @cx: the x coordinate of the origin of the skew transform.
* @cy: the y coordinate of the origin of the skew transform.
*
* Skews the item's coordinate system along the y axis by the given amount,
* about the given origin.
**/
void
goo_canvas_item_model_skew_y (GooCanvasItemModel *model,
double degrees,
double cx,
double cy)
{
GooCanvasItemModelIface *iface = GOO_CANVAS_ITEM_MODEL_GET_IFACE (model);
cairo_matrix_t *matrix, tmp, new_matrix = { 1, 0, 0, 1, 0, 0 };
double radians = degrees * (M_PI / 180);
matrix = iface->get_transform (model);
if (matrix)
new_matrix = *matrix;
cairo_matrix_translate (&new_matrix, cx, cy);
cairo_matrix_init (&tmp, 1, tan (radians), 0, 1, 0, 0);
cairo_matrix_multiply (&new_matrix, &tmp, &new_matrix);
cairo_matrix_translate (&new_matrix, -cx, -cy);
iface->set_transform (model, &new_matrix);
}
/**
* goo_canvas_item_model_get_style:
* @model: an item model.
*
* Gets the item's style. If the item doesn't have its own style it will return
* its parent's style.
*
* Returns: the item's style.
**/
GooCanvasStyle*
goo_canvas_item_model_get_style (GooCanvasItemModel *model)
{
GooCanvasItemModelIface *iface = GOO_CANVAS_ITEM_MODEL_GET_IFACE (model);
return iface->get_style ? iface->get_style (model) : NULL;
}
/**
* goo_canvas_item_model_set_style:
* @model: an item model.
* @style: a style.
*
* Sets the item's style, by copying the properties from the given style.
**/
void
goo_canvas_item_model_set_style (GooCanvasItemModel *model,
GooCanvasStyle *style)
{
GooCanvasItemModelIface *iface = GOO_CANVAS_ITEM_MODEL_GET_IFACE (model);
if (iface->set_style)
iface->set_style (model, style);
}
typedef struct _GooCanvasItemModelAnimation GooCanvasItemModelAnimation;
struct _GooCanvasItemModelAnimation
{
GooCanvasAnimateType type;
GooCanvasItemModel *model;
int num_steps_left, total_steps;
cairo_matrix_t start, step;
gboolean forward;
guint timeout_id;
};
static void
goo_canvas_item_model_free_animation (GooCanvasItemModelAnimation *anim)
{
if (anim->timeout_id)
{
g_source_remove (anim->timeout_id);
anim->timeout_id = 0;
}
g_free (anim);
}
static gboolean
goo_canvas_item_model_animate_cb (GooCanvasItemModelAnimation *anim)
{
GooCanvasItemModelIface *iface;
cairo_matrix_t *matrix, new_matrix = { 1, 0, 0, 1, 0, 0 };
gboolean keep_source = TRUE;
GDK_THREADS_ENTER ();
iface = GOO_CANVAS_ITEM_MODEL_GET_IFACE (anim->model);
matrix = iface->get_transform (anim->model);
if (matrix)
new_matrix = *matrix;
new_matrix.xx += anim->step.xx;
new_matrix.yx += anim->step.yx;
new_matrix.xy += anim->step.xy;
new_matrix.yy += anim->step.yy;
new_matrix.x0 += anim->step.x0;
new_matrix.y0 += anim->step.y0;
iface->set_transform (anim->model, &new_matrix);
if (--anim->num_steps_left == 0)
{
switch (anim->type)
{
case GOO_CANVAS_ANIMATE_RESET:
/* Reset the transform to the initial value. */
/* FIXME: Need to wait one cycle at finish position? */
iface->set_transform (anim->model, &anim->start);
/* Fall through.. */
case GOO_CANVAS_ANIMATE_FREEZE:
keep_source = FALSE;
anim->timeout_id = 0;
/* This will result in call to goo_canvas_item_model_free_animation()
above. We've set the timeout_id to 0 so it isn't removed twice. */
g_object_set_data (G_OBJECT (anim->model), animation_key, NULL);
break;
case GOO_CANVAS_ANIMATE_RESTART:
iface->set_transform (anim->model, &anim->start);
break;
case GOO_CANVAS_ANIMATE_BOUNCE:
/* Switch all the step values around. */
anim->step.xx = -anim->step.xx;
anim->step.yx = -anim->step.yx;
anim->step.xy = -anim->step.xy;
anim->step.yy = -anim->step.yy;
anim->step.x0 = -anim->step.x0;
anim->step.y0 = -anim->step.y0;
/* FIXME: don't need this? Might be wise to reset to the initial
transform each time we restart, to avoid little errors. */
anim->forward = !anim->forward;
break;
}
anim->num_steps_left = anim->total_steps;
}
GDK_THREADS_LEAVE ();
/* Return FALSE to remove the timeout handler when we are finished. */
return keep_source;
}
/**
* goo_canvas_item_model_animate:
* @model: an item model.
* @x: the final x offset from the current position.
* @y: the final y offset from the current position.
* @scale: the final scale of the item.
* @degrees: the final rotation of the item.
* @duration: the duration of the animation, in milliseconds (1/1000ths of a
* second).
* @step_time: the time between each animation step, in milliseconds.
* @type: specifies what happens when the animation finishes.
*
* Animates an item from its current position to the given offsets, scale
* and rotation.
**/
void
goo_canvas_item_model_animate (GooCanvasItemModel *model,
double x,
double y,
double scale,
double degrees,
int duration,
int step_time,
GooCanvasAnimateType type)
{
GooCanvasItemModelIface *iface = GOO_CANVAS_ITEM_MODEL_GET_IFACE (model);
cairo_matrix_t *matrix, identity_matrix = { 1, 0, 0, 1, 0, 0 };
cairo_matrix_t new_matrix = { 1, 0, 0, 1, 0, 0 };
GooCanvasItemModelAnimation *anim;
double radians = degrees * (M_PI / 180);
matrix = iface->get_transform (model);
if (!matrix)
matrix = &identity_matrix;
cairo_matrix_translate (&new_matrix, x, y);
cairo_matrix_scale (&new_matrix, scale, scale);
cairo_matrix_rotate (&new_matrix, radians);
anim = g_new (GooCanvasItemModelAnimation, 1);
anim->type = type;
anim->model = model;
anim->total_steps = anim->num_steps_left = duration / step_time;
anim->start = *matrix;
anim->step.xx = (new_matrix.xx - matrix->xx) / anim->total_steps;
anim->step.yx = (new_matrix.yx - matrix->yx) / anim->total_steps;
anim->step.xy = (new_matrix.xy - matrix->xy) / anim->total_steps;
anim->step.yy = (new_matrix.yy - matrix->yy) / anim->total_steps;
anim->step.x0 = (new_matrix.x0 - matrix->x0) / anim->total_steps;
anim->step.y0 = (new_matrix.y0 - matrix->y0) / anim->total_steps;
anim->forward = TRUE;
/* Store a pointer to the new animation in the item. This will automatically
stop any current animation and free it. */
g_object_set_data_full (G_OBJECT (model), animation_key, anim,
(GDestroyNotify) goo_canvas_item_model_free_animation);
anim->timeout_id = g_timeout_add (step_time,
(GSourceFunc) goo_canvas_item_model_animate_cb,
anim);
}
/**
* goo_canvas_item_model_stop_animation:
* @model: an item model.
*
* Stops any current animation for the given item, leaving it at its current
* position.
**/
void
goo_canvas_item_model_stop_animation (GooCanvasItemModel *model)
{
/* This will result in a call to goo_canvas_item_model_free_animation(). */
g_object_set_data (G_OBJECT (model), animation_key, NULL);
}
--- NEW FILE: goocanvasitemmodel.h ---
/*
* GooCanvas. Copyright (C) 2005 Damon Chaplin.
* Released under the GNU LGPL license. See COPYING for details.
*
* goocanvasitemmodel.h - interface for canvas item models.
*/
#ifndef __GOO_CANVAS_ITEM_MODEL_H__
#define __GOO_CANVAS_ITEM_MODEL_H__
#include <gtk/gtk.h>
#include "goocanvasitem.h"
G_BEGIN_DECLS
#define GOO_TYPE_CANVAS_ITEM_MODEL (goo_canvas_item_model_get_type ())
#define GOO_CANVAS_ITEM_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_CANVAS_ITEM_MODEL, GooCanvasItemModel))
#define GOO_CANVAS_ITEM_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_CANVAS_ITEM_MODEL, GooCanvasItemModelClass))
#define GOO_IS_CANVAS_ITEM_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GOO_TYPE_CANVAS_ITEM_MODEL))
#define GOO_CANVAS_ITEM_MODEL_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GOO_TYPE_CANVAS_ITEM_MODEL, GooCanvasItemModelIface))
/**
* GooCanvasItemModel
*
* #GooCanvasItemModel is a typedef used for objects that implement the
* #GooCanvasItemModel interface.
*
* (There is no actual #GooCanvasItemModel struct, since it is only an interface.
* But using '#GooCanvasItemModel' is more helpful than using '#GObject'.)
*/
/* The typedef is in goocanvasitem.h */
/*typedef struct _GooCanvasItemModel GooCanvasItemModel;*/
/**
* GooCanvasItemModelIface
*
* #GooCanvasItemModelIFace holds the virtual methods that make up the
* #GooCanvasItemModel interface.
*/
typedef struct _GooCanvasItemModelIface GooCanvasItemModelIface;
struct _GooCanvasItemModelIface
{
/*< private >*/
GTypeInterface base_iface;
/*< public >*/
/* Virtual methods that group items must implement. */
gint (* get_n_children) (GooCanvasItemModel *model);
GooCanvasItemModel* (* get_child) (GooCanvasItemModel *model,
gint child_num);
/* Virtual methods that group items may implement. */
void (* add_child) (GooCanvasItemModel *model,
GooCanvasItemModel *child,
gint position);
void (* move_child) (GooCanvasItemModel *model,
gint old_position,
gint new_position);
void (* remove_child) (GooCanvasItemModel *model,
gint child_num);
void (*get_child_property) (GooCanvasItemModel *model,
GooCanvasItemModel *child,
guint property_id,
GValue *value,
GParamSpec *pspec);
void (*set_child_property) (GooCanvasItemModel *item,
GooCanvasItemModel *child,
guint property_id,
const GValue *value,
GParamSpec *pspec);
/* Virtual methods that all canvas items must implement. */
GooCanvasItemModel* (* get_parent) (GooCanvasItemModel *model);
void (* set_parent) (GooCanvasItemModel *model,
GooCanvasItemModel *parent);
cairo_matrix_t* (* get_transform) (GooCanvasItemModel *model);
void (* set_transform) (GooCanvasItemModel *model,
cairo_matrix_t *matrix);
GooCanvasStyle* (* get_style) (GooCanvasItemModel *model);
void (* set_style) (GooCanvasItemModel *model,
GooCanvasStyle *style);
GooCanvasItem* (* create_item) (GooCanvasItemModel *model,
GooCanvas *canvas);
/* Signals. */
void (* child_added) (GooCanvasItemModel *model,
gint child_num);
void (* child_moved) (GooCanvasItemModel *model,
gint old_child_num,
gint new_child_num);
void (* child_removed) (GooCanvasItemModel *model,
gint child_num);
void (* changed) (GooCanvasItemModel *model,
gboolean recompute_bounds);
};
GType goo_canvas_item_model_get_type (void) G_GNUC_CONST;
/*
* Group functions - these should only be called on container models.
*/
gint goo_canvas_item_model_get_n_children (GooCanvasItemModel *model);
GooCanvasItemModel* goo_canvas_item_model_get_child (GooCanvasItemModel *model,
gint child_num);
void goo_canvas_item_model_add_child (GooCanvasItemModel *model,
GooCanvasItemModel *child,
gint position);
void goo_canvas_item_model_move_child (GooCanvasItemModel *model,
gint old_position,
gint new_position);
void goo_canvas_item_model_remove_child (GooCanvasItemModel *model,
gint child_num);
gint goo_canvas_item_model_find_child (GooCanvasItemModel *model,
GooCanvasItemModel *child);
void goo_canvas_item_model_child_get (GooCanvasItemModel *model,
GooCanvasItemModel *child,
...) G_GNUC_NULL_TERMINATED;
void goo_canvas_item_model_child_set (GooCanvasItemModel *model,
GooCanvasItemModel *child,
...) G_GNUC_NULL_TERMINATED;
void goo_canvas_item_model_child_get_valist (GooCanvasItemModel *model,
GooCanvasItemModel *child,
va_list var_args);
void goo_canvas_item_model_child_set_valist (GooCanvasItemModel *model,
GooCanvasItemModel *child,
va_list var_args);
void goo_canvas_item_model_child_get_property (GooCanvasItemModel *model,
GooCanvasItemModel *child,
const gchar *property,
GValue *value);
void goo_canvas_item_model_child_set_property (GooCanvasItemModel *model,
GooCanvasItemModel *child,
const gchar *property,
const GValue *value);
/*
* Model functions - these are safe to call on all models.
*/
GooCanvasItemModel* goo_canvas_item_model_get_parent (GooCanvasItemModel *model);
void goo_canvas_item_model_set_parent (GooCanvasItemModel *model,
GooCanvasItemModel *parent);
gboolean goo_canvas_item_model_is_container (GooCanvasItemModel *model);
void goo_canvas_item_model_raise (GooCanvasItemModel *model,
GooCanvasItemModel *above);
void goo_canvas_item_model_lower (GooCanvasItemModel *model,
GooCanvasItemModel *below);
cairo_matrix_t* goo_canvas_item_model_get_transform (GooCanvasItemModel *model);
void goo_canvas_item_model_set_transform (GooCanvasItemModel *model,
cairo_matrix_t *matrix);
void goo_canvas_item_model_translate (GooCanvasItemModel *model,
double tx,
double ty);
void goo_canvas_item_model_scale (GooCanvasItemModel *model,
double sx,
double sy);
void goo_canvas_item_model_rotate (GooCanvasItemModel *model,
double degrees,
double cx,
double cy);
void goo_canvas_item_model_skew_x (GooCanvasItemModel *model,
double degrees,
double cx,
double cy);
void goo_canvas_item_model_skew_y (GooCanvasItemModel *model,
double degrees,
double cx,
double cy);
GooCanvasStyle* goo_canvas_item_model_get_style (GooCanvasItemModel *model);
void goo_canvas_item_model_set_style (GooCanvasItemModel *model,
GooCanvasStyle *style);
void goo_canvas_item_model_animate (GooCanvasItemModel *model,
double x,
double y,
double scale,
double degrees,
gint duration,
gint step_time,
GooCanvasAnimateType type);
void goo_canvas_item_model_stop_animation (GooCanvasItemModel *model);
G_END_DECLS
#endif /* __GOO_CANVAS_ITEM_MODEL_H__ */
--- NEW FILE: goocanvasstyle.c ---
/*
* GooCanvas. Copyright (C) 2005-6 Damon Chaplin.
* Released under the GNU LGPL license. See COPYING for details.
*
* goocanvasstyle.c - cascading styles.
*/
/**
* SECTION:goocanvasstyle
* @Title: GooCanvasStyle
* @Short_Description: support for cascading style properties for canvas items.
*
* #GooCanvasStyle provides support for cascading style properties for canvas
* items. It is intended to be used when implementing new canvas items.
*
* Style properties are identified by a unique #GQuark, and contain
* arbitrary data stored in a #GValue.
*
* #GooCanvasStyle also provides a few convenience functions such as
* goo_canvas_style_set_stroke_options() and
* goo_canvas_style_set_fill_options() which efficiently apply an item's
* standard style properties to the given cairo_t.
*/
#include <config.h>
#include <gtk/gtk.h>
#include "goocanvasstyle.h"
#include "goocanvasutils.h"
static void goo_canvas_style_finalize (GObject *object);
G_DEFINE_TYPE (GooCanvasStyle, goo_canvas_style, G_TYPE_OBJECT)
/* Create GQuarks for the basic properties. This is called by
goo_canvas_style_class_init(), goo_canvas_item_base_init() and
goo_canvas_item_model_base_init() to try to ensure the GQuarks are
initialized before they are needed. */
void
_goo_canvas_style_init (void)
{
static gboolean initialized = FALSE;
if (!initialized)
{
goo_canvas_style_stroke_pattern_id = g_quark_from_static_string ("GooCanvasStyle:stroke_pattern");
goo_canvas_style_fill_pattern_id = g_quark_from_static_string ("GooCanvasStyle:fill_pattern");
goo_canvas_style_fill_rule_id = g_quark_from_static_string ("GooCanvasStyle:fill_rule");
goo_canvas_style_operator_id = g_quark_from_static_string ("GooCanvasStyle:operator");
goo_canvas_style_antialias_id = g_quark_from_static_string ("GooCanvasStyle:antialias");
goo_canvas_style_line_width_id = g_quark_from_static_string ("GooCanvasStyle:line_width");
goo_canvas_style_line_cap_id = g_quark_from_static_string ("GooCanvasStyle:line_cap");
goo_canvas_style_line_join_id = g_quark_from_static_string ("GooCanvasStyle:line_join");
goo_canvas_style_line_join_miter_limit_id = g_quark_from_static_string ("GooCanvasStyle:line_join_miter_limit");
goo_canvas_style_line_dash_id = g_quark_from_static_string ("GooCanvasStyle:line_dash");
goo_canvas_style_font_desc_id = g_quark_from_static_string ("GooCanvasStyle:font_desc");
initialized = TRUE;
}
}
static void
goo_canvas_style_class_init (GooCanvasStyleClass *klass)
{
GObjectClass *gobject_class = (GObjectClass*) klass;
gobject_class->finalize = goo_canvas_style_finalize;
_goo_canvas_style_init ();
}
static void
goo_canvas_style_init (GooCanvasStyle *style)
{
style->properties = g_array_new (0, 0, sizeof (GooCanvasStyleProperty));
}
GooCanvasStyle*
goo_canvas_style_new (void)
{
return GOO_CANVAS_STYLE (g_object_new (GOO_TYPE_CANVAS_STYLE, NULL));
}
static void
goo_canvas_style_finalize (GObject *object)
{
GooCanvasStyle *style = (GooCanvasStyle*) object;
GooCanvasStyleProperty *property;
gint i;
if (style->parent)
{
g_object_unref (style->parent);
style->parent = NULL;
}
/* Free the property GValues. */
for (i = 0; i < style->properties->len; i++)
{
property = &g_array_index (style->properties, GooCanvasStyleProperty, i);
g_value_unset (&property->value);
}
g_array_free (style->properties, TRUE);
G_OBJECT_CLASS (goo_canvas_style_parent_class)->finalize (object);
}
GooCanvasStyle*
goo_canvas_style_copy (GooCanvasStyle *style)
{
GooCanvasStyle *copy;
GooCanvasStyleProperty *property;
gint i;
copy = goo_canvas_style_new ();
for (i = 0; i < style->properties->len; i++)
{
property = &g_array_index (style->properties, GooCanvasStyleProperty, i);
goo_canvas_style_set_property (copy, property->id, &property->value);
}
return copy;
}
/**
* goo_canvas_style_get_parent:
* @style: a style.
*
* Gets the parent of the style.
*
* Returns: the parent of the given style, or %NULL.
**/
GooCanvasStyle*
goo_canvas_style_get_parent (GooCanvasStyle *style)
{
return style->parent;
}
/**
* goo_canvas_style_set_parent:
* @style: a style.
* @parent: the new parent.
*
* Sets the parent of the style.
**/
void
goo_canvas_style_set_parent (GooCanvasStyle *style,
GooCanvasStyle *parent)
{
if (style->parent == parent)
return;
if (style->parent)
g_object_unref (style->parent);
style->parent = parent;
if (style->parent)
g_object_ref (style->parent);
}
/**
* goo_canvas_style_get_property:
* @style: a style.
* @property_id: the property identifier.
*
* Gets the value of a property.
*
* Returns: the property value, or %NULL if it isn't set.
**/
GValue*
goo_canvas_style_get_property (GooCanvasStyle *style,
GQuark property_id)
{
GooCanvasStyleProperty *property;
gint i;
/* Step up the hierarchy of styles until we find the property. Note that
if style is passed in as NULL we simply return NULL. */
while (style)
{
for (i = 0; i < style->properties->len; i++)
{
property = &g_array_index (style->properties, GooCanvasStyleProperty,
i);
if (property->id == property_id)
return &property->value;
}
style = style->parent;
}
return NULL;
}
/**
* goo_canvas_style_set_property:
* @style: a style.
* @property_id: the property identifier.
* @value: the value of the property.
*
* Sets a property in the style, replacing any current setting.
**/
void
goo_canvas_style_set_property (GooCanvasStyle *style,
GQuark property_id,
const GValue *value)
{
GooCanvasStyleProperty *property, new_property = { 0 };
gint i;
/* See if the property is already set. */
for (i = 0; i < style->properties->len; i++)
{
property = &g_array_index (style->properties, GooCanvasStyleProperty, i);
if (property->id == property_id)
{
/* If the new value is NULL, remove the property setting, otherwise
update the property value. */
if (value)
{
g_value_copy (value, &property->value);
}
else
{
g_value_unset (&property->value);
g_array_remove_index_fast (style->properties, i);
}
return;
}
}
/* The property isn't set, so append a new property. */
if (value)
{
new_property.id = property_id;
g_value_init (&new_property.value, G_VALUE_TYPE (value));
g_value_copy (value, &new_property.value);
g_array_append_val (style->properties, new_property);
}
}
/**
* goo_canvas_style_set_stroke_options:
* @style: a style.
* @cr: a cairo context.
*
* Sets the standard cairo stroke options using the given style.
*
* Returns: %TRUE if a paint source is set, or %FALSE if the stroke should
* be skipped.
**/
gboolean
goo_canvas_style_set_stroke_options (GooCanvasStyle *style,
cairo_t *cr)
{
GooCanvasStyleProperty *property;
gboolean operator_set = FALSE, antialias_set = FALSE;
gboolean stroke_pattern_set = FALSE, line_width_set = FALSE;
gboolean line_cap_set = FALSE, line_join_set = FALSE;
gboolean miter_limit_set = FALSE, line_dash_set = FALSE;
gboolean source_set = FALSE, need_stroke = TRUE;
gint i;
if (!style)
return TRUE;
/* Step up the hierarchy of styles looking for the properties. */
while (style)
{
for (i = 0; i < style->properties->len; i++)
{
property = &g_array_index (style->properties, GooCanvasStyleProperty,
i);
if (property->id == goo_canvas_style_operator_id && !operator_set)
{
cairo_set_operator (cr, property->value.data[0].v_long);
operator_set = TRUE;
}
else if (property->id == goo_canvas_style_antialias_id && !antialias_set)
{
cairo_set_antialias (cr, property->value.data[0].v_long);
antialias_set = TRUE;
}
else if (property->id == goo_canvas_style_stroke_pattern_id && !stroke_pattern_set)
{
if (property->value.data[0].v_pointer)
{
cairo_set_source (cr, property->value.data[0].v_pointer);
source_set = TRUE;
}
else
{
/* If the stroke pattern has been explicitly set to NULL,
then we don't need to do the stroke. */
need_stroke = FALSE;
}
stroke_pattern_set = TRUE;
}
else if (property->id == goo_canvas_style_line_width_id && !line_width_set)
{
cairo_set_line_width (cr, property->value.data[0].v_double);
line_width_set = TRUE;
}
else if (property->id == goo_canvas_style_line_cap_id && !line_cap_set)
{
cairo_set_line_cap (cr, property->value.data[0].v_long);
line_cap_set = TRUE;
}
else if (property->id == goo_canvas_style_line_join_id && !line_join_set)
{
cairo_set_line_join (cr, property->value.data[0].v_long);
line_join_set = TRUE;
}
else if (property->id == goo_canvas_style_line_join_miter_limit_id && !miter_limit_set)
{
cairo_set_miter_limit (cr, property->value.data[0].v_double);
miter_limit_set = TRUE;
}
else if (property->id == goo_canvas_style_line_dash_id && !line_dash_set)
{
GooCanvasLineDash *dash = property->value.data[0].v_pointer;
cairo_set_dash (cr, dash->dashes, dash->num_dashes,
dash->dash_offset);
line_dash_set = TRUE;
}
}
style = style->parent;
}
/* If a stroke pattern hasn't been set in the style we reset the source to
black, just in case a fill pattern was used for the item. */
if (!source_set)
cairo_set_source_rgb (cr, 0, 0, 0);
return need_stroke;
}
/**
* goo_canvas_style_set_fill_options:
* @style: a style.
* @cr: a cairo context.
*
* Sets the standard cairo fill options using the given style.
*
* Returns: %TRUE if a paint source is set, or %FALSE if the fill should
* be skipped.
**/
gboolean
goo_canvas_style_set_fill_options (GooCanvasStyle *style,
cairo_t *cr)
{
GooCanvasStyleProperty *property;
gboolean operator_set = FALSE, antialias_set = FALSE;
gboolean fill_rule_set = FALSE, fill_pattern_set = FALSE;
gint i;
if (!style)
return FALSE;
/* Step up the hierarchy of styles looking for the properties. */
while (style)
{
for (i = 0; i < style->properties->len; i++)
{
property = &g_array_index (style->properties, GooCanvasStyleProperty,
i);
if (property->id == goo_canvas_style_operator_id && !operator_set)
{
cairo_set_operator (cr, property->value.data[0].v_long);
operator_set = TRUE;
}
else if (property->id == goo_canvas_style_antialias_id && !antialias_set)
{
cairo_set_antialias (cr, property->value.data[0].v_long);
antialias_set = TRUE;
}
else if (property->id == goo_canvas_style_fill_rule_id && !fill_rule_set)
{
cairo_set_fill_rule (cr, property->value.data[0].v_long);
fill_rule_set = TRUE;
}
else if (property->id == goo_canvas_style_fill_pattern_id && !fill_pattern_set)
{
cairo_set_source (cr, property->value.data[0].v_pointer);
fill_pattern_set = TRUE;
}
}
style = style->parent;
}
return fill_pattern_set;
}
--- NEW FILE: goocanvasstyle.h ---
/*
* GooCanvas. Copyright (C) 2005-6 Damon Chaplin.
* Released under the GNU LGPL license. See COPYING for details.
*
* goocanvasstyle.h - cascading styles.
*/
#ifndef __GOO_CANVAS_STYLE_H__
#define __GOO_CANVAS_STYLE_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
/* GQuarks for the basic properties. */
GQuark goo_canvas_style_stroke_pattern_id;
GQuark goo_canvas_style_fill_pattern_id;
GQuark goo_canvas_style_fill_rule_id;
GQuark goo_canvas_style_operator_id;
GQuark goo_canvas_style_antialias_id;
GQuark goo_canvas_style_line_width_id;
GQuark goo_canvas_style_line_cap_id;
GQuark goo_canvas_style_line_join_id;
GQuark goo_canvas_style_line_join_miter_limit_id;
GQuark goo_canvas_style_line_dash_id;
GQuark goo_canvas_style_font_desc_id;
typedef struct _GooCanvasStyleProperty GooCanvasStyleProperty;
struct _GooCanvasStyleProperty
{
/* The property id. */
GQuark id;
/* The property value. */
GValue value;
};
#define GOO_TYPE_CANVAS_STYLE (goo_canvas_style_get_type ())
#define GOO_CANVAS_STYLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_CANVAS_STYLE, GooCanvasStyle))
#define GOO_CANVAS_STYLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_CANVAS_STYLE, GooCanvasStyleClass))
#define GOO_IS_CANVAS_STYLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GOO_TYPE_CANVAS_STYLE))
#define GOO_IS_CANVAS_STYLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GOO_TYPE_CANVAS_STYLE))
#define GOO_CANVAS_STYLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GOO_TYPE_CANVAS_STYLE, GooCanvasStyleClass))
typedef struct _GooCanvasStyle GooCanvasStyle;
typedef struct _GooCanvasStyleClass GooCanvasStyleClass;
struct _GooCanvasStyle
{
GObject parent_object;
/* The parent style. */
GooCanvasStyle *parent;
/* An array of GooCanvasStyleProperty. */
GArray *properties;
};
struct _GooCanvasStyleClass
{
GObjectClass parent_class;
};
GType goo_canvas_style_get_type (void) G_GNUC_CONST;
GooCanvasStyle* goo_canvas_style_new (void);
GooCanvasStyle* goo_canvas_style_copy (GooCanvasStyle *style);
GooCanvasStyle* goo_canvas_style_get_parent (GooCanvasStyle *style);
void goo_canvas_style_set_parent (GooCanvasStyle *style,
GooCanvasStyle *parent);
GValue* goo_canvas_style_get_property (GooCanvasStyle *style,
GQuark property_id);
void goo_canvas_style_set_property (GooCanvasStyle *style,
GQuark property_id,
const GValue *value);
/* Convenience functions to set the standard cairo stroke and fill options. */
gboolean goo_canvas_style_set_stroke_options (GooCanvasStyle *style,
cairo_t *cr);
gboolean goo_canvas_style_set_fill_options (GooCanvasStyle *style,
cairo_t *cr);
G_END_DECLS
#endif /* __GOO_CANVAS_STYLE_H__ */
--- NEW FILE: goocanvaswidget.c ---
/*
* GooCanvas. Copyright (C) 2005-6 Damon Chaplin.
* Released under the GNU LGPL license. See COPYING for details.
*
* goocanvaswidget.c - wrapper item for an embedded GtkWidget.
*/
/**
* SECTION:goocanvaswidget
* @Title: GooCanvasWidget
* @Short_Description: an embedded widget item.
*
* GooCanvasWidget provides support for placing any GtkWidget in the canvas.
*
* Note that there are a number of limitations in the use of #GooCanvasWidget:
*
* 1) It doesn't support any transformation besides simple translation.
* This means you can't scale a canvas with a #GooCanvasWidget in it.
*
* 2) It doesn't support layering, so you can't place other items beneath
* or above the #GooCanvasWidget.
*
* 3) It doesn't support rendering of widgets to a given cairo_t, which
* means you can't output the widget to a pdf or postscript file.
*
* 4) It doesn't have a model/view variant like the other standard items,
* so it can only be used in a simple canvas without a model.
*/
#include <config.h>
#include <glib/gi18n-lib.h>
#include <gtk/gtk.h>
#include "goocanvas.h"
#include "goocanvasatk.h"
enum {
PROP_0,
PROP_WIDGET,
PROP_X,
PROP_Y,
PROP_WIDTH,
PROP_HEIGHT,
PROP_ANCHOR,
PROP_VISIBILITY
};
static void canvas_item_interface_init (GooCanvasItemIface *iface);
static void goo_canvas_widget_finalize (GObject *object);
static void goo_canvas_widget_get_property (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec);
static void goo_canvas_widget_set_property (GObject *object,
guint param_id,
const GValue *value,
GParamSpec *pspec);
G_DEFINE_TYPE_WITH_CODE (GooCanvasWidget, goo_canvas_widget,
GOO_TYPE_CANVAS_ITEM_SIMPLE,
G_IMPLEMENT_INTERFACE (GOO_TYPE_CANVAS_ITEM,
canvas_item_interface_init))
static void
goo_canvas_widget_class_init (GooCanvasWidgetClass *klass)
{
GObjectClass *gobject_class = (GObjectClass*) klass;
gobject_class->finalize = goo_canvas_widget_finalize;
gobject_class->get_property = goo_canvas_widget_get_property;
gobject_class->set_property = goo_canvas_widget_set_property;
/* Register our accessible factory, but only if accessibility is enabled. */
if (!ATK_IS_NO_OP_OBJECT_FACTORY (atk_registry_get_factory (atk_get_default_registry (), GTK_TYPE_WIDGET)))
{
atk_registry_set_factory_type (atk_get_default_registry (),
GOO_TYPE_CANVAS_WIDGET,
goo_canvas_widget_accessible_factory_get_type ());
}
g_object_class_install_property (gobject_class, PROP_WIDGET,
g_param_spec_object ("widget",
_("Widget"),
_("The widget to place in the canvas"),
GTK_TYPE_WIDGET,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class, PROP_X,
g_param_spec_double ("x",
"X",
_("The x coordinate of the widget"),
-G_MAXDOUBLE,
G_MAXDOUBLE, 0.0,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class, PROP_Y,
g_param_spec_double ("y",
"Y",
_("The y coordinate of the widget"),
-G_MAXDOUBLE,
G_MAXDOUBLE, 0.0,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class, PROP_WIDTH,
g_param_spec_double ("width",
_("Width"),
_("The width of the widget, or -1 to use its requested width"),
-G_MAXDOUBLE,
G_MAXDOUBLE, -1.0,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class, PROP_HEIGHT,
g_param_spec_double ("height",
_("Height"),
_("The height of the widget, or -1 to use its requested height"),
-G_MAXDOUBLE,
G_MAXDOUBLE, -1.0,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class, PROP_ANCHOR,
g_param_spec_enum ("anchor",
_("Anchor"),
_("How to position the widget relative to the item's x and y coordinate settings"),
GTK_TYPE_ANCHOR_TYPE,
GTK_ANCHOR_NW,
G_PARAM_READWRITE));
g_object_class_override_property (gobject_class, PROP_VISIBILITY,
"visibility");
}
static void
goo_canvas_widget_init (GooCanvasWidget *witem)
{
/* By default we place the widget at the top-left of the canvas at its
requested size. */
witem->x = 0.0;
witem->y = 0.0;
witem->width = -1.0;
witem->height = -1.0;
witem->anchor = GTK_ANCHOR_NW;
}
/**
* goo_canvas_widget_new:
* @parent: the parent item, or %NULL. If a parent is specified, it will assume
* ownership of the item, and the item will automatically be freed when it is
* removed from the parent. Otherwise call g_object_unref() to free it.
* @widget: the widget.
* @x: the x coordinate of the item.
* @y: the y coordinate of the item.
* @width: the width of the item, or -1 to use the widget's requested width.
* @height: the height of the item, or -1 to use the widget's requested height.
* @...: optional pairs of property names and values, and a terminating %NULL.
*
* Creates a new widget item.
*
* <!--PARAMETERS-->
*
* Here's an example showing how to create an entry widget centered at (100.0,
* 100.0):
*
* <informalexample><programlisting>
* GtkWidget *entry = gtk_entry_new ();
* GooCanvasItem *witem = goo_canvas_widget_new (mygroup, entry,
* 100, 100, -1, -1,
* "anchor", GTK_ANCHOR_CENTER,
* NULL);
* </programlisting></informalexample>
*
* Returns: a new widget item.
**/
GooCanvasItem*
goo_canvas_widget_new (GooCanvasItem *parent,
GtkWidget *widget,
gdouble x,
gdouble y,
gdouble width,
gdouble height,
...)
{
GooCanvasItem *item;
GooCanvasWidget *witem;
const char *first_property;
va_list var_args;
item = g_object_new (GOO_TYPE_CANVAS_WIDGET, NULL);
witem = (GooCanvasWidget*) item;
witem->widget = widget;
witem->x = x;
witem->y = y;
witem->width = width;
witem->height = height;
/* The widget defaults to being visible, like the canvas item, but this
can be overridden by the object property below. */
if (widget)
gtk_widget_show (widget);
va_start (var_args, height);
first_property = va_arg (var_args, char*);
if (first_property)
g_object_set_valist ((GObject*) item, first_property, var_args);
va_end (var_args);
if (parent)
{
goo_canvas_item_add_child (parent, item, -1);
g_object_unref (item);
}
return item;
}
static void
goo_canvas_widget_set_widget (GooCanvasWidget *witem,
GtkWidget *widget)
{
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) witem;
if (witem->widget)
{
g_object_set_data (G_OBJECT (witem->widget), "goo-canvas-item", NULL);
gtk_widget_unparent (witem->widget);
witem->widget = NULL;
}
if (widget)
{
witem->widget = widget;
g_object_set_data (G_OBJECT (witem->widget), "goo-canvas-item", witem);
if (simple->simple_data->visibility == GOO_CANVAS_ITEM_INVISIBLE)
gtk_widget_hide (widget);
else
gtk_widget_show (widget);
if (simple->canvas)
{
if (GTK_WIDGET_REALIZED (simple->canvas))
gtk_widget_set_parent_window (widget,
simple->canvas->canvas_window);
gtk_widget_set_parent (widget, GTK_WIDGET (simple->canvas));
}
}
}
static void
goo_canvas_widget_finalize (GObject *object)
{
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) object;
GooCanvasWidget *witem = (GooCanvasWidget*) object;
if (simple->canvas)
goo_canvas_unregister_widget_item (simple->canvas, witem);
goo_canvas_widget_set_widget (witem, NULL);
G_OBJECT_CLASS (goo_canvas_widget_parent_class)->finalize (object);
}
static void
goo_canvas_widget_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) object;
GooCanvasWidget *witem = (GooCanvasWidget*) object;
switch (prop_id)
{
case PROP_WIDGET:
g_value_set_object (value, witem->widget);
break;
case PROP_X:
g_value_set_double (value, witem->x);
break;
case PROP_Y:
g_value_set_double (value, witem->y);
break;
case PROP_WIDTH:
g_value_set_double (value, witem->width);
break;
case PROP_HEIGHT:
g_value_set_double (value, witem->height);
break;
case PROP_ANCHOR:
g_value_set_enum (value, witem->anchor);
break;
case PROP_VISIBILITY:
g_value_set_enum (value, simple->simple_data->visibility);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
goo_canvas_widget_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) object;
GooCanvasWidget *witem = (GooCanvasWidget*) object;
switch (prop_id)
{
case PROP_WIDGET:
goo_canvas_widget_set_widget (witem, g_value_get_object (value));
break;
case PROP_X:
witem->x = g_value_get_double (value);
break;
case PROP_Y:
witem->y = g_value_get_double (value);
break;
case PROP_WIDTH:
witem->width = g_value_get_double (value);
break;
case PROP_HEIGHT:
witem->height = g_value_get_double (value);
break;
case PROP_ANCHOR:
witem->anchor = g_value_get_enum (value);
break;
case PROP_VISIBILITY:
simple->simple_data->visibility = g_value_get_enum (value);
if (simple->simple_data->visibility == GOO_CANVAS_ITEM_INVISIBLE)
gtk_widget_hide (witem->widget);
else
gtk_widget_show (witem->widget);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
goo_canvas_item_simple_changed (simple, TRUE);
}
static void
goo_canvas_widget_set_canvas (GooCanvasItem *item,
GooCanvas *canvas)
{
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
GooCanvasWidget *witem = (GooCanvasWidget*) item;
if (simple->canvas != canvas)
{
if (simple->canvas)
goo_canvas_unregister_widget_item (simple->canvas, witem);
simple->canvas = canvas;
if (simple->canvas)
{
goo_canvas_register_widget_item (simple->canvas, witem);
if (witem->widget)
{
if (GTK_WIDGET_REALIZED (simple->canvas))
gtk_widget_set_parent_window (witem->widget,
simple->canvas->canvas_window);
gtk_widget_set_parent (witem->widget,
GTK_WIDGET (simple->canvas));
}
}
}
}
static void
goo_canvas_widget_set_parent (GooCanvasItem *item,
GooCanvasItem *parent)
{
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
GooCanvas *canvas;
simple->parent = parent;
simple->need_update = TRUE;
simple->need_entire_subtree_update = TRUE;
canvas = parent ? goo_canvas_item_get_canvas (parent) : NULL;
goo_canvas_widget_set_canvas (item, canvas);
}
static void
goo_canvas_widget_update (GooCanvasItem *item,
gboolean entire_tree,
cairo_t *cr,
GooCanvasBounds *bounds)
{
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
GooCanvasItemSimpleData *simple_data = simple->simple_data;
GooCanvasWidget *witem = (GooCanvasWidget*) item;
GtkRequisition requisition;
gdouble width, height;
if (entire_tree || simple->need_update)
{
simple->need_update = FALSE;
goo_canvas_item_simple_check_style (simple);
cairo_save (cr);
if (simple_data->transform)
cairo_transform (cr, simple_data->transform);
/* Request a redraw of the existing bounds. */
goo_canvas_request_redraw (simple->canvas, &simple->bounds);
if (witem->widget)
{
/* Compute the new bounds. */
if (witem->width < 0 || witem->height < 0)
{
gtk_widget_size_request (witem->widget, &requisition);
}
simple->bounds.x1 = witem->x;
simple->bounds.y1 = witem->y;
width = witem->width < 0 ? requisition.width : witem->width;
height = witem->height < 0 ? requisition.height : witem->height;
switch (witem->anchor)
{
case GTK_ANCHOR_N:
case GTK_ANCHOR_CENTER:
case GTK_ANCHOR_S:
simple->bounds.x1 -= width / 2.0;
break;
case GTK_ANCHOR_NE:
case GTK_ANCHOR_E:
case GTK_ANCHOR_SE:
simple->bounds.x1 -= width;
break;
default:
break;
}
switch (witem->anchor)
{
case GTK_ANCHOR_W:
case GTK_ANCHOR_CENTER:
case GTK_ANCHOR_E:
simple->bounds.y1 -= height / 2.0;
break;
case GTK_ANCHOR_SW:
case GTK_ANCHOR_S:
case GTK_ANCHOR_SE:
simple->bounds.y1 -= height;
break;
default:
break;
}
simple->bounds.x2 = simple->bounds.x1 + width;
simple->bounds.y2 = simple->bounds.y1 + height;
goo_canvas_item_simple_user_bounds_to_device (simple, cr,
&simple->bounds);
/* Request a redraw of the new bounds. */
goo_canvas_request_redraw (simple->canvas, &simple->bounds);
/* Queue a resize of the widget so it gets moved. */
gtk_widget_queue_resize (witem->widget);
}
else
{
simple->bounds.x1 = simple->bounds.y1 = 0.0;
simple->bounds.x2 = simple->bounds.y2 = 0.0;
}
cairo_restore (cr);
}
*bounds = simple->bounds;
}
static void
goo_canvas_widget_paint (GooCanvasItem *item,
cairo_t *cr,
GooCanvasBounds *bounds,
gdouble scale)
{
/* Do nothing for now. Maybe render for printing in future. */
}
static GooCanvasItem*
goo_canvas_widget_get_item_at (GooCanvasItem *item,
gdouble x,
gdouble y,
cairo_t *cr,
gboolean is_pointer_event,
gboolean parent_visible)
{
/* FIXME: Should we return the widget here? */
return NULL;
}
static void
canvas_item_interface_init (GooCanvasItemIface *iface)
{
iface->set_canvas = goo_canvas_widget_set_canvas;
iface->set_parent = goo_canvas_widget_set_parent;
iface->get_item_at = goo_canvas_widget_get_item_at;
iface->update = goo_canvas_widget_update;
iface->paint = goo_canvas_widget_paint;
}
--- NEW FILE: goocanvaswidget.h ---
/*
* GooCanvas. Copyright (C) 2005-6 Damon Chaplin.
* Released under the GNU LGPL license. See COPYING for details.
*
* goocanvaswidget.h - wrapper item for an embedded GtkWidget.
*/
#ifndef __GOO_CANVAS_WIDGET_H__
#define __GOO_CANVAS_WIDGET_H__
#include <gtk/gtk.h>
#include "goocanvasitemsimple.h"
G_BEGIN_DECLS
#define GOO_TYPE_CANVAS_WIDGET (goo_canvas_widget_get_type ())
#define GOO_CANVAS_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_CANVAS_WIDGET, GooCanvasWidget))
#define GOO_CANVAS_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_CANVAS_WIDGET, GooCanvasWidgetClass))
#define GOO_IS_CANVAS_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GOO_TYPE_CANVAS_WIDGET))
#define GOO_IS_CANVAS_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GOO_TYPE_CANVAS_WIDGET))
#define GOO_CANVAS_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GOO_TYPE_CANVAS_WIDGET, GooCanvasWidgetClass))
typedef struct _GooCanvasWidget GooCanvasWidget;
typedef struct _GooCanvasWidgetClass GooCanvasWidgetClass;
/**
* GooCanvasWidget
*
* The #GooCanvasWidget-struct struct contains private data only.
*/
struct _GooCanvasWidget
{
GooCanvasItemSimple parent_object;
GtkWidget *widget;
gdouble x, y, width, height;
GtkAnchorType anchor;
};
struct _GooCanvasWidgetClass
{
GooCanvasItemSimpleClass parent_class;
};
GType goo_canvas_widget_get_type (void) G_GNUC_CONST;
GooCanvasItem* goo_canvas_widget_new (GooCanvasItem *parent,
GtkWidget *widget,
gdouble x,
gdouble y,
gdouble width,
gdouble height,
...);
G_END_DECLS
#endif /* __GOO_CANVAS_WIDGET_H__ */
- Previous message: [cairo-commit] goocanvas/demo mv-demo-arrowhead.c, NONE,
1.1 mv-demo-events.c, NONE, 1.1 mv-demo-features.c, NONE,
1.1 mv-demo-fifteen.c, NONE, 1.1 mv-demo-focus.c, NONE,
1.1 mv-demo-grabs.c, NONE, 1.1 mv-demo-paths.c, NONE,
1.1 mv-demo-scalability.c, NONE, 1.1 mv-demo.c, NONE,
1.1 mv-simple-demo.c, NONE, 1.1 widgets-demo.c, NONE, 1.1
- Next message: [cairo-commit] goocanvas/src Makefile.am, 1.10, 1.11 goocanvas.h,
1.2, 1.3 goocanvasatk.c, 1.6, 1.7 goocanvasatk.h, 1.1,
1.2 goocanvasellipse.c, 1.6, 1.7 goocanvasellipse.h, 1.2,
1.3 goocanvasgroup.c, 1.13, 1.14 goocanvasgroup.h, 1.8,
1.9 goocanvasimage.c, 1.7, 1.8 goocanvasimage.h, 1.2,
1.3 goocanvasimageview.c, 1.16, NONE goocanvasimageview.h, 1.4,
NONE goocanvasitem.c, 1.10, 1.11 goocanvasitem.h, 1.7,
1.8 goocanvasitemsimple.c, 1.14, 1.15 goocanvasitemsimple.h,
1.10, 1.11 goocanvasitemview.c, 1.14, NONE goocanvasitemview.h,
1.12, NONE goocanvasitemviewsimple.c, 1.13,
NONE goocanvasitemviewsimple.h, 1.5, NONE goocanvasmodel.c,
1.3, NONE goocanvasmodel.h, 1.2, NONE goocanvasmodelsimple.c,
1.5, NONE goocanvasmodelsimple.h, 1.2, NONE goocanvaspath.c,
1.7, 1.8 goocanvaspath.h, 1.5, 1.6 goocanvaspathview.c, 1.11,
NONE goocanvaspathview.h, 1.4, NONE goocanvaspolyline.c, 1.6,
1.7 goocanvaspolyline.h, 1.4, 1.5 goocanvaspolylineview.c,
1.19, NONE goocanvaspolylineview.h, 1.5, NONE goocanvasrect.c,
1.6, 1.7 goocanvasrect.h, 1.2, 1.3 goocanvasrectview.c, 1.12,
NONE goocanvasrectview.h, 1.4, NONE goocanvastext.c, 1.6,
1.7 goocanvastext.h, 1.3, 1.4 goocanvastextview.c, 1.19,
NONE goocanvastextview.h, 1.5, NONE goocanvasview.c, 1.32,
NONE goocanvasview.h, 1.11, NONE
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the cairo-commit
mailing list