Highlight symbol terminals on mouse hover.
This commit is contained in:
parent
f12df021f7
commit
61ae34236a
114
src/ld-canvas.c
114
src/ld-canvas.c
@ -46,6 +46,11 @@
|
|||||||
/* Tolerance on all sides of symbols for strokes. */
|
/* Tolerance on all sides of symbols for strokes. */
|
||||||
#define SYMBOL_CLIP_TOLERANCE 5
|
#define SYMBOL_CLIP_TOLERANCE 5
|
||||||
|
|
||||||
|
/* Size of a highlighted terminal. */
|
||||||
|
#define TERMINAL_RADIUS 5
|
||||||
|
/* Tolerance around terminal points. */
|
||||||
|
#define TERMINAL_HOVER_TOLERANCE 8
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* OperationEnd:
|
* OperationEnd:
|
||||||
*
|
*
|
||||||
@ -73,6 +78,7 @@ enum
|
|||||||
COLOR_GRID,
|
COLOR_GRID,
|
||||||
COLOR_OBJECT,
|
COLOR_OBJECT,
|
||||||
COLOR_SELECTION,
|
COLOR_SELECTION,
|
||||||
|
COLOR_TERMINAL,
|
||||||
COLOR_COUNT
|
COLOR_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -112,6 +118,9 @@ struct _LdCanvasPrivate
|
|||||||
gdouble y;
|
gdouble y;
|
||||||
gdouble zoom;
|
gdouble zoom;
|
||||||
|
|
||||||
|
LdPoint terminal;
|
||||||
|
gboolean terminal_highlighted;
|
||||||
|
|
||||||
gint operation;
|
gint operation;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
@ -200,8 +209,10 @@ static gboolean get_object_area (LdCanvas *self, LdDiagramObject *object,
|
|||||||
LdRectangle *rect);
|
LdRectangle *rect);
|
||||||
static gboolean object_hit_test (LdCanvas *self, LdDiagramObject *object,
|
static gboolean object_hit_test (LdCanvas *self, LdDiagramObject *object,
|
||||||
gdouble x, gdouble y);
|
gdouble x, gdouble y);
|
||||||
|
static void check_terminals (LdCanvas *self, gdouble x, gdouble y);
|
||||||
static void queue_draw (LdCanvas *self, LdRectangle *rect);
|
static void queue_draw (LdCanvas *self, LdRectangle *rect);
|
||||||
static void queue_object_draw (LdCanvas *self, LdDiagramObject *object);
|
static void queue_object_draw (LdCanvas *self, LdDiagramObject *object);
|
||||||
|
static void queue_terminal_draw (LdCanvas *self, LdPoint *terminal);
|
||||||
|
|
||||||
static void ld_canvas_real_cancel_operation (LdCanvas *self);
|
static void ld_canvas_real_cancel_operation (LdCanvas *self);
|
||||||
static void ld_canvas_add_object_end (LdCanvas *self);
|
static void ld_canvas_add_object_end (LdCanvas *self);
|
||||||
@ -210,6 +221,7 @@ static gboolean on_expose_event (GtkWidget *widget, GdkEventExpose *event,
|
|||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
static void draw_grid (GtkWidget *widget, DrawData *data);
|
static void draw_grid (GtkWidget *widget, DrawData *data);
|
||||||
static void draw_diagram (GtkWidget *widget, DrawData *data);
|
static void draw_diagram (GtkWidget *widget, DrawData *data);
|
||||||
|
static void draw_terminal (GtkWidget *widget, DrawData *data);
|
||||||
static void draw_object (LdDiagramObject *diagram_object, DrawData *data);
|
static void draw_object (LdDiagramObject *diagram_object, DrawData *data);
|
||||||
static void draw_symbol (LdDiagramSymbol *diagram_symbol, DrawData *data);
|
static void draw_symbol (LdDiagramSymbol *diagram_symbol, DrawData *data);
|
||||||
|
|
||||||
@ -302,6 +314,7 @@ ld_canvas_init (LdCanvas *self)
|
|||||||
ld_canvas_color_set (COLOR_GET (self, COLOR_GRID), 0.5, 0.5, 0.5, 1);
|
ld_canvas_color_set (COLOR_GET (self, COLOR_GRID), 0.5, 0.5, 0.5, 1);
|
||||||
ld_canvas_color_set (COLOR_GET (self, COLOR_OBJECT), 0, 0, 0, 1);
|
ld_canvas_color_set (COLOR_GET (self, COLOR_OBJECT), 0, 0, 0, 1);
|
||||||
ld_canvas_color_set (COLOR_GET (self, COLOR_SELECTION), 0, 0, 1, 1);
|
ld_canvas_color_set (COLOR_GET (self, COLOR_SELECTION), 0, 0, 1, 1);
|
||||||
|
ld_canvas_color_set (COLOR_GET (self, COLOR_TERMINAL), 1, 0.5, 0.5, 1);
|
||||||
|
|
||||||
g_signal_connect (self, "size-allocate",
|
g_signal_connect (self, "size-allocate",
|
||||||
G_CALLBACK (on_size_allocate), NULL);
|
G_CALLBACK (on_size_allocate), NULL);
|
||||||
@ -918,6 +931,72 @@ object_hit_test (LdCanvas *self, LdDiagramObject *object, gdouble x, gdouble y)
|
|||||||
return ld_rectangle_contains (&rect, x, y);
|
return ld_rectangle_contains (&rect, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
check_terminals (LdCanvas *self, gdouble x, gdouble y)
|
||||||
|
{
|
||||||
|
GSList *objects, *iter;
|
||||||
|
LdDiagramSymbol *closest_symbol = NULL;
|
||||||
|
gdouble closest_distance = TERMINAL_HOVER_TOLERANCE;
|
||||||
|
LdPoint closest_terminal;
|
||||||
|
|
||||||
|
objects = (GSList *) ld_diagram_get_objects (self->priv->diagram);
|
||||||
|
for (iter = objects; iter; iter = g_slist_next (iter))
|
||||||
|
{
|
||||||
|
LdDiagramObject *diagram_object;
|
||||||
|
gdouble object_x, object_y;
|
||||||
|
LdDiagramSymbol *diagram_symbol;
|
||||||
|
LdSymbol *symbol;
|
||||||
|
const LdPointArray *terminals;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
if (!LD_IS_DIAGRAM_SYMBOL (iter->data))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
diagram_symbol = LD_DIAGRAM_SYMBOL (iter->data);
|
||||||
|
symbol = resolve_diagram_symbol (self, diagram_symbol);
|
||||||
|
if (!symbol)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
diagram_object = LD_DIAGRAM_OBJECT (iter->data);
|
||||||
|
object_x = ld_diagram_object_get_x (diagram_object);
|
||||||
|
object_y = ld_diagram_object_get_y (diagram_object);
|
||||||
|
|
||||||
|
terminals = ld_symbol_get_terminals (symbol);
|
||||||
|
|
||||||
|
for (i = 0; i < terminals->num_points; i++)
|
||||||
|
{
|
||||||
|
LdPoint cur_term;
|
||||||
|
gdouble distance;
|
||||||
|
|
||||||
|
cur_term = terminals->points[i];
|
||||||
|
cur_term.x += object_x;
|
||||||
|
cur_term.y += object_y;
|
||||||
|
ld_canvas_diagram_to_widget_coords (self,
|
||||||
|
cur_term.x, cur_term.y, &cur_term.x, &cur_term.y);
|
||||||
|
|
||||||
|
distance = ld_point_distance (&cur_term, x, y);
|
||||||
|
if (distance <= closest_distance)
|
||||||
|
{
|
||||||
|
closest_symbol = diagram_symbol;
|
||||||
|
closest_distance = distance;
|
||||||
|
closest_terminal = cur_term;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->priv->terminal_highlighted)
|
||||||
|
queue_terminal_draw (self, &self->priv->terminal);
|
||||||
|
|
||||||
|
if (closest_symbol)
|
||||||
|
{
|
||||||
|
self->priv->terminal_highlighted = TRUE;
|
||||||
|
self->priv->terminal = closest_terminal;
|
||||||
|
queue_terminal_draw (self, &closest_terminal);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
self->priv->terminal_highlighted = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
queue_draw (LdCanvas *self, LdRectangle *rect)
|
queue_draw (LdCanvas *self, LdRectangle *rect)
|
||||||
{
|
{
|
||||||
@ -942,6 +1021,18 @@ queue_object_draw (LdCanvas *self, LdDiagramObject *object)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
queue_terminal_draw (LdCanvas *self, LdPoint *terminal)
|
||||||
|
{
|
||||||
|
LdRectangle rect;
|
||||||
|
|
||||||
|
rect.x = terminal->x - TERMINAL_RADIUS;
|
||||||
|
rect.y = terminal->y - TERMINAL_RADIUS;
|
||||||
|
rect.width = 2 * TERMINAL_RADIUS;
|
||||||
|
rect.height = 2 * TERMINAL_RADIUS;
|
||||||
|
queue_draw (self, &rect);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
on_motion_notify (GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
|
on_motion_notify (GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
|
||||||
{
|
{
|
||||||
@ -960,6 +1051,9 @@ on_motion_notify (GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
|
|||||||
move_object_to_coords (self, data->object, event->x, event->y);
|
move_object_to_coords (self, data->object, event->x, event->y);
|
||||||
queue_object_draw (self, data->object);
|
queue_object_draw (self, data->object);
|
||||||
break;
|
break;
|
||||||
|
case OPER_0:
|
||||||
|
check_terminals (self, event->x, event->y);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -1051,6 +1145,7 @@ on_scroll (GtkWidget *widget, GdkEventScroll *event, gpointer user_data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
update_adjustments (self);
|
update_adjustments (self);
|
||||||
|
check_terminals (self, event->x, event->y);
|
||||||
gtk_widget_queue_draw (widget);
|
gtk_widget_queue_draw (widget);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -1076,6 +1171,7 @@ on_expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
|
|||||||
|
|
||||||
draw_grid (widget, &data);
|
draw_grid (widget, &data);
|
||||||
draw_diagram (widget, &data);
|
draw_diagram (widget, &data);
|
||||||
|
draw_terminal (widget, &data);
|
||||||
|
|
||||||
cairo_destroy (data.cr);
|
cairo_destroy (data.cr);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -1116,6 +1212,24 @@ draw_grid (GtkWidget *widget, DrawData *data)
|
|||||||
cairo_stroke (data->cr);
|
cairo_stroke (data->cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
draw_terminal (GtkWidget *widget, DrawData *data)
|
||||||
|
{
|
||||||
|
LdCanvasPrivate *priv;
|
||||||
|
|
||||||
|
priv = data->self->priv;
|
||||||
|
if (!priv->terminal_highlighted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ld_canvas_color_apply (COLOR_GET (data->self, COLOR_TERMINAL), data->cr);
|
||||||
|
cairo_set_line_width (data->cr, 1);
|
||||||
|
|
||||||
|
cairo_new_path (data->cr);
|
||||||
|
cairo_arc (data->cr, priv->terminal.x, priv->terminal.y,
|
||||||
|
TERMINAL_RADIUS, 0, 2 * G_PI);
|
||||||
|
cairo_stroke (data->cr);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
draw_diagram (GtkWidget *widget, DrawData *data)
|
draw_diagram (GtkWidget *widget, DrawData *data)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user