Re: is_item_at
- From: control H <control h gmail com>
- To: Damon Chaplin <damonachaplin gmail com>
- Cc: goocanvas-list gnome org, Damon Chaplin <damon karuna eclipse co uk>
- Subject: Re: is_item_at
- Date: Tue, 24 May 2011 13:56:19 +0200
On Tue, May 24, 2011 at 12:34 PM, Damon Chaplin <damonachaplin gmail com> wrote:
> On 23 May 2011 14:28, control H <control h gmail com> wrote:
>
>> I'm not using large coordinates. The x&y coordinates look very reasonable.
>> The only place where I'm using a transformation matrix (I think) is in
>> the constructor:
>>
>> goo_line_item_new (GooCanvasItem *parent,
>> double x, double y,
>> gdouble dx,
>> gdouble dy,
>> ...)
>> {
>> GooCanvasItem *item;
>> GooLineItem *line_item;
>> const char *first_property;
>> va_list var_args;
>>
>> item = g_object_new (GOO_TYPE_LINE_ITEM, NULL);
>>
>> line_item = (GooLineItem*) item;
>> line_item->dx = dx;
>> line_item->dy = dy;
>>
>> goo_canvas_item_translate(item,x,y);
>>
>> va_start (var_args, dy);
>> 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);
>> }
>>
>> g_object_set(item,"can-focus", TRUE,NULL);
>>
>> return item;
>> }
>>
>> Example line showing problems:
>>
>> goo_line_item_new (root, 50,50,140, 30,
>> "stroke-color", "blue",
>> "line-width", 3.0,
>> NULL);
>>
>> In addition it seems that the line-width + 4.0 in the is_item_at()
>> code doesn't seem to have any influence.
>
> I can't understand the problem either.
>
> If you can produce a simple test app I'll have a look at it.
>
> Damon
>
Well, luckily I'm not the only one who doesn't understand. ;)
I have checked my code over and over again to make sure I didn't miss
something elementary. Can't find anything though.
Attached you'll find the class line-item.[ch] and an example program lijn.c.
regards,
CH
/*
* GooCanvas Demo. Copyright (C) 2006 Damon Chaplin.
* Released under the GNU LGPL license. See COPYING for details.
*
* demo-item.c - a simple demo item.
*/
#include "goocanvas.h"
#include "line-item.h"
#define DRAG_BOX_WIDTH 8
static double drag_x,drag_y;
static gboolean leave_notify (GooCanvasItem *item,
GooCanvasItem *target,
GdkEventCrossing *event)
{
GooLineItem *line=GOO_LINE_ITEM(item);
printf("line_item leave event\n");
goo_canvas_item_simple_changed(GOO_CANVAS_ITEM_SIMPLE(line),TRUE);
return FALSE;
}
static gboolean enter_notify(GooCanvasItem *item,
GooCanvasItem *target_item,
GdkEventCrossing *event)
{
GooLineItem *line=GOO_LINE_ITEM(item);
printf("line_item enter event\n");
goo_canvas_item_simple_changed(GOO_CANVAS_ITEM_SIMPLE(line),TRUE);
return FALSE;
}
static gboolean motion_notify(GooCanvasItem *item,
GooCanvasItem *target,
GdkEventMotion *event)
{
double x,y;
GooLineItem *line=GOO_LINE_ITEM(item);
x=event->x;
y=event->y;
printf("line_item motion event (%.2f,%.2f)\n",x,y);
if(line->dragging){
printf("in drag\n");
goo_canvas_item_translate(item,x-drag_x,y-drag_y);
}else{
printf("not in drag\n");
}
// return TRUE;
return FALSE;
}
static gboolean button_press(GooCanvasItem *item,
GooCanvasItem *target_item,
GdkEventButton *event)
{
GooLineItem *line=GOO_LINE_ITEM(item);
GooCanvasItemSimple *simple=GOO_CANVAS_ITEM_SIMPLE(item);
GdkCursor *fleur;
GooCanvas *canvas;
printf("line button press (%.2f,%.2f)\n",event->x,event->y);
drag_x = event->x;
drag_y = event->y;
fleur = gdk_cursor_new (GDK_FLEUR);
goo_canvas_pointer_grab (canvas, item,
GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
fleur,
event->time);
gdk_cursor_unref (fleur);
line->dragging=TRUE;
printf("current bounds: %.2f, %.2f, %.2f, %.2f\n",
simple->bounds.x1,simple->bounds.y1,simple->bounds.x2,
simple->bounds.y2);
return TRUE;
}
static gboolean button_release(GooCanvasItem *item,
GooCanvasItem *target,
GdkEventButton *event)
{
GooLineItem *line=GOO_LINE_ITEM(item);
GooCanvas *canvas;
canvas = goo_canvas_item_get_canvas (item);
line->dragging=FALSE;
return TRUE;
}
static void canvas_item_interface_init (GooCanvasItemIface *iface)
{
printf("line_item interface init\n");
iface->motion_notify_event = motion_notify;
iface->button_press_event = button_press;
iface->button_release_event = button_release;
}
/* Use the GLib convenience macro to define the type. GooLineItem is the
class struct, goo_line_item is the function prefix, and our class is a
subclass of GOO_TYPE_CANVAS_ITEM_SIMPLE. */
//G_DEFINE_TYPE (GooLineItem, goo_line_item, GOO_TYPE_CANVAS_ITEM_SIMPLE)
G_DEFINE_TYPE_WITH_CODE (GooLineItem, goo_line_item,
GOO_TYPE_CANVAS_ITEM_SIMPLE,
G_IMPLEMENT_INTERFACE(GOO_TYPE_CANVAS_ITEM,
canvas_item_interface_init))
/* The standard object initialization function. */
static void
goo_line_item_init (GooLineItem *line_item)
{
printf("line_item init\n");
line_item->dx = 80.0;
line_item->dy = 30.0;
line_item->dragging=FALSE;
}
/* The convenience function to create new items. This should start with a
parent argument and end with a variable list of object properties to fit
in with the standard canvas items. */
GooCanvasItem*
goo_line_item_new (GooCanvasItem *parent,
double x, double y,
gdouble dx,
gdouble dy,
...)
{
GooCanvasItem *item;
GooLineItem *line_item;
const char *first_property;
va_list var_args;
item = g_object_new (GOO_TYPE_LINE_ITEM, NULL);
line_item = (GooLineItem*) item;
line_item->dx = dx;
line_item->dy = dy;
goo_canvas_item_translate(item,x,y);
va_start (var_args, dy);
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);
}
g_object_set(item,"can-focus", TRUE,NULL);
return item;
}
/* The update method. This is called when the canvas is initially shown and
also whenever the object is updated and needs to change its size and/or
shape. It should calculate its new bounds in its own coordinate space,
storing them in simple->bounds. */
static void
goo_line_item_update (GooCanvasItemSimple *simple,
cairo_t *cr)
{
GooLineItem *line = (GooLineItem*) simple;
gdouble lw;
GooCanvas *canvas;
GooCanvasItem *item=GOO_CANVAS_ITEM(simple);
canvas=goo_canvas_item_get_canvas(item);
printf("line_item update\n");
g_object_get (G_OBJECT(simple),"line-width", &lw,NULL);
/* Compute the new bounds. */
simple->bounds.x1 = MIN(0,line->dx)-lw;
simple->bounds.y1 = MIN(0,line->dy)-lw;
simple->bounds.x2 = MAX(0,line->dx)+lw;
simple->bounds.y2 = MAX(0,line->dy)+lw;
printf("new bounds user: %.2f, %.2f, %.2f, %.2f\n",
simple->bounds.x1,simple->bounds.y1,simple->bounds.x2,
simple->bounds.y2);
}
/* The paint method. This should draw the item on the given cairo_t, using
the item's own coordinate space. */
static void
goo_line_item_paint (GooCanvasItemSimple *simple,
cairo_t *cr,
const GooCanvasBounds *bounds)
{
//GooCanvasItemSimple *group,*handle;
GooLineItem *line_item;
cairo_pattern_t *pattern;
gdouble w;
line_item = (GooLineItem*) simple;
printf("line_item paint\n");
printf("(%.2f,%.2f)\n",line_item->dx,line_item->dy);
g_object_get (G_OBJECT(line_item),"line-width", &w,NULL);
//printf("line width: %.2f\n",w);
cairo_move_to(cr,0,0);
cairo_line_to(cr,line_item->dx,line_item->dy);
goo_canvas_style_set_stroke_options(simple->simple_data->style, cr);
goo_canvas_style_set_fill_options (simple->simple_data->style, cr);
cairo_stroke (cr);
}
/* Hit detection. This should check if the given coordinate (in the item's
coordinate space) is within the item. If it is it should return TRUE,
otherwise it should return FALSE. */
static gboolean
goo_line_item_is_item_at (GooCanvasItemSimple *simple,
gdouble x,
gdouble y,
cairo_t *cr,
gboolean is_pointer_event)
{
GooLineItem *line=(GooLineItem*)simple;
gboolean r,r2;
GooCanvasPointerEvents pointer_events = GOO_CANVAS_EVENTS_ALL;
gdouble width;
printf("line_item is_item_at (%.2f,%.2f), pointer event: %d",
x,y,is_pointer_event);
g_object_get (G_OBJECT(line),"line-width", &width,NULL);
cairo_move_to(cr,0,0);
cairo_line_to(cr,line->dx,line->dy);
cairo_set_line_width(cr,width+4.0); // to make it easier to pick up
// thin lines
cairo_set_source_rgb(cr,1,0,0);
r2=goo_canvas_item_simple_check_in_path(simple,x,y,cr,pointer_events);
r=cairo_in_stroke (cr, x, y);
printf(", r: %d, r2: %d\n",r,r2);
return r;
}
/* The class initialization function. Here we set the class' update(), paint()
and is_item_at() methods. */
static void
goo_line_item_class_init (GooLineItemClass *klass)
{
GooCanvasItemSimpleClass *simple_class = (GooCanvasItemSimpleClass*) klass;
printf("line_item class init\n");
simple_class->simple_update = goo_line_item_update;
simple_class->simple_paint = goo_line_item_paint;
simple_class->simple_is_item_at = goo_line_item_is_item_at;
}
/*
* GooCanvas Demo. Copyright (C) 2006 Damon Chaplin.
* Released under the GNU LGPL license. See COPYING for details.
*
* demo-item.c - a simple demo item.
*/
#ifndef __GOO_LINE_ITEM_H__
#define __GOO_LINE_ITEM_H__
#include <gtk/gtk.h>
#include "goocanvasitemsimple.h"
G_BEGIN_DECLS
#define GOO_TYPE_LINE_ITEM (goo_line_item_get_type ())
#define GOO_LINE_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_LINE_ITEM, GooLineItem))
#define GOO_LINE_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_LINE_ITEM, GooLineItemClass))
#define GOO_IS_LINE_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GOO_TYPE_LINE_ITEM))
#define GOO_IS_LINE_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GOO_TYPE_LINE_ITEM))
#define GOO_LINE_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GOO_TYPE_LINE_ITEM, GooLineItemClass))
typedef struct _GooLineItem GooLineItem;
typedef struct _GooLineItemClass GooLineItemClass;
struct _GooLineItem
{
GooCanvasItemSimple parent_object;
gdouble dx,dy;
gboolean dragging;
};
struct _GooLineItemClass
{
GooCanvasItemSimpleClass parent_class;
};
GType goo_line_item_get_type (void) G_GNUC_CONST;
GooCanvasItem* goo_line_item_new (GooCanvasItem *parent,
double x,double y,
gdouble dx,
gdouble dy,
...);
G_END_DECLS
#endif /* __GOO_LINE_ITEM_H__ */
#include <stdlib.h>
#include <goocanvas.h>
#include "line-item.h"
static gboolean dragging = FALSE;
static double drag_x, drag_y;
gboolean button_event(GooCanvasItem *item,
GooCanvasItem *target_item,
GdkEventButton *event,
gpointer user_data)
{
GooCanvasBounds bounds;
printf("line instance: button pressed\n");
g_print ("%p received 'button-press' signal at %g, %g (root: %g, %g)\n",
item, event->x, event->y, event->x_root, event->y_root);
goo_canvas_item_get_bounds(item,&bounds);
printf("bounds: %.2f, %.2f, %.2f, %.2f\n",bounds.x1,bounds.y1,
bounds.x2,bounds.y2);
return FALSE;
//return TRUE;
}
static gboolean
on_motion_notify (GooCanvasItem *item,
GooCanvasItem *target,
GdkEventMotion *event,
gpointer data)
{
#if 0
g_print ("received 'motion-notify' signal at %g, %g\n",
event->x, event->y);
#endif
if (dragging && (event->state & GDK_BUTTON1_MASK))
{
double new_x = event->x;
double new_y = event->y;
goo_canvas_item_translate (item, new_x - drag_x, new_y - drag_y);
}
return TRUE;
}
static void
output_items_in_area (GooCanvas *canvas,
gdouble x,
gdouble y)
{
static gdouble last_x = 0.0, last_y = 0.0;
GooCanvasBounds area;
GList *items, *elem;
/* Print out the items from the last point to this one. */
area.x1 = MIN (x, last_x);
area.x2 = MAX (x, last_x);
area.y1 = MIN (y, last_y);
area.y2 = MAX (y, last_y);
items = goo_canvas_get_items_in_area (canvas, &area, TRUE, FALSE, FALSE);
for (elem = items; elem; elem = elem->next)
{
g_print (" found items in area (%g, %g - %g, %g): %p\n",
area.x1, area.y1, area.x2, area.y2, elem->data);
}
g_list_free (items);
last_x = x;
last_y = y;
}
static gboolean
on_button_press (GooCanvasItem *item,
GooCanvasItem *target,
GdkEventButton *event,
gpointer data)
{
GooCanvas *canvas;
GdkCursor *fleur;
GList *items, *elem;
GooCanvasBounds bounds;
g_print ("%p received 'button-press' signal at %g, %g (root: %g, %g)\n",
item, event->x, event->y, event->x_root, event->y_root);
goo_canvas_item_get_bounds(item,&bounds);
printf("bounds: %.2f, %.2f, %.2f, %.2f\n",bounds.x1,bounds.y1,
bounds.x2,bounds.y2);
canvas = goo_canvas_item_get_canvas (item);
items = goo_canvas_get_items_at (canvas, event->x_root, event->y_root,
TRUE);
for (elem = items; elem; elem = elem->next)
g_print (" found items: %p\n", elem->data);
g_list_free (items);
output_items_in_area (canvas, event->x_root, event->y_root);
switch (event->button)
{
case 1:
if (event->state & GDK_SHIFT_MASK)
{
goo_canvas_item_remove (item);
}
else
{
drag_x = event->x;
drag_y = event->y;
fleur = gdk_cursor_new (GDK_FLEUR);
goo_canvas_pointer_grab (canvas, item,
GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
fleur,
event->time);
gdk_cursor_unref (fleur);
dragging = TRUE;
}
break;
case 2:
goo_canvas_item_lower (item, NULL);
break;
case 3:
goo_canvas_item_raise (item, NULL);
break;
default:
break;
}
// return TRUE;
return FALSE;
}
static gboolean
on_button_release (GooCanvasItem *item,
GooCanvasItem *target,
GdkEventButton *event,
gpointer data)
{
GooCanvas *canvas;
#if 0
g_print ("received 'button-release' signal\n");
#endif
canvas = goo_canvas_item_get_canvas (item);
goo_canvas_pointer_ungrab (canvas, item, event->time);
dragging = FALSE;
return TRUE;
}
/*
*/
static gboolean on_rect_button_press (GooCanvasItem *view,
GooCanvasItem *target,
GdkEventButton *event,
gpointer data);
static gboolean on_delete_event (GtkWidget *window,
GdkEvent *event,
gpointer unused_data);
static void
setup_item_signals (GooCanvasItem *item)
{
g_signal_connect (item, "motion_notify_event",
G_CALLBACK(on_motion_notify), NULL);
g_signal_connect (item, "button_press_event",
G_CALLBACK(on_button_press), NULL);
g_signal_connect (item, "button_release_event",
G_CALLBACK(on_button_release), NULL);
}
int
main (int argc, char *argv[])
{
GtkWidget *window, *scrolled_win, *canvas;
GooCanvasItem *root, *rect_item, *text_item;
/* Initialize GTK+. */
gtk_init (&argc, &argv);
/* Create the window and widgets. */
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (window), 640, 600);
gtk_widget_show (window);
g_signal_connect (window, "delete_event", G_CALLBACK(on_delete_event),
NULL);
scrolled_win = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win),
GTK_SHADOW_IN);
gtk_widget_show (scrolled_win);
gtk_container_add (GTK_CONTAINER (window), scrolled_win);
canvas = goo_canvas_new ();
gtk_widget_set_size_request (canvas, 600, 450);
goo_canvas_set_bounds (GOO_CANVAS (canvas), 0, 0, 1000, 1000);
gtk_widget_show (canvas);
gtk_container_add (GTK_CONTAINER (scrolled_win), canvas);
root = goo_canvas_get_root_item (GOO_CANVAS (canvas));
/* Add a few simple items. */
rect_item = goo_canvas_rect_new (root, 100, 100, 400, 400,
"line-width", 10.0,
"radius-x", 20.0,
"radius-y", 10.0,
"stroke-color", "yellow",
"fill-color", "red",
NULL);
text_item = goo_canvas_text_new (root, "Hello World", 300, 300, -1,
GOO_CANVAS_ANCHOR_CENTER,
"font", "Sans 24",
NULL);
goo_canvas_item_rotate (text_item, 45, 300, 300);
setup_item_signals(rect_item);
GooCanvasItem *ellipse1;
ellipse1 = goo_canvas_ellipse_new (root, 245, 45, 25, 15,
"stroke-color", "goldenrod",
"line-width", 8.0,
NULL);
setup_item_signals (ellipse1);
GooCanvasItem *lijn1;
lijn1 = goo_line_item_new (root, 50,50,140, 30,
"stroke-color", "blue",
"line-width", 3.0,
NULL);
lijn1 = goo_line_item_new (root, 250,150,130, 30,
"stroke-color", "green",
NULL);
GooCanvasLineDash *dash;
dash = goo_canvas_line_dash_new (2, 5.0, 5.0);
lijn1 = goo_line_item_new (root, 250,20,100, 140,
"stroke-color", "brown",
"line-width", 3.0,
"line-dash",dash,
NULL);
goo_canvas_line_dash_unref(dash);
/* Pass control to the GTK+ main event loop. */
gtk_main ();
return 0;
}
/* This handles button presses in item views. We simply output a message to
the console. */
static gboolean
on_rect_button_press (GooCanvasItem *item,
GooCanvasItem *target,
GdkEventButton *event,
gpointer data)
{
g_print ("rect item received button press event\n");
return TRUE;
}
/* This is our handler for the "delete-event" signal of the window, which
is emitted when the 'x' close button is clicked. We just exit here. */
static gboolean
on_delete_event (GtkWidget *window,
GdkEvent *event,
gpointer unused_data)
{
exit (0);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]