diff options
author | Ruben Undheim <ruben.undheim@gmail.com> | 2018-07-13 06:17:58 +0000 |
---|---|---|
committer | Ruben Undheim <ruben.undheim@gmail.com> | 2018-07-13 06:17:58 +0000 |
commit | 9e0bd16a997e55d6b9c2e80734ea8e61794c7602 (patch) | |
tree | d73377e0368b0c730d5a14019b1eee53897505bf /src/model/item-data.c | |
parent | e1fffcb07ce0d8b0db9e0b4b5e1e0c1128197af5 (diff) |
New upstream version 0.84.22
Diffstat (limited to 'src/model/item-data.c')
-rw-r--r-- | src/model/item-data.c | 403 |
1 files changed, 193 insertions, 210 deletions
diff --git a/src/model/item-data.c b/src/model/item-data.c index 382a012..c9391d4 100644 --- a/src/model/item-data.c +++ b/src/model/item-data.c @@ -8,12 +8,14 @@ * Ricardo Markiewicz <rmarkie@fi.uba.ar> * Andres de Barbara <adebarbara@fi.uba.ar> * Marc Lorber <lorber.marc@wanadoo.fr> + * Bernhard Schuster <bernhard@ahoi.io> * - * Web page: https://github.com/marc-lorber/oregano + * Web page: https://ahoi.io/project/oregano * * Copyright (C) 1999-2001 Richard Hult * Copyright (C) 2003,2006 Ricardo Markiewicz * Copyright (C) 2009-2012 Marc Lorber + * Copyright (C) 2013 Bernhard Schuster * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -27,80 +29,87 @@ * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. */ -#include "goocanvas.h" +#include <glib.h> +#include <goocanvas.h> #include "item-data.h" #include "node-store.h" -#define NG_DEBUG(s) if (0) g_print ("%s\n", s) +#include "debug.h" static void item_data_class_init (ItemDataClass *klass); static void item_data_init (ItemData *item_data); -static void item_data_set_gproperty (GObject *object, guint prop_id, - const GValue *value, GParamSpec *spec); -static void item_data_get_gproperty (GObject *object, guint prop_id, - GValue *value, GParamSpec *spec); +static void item_data_set_gproperty (GObject *object, guint prop_id, const GValue *value, + GParamSpec *spec); +static void item_data_get_gproperty (GObject *object, guint prop_id, GValue *value, + GParamSpec *spec); static void item_data_copy (ItemData *dest, ItemData *src); -static gboolean emit_moved_signal_when_handler_connected (gpointer data); -enum { - ARG_0, - ARG_STORE, - ARG_POS -}; +enum { ARG_0, ARG_STORE, ARG_POS }; enum { MOVED, ROTATED, FLIPPED, + CHANGED, // used to notify the view to reset and recalc the transformation HIGHLIGHT, LAST_SIGNAL }; -struct _ItemDataPriv { +struct _ItemDataPriv +{ NodeStore *store; - SheetPos pos; - // Bounding box. + + // modificator matrices + cairo_matrix_t translate; + cairo_matrix_t rotate; + cairo_matrix_t flip; + + // Bounding box GooCanvasBounds bounds; }; -// Structure defined to cover exchange between g_timeout_add and the -// function in charge to emit the moved signal only once the handler -// has been connected. -typedef struct { - ItemData *item_data; - SheetPos delta; -} SignalStruct; +G_DEFINE_TYPE (ItemData, item_data, G_TYPE_OBJECT); -G_DEFINE_TYPE (ItemData, item_data, G_TYPE_OBJECT) +static guint item_data_signals[LAST_SIGNAL] = {0}; -static guint item_data_signals [LAST_SIGNAL] = { 0 }; +static void item_data_init (ItemData *item_data) +{ + ItemDataPriv *priv; + + priv = g_slice_new0 (ItemDataPriv); + + priv->bounds.x1 = priv->bounds.x2 = priv->bounds.y1 = priv->bounds.y2 = 0; -static void -item_data_dispose (GObject *object) + cairo_matrix_init_identity (&(priv->translate)); + cairo_matrix_init_identity (&(priv->rotate)); + cairo_matrix_init_identity (&(priv->flip)); + + item_data->priv = priv; +} + +static void item_data_dispose (GObject *object) { + ItemDataPriv *priv = ITEM_DATA (object)->priv; // Remove the item from the sheet node store if there. - if (ITEM_DATA (object)->priv->store) { + if (priv->store) { item_data_unregister (ITEM_DATA (object)); } - + g_slice_free (ItemDataPriv, priv); G_OBJECT_CLASS (item_data_parent_class)->dispose (object); } - -static void -item_data_finalize (GObject *object) +static void item_data_finalize (GObject *object) { g_return_if_fail (object != NULL); G_OBJECT_CLASS (item_data_parent_class)->finalize (object); } -static void -item_data_class_init (ItemDataClass *klass) +static void item_data_class_init (ItemDataClass *klass) { GObjectClass *object_class; @@ -108,63 +117,41 @@ item_data_class_init (ItemDataClass *klass) object_class = G_OBJECT_CLASS (klass); - // This assignment must be performed before the call + // This assignment must be performed before the call // to g_object_class_install_property object_class->set_property = item_data_set_gproperty; object_class->get_property = item_data_get_gproperty; - g_object_class_install_property (object_class, ARG_STORE, - g_param_spec_pointer ("store", "ItemData::store", - "the store data", G_PARAM_READWRITE)); + g_object_class_install_property ( + object_class, ARG_STORE, + g_param_spec_pointer ("store", "ItemData::store", "the store data", G_PARAM_READWRITE)); - g_object_class_install_property (object_class, ARG_POS, - g_param_spec_pointer ("pos", "ItemData::pos", - "the pos data", G_PARAM_READWRITE)); + g_object_class_install_property ( + object_class, ARG_POS, + g_param_spec_pointer ("pos", "ItemData::pos", "the pos data", G_PARAM_READWRITE)); object_class->dispose = item_data_dispose; object_class->finalize = item_data_finalize; - item_data_signals [MOVED] = g_signal_new ("moved", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (ItemDataClass, moved), - NULL, - NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, - 1, - G_TYPE_POINTER); - - item_data_signals [ROTATED] = g_signal_new ("rotated", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, - NULL, - g_cclosure_marshal_VOID__INT, - G_TYPE_NONE, - 1, - G_TYPE_INT); - - item_data_signals [FLIPPED] = g_signal_new ("flipped", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, - NULL, - g_cclosure_marshal_VOID__INT, - G_TYPE_NONE, - 1, - G_TYPE_INT); - - item_data_signals [HIGHLIGHT] = g_signal_new ("highlight", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, - NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, - 0); + item_data_signals[MOVED] = + g_signal_new ("moved", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ItemDataClass, moved), NULL, NULL, + g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); + + item_data_signals[ROTATED] = + g_signal_new ("rotated", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_FIRST, 0, NULL, + NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); + + item_data_signals[FLIPPED] = + g_signal_new ("flipped", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_FIRST, 0, NULL, + NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); + + item_data_signals[CHANGED] = + g_signal_new ("changed", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_FIRST, 0, NULL, + NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + item_data_signals[HIGHLIGHT] = + g_signal_new ("highlight", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_FIRST, 0, NULL, + NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); // Methods. klass->clone = NULL; @@ -173,38 +160,27 @@ item_data_class_init (ItemDataClass *klass) klass->flip = NULL; klass->reg = NULL; klass->unreg = NULL; + klass->changed = NULL; // Signals. klass->moved = NULL; } -static void -item_data_init (ItemData *item_data) -{ - ItemDataPriv *priv; - - priv = g_new0 (ItemDataPriv, 1); - - priv->pos.x = 0; - priv->pos.y = 0; - priv->bounds.x1 = priv->bounds.x2 = priv->bounds.y1 = priv->bounds.y2 = 0; +//////////////////////////////////////////////////////////////////////////////// +// END BOILER PLATE +//////////////////////////////////////////////////////////////////////////////// - item_data->priv = priv; -} - -ItemData * -item_data_new (void) +ItemData *item_data_new (void) { ItemData *item_data; - item_data = ITEM_DATA (g_object_new (item_data_get_type(), NULL)); + item_data = ITEM_DATA (g_object_new (item_data_get_type (), NULL)); return item_data; } -static void -item_data_set_gproperty (GObject *object, guint prop_id, const GValue *value, - GParamSpec *spec) +static void item_data_set_gproperty (GObject *object, guint prop_id, const GValue *value, + GParamSpec *spec) { ItemData *item_data = ITEM_DATA (object); @@ -213,13 +189,12 @@ item_data_set_gproperty (GObject *object, guint prop_id, const GValue *value, item_data->priv->store = g_value_get_pointer (value); break; default: - break; + G_OBJECT_WARN_INVALID_PROPERTY_ID (item_data, prop_id, spec); } } -static void -item_data_get_gproperty (GObject *object, guint prop_id, GValue *value, - GParamSpec *spec) +static void item_data_get_gproperty (GObject *object, guint prop_id, GValue *value, + GParamSpec *spec) { ItemData *item_data = ITEM_DATA (object); @@ -232,72 +207,48 @@ item_data_get_gproperty (GObject *object, guint prop_id, GValue *value, } } -void -item_data_get_pos (ItemData *item_data, SheetPos *pos) +/** + * returns the top left corner of the item + */ +void item_data_get_pos (ItemData *item_data, Coords *pos) { g_return_if_fail (item_data != NULL); g_return_if_fail (IS_ITEM_DATA (item_data)); g_return_if_fail (pos != NULL); - - *pos = item_data->priv->pos; + ItemDataPriv *priv; + priv = item_data->priv; + pos->x = priv->translate.x0; + pos->y = priv->translate.y0; } -void -item_data_set_pos (ItemData *item_data, SheetPos *pos) +void item_data_set_pos (ItemData *item_data, Coords *pos) { ItemDataPriv *priv; - SheetPos delta; - SignalStruct *signal_struct; + gboolean handler_connected; - g_return_if_fail (pos != NULL); - g_return_if_fail (item_data != NULL); + g_return_if_fail (pos); + g_return_if_fail (item_data); g_return_if_fail (IS_ITEM_DATA (item_data)); - if (pos == NULL) - return; - priv = item_data->priv; - priv->pos.x = pos->x; - priv->pos.y = pos->y; - - delta.x = pos->x; - delta.y = pos->y; - - signal_struct = g_new0 (SignalStruct, 1); - signal_struct->item_data = item_data; - signal_struct->delta = delta; - g_timeout_add (10, - (gpointer) emit_moved_signal_when_handler_connected, - (gpointer) signal_struct); -} -static gboolean -emit_moved_signal_when_handler_connected (gpointer data) -{ - gboolean handler_connected; - SignalStruct *signal_struct = (SignalStruct *) data; - SheetPos delta; - ItemData *item_data; + cairo_matrix_init_translate (&(priv->translate), pos->x, pos->y); - item_data = signal_struct->item_data; - delta.x = signal_struct->delta.x; - delta.y = signal_struct->delta.y; - - handler_connected = g_signal_handler_is_connected (G_OBJECT (item_data), - item_data->moved_handler_id); + handler_connected = + g_signal_handler_is_connected (G_OBJECT (item_data), item_data->moved_handler_id); if (handler_connected) { - g_signal_emit_by_name (G_OBJECT (item_data), - "moved", &delta); + g_signal_emit_by_name (G_OBJECT (item_data), "moved", pos); + } + handler_connected = + g_signal_handler_is_connected (G_OBJECT (item_data), item_data->changed_handler_id); + if (handler_connected) { + g_signal_emit_by_name (G_OBJECT (item_data), "changed"); } - - return !handler_connected; } -void -item_data_move (ItemData *item_data, SheetPos *delta) +void item_data_move (ItemData *item_data, const Coords *delta) { ItemDataPriv *priv; - SignalStruct *signal_struct; g_return_if_fail (item_data != NULL); g_return_if_fail (IS_ITEM_DATA (item_data)); @@ -305,22 +256,17 @@ item_data_move (ItemData *item_data, SheetPos *delta) if (delta == NULL) return; + if (fabs (delta->x) < 1e-2 && fabs (delta->y) < 1e-2) + return; + priv = item_data->priv; - priv->pos.x += delta->x; - priv->pos.y += delta->y; - delta->x = priv->pos.x; - delta->y = priv->pos.y; - - signal_struct = g_new0 (SignalStruct, 1); - signal_struct->item_data = item_data; - signal_struct->delta = (* delta); - g_timeout_add (10, - (gpointer) emit_moved_signal_when_handler_connected, - (gpointer) signal_struct); + cairo_matrix_translate (&(priv->translate), delta->x, delta->y); + + g_signal_emit_by_name (G_OBJECT (item_data), "changed"); } -gpointer // NodeStore * -item_data_get_store (ItemData *item_data) +// NodeStore * +gpointer item_data_get_store (ItemData *item_data) { g_return_val_if_fail (item_data != NULL, NULL); g_return_val_if_fail (IS_ITEM_DATA (item_data), NULL); @@ -328,8 +274,7 @@ item_data_get_store (ItemData *item_data) return item_data->priv->store; } -ItemData * -item_data_clone (ItemData *src) +ItemData *item_data_clone (ItemData *src) { ItemDataClass *id_class; @@ -343,20 +288,20 @@ item_data_clone (ItemData *src) return id_class->clone (src); } -static void -item_data_copy (ItemData *dest, ItemData *src) +static void item_data_copy (ItemData *dest, ItemData *src) { g_return_if_fail (dest != NULL); g_return_if_fail (IS_ITEM_DATA (dest)); g_return_if_fail (src != NULL); g_return_if_fail (IS_ITEM_DATA (src)); - dest->priv->pos = src->priv->pos; + dest->priv->translate = src->priv->translate; + dest->priv->rotate = src->priv->rotate; + dest->priv->flip = src->priv->flip; dest->priv->store = NULL; } -void -item_data_get_relative_bbox (ItemData *data, SheetPos *p1, SheetPos *p2) +void item_data_get_relative_bbox (ItemData *data, Coords *p1, Coords *p2) { g_return_if_fail (data != NULL); g_return_if_fail (IS_ITEM_DATA (data)); @@ -372,27 +317,28 @@ item_data_get_relative_bbox (ItemData *data, SheetPos *p1, SheetPos *p2) } } -void -item_data_get_absolute_bbox (ItemData *data, SheetPos *p1, SheetPos *p2) +void item_data_get_absolute_bbox (ItemData *data, Coords *p1, Coords *p2) { g_return_if_fail (data != NULL); g_return_if_fail (IS_ITEM_DATA (data)); + ItemDataPriv *priv; + item_data_get_relative_bbox (data, p1, p2); + priv = data->priv; if (p1) { - p1->x += data->priv->pos.x; - p1->y += data->priv->pos.y; + p1->x += priv->translate.x0; + p1->y += priv->translate.y0; } if (p2) { - p2->x += data->priv->pos.x; - p2->y += data->priv->pos.y; + p2->x += priv->translate.x0; + p2->y += priv->translate.y0; } } -void -item_data_set_relative_bbox (ItemData *data, SheetPos *p1, SheetPos *p2) +void item_data_set_relative_bbox (ItemData *data, Coords *p1, Coords *p2) { g_return_if_fail (data != NULL); g_return_if_fail (IS_ITEM_DATA (data)); @@ -408,20 +354,20 @@ item_data_set_relative_bbox (ItemData *data, SheetPos *p1, SheetPos *p2) } } -void -item_data_list_get_absolute_bbox (GList *item_data_list, SheetPos *p1, - SheetPos *p2) +void item_data_list_get_absolute_bbox (GList *item_data_list, Coords *p1, Coords *p2) { - GList *list; - SheetPos b1, b2; + GList *iter; + Coords b1, b2; if (item_data_list == NULL) return; item_data_get_absolute_bbox (item_data_list->data, p1, p2); - for (list = item_data_list; list; list = list->next) { - item_data_get_absolute_bbox (list->data, &b1, &b2); + for (iter = item_data_list; iter; iter = iter->next) { + if (G_UNLIKELY (iter->data == NULL)) + continue; + item_data_get_absolute_bbox (iter->data, &b1, &b2); if (p1) { p1->x = MIN (p1->x, b1.x); @@ -433,11 +379,9 @@ item_data_list_get_absolute_bbox (GList *item_data_list, SheetPos *p1, p2->y = MAX (p2->y, b2.y); } } - g_list_free_full (list, g_object_unref); } -void -item_data_rotate (ItemData *data, int angle, SheetPos *center) +void item_data_rotate (ItemData *data, int angle, Coords *center) { ItemDataClass *id_class; @@ -450,8 +394,7 @@ item_data_rotate (ItemData *data, int angle, SheetPos *center) } } -void -item_data_flip (ItemData *data, gboolean horizontal, SheetPos *center) +void item_data_flip (ItemData *data, IDFlip direction, Coords *center) { ItemDataClass *id_class; @@ -460,12 +403,11 @@ item_data_flip (ItemData *data, gboolean horizontal, SheetPos *center) id_class = ITEM_DATA_CLASS (G_OBJECT_GET_CLASS (data)); if (id_class->flip) { - id_class->flip (data, horizontal, center); + id_class->flip (data, direction, center); } } -void -item_data_unregister (ItemData *data) +void item_data_unregister (ItemData *data) { ItemDataClass *id_class; @@ -478,23 +420,21 @@ item_data_unregister (ItemData *data) } } -int -item_data_register (ItemData *data) +gboolean item_data_register (ItemData *data) { ItemDataClass *id_class; - g_return_val_if_fail (data != NULL, -1); - g_return_val_if_fail (IS_ITEM_DATA (data), -1); + g_return_val_if_fail (data != NULL, FALSE); + g_return_val_if_fail (IS_ITEM_DATA (data), FALSE); id_class = ITEM_DATA_CLASS (G_OBJECT_GET_CLASS (data)); if (id_class->reg) { return id_class->reg (data); } - return -1; + return FALSE; } -char * -item_data_get_refdes_prefix (ItemData *data) +char *item_data_get_refdes_prefix (ItemData *data) { ItemDataClass *id_class; @@ -509,8 +449,7 @@ item_data_get_refdes_prefix (ItemData *data) return NULL; } -void -item_data_set_property (ItemData *data, char *property, char *value) +void item_data_set_property (ItemData *data, char *property, char *value) { ItemDataClass *id_class; @@ -524,8 +463,7 @@ item_data_set_property (ItemData *data, char *property, char *value) } } -gboolean -item_data_has_properties (ItemData *data) +gboolean item_data_has_properties (ItemData *data) { ItemDataClass *id_class; @@ -539,8 +477,7 @@ item_data_has_properties (ItemData *data) return FALSE; } -void -item_data_print (ItemData *data, cairo_t *cr, SchematicPrintContext *ctx) +void item_data_print (ItemData *data, cairo_t *cr, SchematicPrintContext *ctx) { ItemDataClass *id_class; @@ -553,3 +490,49 @@ item_data_print (ItemData *data, cairo_t *cr, SchematicPrintContext *ctx) id_class->print (data, cr, ctx); } } + +/** + * \brief changed, forcefully emits a changed signal to recalculate the morph + *matrix + * + * @param data determines which item to refresh + * + * \note this function does _not_ request a redraw + */ +void item_data_changed (ItemData *data) +{ + ItemDataClass *id_class; + + g_return_if_fail (data != NULL); + g_return_if_fail (IS_ITEM_DATA (data)); + + id_class = ITEM_DATA_CLASS (G_OBJECT_GET_CLASS (data)); + if (id_class->changed == NULL) + return; + + return id_class->changed (data); +} + +/** + * @param data + * @returns [transfer-none] pointer to cairo matrix which only includes the + * translation + */ +cairo_matrix_t *item_data_get_translate (ItemData *data) +{ + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (IS_ITEM_DATA (data), NULL); + return &(data->priv->translate); +} + +/** + * @param data + * @returns [transfer-none] pointer to cairo matrix which only includes the + * rotation + */ +cairo_matrix_t *item_data_get_rotate (ItemData *data) +{ + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (IS_ITEM_DATA (data), NULL); + return &(data->priv->rotate); +} |