app: add an infrastructure that allows to stroke multiple items at once

In order to avoid visually overlapping lines:

- GimpCanvasItem got a "suspend_stroking" API that allows to skip
  stroking and instead starts a new sub-path
- GimpCanvasGroup got a "group_stroking" API that sets suspend_stroking
  on all its children and does one stroke after calling all items'
  draw().
This commit is contained in:
Michael Natterer
2010-09-26 14:12:54 +02:00
parent ea5190e630
commit e6ce564de4
4 changed files with 125 additions and 28 deletions

View File

@ -35,7 +35,8 @@
enum
{
PROP_0
PROP_0,
PROP_GROUP_STROKING
};
@ -44,6 +45,7 @@ typedef struct _GimpCanvasGroupPrivate GimpCanvasGroupPrivate;
struct _GimpCanvasGroupPrivate
{
GList *items;
gboolean group_stroking;
};
#define GET_PRIVATE(group) \
@ -88,6 +90,12 @@ gimp_canvas_group_class_init (GimpCanvasGroupClass *klass)
item_class->draw = gimp_canvas_group_draw;
item_class->get_extents = gimp_canvas_group_get_extents;
g_object_class_install_property (object_class, PROP_GROUP_STROKING,
g_param_spec_boolean ("group-stroking",
NULL, NULL,
FALSE,
GIMP_PARAM_READWRITE));
g_type_class_add_private (klass, sizeof (GimpCanvasGroupPrivate));
}
@ -117,10 +125,14 @@ gimp_canvas_group_set_property (GObject *object,
const GValue *value,
GParamSpec *pspec)
{
/* GimpCanvasGroupPrivate *private = GET_PRIVATE (object); */
GimpCanvasGroupPrivate *private = GET_PRIVATE (object);
switch (property_id)
{
case PROP_GROUP_STROKING:
private->group_stroking = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@ -133,10 +145,14 @@ gimp_canvas_group_get_property (GObject *object,
GValue *value,
GParamSpec *pspec)
{
/* GimpCanvasGroupPrivate *private = GET_PRIVATE (object); */
GimpCanvasGroupPrivate *private = GET_PRIVATE (object);
switch (property_id)
{
case PROP_GROUP_STROKING:
g_value_set_boolean (value, private->group_stroking);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@ -157,6 +173,9 @@ gimp_canvas_group_draw (GimpCanvasItem *item,
gimp_canvas_item_draw (sub_item, shell, cr);
}
if (private->group_stroking)
_gimp_canvas_item_stroke (item, shell, cr);
}
static GdkRegion *
@ -205,5 +224,36 @@ gimp_canvas_group_add_item (GimpCanvasGroup *group,
private = GET_PRIVATE (group);
if (private->group_stroking)
gimp_canvas_item_suspend_stroking (item);
private->items = g_list_append (private->items, g_object_ref (item));
}
void
gimp_canvas_group_remove_item (GimpCanvasGroup *group,
GimpCanvasItem *item)
{
GimpCanvasGroupPrivate *private;
g_return_if_fail (GIMP_IS_CANVAS_GROUP (group));
g_return_if_fail (GIMP_IS_CANVAS_ITEM (item));
private = GET_PRIVATE (group);
g_return_if_fail (g_list_find (private->items, item));
private->items = g_list_remove (private->items, item);
g_object_unref (item);
}
void
gimp_canvas_group_set_group_stroking (GimpCanvasGroup *group,
gboolean group_stroking)
{
g_return_if_fail (GIMP_IS_CANVAS_GROUP (group));
g_object_set (group,
"group-stroking", group_stroking ? TRUE : FALSE,
NULL);
}

View File

@ -53,6 +53,11 @@ GimpCanvasItem * gimp_canvas_group_new (void);
void gimp_canvas_group_add_item (GimpCanvasGroup *group,
GimpCanvasItem *item);
void gimp_canvas_group_remove_item (GimpCanvasGroup *group,
GimpCanvasItem *item);
void gimp_canvas_group_set_group_stroking (GimpCanvasGroup *group,
gboolean group_stroking);
#endif /* __GIMP_CANVAS_GROUP_H__ */

View File

@ -37,6 +37,7 @@ typedef struct _GimpCanvasItemPrivate GimpCanvasItemPrivate;
struct _GimpCanvasItemPrivate
{
gboolean highlight;
gint suspend_stroking;
};
#define GET_PRIVATE(item) \
@ -122,15 +123,43 @@ void
gimp_canvas_item_set_highlight (GimpCanvasItem *item,
gboolean highlight)
{
GimpCanvasItemPrivate *private = GET_PRIVATE (item);
GimpCanvasItemPrivate *private;
g_return_if_fail (GIMP_IS_CANVAS_ITEM (item));
private = GET_PRIVATE (item);
private->highlight = highlight ? TRUE : FALSE;
}
void
gimp_canvas_item_suspend_stroking (GimpCanvasItem *item)
{
GimpCanvasItemPrivate *private;
/* protexted functions */
g_return_if_fail (GIMP_IS_CANVAS_ITEM (item));
private = GET_PRIVATE (item);
private->suspend_stroking++;
}
void
gimp_canvas_item_resume_stroking (GimpCanvasItem *item)
{
GimpCanvasItemPrivate *private;
g_return_if_fail (GIMP_IS_CANVAS_ITEM (item));
private = GET_PRIVATE (item);
g_return_if_fail (private->suspend_stroking > 0);
private->suspend_stroking--;
}
/* protected functions */
void
_gimp_canvas_item_stroke (GimpCanvasItem *item,
@ -139,12 +168,19 @@ _gimp_canvas_item_stroke (GimpCanvasItem *item,
{
GimpCanvasItemPrivate *private = GET_PRIVATE (item);
if (private->suspend_stroking == 0)
{
gimp_display_shell_set_tool_bg_style (shell, cr);
cairo_stroke_preserve (cr);
gimp_display_shell_set_tool_fg_style (shell, cr, private->highlight);
cairo_stroke (cr);
}
else
{
cairo_new_sub_path (cr);
}
}
void
_gimp_canvas_item_fill (GimpCanvasItem *item,
@ -153,6 +189,9 @@ _gimp_canvas_item_fill (GimpCanvasItem *item,
{
GimpCanvasItemPrivate *private = GET_PRIVATE (item);
if (private->suspend_stroking > 0)
g_warning ("_gimp_canvas_item_fill() on an item that is in a stroking group");
gimp_display_shell_set_tool_bg_style (shell, cr);
cairo_set_line_width (cr, 2.0);
cairo_stroke_preserve (cr);

View File

@ -63,6 +63,9 @@ GdkRegion * gimp_canvas_item_get_extents (GimpCanvasItem *item,
void gimp_canvas_item_set_highlight (GimpCanvasItem *item,
gboolean highlight);
void gimp_canvas_item_suspend_stroking (GimpCanvasItem *item);
void gimp_canvas_item_resume_stroking (GimpCanvasItem *item);
/* protected */