Allow rotation of symbols.

Bind this action to the right mouse button.

Due to limitations of json-glib, we can't store rotation as an enum.
This commit is contained in:
Přemysl Eric Janouch 2011-02-14 10:14:28 +01:00
parent 5ccabad6ce
commit baed5ee4bd
4 changed files with 181 additions and 16 deletions

View File

@ -240,6 +240,7 @@ static void queue_object_draw (LdCanvas *self, LdDiagramObject *object);
/* Symbol terminals. */ /* Symbol terminals. */
static void check_terminals (LdCanvas *self, const LdPoint *point); static void check_terminals (LdCanvas *self, const LdPoint *point);
static void rotate_terminal (LdPoint *terminal, gint symbol_rotation);
static void hide_terminals (LdCanvas *self); static void hide_terminals (LdCanvas *self);
static void queue_terminal_draw (LdCanvas *self, LdPoint *terminal); static void queue_terminal_draw (LdCanvas *self, LdPoint *terminal);
@ -251,6 +252,8 @@ static gboolean get_symbol_clip_area (LdCanvas *self,
static gboolean get_symbol_area (LdCanvas *self, static gboolean get_symbol_area (LdCanvas *self,
LdDiagramSymbol *symbol, LdRectangle *rect); LdDiagramSymbol *symbol, LdRectangle *rect);
static void rotate_symbol_area (LdRectangle *area, gint rotation);
static void rotate_symbol (LdCanvas *self, LdDiagramSymbol *symbol);
static LdSymbol *resolve_symbol (LdCanvas *self, static LdSymbol *resolve_symbol (LdCanvas *self,
LdDiagramSymbol *diagram_symbol); LdDiagramSymbol *diagram_symbol);
@ -1162,12 +1165,12 @@ check_terminals (LdCanvas *self, const LdPoint *point)
objects = (GList *) ld_diagram_get_objects (self->priv->diagram); objects = (GList *) ld_diagram_get_objects (self->priv->diagram);
for (iter = objects; iter; iter = g_list_next (iter)) for (iter = objects; iter; iter = g_list_next (iter))
{ {
LdDiagramObject *diagram_object;
gdouble object_x, object_y; gdouble object_x, object_y;
LdDiagramSymbol *diagram_symbol; LdDiagramSymbol *diagram_symbol;
LdSymbol *symbol; LdSymbol *symbol;
const LdPointArray *terminals; const LdPointArray *terminals;
guint i; guint i;
gint rotation;
if (!LD_IS_DIAGRAM_SYMBOL (iter->data)) if (!LD_IS_DIAGRAM_SYMBOL (iter->data))
continue; continue;
@ -1177,17 +1180,17 @@ check_terminals (LdCanvas *self, const LdPoint *point)
if (!symbol) if (!symbol)
continue; continue;
diagram_object = LD_DIAGRAM_OBJECT (iter->data); g_object_get (diagram_symbol, "x", &object_x, "y", &object_y,
g_object_get (diagram_object, "x", &object_x, "y", &object_y, NULL); "rotation", &rotation, NULL);
terminals = ld_symbol_get_terminals (symbol); terminals = ld_symbol_get_terminals (symbol);
for (i = 0; i < terminals->length; i++) for (i = 0; i < terminals->length; i++)
{ {
LdPoint cur_term, widget_coords; LdPoint cur_term, widget_coords;
gdouble distance; gdouble distance;
cur_term = terminals->points[i]; cur_term = terminals->points[i];
rotate_terminal (&cur_term, rotation);
cur_term.x += object_x; cur_term.x += object_x;
cur_term.y += object_y; cur_term.y += object_y;
@ -1213,6 +1216,30 @@ check_terminals (LdCanvas *self, const LdPoint *point)
} }
} }
static void
rotate_terminal (LdPoint *terminal, gint symbol_rotation)
{
gdouble temp;
switch (symbol_rotation)
{
case LD_DIAGRAM_SYMBOL_ROTATION_90:
temp = terminal->y;
terminal->y = terminal->x;
terminal->x = -temp;
break;
case LD_DIAGRAM_SYMBOL_ROTATION_180:
terminal->y = -terminal->y;
terminal->x = -terminal->x;
break;
case LD_DIAGRAM_SYMBOL_ROTATION_270:
temp = terminal->x;
terminal->x = terminal->y;
terminal->y = -temp;
break;
}
}
static void static void
hide_terminals (LdCanvas *self) hide_terminals (LdCanvas *self)
{ {
@ -1276,8 +1303,10 @@ get_symbol_area (LdCanvas *self, LdDiagramSymbol *symbol, LdRectangle *rect)
LdRectangle area; LdRectangle area;
gdouble x1, x2; gdouble x1, x2;
gdouble y1, y2; gdouble y1, y2;
gint rotation;
g_object_get (symbol, "x", &object_x, "y", &object_y, NULL); g_object_get (symbol, "x", &object_x, "y", &object_y,
"rotation", &rotation, NULL);
library_symbol = resolve_symbol (self, symbol); library_symbol = resolve_symbol (self, symbol);
if (library_symbol) if (library_symbol)
@ -1285,7 +1314,8 @@ get_symbol_area (LdCanvas *self, LdDiagramSymbol *symbol, LdRectangle *rect)
else else
return FALSE; return FALSE;
/* TODO: Rotate the rectangle for other orientations. */ rotate_symbol_area (&area, rotation);
ld_canvas_diagram_to_widget_coords (self, ld_canvas_diagram_to_widget_coords (self,
object_x + area.x, object_x + area.x,
object_y + area.y, object_y + area.y,
@ -1307,6 +1337,68 @@ get_symbol_area (LdCanvas *self, LdDiagramSymbol *symbol, LdRectangle *rect)
return TRUE; return TRUE;
} }
static void
rotate_symbol_area (LdRectangle *area, gint rotation)
{
gdouble temp;
switch (rotation)
{
case LD_DIAGRAM_SYMBOL_ROTATION_90:
temp = area->y;
area->y = area->x;
area->x = -(temp + area->height);
break;
case LD_DIAGRAM_SYMBOL_ROTATION_180:
area->y = -(area->y + area->height);
area->x = -(area->x + area->width);
break;
case LD_DIAGRAM_SYMBOL_ROTATION_270:
temp = area->x;
area->x = area->y;
area->y = -(temp + area->width);
break;
}
switch (rotation)
{
case LD_DIAGRAM_SYMBOL_ROTATION_90:
case LD_DIAGRAM_SYMBOL_ROTATION_270:
temp = area->width;
area->width = area->height;
area->height = temp;
break;
}
}
static void
rotate_symbol (LdCanvas *self, LdDiagramSymbol *symbol)
{
gint rotation;
g_object_get (symbol, "rotation", &rotation, NULL);
queue_object_draw (self, LD_DIAGRAM_OBJECT (symbol));
switch (rotation)
{
case LD_DIAGRAM_SYMBOL_ROTATION_0:
rotation = LD_DIAGRAM_SYMBOL_ROTATION_90;
break;
case LD_DIAGRAM_SYMBOL_ROTATION_90:
rotation = LD_DIAGRAM_SYMBOL_ROTATION_180;
break;
case LD_DIAGRAM_SYMBOL_ROTATION_180:
rotation = LD_DIAGRAM_SYMBOL_ROTATION_270;
break;
case LD_DIAGRAM_SYMBOL_ROTATION_270:
rotation = LD_DIAGRAM_SYMBOL_ROTATION_0;
break;
}
g_object_set (symbol, "rotation", rotation, NULL);
queue_object_draw (self, LD_DIAGRAM_OBJECT (symbol));
}
static LdSymbol * static LdSymbol *
resolve_symbol (LdCanvas *self, LdDiagramSymbol *diagram_symbol) resolve_symbol (LdCanvas *self, LdDiagramSymbol *diagram_symbol)
{ {
@ -1846,11 +1938,6 @@ on_button_press (GtkWidget *widget, GdkEventButton *event, gpointer user_data)
AddObjectData *data; AddObjectData *data;
LdDiagramObject *object; LdDiagramObject *object;
if (event->button != 1)
return FALSE;
if (!gtk_widget_has_focus (widget))
gtk_widget_grab_focus (widget);
point.x = event->x; point.x = event->x;
point.y = event->y; point.y = event->y;
@ -1858,6 +1945,19 @@ on_button_press (GtkWidget *widget, GdkEventButton *event, gpointer user_data)
if (!self->priv->diagram) if (!self->priv->diagram)
return FALSE; return FALSE;
if (event->button == 3 && self->priv->operation == OPER_0)
{
object = get_object_at_point (self, &point);
if (object && LD_IS_DIAGRAM_SYMBOL (object))
rotate_symbol (self, LD_DIAGRAM_SYMBOL (object));
return FALSE;
}
if (event->button != 1)
return FALSE;
if (!gtk_widget_has_focus (widget))
gtk_widget_grab_focus (widget);
self->priv->drag_operation = OPER_0; self->priv->drag_operation = OPER_0;
switch (self->priv->operation) switch (self->priv->operation)
{ {
@ -2151,6 +2251,7 @@ draw_symbol (LdDiagramSymbol *diagram_symbol, DrawData *data)
LdSymbol *symbol; LdSymbol *symbol;
LdRectangle clip_rect; LdRectangle clip_rect;
gdouble x, y; gdouble x, y;
gint rotation;
symbol = resolve_symbol (data->self, diagram_symbol); symbol = resolve_symbol (data->self, diagram_symbol);
@ -2175,12 +2276,25 @@ draw_symbol (LdDiagramSymbol *diagram_symbol, DrawData *data)
clip_rect.width, clip_rect.height); clip_rect.width, clip_rect.height);
cairo_clip (data->cr); cairo_clip (data->cr);
/* TODO: Rotate the space for other orientations. */ g_object_get (diagram_symbol, "x", &x, "y", &y,
g_object_get (diagram_symbol, "x", &x, "y", &y, NULL); "rotation", &rotation, NULL);
ld_canvas_diagram_to_widget_coords (data->self, x, y, &x, &y); ld_canvas_diagram_to_widget_coords (data->self, x, y, &x, &y);
cairo_translate (data->cr, x, y); cairo_translate (data->cr, x, y);
cairo_scale (data->cr, data->scale, data->scale); cairo_scale (data->cr, data->scale, data->scale);
switch (rotation)
{
case LD_DIAGRAM_SYMBOL_ROTATION_90:
cairo_rotate (data->cr, G_PI * 0.5);
break;
case LD_DIAGRAM_SYMBOL_ROTATION_180:
cairo_rotate (data->cr, G_PI);
break;
case LD_DIAGRAM_SYMBOL_ROTATION_270:
cairo_rotate (data->cr, G_PI * 1.5);
break;
}
ld_symbol_draw (symbol, data->cr); ld_symbol_draw (symbol, data->cr);
cairo_restore (data->cr); cairo_restore (data->cr);
} }

View File

@ -87,8 +87,6 @@ void ld_canvas_zoom_out (LdCanvas *self);
void ld_canvas_add_object_begin (LdCanvas *self, LdDiagramObject *object); void ld_canvas_add_object_begin (LdCanvas *self, LdDiagramObject *object);
/* TODO: The rest of the interface. */
G_END_DECLS G_END_DECLS

View File

@ -23,7 +23,8 @@
enum enum
{ {
PROP_0, PROP_0,
PROP_CLASS PROP_CLASS,
PROP_ROTATION
}; };
static void ld_diagram_symbol_get_property (GObject *object, guint property_id, static void ld_diagram_symbol_get_property (GObject *object, guint property_id,
@ -53,6 +54,16 @@ ld_diagram_symbol_class_init (LdDiagramSymbolClass *klass)
"The class of this symbol.", "The class of this symbol.",
"", G_PARAM_READWRITE); "", G_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_CLASS, pspec); g_object_class_install_property (object_class, PROP_CLASS, pspec);
/**
* LdDiagramSymbol:rotation:
*
* Rotation of this symbol.
*/
pspec = g_param_spec_int ("rotation", "Rotation",
"Rotation of this symbol.",
0, 3, 0, G_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_ROTATION, pspec);
} }
static void static void
@ -70,6 +81,7 @@ ld_diagram_symbol_get_property (GObject *object, guint property_id,
switch (property_id) switch (property_id)
{ {
case PROP_CLASS: case PROP_CLASS:
case PROP_ROTATION:
ld_diagram_object_get_data_for_param (self, value, pspec); ld_diagram_object_get_data_for_param (self, value, pspec);
break; break;
default: default:
@ -87,6 +99,7 @@ ld_diagram_symbol_set_property (GObject *object, guint property_id,
switch (property_id) switch (property_id)
{ {
case PROP_CLASS: case PROP_CLASS:
case PROP_ROTATION:
ld_diagram_object_set_data_for_param (self, value, pspec); ld_diagram_object_set_data_for_param (self, value, pspec);
break; break;
default: default:
@ -139,3 +152,33 @@ ld_diagram_symbol_set_class (LdDiagramSymbol *self, const gchar *klass)
g_return_if_fail (LD_IS_DIAGRAM_SYMBOL (self)); g_return_if_fail (LD_IS_DIAGRAM_SYMBOL (self));
g_object_set (self, "class", klass, NULL); g_object_set (self, "class", klass, NULL);
} }
/**
* ld_diagram_symbol_get_rotation:
* @self: an #LdDiagramSymbol object.
*
* Return value: rotation of the symbol.
*/
gint
ld_diagram_symbol_get_rotation (LdDiagramSymbol *self)
{
gint rotation;
g_return_val_if_fail (LD_IS_DIAGRAM_SYMBOL (self), 0);
g_object_get (self, "rotation", &rotation, NULL);
return rotation;
}
/**
* ld_diagram_symbol_set_rotation:
* @self: an #LdDiagramSymbol object.
* @rotation: the rotation.
*
* Set rotation of the symbol.
*/
void
ld_diagram_symbol_set_rotation (LdDiagramSymbol *self, gint rotation)
{
g_return_if_fail (LD_IS_DIAGRAM_SYMBOL (self));
g_object_set (self, "rotation", rotation, NULL);
}

View File

@ -50,11 +50,21 @@ struct _LdDiagramSymbolClass
}; };
enum
{
LD_DIAGRAM_SYMBOL_ROTATION_0,
LD_DIAGRAM_SYMBOL_ROTATION_90,
LD_DIAGRAM_SYMBOL_ROTATION_180,
LD_DIAGRAM_SYMBOL_ROTATION_270
};
GType ld_diagram_symbol_get_type (void) G_GNUC_CONST; GType ld_diagram_symbol_get_type (void) G_GNUC_CONST;
LdDiagramSymbol *ld_diagram_symbol_new (JsonObject *storage); LdDiagramSymbol *ld_diagram_symbol_new (JsonObject *storage);
gchar *ld_diagram_symbol_get_class (LdDiagramSymbol *self); gchar *ld_diagram_symbol_get_class (LdDiagramSymbol *self);
void ld_diagram_symbol_set_class (LdDiagramSymbol *self, const gchar *klass); void ld_diagram_symbol_set_class (LdDiagramSymbol *self, const gchar *klass);
gint ld_diagram_symbol_get_rotation (LdDiagramSymbol *self);
void ld_diagram_symbol_set_rotation (LdDiagramSymbol *self, gint rotation);
G_END_DECLS G_END_DECLS