// Event handler for a "floating" group of objects. int sheet_item_floating_event (Sheet *sheet, const GdkEvent *event) { SheetPriv *priv; GList *list; static Coords pos; static int keep = 0; // Remember the last position of the mouse cursor. static double last_x, last_y; // Mouse cursor position in window coordinates, snapped to the grid spacing. double snapped_x, snapped_y; // Move the selected item(s) by this movement. double dx, dy; g_return_val_if_fail (sheet != NULL, FALSE); g_return_val_if_fail (IS_SHEET (sheet), FALSE); g_return_val_if_fail (sheet->priv->floating_objects != NULL, FALSE); priv = sheet->priv; switch (event->type) { case GDK_BUTTON_RELEASE: g_signal_stop_emission_by_name (sheet, "event"); break; case GDK_BUTTON_PRESS: if (sheet->state != SHEET_STATE_FLOAT) return TRUE; switch (event->button.button) { case 2: case 4: case 5: return FALSE; case 1: // do not free the floating items, but use them like a stamp keep = event->button.state & GDK_CONTROL_MASK; // Continue adding if CTRL is pressed if (!keep) { sheet->state = SHEET_STATE_NONE; g_signal_stop_emission_by_name (sheet, "event"); if (g_signal_handler_is_connected (sheet, sheet->priv->float_handler_id)) g_signal_handler_disconnect (sheet, sheet->priv->float_handler_id); sheet->priv->float_handler_id = 0; } // Get pointer position in canvas coordinates sheet_get_pointer (sheet, &pos.x, &pos.y); for (list = priv->floating_objects; list; list = list->next) { SheetItem *floating_item; ItemData *floating_data; // Create a real item. floating_item = list->data; if (!keep) { floating_data = sheet_item_get_data (floating_item); g_object_set (floating_item, "visibility", GOO_CANVAS_ITEM_INVISIBLE, NULL); } else { floating_data = item_data_clone (sheet_item_get_data (floating_item)); } g_object_ref (G_OBJECT (floating_data)); item_data_set_pos (floating_data, &pos); schematic_add_item (schematic_view_get_schematic_from_sheet (sheet), floating_data); if (!keep) g_object_unref (G_OBJECT (floating_item)); } if (keep) { g_object_set (G_OBJECT (sheet->priv->floating_group), "x", pos.x, "y", pos.y, NULL); } else { g_list_free (sheet->priv->floating_objects); sheet->priv->floating_objects = NULL; } pos.x = 0.0; pos.y = 0.0; break; case 3: // Cancel the "float-placement" for button-3 clicks. g_signal_stop_emission_by_name (sheet, "event"); sheet_item_cancel_floating (sheet); break; } break; case GDK_2BUTTON_PRESS: case GDK_3BUTTON_PRESS: g_signal_stop_emission_by_name (sheet, "event"); return TRUE; case GDK_MOTION_NOTIFY: if (sheet->state != SHEET_STATE_FLOAT && sheet->state != SHEET_STATE_FLOAT_START) return FALSE; g_signal_stop_emission_by_name (sheet, "event"); if (sheet->state == SHEET_STATE_FLOAT_START) { sheet->state = SHEET_STATE_FLOAT; // Reparent the selected objects so that we can move them // efficiently. for (list = priv->floating_objects; list; list = list->next) { sheet_item_reparent (SHEET_ITEM (list->data), priv->floating_group); // Set the floating item visible g_object_set (G_OBJECT (list->data), "visibility", GOO_CANVAS_ITEM_VISIBLE, NULL); } last_x = 0.0; last_y = 0.0; } // Get pointer position independantly of the zoom sheet_get_pointer (sheet, &snapped_x, &snapped_y); // Calculate which amount to move the selected objects by. dx = snapped_x - last_x; dy = snapped_y - last_y; last_x = snapped_x; last_y = snapped_y; for (list = priv->floating_objects; list; list = list->next) { goo_canvas_item_translate (GOO_CANVAS_ITEM (list->data), dx, dy); } g_list_free_full (list, g_object_unref); break; case GDK_KEY_PRESS: switch (event->key.keyval) { case GDK_KEY_r: case GDK_KEY_R: sheet_rotate_ghosts (sheet); { gdouble x, y; GooCanvasBounds bounds; sheet_get_pointer (sheet, &x, &y); // Center the objects around the mouse pointer. goo_canvas_item_get_bounds ( GOO_CANVAS_ITEM (priv->floating_group), &bounds); snapped_x = x - (bounds.x1 + bounds.x2) / 2; snapped_y = y - (bounds.y1 + bounds.y2) / 2; snap_to_grid (sheet->grid, &snapped_x, &snapped_y); goo_canvas_item_translate ( GOO_CANVAS_ITEM (priv->floating_group), snapped_x, snapped_y); last_x = snapped_x; last_y = snapped_y; } break; default: return FALSE; } default: return FALSE; } return TRUE; }
// Event handler for a "floating" group of objects. int sheet_item_floating_event (Sheet *sheet, const GdkEvent *event) { SheetPriv *priv; GList *list; static gboolean keep = FALSE; // Remember the start position of the mouse cursor. static Coords last = {0., 0.}; // Mouse cursor position in window coordinates, snapped to the grid spacing. static Coords snapped = {0., 0.}; // Move the selected item(s) by this movement. Coords delta = {0., 0.}; g_return_val_if_fail (sheet != NULL, FALSE); g_return_val_if_fail (IS_SHEET (sheet), FALSE); g_return_val_if_fail (sheet->priv->floating_objects != NULL, FALSE); priv = sheet->priv; switch (event->type) { case GDK_BUTTON_RELEASE: g_signal_stop_emission_by_name (sheet, "event"); break; case GDK_BUTTON_PRESS: if (sheet->state != SHEET_STATE_FLOAT) return TRUE; switch (event->button.button) { case 2: case 4: case 5: return FALSE; case 1: // do not free the floating items, but use them like a stamp keep = event->button.state & GDK_CONTROL_MASK; // Continue adding if CTRL is pressed if (!keep) { sheet->state = SHEET_STATE_NONE; g_signal_stop_emission_by_name (sheet, "event"); if (g_signal_handler_is_connected (sheet, sheet->priv->float_handler_id)) g_signal_handler_disconnect (sheet, sheet->priv->float_handler_id); sheet->priv->float_handler_id = 0; } // FIXME assert that `Coords current` has been set by now! for (list = priv->floating_objects; list; list = list->next) { SheetItem *floating_item; ItemData *floating_data; // Create a real item. floating_item = list->data; if (!keep) { floating_data = sheet_item_get_data (floating_item); g_object_set (floating_item, "visibility", GOO_CANVAS_ITEM_INVISIBLE, NULL); } else { // FIXME the bounding box of the clone is wrong floating_data = item_data_clone (sheet_item_get_data (floating_item)); } g_object_ref (G_OBJECT (floating_data)); NG_DEBUG ("Item Data Pos will be %lf %lf", snapped.x, snapped.y) item_data_set_pos (floating_data, &snapped); item_data_snap (floating_data, sheet->grid); schematic_add_item (schematic_view_get_schematic_from_sheet (sheet), floating_data); if (!keep) g_object_unref (G_OBJECT (floating_item)); } if (keep) { g_object_set (G_OBJECT (priv->floating_group), "x", snapped.x, "y", snapped.y, NULL); } else { g_list_free (priv->floating_objects); priv->floating_objects = NULL; } break; case 3: // Cancel the "float-placement" for button-3 clicks. g_signal_stop_emission_by_name (sheet, "event"); sheet_item_cancel_floating (sheet); break; } break; case GDK_2BUTTON_PRESS: case GDK_3BUTTON_PRESS: g_signal_stop_emission_by_name (sheet, "event"); return TRUE; case GDK_MOTION_NOTIFY: // keep track of the position, as `sheet_get_pointer*()` does not work // in other events than MOTION_NOTIFY #if 0 { Coords tmp; last = current; if (sheet_get_pointer (sheet, &tmp.x, &tmp.y)) { snapped_current = current = tmp; snap_to_grid (sheet->grid, &snapped_current.x, &snapped_current.y); } } #endif if (sheet->state != SHEET_STATE_FLOAT && sheet->state != SHEET_STATE_FLOAT_START) return FALSE; g_signal_stop_emission_by_name (sheet, "event"); // Get pointer position independantly of the zoom if (sheet->state == SHEET_STATE_FLOAT_START) { sheet->state = SHEET_STATE_FLOAT; last.x = last.y = 0.; // Reparent the selected objects so that we can move them // efficiently. for (list = priv->floating_objects; list; list = list->next) { sheet_item_reparent (SHEET_ITEM (list->data), priv->floating_group); // Set the floating item visible g_object_set (G_OBJECT (list->data), "visibility", GOO_CANVAS_ITEM_VISIBLE, NULL); } #if 0 GooCanvasBounds box; goo_canvas_item_get_bounds (priv->floating_group, &box); #endif NG_DEBUG ("\n\n\nFLOAT ### START\n\n\n\n"); } sheet_get_pointer_snapped (sheet, &snapped.x, &snapped.y); delta = coords_sub (&snapped, &last); NG_DEBUG ("drag floating current sx=%lf sy=%lf \n", snapped.x, snapped.y); NG_DEBUG ("drag floating last lx=%lf ly=%lf \n", last.x, last.y); NG_DEBUG ("drag floating delta -> dx=%lf dy=%lf \n", delta.x, delta.y); #if !FIXME_INCREMENTAL_MOVMENT_DOES_NOT_WORK last = snapped; #else goo_canvas_item_set_transform (GOO_CANVAS_ITEM (priv->floating_group), NULL); #endif goo_canvas_item_translate (GOO_CANVAS_ITEM (priv->floating_group), delta.x, delta.y); break; case GDK_KEY_PRESS: switch (event->key.keyval) { case GDK_KEY_r: case GDK_KEY_R: { Coords bbdelta; GooCanvasBounds bounds; // Center the objects around the mouse pointer. goo_canvas_item_get_bounds (GOO_CANVAS_ITEM (priv->floating_group), &bounds); bbdelta.x = (bounds.x2 - bounds.x1) / 2.; bbdelta.y = (bounds.y2 - bounds.y1) / 2.; sheet_rotate_ghosts (sheet); // Center the objects around the mouse pointer. goo_canvas_item_get_bounds (GOO_CANVAS_ITEM (priv->floating_group), &bounds); bbdelta.x -= (bounds.x2 - bounds.x1) / 2.; bbdelta.y -= (bounds.y2 - bounds.y1) / 2.; snap_to_grid (sheet->grid, &bbdelta.x, &bbdelta.y); goo_canvas_item_translate (GOO_CANVAS_ITEM (priv->floating_group), bbdelta.x, bbdelta.y); } break; default: return FALSE; } default: return FALSE; } return TRUE; }