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. */
|
||||
#define SYMBOL_CLIP_TOLERANCE 5
|
||||
|
||||
/* Size of a highlighted terminal. */
|
||||
#define TERMINAL_RADIUS 5
|
||||
/* Tolerance around terminal points. */
|
||||
#define TERMINAL_HOVER_TOLERANCE 8
|
||||
|
||||
/*
|
||||
* OperationEnd:
|
||||
*
|
||||
@ -73,6 +78,7 @@ enum
|
||||
COLOR_GRID,
|
||||
COLOR_OBJECT,
|
||||
COLOR_SELECTION,
|
||||
COLOR_TERMINAL,
|
||||
COLOR_COUNT
|
||||
};
|
||||
|
||||
@ -112,6 +118,9 @@ struct _LdCanvasPrivate
|
||||
gdouble y;
|
||||
gdouble zoom;
|
||||
|
||||
LdPoint terminal;
|
||||
gboolean terminal_highlighted;
|
||||
|
||||
gint operation;
|
||||
union
|
||||
{
|
||||
@ -200,8 +209,10 @@ static gboolean get_object_area (LdCanvas *self, LdDiagramObject *object,
|
||||
LdRectangle *rect);
|
||||
static gboolean object_hit_test (LdCanvas *self, LdDiagramObject *object,
|
||||
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_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_add_object_end (LdCanvas *self);
|
||||
@ -210,6 +221,7 @@ static gboolean on_expose_event (GtkWidget *widget, GdkEventExpose *event,
|
||||
gpointer user_data);
|
||||
static void draw_grid (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_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_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_TERMINAL), 1, 0.5, 0.5, 1);
|
||||
|
||||
g_signal_connect (self, "size-allocate",
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
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);
|
||||
queue_object_draw (self, data->object);
|
||||
break;
|
||||
case OPER_0:
|
||||
check_terminals (self, event->x, event->y);
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@ -1051,6 +1145,7 @@ on_scroll (GtkWidget *widget, GdkEventScroll *event, gpointer user_data)
|
||||
}
|
||||
|
||||
update_adjustments (self);
|
||||
check_terminals (self, event->x, event->y);
|
||||
gtk_widget_queue_draw (widget);
|
||||
return TRUE;
|
||||
}
|
||||
@ -1076,6 +1171,7 @@ on_expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
|
||||
|
||||
draw_grid (widget, &data);
|
||||
draw_diagram (widget, &data);
|
||||
draw_terminal (widget, &data);
|
||||
|
||||
cairo_destroy (data.cr);
|
||||
return FALSE;
|
||||
@ -1116,6 +1212,24 @@ draw_grid (GtkWidget *widget, DrawData *data)
|
||||
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
|
||||
draw_diagram (GtkWidget *widget, DrawData *data)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user