PartItem * part_item_canvas_new (Sheet *sheet, Part *part) { PartItem *part_item; PartItemPriv *priv; GooCanvasItem *item; ItemData *item_data; g_return_val_if_fail (sheet != NULL, NULL); g_return_val_if_fail (IS_SHEET (sheet), NULL); g_return_val_if_fail (part != NULL, NULL); g_return_val_if_fail (IS_PART (part), NULL); item = g_object_new (TYPE_PART_ITEM, NULL); g_object_set (item, "parent", sheet->object_group, NULL); part_item = PART_ITEM (item); g_object_set (part_item, "data", part, NULL); priv = part_item->priv; priv->label_group = GOO_CANVAS_ITEM (goo_canvas_group_new ( GOO_CANVAS_ITEM (part_item), "width", -1.0, "height", -1.0, NULL)); g_object_unref (item); priv->node_group = GOO_CANVAS_ITEM (goo_canvas_group_new ( GOO_CANVAS_ITEM (part_item), NULL)); g_object_set (GOO_CANVAS_ITEM (priv->node_group), "visibility", GOO_CANVAS_ITEM_INVISIBLE, NULL); item_data = ITEM_DATA (part); item_data->rotated_handler_id = g_signal_connect_object (G_OBJECT (part), "rotated", G_CALLBACK (part_rotated_callback), G_OBJECT (part_item), 0); item_data->flipped_handler_id = g_signal_connect_object (G_OBJECT (part), "flipped", G_CALLBACK (part_flipped_callback), G_OBJECT (part_item), 0); item_data->moved_handler_id = g_signal_connect_object (G_OBJECT (part), "moved", G_CALLBACK (part_moved_callback), G_OBJECT (part_item), 0); item_data->changed_handler_id = g_signal_connect_object (G_OBJECT (part), "changed", G_CALLBACK (part_changed_callback), G_OBJECT (part_item), 0); return part_item; }
/** * update the node lables of all parts in the current sheet */ void sheet_update_parts (Sheet *sheet) { GList *list; g_return_if_fail (sheet != NULL); g_return_if_fail (IS_SHEET (sheet)); for (list = sheet->priv->items; list; list = list->next) { if (IS_PART_ITEM (list->data)) part_item_update_node_label (PART_ITEM (list->data)); } }
static void part_item_finalize (GObject *object) { PartItemPriv *priv; priv = PART_ITEM (object)->priv; g_slist_free (priv->label_nodes); g_slist_free (priv->label_items); g_free (priv); priv = NULL; G_OBJECT_CLASS (parent_class)->finalize (object); }
void sheet_show_node_labels (Sheet *sheet, gboolean show) { g_return_if_fail (sheet != NULL); g_return_if_fail (IS_SHEET (sheet)); GList *item = NULL; for (item = sheet->priv->items; item; item = item->next) { if (IS_PART_ITEM (item->data)) if (part_get_num_pins (PART (sheet_item_get_data (SHEET_ITEM (item->data)))) == 1) part_item_show_node_labels (PART_ITEM (item->data), show); } }
static gboolean is_in_area (SheetItem *object, Coords *p1, Coords *p2) { PartItem *item; Coords bbox_start, bbox_end; item = PART_ITEM (object); get_cached_bounds (item, &bbox_start, &bbox_end); if ((p1->x < bbox_start.x) && (p2->x > bbox_end.x) && (p1->y < bbox_start.y) && (p2->y > bbox_end.y)) { return TRUE; } return FALSE; }
static void show_labels (SheetItem *sheet_item, gboolean show) { PartItem *item; PartItemPriv *priv; g_return_if_fail (sheet_item != NULL); g_return_if_fail (IS_PART_ITEM (sheet_item)); item = PART_ITEM (sheet_item); priv = item->priv; if (show) g_object_set (priv->label_group, "visibility", GOO_CANVAS_ITEM_VISIBLE, NULL); else g_object_set (priv->label_group, "visibility", GOO_CANVAS_ITEM_INVISIBLE, NULL); }
/** * whenever the model changes, this one gets called to update the view representation * @attention this recalculates the matrix every time, this makes sure no errors stack up * @attention further reading on matrix manipulations * @attention http://www.cairographics.org/matrix_transform/ * @param data the model item, a bare C struct derived from ItemData * @param sheet_item the view item, derived from goo_canvas_group/item */ static void part_changed_callback (ItemData *data, SheetItem *sheet_item) { //TODO add static vars in order to skip the redraw if nothing changed //TODO may happen once in a while and the check is really cheap GSList *iter; GooCanvasAnchorType anchor; GooCanvasGroup *group; GooCanvasItem *canvas_item; PartItem *item; PartItemPriv *priv; Part *part; int index = 0; Coords pos; double scale_h, scale_v; // states int rotation; IDFlip flip; g_return_if_fail (sheet_item != NULL); g_return_if_fail (IS_PART_ITEM (sheet_item)); item = PART_ITEM (sheet_item); group = GOO_CANVAS_GROUP (item); part = PART (data); priv = item->priv; // init the states flip = part_get_flip (part); rotation = part_get_rotation (part); DEGSANITY (rotation); scale_h = (flip & ID_FLIP_HORIZ) ? -1. : 1.; scale_v = (flip & ID_FLIP_VERT) ? -1. : 1.; item_data_get_pos (data, &pos); // Move the canvas item and invalidate the bbox cache. goo_canvas_item_set_simple_transform (GOO_CANVAS_ITEM (sheet_item), pos.x, pos.y, 1.0, 0.0); cairo_matrix_t morph, inv; cairo_status_t done; cairo_matrix_init_rotate (&morph, DEG2RAD (rotation)); cairo_matrix_scale (&morph, scale_h, scale_v); inv = morph; done = cairo_matrix_invert (&inv); if (done != CAIRO_STATUS_SUCCESS) { g_warning ("Failed to invert matrix. This should never happen. Never!"); return; } // rotate all items in the canvas group for (index = 0; index < group->items->len; index++) { canvas_item = GOO_CANVAS_ITEM (group->items->pdata[index]); goo_canvas_item_set_transform (GOO_CANVAS_ITEM (canvas_item), &morph); } // revert the rotation of all labels and change their anchor to not overlap too badly // this assures that the text is always horizontal and properly aligned anchor = angle_to_anchor (rotation); for (iter = priv->label_items; iter; iter = iter->next) { g_object_set (iter->data, "anchor", anchor, NULL); goo_canvas_item_set_transform (iter->data, &inv); } // same for label nodes for (iter = priv->label_nodes; iter; iter = iter->next) { g_object_set (iter->data, "anchor", anchor, NULL); goo_canvas_item_set_transform (iter->data, &inv); } // Invalidate the bounding box cache. priv->cache_valid = FALSE; }
static void edit_properties (SheetItem *object) { GSList *properties; PartItem *item; Part *part; char *internal, *msg; GtkBuilder *gui; GError *error = NULL; GtkGrid *prop_grid; GtkNotebook *notebook; gint response, y = 0; gboolean has_model; gchar *model_name = NULL; g_return_if_fail (object != NULL); g_return_if_fail (IS_PART_ITEM (object)); item = PART_ITEM (object); part = PART (sheet_item_get_data (SHEET_ITEM (item))); internal = part_get_property (part, "internal"); if (internal) { if (g_ascii_strcasecmp (internal, "ground") == 0) { g_free (internal); return; } if (g_ascii_strcasecmp (internal, "point") == 0) { edit_properties_point (item); return; } } g_free (internal); if ((gui = gtk_builder_new ()) == NULL) { oregano_error (_("Could not create part properties dialog.")); return; } else gtk_builder_set_translation_domain (gui, NULL); if (gtk_builder_add_from_file (gui, OREGANO_UIDIR "/part-properties-dialog.ui", &error) <= 0) { msg = error->message; oregano_error_with_title (_("Could not create part properties dialog."), msg); g_error_free (error); return; } prop_dialog = g_new0 (PartPropDialog, 1); prop_dialog->part_item = item; prop_dialog->dialog = GTK_DIALOG (gtk_builder_get_object (gui, "part-properties-dialog")); prop_grid = GTK_GRID (gtk_builder_get_object (gui, "prop_grid")); notebook = GTK_NOTEBOOK (gtk_builder_get_object (gui, "notebook")); g_signal_connect (prop_dialog->dialog, "destroy", G_CALLBACK (prop_dialog_destroy), prop_dialog); prop_dialog->widgets = NULL; has_model = FALSE; for (properties = part_get_properties (part); properties; properties = properties->next) { Property *prop; prop = properties->data; if (prop->name) { GtkWidget *entry; GtkWidget *label; gchar *temp=NULL; if (!g_ascii_strcasecmp (prop->name, "internal")) continue; if (!g_ascii_strcasecmp (prop->name, "model")) { has_model = TRUE; model_name = g_strdup (prop->value); } // Find the Refdes and replace by their real value temp = prop->name; if (!g_ascii_strcasecmp (temp, "Refdes")) temp = _("Designation"); if (!g_ascii_strcasecmp (temp, "Template")) temp = _("Template"); if (!g_ascii_strcasecmp (temp, "Res")) temp = _("Resistor"); if (!g_ascii_strcasecmp (temp, "Cap")) temp = _("Capacitor"); if (!g_ascii_strcasecmp (temp, "Ind")) temp = _("Inductor"); label = gtk_label_new (temp); entry = gtk_entry_new (); gtk_entry_set_text (GTK_ENTRY (entry), prop->value); g_object_set_data (G_OBJECT (entry), "user", g_strdup (prop->name)); gtk_grid_attach (prop_grid, label, 0,y, 1,1); gtk_grid_attach (prop_grid, entry, 1,y, 1,1); y++; gtk_widget_show (label); gtk_widget_show (entry); prop_dialog->widgets = g_list_prepend (prop_dialog->widgets, entry); } } if (!has_model) { gtk_notebook_remove_page (notebook, 1); } else { GtkTextBuffer *txtbuffer; GtkTextView *txtmodel; gchar *filename, *str; GError *read_error = NULL; txtmodel = GTK_TEXT_VIEW (gtk_builder_get_object (gui, "txtmodel")); txtbuffer = gtk_text_buffer_new (NULL); filename = g_strdup_printf ("%s/%s.model", OREGANO_MODELDIR, model_name); if (g_file_get_contents (filename, &str, NULL, &read_error)) { gtk_text_buffer_set_text (txtbuffer, str, -1); g_free (str); } else { gtk_text_buffer_set_text (txtbuffer, read_error->message, -1); g_error_free (read_error); } g_free (filename); g_free (model_name); gtk_text_view_set_buffer (txtmodel, txtbuffer); } gtk_dialog_set_default_response (prop_dialog->dialog, 1); response = gtk_dialog_run (prop_dialog->dialog); prop_dialog_response (GTK_WIDGET (prop_dialog->dialog), response, prop_dialog); g_slist_free_full (properties, g_object_unref); gtk_widget_destroy (GTK_WIDGET (prop_dialog->dialog)); }