Ejemplo n.º 1
0
static void
rotate_items (Sheet *sheet, GList *items, gint angle)
{
	GList *list, *item_data_list;
	Coords center, b1, b2;

	item_data_list = NULL;
	for (list = items; list; list = list->next) {
		item_data_list = g_list_prepend (item_data_list,
			sheet_item_get_data (list->data));
	}

	item_data_list_get_absolute_bbox (item_data_list, &b1, &b2);

	center = coords_average(&b1, &b2);

	snap_to_grid (sheet->grid, &center.x, &center.y);

	for (list = item_data_list; list; list = list->next) {
		ItemData *item_data = list->data;
		if (item_data==NULL)
			continue;

		if (sheet->state == SHEET_STATE_NONE)
			item_data_unregister (item_data);

		item_data_rotate (item_data, angle, &center);

		if (sheet->state == SHEET_STATE_NONE)
			item_data_register (item_data);
	}

	g_list_free (item_data_list);
}
Ejemplo n.º 2
0
static void
rotate_items (Sheet *sheet, GList *items)
{
	GList *list, *item_data_list;
	Coords center, b1, b2;

	item_data_list = NULL;
	for (list = items; list; list = list->next) {
		item_data_list = g_list_prepend (item_data_list,
			sheet_item_get_data (list->data));
	}

	item_data_list_get_absolute_bbox (item_data_list, &b1, &b2);

	center.x = (b2.x + b1.x) / 2.;
	center.y = (b2.y + b1.y) / 2.;

	snap_to_grid (sheet->grid, &center.x, &center.y);

	for (list = item_data_list; list; list = list->next) {
		ItemData *item_data = list->data;

		if (sheet->state == SHEET_STATE_NONE)
			item_data_unregister (item_data);

		item_data_rotate (item_data, 90, &center);

		if (sheet->state == SHEET_STATE_NONE)
			item_data_register (item_data);
	}

	g_list_free (item_data_list);
}
Ejemplo n.º 3
0
/**
 * \brief snaps to the grid, updates the model if snapping was necessary
 *
 * \attention this will cause a loop cycle of "changed" signals
 *            until no more snapping is necessary
 *
 * @param item_data
 * @param grid
 */
void item_data_snap (ItemData *item_data, Grid *grid)
{
	gboolean handler_connected;

	g_return_if_fail (item_data);
	g_return_if_fail (IS_ITEM_DATA (item_data));
	g_return_if_fail (grid);
	g_return_if_fail (IS_GRID (grid));

	if (snap_to_grid (grid, &(item_data->priv->translate.x0), &(item_data->priv->translate.y0))) {

#if 1 // TODO FIXME XXX rename this to "snapped" instead of moved
		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"); // FIXME replace this by a "snapped" signal
		}
#endif
		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");
		}
	}
}
Ejemplo n.º 4
0
gboolean sheet_get_pointer_snapped (Sheet *sheet, gdouble *x, gdouble *y)
{
	if (!sheet_get_pointer_pixel (sheet, x, y))
		return FALSE;
	goo_canvas_convert_from_pixels (GOO_CANVAS (sheet), x, y);
	snap_to_grid (sheet->grid, x, y);
	return TRUE;
}
Ejemplo n.º 5
0
void		
sheet_get_pointer (Sheet *sheet, gdouble *x, gdouble *y)
{
	GtkWidget        *widget;
	GtkAdjustment    *hadjustment;
	GtkAdjustment    *vadjustment;
	gdouble           value, x1, y1;
	gint              _x, _y;
	GdkDeviceManager *device_manager;
    GdkDevice        *device_pointer;
    GdkRectangle      allocation;


	// gtk_widget_get_pointer (GTK_WIDGET (sheet), &_x, &_y);
	// replaced by a code copied from evince
	
    if (!gtk_widget_get_realized (GTK_WIDGET (sheet)))
    	return;
	
	device_manager = gdk_display_get_device_manager (
	                gtk_widget_get_display (GTK_WIDGET (sheet)));
    device_pointer = gdk_device_manager_get_client_pointer (device_manager);
    gdk_window_get_device_position (gtk_widget_get_window (GTK_WIDGET (sheet)),
                    device_pointer,
                    &_x, &_y, NULL);
	if (!gtk_widget_get_has_window (GTK_WIDGET (sheet)))
    	return;
	
	gtk_widget_get_allocation (GTK_WIDGET (sheet), &allocation);
	
	_x -= allocation.x;
	_y -= allocation.y;

	x1 = (gdouble) _x;
	y1 = (gdouble) _y;
	
	widget = gtk_widget_get_parent (GTK_WIDGET (sheet));
	hadjustment =  gtk_scrolled_window_get_hadjustment (
	                 GTK_SCROLLED_WINDOW (widget));
	value = gtk_adjustment_get_value (hadjustment);

	x1 += value;
	vadjustment =  gtk_scrolled_window_get_vadjustment (
	                 GTK_SCROLLED_WINDOW (widget));
	value = gtk_adjustment_get_value (vadjustment);
	y1 += value;
	*x = x1;
	*y = y1;
	goo_canvas_convert_from_pixels (GOO_CANVAS (sheet), x, y);
	snap_to_grid (sheet->grid, x, y);
}
Ejemplo n.º 6
0
static void
flip_items (Sheet *sheet, GList *items, IDFlip direction)
{
	GList *iter, *item_data_list;
	Coords center, b1, b2;
	Coords after;

	item_data_list = NULL;
	for (iter = items; iter; iter = iter->next) {
		item_data_list = g_list_prepend (item_data_list,
					sheet_item_get_data (iter->data));
	}

	item_data_list_get_absolute_bbox (item_data_list, &b1, &b2);

	// FIXME center is currently not used by item_data_flip (part.c implentation)
	center.x = (b2.x + b1.x) / 2;
	center.y = (b2.y + b1.y) / 2;

	// FIXME - registering an item after flipping it still creates an offset as the position is still 0
	for (iter = item_data_list; iter; iter = iter->next) {
		ItemData *item_data = iter->data;

		if (sheet->state == SHEET_STATE_NONE)
			item_data_unregister (item_data);

		item_data_flip (item_data, direction, &center);

		// Make sure we snap to grid.
		item_data_get_pos (item_data, &after);

		snap_to_grid (sheet->grid, &after.x, &after.y);

		item_data_set_pos (item_data, &after);

		if (sheet->state == SHEET_STATE_NONE)
			item_data_register (item_data);
	}

	g_list_free (item_data_list);
}
Ejemplo n.º 7
0
static void
flip_items (Sheet *sheet, GList *items, gboolean horizontal)
{
	GList *list, *item_data_list;
	SheetPos center, b1, b2;
	SheetPos after;

	item_data_list = NULL;
	for (list = items; list; list = list->next) {
		item_data_list = g_list_prepend (item_data_list,
					sheet_item_get_data (list->data));
	}

	item_data_list_get_absolute_bbox (item_data_list, &b1, &b2);

	center.x = (b2.x + b1.x) / 2;
	center.y = (b2.y + b1.y) / 2;

	for (list = item_data_list; list; list = list->next) {
		ItemData *item_data = list->data;

		if (sheet->state == SHEET_STATE_NONE)
			item_data_unregister (item_data);

		item_data_flip (item_data, horizontal, &center);

		// Make sure we snap to grid.
		item_data_get_pos (item_data, &after);

		snap_to_grid (sheet->grid, &after.x, &after.y);

		item_data_move (item_data, &after);

		if (sheet->state == SHEET_STATE_NONE)
			item_data_register (item_data);
	}

	g_list_free (item_data_list);
	g_list_free_full (list, g_object_unref);
}
Ejemplo n.º 8
0
void
part_browser_dnd (GtkSelectionData *selection_data, int x, int y)
{
	LibraryPart *library_part;
	Coords pos;
	DndData *data;
	Sheet *sheet;
	Part *part;

	data = (DndData *) (gtk_selection_data_get_data (selection_data));

	g_return_if_fail (data != NULL);

	pos.x = x;
	pos.y = y;

	sheet = schematic_view_get_sheet (data->schematic_view);

	snap_to_grid (sheet->grid, &pos.x, &pos.y);

	library_part = library_get_part (data->br->library, data->part_name);
	part = part_new_from_library_part (library_part);
	if (!part) {
		oregano_error (_("Unable to load required part"));
		return;
	}

	item_data_set_pos (ITEM_DATA (part), &pos);
	sheet_connect_part_item_to_floating_group (sheet, (gpointer) data->schematic_view);

	sheet_select_all (sheet, FALSE);
	sheet_clear_ghosts (schematic_view_get_sheet (data->schematic_view));
	sheet_add_ghost_item (sheet, ITEM_DATA (part));


}
Ejemplo n.º 9
0
void bordwalk(const struct Cell_head *from_hd, struct Cell_head *to_hd,
	      const struct pj_info *from_pj, const struct pj_info *to_pj)
{
    struct Cell_head cur_hd;

    /* Set some (un)reasonable defaults before we walk the borders */

    invert(&cur_hd, to_hd, 1.0e-6);

    /* Start walking */

    bordwalk1(from_pj, to_pj, from_hd, &cur_hd);

    intersect(&cur_hd, to_hd);

    /* check some special cases by reversing the projection */

    reverse_check(from_pj, to_pj, from_hd, to_hd, &cur_hd);

    debug("Extra check", &cur_hd);

    /* if we still have some unresonable default minmax left, then abort */

    if (outside(&cur_hd, to_hd))
	G_fatal_error(_("Input raster map is outside current region"));

    intersect(&cur_hd, to_hd);

    /* adjust to edges */

    snap_to_grid(&cur_hd, to_hd);

    intersect(to_hd, &cur_hd);

    debug("Final check", to_hd);
}
Ejemplo n.º 10
0
static void
modify_motion (ModifyTool     *tool,
               GdkEventMotion *event,
               DDisplay       *ddisp)
{
  Point to;
  Point now, delta, full_delta;
  gboolean auto_scroll, vertical = FALSE;
  ConnectionPoint *connectionpoint = NULL;
  ObjectChange *objchange = NULL;

  ddisplay_untransform_coords(ddisp, event->x, event->y, &to.x, &to.y);

  if (tool->state==STATE_NONE) {
    DiaObject *obj = NULL;
    Handle *handle = NULL;

    diagram_find_closest_handle (ddisp->diagram, &handle, &obj, &to);
    if  (handle && handle->type != HANDLE_NON_MOVABLE
      && handle->id >= HANDLE_RESIZE_NW && handle->id <= HANDLE_RESIZE_SE
      && handle_is_clicked(ddisp, handle, &to)
      && g_list_length (ddisp->diagram->data->selected) == 1)
      ddisplay_set_all_cursor (get_direction_cursor (CURSOR_DIRECTION_0 + handle->id));
    else
      ddisplay_set_all_cursor_name (NULL, "default");
    return; /* Fast path... */
  }
  auto_scroll = ddisplay_autoscroll(ddisp, event->x, event->y);

  if (!modify_move_already(tool, ddisp, &to)) return;

  switch (tool->state) {
  case STATE_MOVE_OBJECT:

    if (tool->orig_pos == NULL) {
      GList *list, *pla;
      int i;
      DiaObject *obj;

      /* consider non-selected children affected */
      pla = list = parent_list_affected(ddisp->diagram->data->selected);
      tool->orig_pos = g_new(Point, g_list_length(list));
      i=0;
      while (list != NULL) {
        obj = (DiaObject *)  list->data;
        tool->orig_pos[i] = obj->position;
        list = g_list_next(list); i++;
      }
      g_list_free (pla);
    }

    if (tool->break_connections)
      diagram_unconnect_selected(ddisp->diagram); /* Pushes UNDO info */

    if (gdk_event_to_dia_ModifierKeys (event->state) & MODIFIER_CONTROL) {
      full_delta = to;
      point_sub(&full_delta, &tool->start_at);
      vertical = (fabs(full_delta.x) < fabs(full_delta.y));
    }

    point_add(&to, &tool->move_compensate);
    snap_to_grid(ddisp, &to.x, &to.y);

    now = tool->object->position;

    delta = to;
    point_sub(&delta, &now);

    if (gdk_event_to_dia_ModifierKeys (event->state) & MODIFIER_CONTROL) {
      /* Up-down or left-right */
      if (vertical) {
       delta.x = tool->start_at.x + tool->move_compensate.x - now.x;
      } else {
       delta.y = tool->start_at.y + tool->move_compensate.y - now.y;
      }
    }

    object_add_updates_list(ddisp->diagram->data->selected, ddisp->diagram);
    objchange = object_list_move_delta(ddisp->diagram->data->selected, &delta);
    if (objchange != NULL) {
      undo_object_change(ddisp->diagram, tool->object, objchange);
    }
    object_add_updates_list(ddisp->diagram->data->selected, ddisp->diagram);

    object_add_updates(tool->object, ddisp->diagram);

    /* Put current mouse position in status bar */
    {
      gchar *postext;
      GtkStatusbar *statusbar = GTK_STATUSBAR (ddisp->modified_status);
      guint context_id = gtk_statusbar_get_context_id (statusbar, "ObjectPos");
      gtk_statusbar_pop (statusbar, context_id);
      postext = g_strdup_printf("%.3f, %.3f - %.3f, %.3f",
			        tool->object->bounding_box.left,
			        tool->object->bounding_box.top,
			        tool->object->bounding_box.right,
			        tool->object->bounding_box.bottom);

      gtk_statusbar_pop (statusbar, context_id);
      gtk_statusbar_push (statusbar, context_id, postext);

      g_free(postext);
    }

    diagram_update_connections_selection(ddisp->diagram);
    diagram_flush(ddisp->diagram);
    break;
  case STATE_MOVE_HANDLE:
    full_delta = to;
    point_sub(&full_delta, &tool->start_at);
    /* make sure resizing is restricted to its parent */

    /* if resize was blocked by parent, that means the resizing was
      outward, thus it won't bother the children so we don't have to
      check the children */
    if (!parent_handle_move_out_check(tool->object, &to))
      parent_handle_move_in_check(tool->object, &to, &tool->start_at);

    if (gdk_event_to_dia_ModifierKeys (event->state) & MODIFIER_CONTROL)
      vertical = (fabs(full_delta.x) < fabs(full_delta.y));

    highlight_reset_all(ddisp->diagram);
    if ((tool->handle->connect_type != HANDLE_NONCONNECTABLE)) {
      /* Move to ConnectionPoint if near: */
      connectionpoint = object_find_connectpoint_display (ddisp,
                                                          &to,
                                                          tool->object, TRUE);
      if (connectionpoint != NULL) {
        DiaHighlightType type;
        to = connectionpoint->pos;
        if (connectionpoint->flags & CP_FLAGS_MAIN) {
          type = DIA_HIGHLIGHT_CONNECTIONPOINT_MAIN;
        } else {
          type = DIA_HIGHLIGHT_CONNECTIONPOINT;
        }
        highlight_object(connectionpoint->object, type, ddisp->diagram);
        ddisplay_set_all_cursor_name (NULL, "crosshair");
      }
    }
    if (connectionpoint == NULL) {
      /* No connectionopoint near, then snap to grid (if enabled) */
      snap_to_grid(ddisp, &to.x, &to.y);
      ddisplay_set_all_cursor_name (NULL, "move");
    }

    if (tool->break_connections) {
      /* break connections to the handle currently selected. */
      if (tool->handle->connected_to!=NULL) {
        Change *change = undo_unconnect (ddisp->diagram,
                                         tool->object,
                                         tool->handle);

        (change->apply)(change, ddisp->diagram);
      }
    }

    if (gdk_event_to_dia_ModifierKeys (event->state) & MODIFIER_CONTROL) {
      /* Up-down or left-right */
      if (vertical) {
       to.x = tool->start_at.x;
      } else {
       to.y = tool->start_at.y;
      }
    }

    if (tool->orig_pos == NULL) {
      tool->orig_pos = g_new(Point, 1);
      *tool->orig_pos = tool->handle->pos;
    }

    /* Put current mouse position in status bar */
    {
      gchar *postext;
      GtkStatusbar *statusbar = GTK_STATUSBAR (ddisp->modified_status);
      guint context_id = gtk_statusbar_get_context_id (statusbar, "ObjectPos");

      if (tool->object) { /* play safe */
        real w = tool->object->bounding_box.right - tool->object->bounding_box.left;
        real h = tool->object->bounding_box.bottom - tool->object->bounding_box.top;
        postext = g_strdup_printf("%.3f, %.3f (%.3fx%.3f)", to.x, to.y, w, h);
      } else {
        postext = g_strdup_printf("%.3f, %.3f", to.x, to.y);
      }

      gtk_statusbar_pop (statusbar, context_id);
      gtk_statusbar_push (statusbar, context_id, postext);

      g_free(postext);
    }

    object_add_updates(tool->object, ddisp->diagram);

    /* Handle undo */
    if (tool->object)
      objchange = tool->object->ops->move_handle(tool->object, tool->handle,
					         &to, connectionpoint,
					         HANDLE_MOVE_USER, gdk_event_to_dia_ModifierKeys(event->state));
    if (objchange != NULL) {
      undo_object_change(ddisp->diagram, tool->object, objchange);
    }
    object_add_updates(tool->object, ddisp->diagram);

    diagram_update_connections_selection(ddisp->diagram);
    diagram_flush(ddisp->diagram);
    break;
  case STATE_BOX_SELECT:
    tool->end_box = to;

    ddisplay_transform_coords (ddisp,
                               MIN (tool->start_box.x, tool->end_box.x),
                               MIN (tool->start_box.y, tool->end_box.y),
                               &tool->x1, &tool->y1);
    ddisplay_transform_coords (ddisp,
                               MAX (tool->start_box.x, tool->end_box.x),
                               MAX (tool->start_box.y, tool->end_box.y),
                               &tool->x2, &tool->y2);

    dia_interactive_renderer_set_selection (ddisp->renderer,
                                            TRUE,
                                            tool->x1,
                                            tool->y1,
                                            tool->x2 - tool->x1,
                                            tool->y2 - tool->y1);
    ddisplay_flush (ddisp);

    break;
  case STATE_NONE:
    break;
  default:
    message_error("Internal error: Strange state in modify_tool\n");
  }

  tool->last_to = to;
  tool->auto_scrolled = auto_scroll;
}
Ejemplo n.º 11
0
gboolean
wire_item_event (WireItem *wire_item,
		 GooCanvasItem *sheet_target_item,
         GdkEvent *event, Sheet *sheet)
{
	SheetPos start_pos, length;
	Wire *wire;
	GooCanvas *canvas;
	static double last_x, last_y;
	double dx, dy, zoom;
	// The selected group's bounding box in window resp. canvas coordinates.
	double snapped_x, snapped_y;
	SheetPos pos;

	
	canvas = GOO_CANVAS (sheet);
	g_object_get (G_OBJECT (wire_item), 
	              "data", &wire, 
	              NULL);

	wire_get_pos_and_length (WIRE (wire), &start_pos, &length);
	sheet_get_zoom (sheet, &zoom);

	switch (event->type) {
		case GDK_BUTTON_PRESS:
			switch (event->button.button) {
				case 1: {
					double x, y;
					g_signal_stop_emission_by_name (wire_item, 
					                                "button_press_event");
					sheet_get_pointer (sheet, &x, &y);
					x = x - start_pos.x;
					y = y - start_pos.y;
					if ((x > -RESIZER_SIZE) && (x < RESIZER_SIZE)  &&
						(y > -RESIZER_SIZE) && (y < RESIZER_SIZE)) {
						gtk_widget_grab_focus (GTK_WIDGET (sheet));
						sheet->state = SHEET_STATE_DRAG_START;
						wire_item->priv->resize_state = WIRE_RESIZER_1;

						sheet_get_pointer (sheet, &x, &y);
						last_x = x;
						last_y = y;
						item_data_unregister (ITEM_DATA (wire)); 
						return TRUE;
					}
                    if ((x > (length.x-RESIZER_SIZE)) && 
                        (x < (length.x+RESIZER_SIZE)) &&
						(y > (length.y-RESIZER_SIZE)) && 
                        (y < (length.y+RESIZER_SIZE))) {
						gtk_widget_grab_focus (GTK_WIDGET (sheet));
						sheet->state = SHEET_STATE_DRAG_START;
						wire_item->priv->resize_state = WIRE_RESIZER_2;

						sheet_get_pointer (sheet, &x, &y);
						last_x = x;
						last_y = y;
						item_data_unregister (ITEM_DATA (wire));
						return TRUE;
					}
				}
				break;
			}
			break;

		case GDK_MOTION_NOTIFY:
            if (sheet->state != SHEET_STATE_DRAG &&
				sheet->state != SHEET_STATE_DRAG_START)
				break;

			if (wire_item->priv->resize_state == WIRE_RESIZER_NONE)
				break;

			if (sheet->state == SHEET_STATE_DRAG_START || 
			    sheet->state == SHEET_STATE_DRAG) 	   {

				g_signal_stop_emission_by_name (wire_item, 
				                                "motion-notify-event");
					
				sheet->state = SHEET_STATE_DRAG;
				
				sheet_get_pointer (sheet, &snapped_x, &snapped_y);
		
				dx = snapped_x - last_x;
				dy = snapped_y - last_y;

				last_x = snapped_x;
				last_y = snapped_y;

				wire_get_pos_and_length (wire, &pos, &length);

				if (wire_item->priv->resize_state == WIRE_RESIZER_1) {
					switch (wire->priv->direction) {
						case WIRE_DIR_VERT:
							/* Vertical Wire */
							pos.y = last_y;
							length.y -= dy;
						break;
						case WIRE_DIR_HORIZ:
							/* Horizontal Wire */
							pos.x = last_x;
							length.x -= dx;
						break;
						default:
							pos.y = last_y;
							length.y -= dy;
							pos.x = last_x;
							length.x -= dx;
					}
				} 
				else {
					switch (wire->priv->direction) {
						case WIRE_DIR_VERT:
							/* Vertical Wire */
							length.y += dy;
						break;
						case WIRE_DIR_HORIZ:
							/* Horizontal Wire */
							length.x += dx;
						break;
						default:
							length.y += dy;
							length.x += dx;
					}
				}
				snap_to_grid (sheet->grid, &length.x, &length.y);
				item_data_set_pos (sheet_item_get_data (SHEET_ITEM (wire_item)), 
				                   &pos);

				wire_set_length (wire, &length);
				return TRUE;
			}
			break;
		case GDK_BUTTON_RELEASE:
			switch (event->button.button) {
			case 1:
				if (sheet->state != SHEET_STATE_DRAG &&
					sheet->state != SHEET_STATE_DRAG_START) {
					break;
				}
				if (wire_item->priv->resize_state == WIRE_RESIZER_NONE) {
					break;
				}
				
				g_signal_stop_emission_by_name (wire_item, 
				                                "button-release-event");
				   
				goo_canvas_pointer_ungrab (canvas, GOO_CANVAS_ITEM (wire_item),
					event->button.time);
					
				wire_item->priv->resize_state = WIRE_RESIZER_NONE;
				sheet->state = SHEET_STATE_NONE;
				item_data_register (ITEM_DATA (wire));
				return TRUE;
			}
			break;
		default:
			return sheet_item_event (GOO_CANVAS_ITEM (wire_item), 
			                         GOO_CANVAS_ITEM (wire_item), event, sheet);
	}
	return sheet_item_event (GOO_CANVAS_ITEM (wire_item), 
	                         GOO_CANVAS_ITEM (wire_item), event, sheet);
}
Ejemplo n.º 12
0
int
common_dm(int argc, const char *argv[])
{
    int status;
    struct bu_vls vls = BU_VLS_INIT_ZERO;

    if (dbip == DBI_NULL)
	return TCL_OK;

    if (BU_STR_EQUAL(argv[0], "idle")) {

	/* redraw after scaling */
	if (gedp && gedp->ged_gvp &&
	    gedp->ged_gvp->gv_adaptive_plot &&
	    gedp->ged_gvp->gv_redraw_on_zoom &&
	    (am_mode == AMM_SCALE ||
	     am_mode == AMM_CON_SCALE_X ||
	     am_mode == AMM_CON_SCALE_Y ||
	     am_mode == AMM_CON_SCALE_Z))
	{
	    if (redraw_visible_objects() == TCL_ERROR) {
		return TCL_ERROR;
	    }
	}

	am_mode = AMM_IDLE;
	scroll_active = 0;
	if (rubber_band->rb_active) {
	    rubber_band->rb_active = 0;

	    if (mged_variables->mv_mouse_behavior == 'p')
		rb_set_dirty_flag();
	    else if (mged_variables->mv_mouse_behavior == 'r')
		rt_rect_area();
	    else if (mged_variables->mv_mouse_behavior == 'z')
		zoom_rect_area();
	}

	return TCL_OK;
    }

    if (BU_STR_EQUAL(argv[0], "m")) {
	int x;
	int y;
	int old_orig_gui;
	int stolen = 0;
	fastf_t fx, fy;

	if (argc < 3) {
	    Tcl_AppendResult(INTERP, "dm m: need more parameters\n",
			     "dm m xpos ypos\n", (char *)NULL);
	    return TCL_ERROR;
	}

	old_orig_gui = mged_variables->mv_orig_gui;

	fx = dm_Xx2Normal(dmp, atoi(argv[1]));
	fy = dm_Xy2Normal(dmp, atoi(argv[2]), 0);
	x = fx * GED_MAX;
	y = fy * GED_MAX;

	if (mged_variables->mv_faceplate &&
	    mged_variables->mv_orig_gui) {
#define MENUXLIM (-1250)

	    if (x >= MENUXLIM && scroll_select(x, y, 0)) {
		stolen = 1;
		goto end;
	    }

	    if (x < MENUXLIM && mmenu_select(y, 0)) {
		stolen = 1;
		goto end;
	    }
	}

	mged_variables->mv_orig_gui = 0;
	fy = dm_Xy2Normal(dmp, atoi(argv[2]), 1);
	y = fy * GED_MAX;

    end:
	if (mged_variables->mv_mouse_behavior == 'q' && !stolen) {
	    point_t view_pt;
	    point_t model_pt;

	    if (grid_state->gr_snap)
		snap_to_grid(&fx, &fy);

	    if (mged_variables->mv_perspective_mode)
		VSET(view_pt, fx, fy, 0.0);
	    else
		VSET(view_pt, fx, fy, 1.0);

	    MAT4X3PNT(model_pt, view_state->vs_gvp->gv_view2model, view_pt);
	    VSCALE(model_pt, model_pt, base2local);
	    if (dmp->dm_zclip)
		bu_vls_printf(&vls, "qray_nirt %lf %lf %lf",
			      model_pt[X], model_pt[Y], model_pt[Z]);
	    else
		bu_vls_printf(&vls, "qray_nirt -b %lf %lf %lf",
			      model_pt[X], model_pt[Y], model_pt[Z]);
	} else if ((mged_variables->mv_mouse_behavior == 'p' ||
		    mged_variables->mv_mouse_behavior == 'r' ||
		    mged_variables->mv_mouse_behavior == 'z') && !stolen) {

	    if (grid_state->gr_snap)
		snap_to_grid(&fx, &fy);

	    rubber_band->rb_active = 1;
	    rubber_band->rb_x = fx;
	    rubber_band->rb_y = fy;
	    rubber_band->rb_width = 0.0;
	    rubber_band->rb_height = 0.0;
	    rect_view2image();
	    rb_set_dirty_flag();
	} else if (mged_variables->mv_mouse_behavior == 's' && !stolen) {
#if 0
	    if (grid_state->gr_snap) {
		snap_to_grid(&fx, &fy);
		x = fx * GED_MAX;
		y = fy * GED_MAX;
	    }
#endif
	    bu_vls_printf(&vls, "mouse_solid_edit_select %d %d", x, y);
	} else if (mged_variables->mv_mouse_behavior == 'm' && !stolen) {
#if 0
	    if (grid_state->gr_snap) {
		snap_to_grid(&fx, &fy);
		x = fx * GED_MAX;
		y = fy * GED_MAX;
	    }
#endif
	    bu_vls_printf(&vls, "mouse_matrix_edit_select %d %d", x, y);
	} else if (mged_variables->mv_mouse_behavior == 'c' && !stolen) {
#if 0
	    if (grid_state->gr_snap) {
		snap_to_grid(&fx, &fy);
		x = fx * GED_MAX;
		y = fy * GED_MAX;
	    }
#endif
	    bu_vls_printf(&vls, "mouse_comb_edit_select %d %d", x, y);
	} else if (mged_variables->mv_mouse_behavior == 'o' && !stolen) {
#if 0
	    if (grid_state->gr_snap) {
		snap_to_grid(&fx, &fy);
		x = fx * GED_MAX;
		y = fy * GED_MAX;
	    }
#endif
	    bu_vls_printf(&vls, "mouse_rt_obj_select %d %d", x, y);
	} else if (adc_state->adc_draw && mged_variables->mv_transform == 'a' && !stolen) {
	    point_t model_pt;
	    point_t view_pt;

	    if (grid_state->gr_snap)
		snap_to_grid(&fx, &fy);

	    VSET(view_pt, fx, fy, 1.0);
	    MAT4X3PNT(model_pt, view_state->vs_gvp->gv_view2model, view_pt);
	    VSCALE(model_pt, model_pt, base2local);
	    bu_vls_printf(&vls, "adc xyz %lf %lf %lf\n", model_pt[X], model_pt[Y], model_pt[Z]);
	} else if (grid_state->gr_snap && !stolen &&
		   SEDIT_TRAN && mged_variables->mv_transform == 'e') {
	    point_t view_pt;
	    point_t model_pt;

	    snap_to_grid(&fx, &fy);
	    MAT4X3PNT(view_pt, view_state->vs_gvp->gv_model2view, curr_e_axes_pos);
	    view_pt[X] = fx;
	    view_pt[Y] = fy;
	    MAT4X3PNT(model_pt, view_state->vs_gvp->gv_view2model, view_pt);
	    VSCALE(model_pt, model_pt, base2local);
	    bu_vls_printf(&vls, "p %lf %lf %lf", model_pt[X], model_pt[Y], model_pt[Z]);
	} else if (grid_state->gr_snap && !stolen &&
		   OEDIT_TRAN && mged_variables->mv_transform == 'e') {
	    point_t view_pt;
	    point_t model_pt;

	    snap_to_grid(&fx, &fy);
	    MAT4X3PNT(view_pt, view_state->vs_gvp->gv_model2view, curr_e_axes_pos);
	    view_pt[X] = fx;
	    view_pt[Y] = fy;
	    MAT4X3PNT(model_pt, view_state->vs_gvp->gv_view2model, view_pt);
	    VSCALE(model_pt, model_pt, base2local);
	    bu_vls_printf(&vls, "translate %lf %lf %lf", model_pt[X], model_pt[Y], model_pt[Z]);
	} else if (grid_state->gr_snap && !stolen &&
		   STATE != ST_S_PICK && STATE != ST_O_PICK &&
		   STATE != ST_O_PATH && !SEDIT_PICK && !EDIT_SCALE) {
	    point_t view_pt;
	    point_t model_pt;
	    point_t vcenter;

	    snap_to_grid(&fx, &fy);
	    MAT_DELTAS_GET_NEG(vcenter, view_state->vs_gvp->gv_center);
	    MAT4X3PNT(view_pt, view_state->vs_gvp->gv_model2view, vcenter);
	    view_pt[X] = fx;
	    view_pt[Y] = fy;
	    MAT4X3PNT(model_pt, view_state->vs_gvp->gv_view2model, view_pt);
	    VSCALE(model_pt, model_pt, base2local);
	    bu_vls_printf(&vls, "center %lf %lf %lf", model_pt[X], model_pt[Y], model_pt[Z]);
	} else
	    bu_vls_printf(&vls, "M 1 %d %d\n", x, y);

	status = Tcl_Eval(INTERP, bu_vls_addr(&vls));
	mged_variables->mv_orig_gui = old_orig_gui;
	bu_vls_free(&vls);

	return status;
    }

    if (BU_STR_EQUAL(argv[0], "am")) {
	if (argc < 4) {
	    Tcl_AppendResult(INTERP, "dm am: need more parameters\n",
			     "dm am <r|t|s> xpos ypos\n", (char *)NULL);
	    return TCL_ERROR;
	}

	dml_omx = atoi(argv[2]);
	dml_omy = atoi(argv[3]);

	switch (*argv[1]) {
	    case 'r':
		am_mode = AMM_ROT;
		break;
	    case 't':
		am_mode = AMM_TRAN;

		if (grid_state->gr_snap) {
		    int save_edflag;

		    if ((STATE == ST_S_EDIT || STATE == ST_O_EDIT) &&
			mged_variables->mv_transform == 'e') {
			if (STATE == ST_S_EDIT) {
			    save_edflag = es_edflag;
			    if (!SEDIT_TRAN)
				es_edflag = STRANS;
			} else {
			    save_edflag = edobj;
			    edobj = BE_O_XY;
			}

			snap_keypoint_to_grid();

			if (STATE == ST_S_EDIT)
			    es_edflag = save_edflag;
			else
			    edobj = save_edflag;
		    } else
			snap_view_center_to_grid();
		}

		break;
	    case 's':
		if (STATE == ST_S_EDIT && mged_variables->mv_transform == 'e' &&
		    ZERO(acc_sc_sol))
		    acc_sc_sol = 1.0;
		else if (STATE == ST_O_EDIT && mged_variables->mv_transform == 'e') {
		    edit_absolute_scale = acc_sc_obj - 1.0;
		    if (edit_absolute_scale > 0.0)
			edit_absolute_scale /= 3.0;
		}

		am_mode = AMM_SCALE;
		break;
	    default:
		Tcl_AppendResult(INTERP, "dm am: need more parameters\n",
				 "dm am <r|t|s> xpos ypos\n", (char *)NULL);
		return TCL_ERROR;
	}

	return TCL_OK;
    }

    if (BU_STR_EQUAL(argv[0], "adc")) {
	fastf_t fx, fy;
	fastf_t td; /* tick distance */

	if (argc < 4) {
	    Tcl_AppendResult(INTERP, "dm adc: need more parameters\n",
			     "dm adc 1|2|t|d xpos ypos\n", (char *)NULL);
	    return TCL_ERROR;
	}

	dml_omx = atoi(argv[2]);
	dml_omy = atoi(argv[3]);

	switch (*argv[1]) {
	    case '1':
		fx = dm_Xx2Normal(dmp, dml_omx) * GED_MAX - adc_state->adc_dv_x;
		fy = dm_Xy2Normal(dmp, dml_omy, 1) * GED_MAX - adc_state->adc_dv_y;

		bu_vls_printf(&vls, "adc a1 %lf\n", RAD2DEG*atan2(fy, fx));
		Tcl_Eval(INTERP, bu_vls_addr(&vls));
		bu_vls_free(&vls);

		am_mode = AMM_ADC_ANG1;
		break;
	    case '2':
		fx = dm_Xx2Normal(dmp, dml_omx) * GED_MAX - adc_state->adc_dv_x;
		fy = dm_Xy2Normal(dmp, dml_omy, 1) * GED_MAX - adc_state->adc_dv_y;

		bu_vls_printf(&vls, "adc a2 %lf\n", RAD2DEG*atan2(fy, fx));
		Tcl_Eval(INTERP, bu_vls_addr(&vls));
		bu_vls_free(&vls);

		am_mode = AMM_ADC_ANG2;
		break;
	    case 't':
		{
		    point_t model_pt;
		    point_t view_pt;

		    VSET(view_pt, dm_Xx2Normal(dmp, dml_omx), dm_Xy2Normal(dmp, dml_omy, 1), 0.0);

		    if (grid_state->gr_snap)
			snap_to_grid(&view_pt[X], &view_pt[Y]);

		    MAT4X3PNT(model_pt, view_state->vs_gvp->gv_view2model, view_pt);
		    VSCALE(model_pt, model_pt, base2local);

		    bu_vls_printf(&vls, "adc xyz %lf %lf %lf\n", model_pt[X], model_pt[Y], model_pt[Z]);
		    Tcl_Eval(INTERP, bu_vls_addr(&vls));

		    bu_vls_free(&vls);
		    am_mode = AMM_ADC_TRAN;
		}

		break;
	    case 'd':
		fx = (dm_Xx2Normal(dmp, dml_omx) * GED_MAX -
		      adc_state->adc_dv_x) * view_state->vs_gvp->gv_scale * base2local * INV_GED;
		fy = (dm_Xy2Normal(dmp, dml_omy, 1) * GED_MAX -
		      adc_state->adc_dv_y) * view_state->vs_gvp->gv_scale * base2local * INV_GED;

		td = sqrt(fx * fx + fy * fy);

		bu_vls_printf(&vls, "adc dst %lf\n", td);
		Tcl_Eval(INTERP, bu_vls_addr(&vls));
		bu_vls_free(&vls);

		am_mode = AMM_ADC_DIST;
		break;
	    default:
		Tcl_AppendResult(INTERP, "dm adc: unrecognized parameter - ", argv[1],
				 "\ndm adc 1|2|t|d xpos ypos\n", (char *)NULL);
		return TCL_ERROR;
	}

	return TCL_OK;
    }

    if (BU_STR_EQUAL(argv[0], "con")) {
	if (argc < 5) {
	    Tcl_AppendResult(INTERP, "dm con: need more parameters\n",
			     "dm con r|t|s x|y|z xpos ypos\n",
			     "dm con a x|y|1|2|d xpos ypos\n", (char *)NULL);
	    return TCL_ERROR;
	}

	dml_omx = atoi(argv[3]);
	dml_omy = atoi(argv[4]);

	switch (*argv[1]) {
	    case 'a':
		switch (*argv[2]) {
		    case 'x':
			am_mode = AMM_CON_XADC;
			break;
		    case 'y':
			am_mode = AMM_CON_YADC;
			break;
		    case '1':
			am_mode = AMM_CON_ANG1;
			break;
		    case '2':
			am_mode = AMM_CON_ANG2;
			break;
		    case 'd':
			am_mode = AMM_CON_DIST;
			break;
		    default:
			Tcl_AppendResult(INTERP, "dm con: unrecognized parameter - ", argv[2],
					 "\ndm con a x|y|1|2|d xpos ypos\n", (char *)NULL);
		}
		break;
	    case 'r':
		switch (*argv[2]) {
		    case 'x':
			am_mode = AMM_CON_ROT_X;
			break;
		    case 'y':
			am_mode = AMM_CON_ROT_Y;
			break;
		    case 'z':
			am_mode = AMM_CON_ROT_Z;
			break;
		    default:
			Tcl_AppendResult(INTERP, "dm con: unrecognized parameter - ", argv[2],
					 "\ndm con r|t|s x|y|z xpos ypos\n", (char *)NULL);
			return TCL_ERROR;
		}
		break;
	    case 't':
		switch (*argv[2]) {
		    case 'x':
			am_mode = AMM_CON_TRAN_X;
			break;
		    case 'y':
			am_mode = AMM_CON_TRAN_Y;
			break;
		    case 'z':
			am_mode = AMM_CON_TRAN_Z;
			break;
		    default:
			Tcl_AppendResult(INTERP, "dm con: unrecognized parameter - ", argv[2],
					 "\ndm con r|t|s x|y|z xpos ypos\n", (char *)NULL);
			return TCL_ERROR;
		}
		break;
	    case 's':
		switch (*argv[2]) {
		    case 'x':
			if (STATE == ST_S_EDIT && mged_variables->mv_transform == 'e' &&
			    ZERO(acc_sc_sol))
			    acc_sc_sol = 1.0;
			else if (STATE == ST_O_EDIT && mged_variables->mv_transform == 'e') {
			    edit_absolute_scale = acc_sc[0] - 1.0;
			    if (edit_absolute_scale > 0.0)
				edit_absolute_scale /= 3.0;
			}

			am_mode = AMM_CON_SCALE_X;
			break;
		    case 'y':
			if (STATE == ST_S_EDIT && mged_variables->mv_transform == 'e' &&
			    ZERO(acc_sc_sol))
			    acc_sc_sol = 1.0;
			else if (STATE == ST_O_EDIT && mged_variables->mv_transform == 'e') {
			    edit_absolute_scale = acc_sc[1] - 1.0;
			    if (edit_absolute_scale > 0.0)
				edit_absolute_scale /= 3.0;
			}

			am_mode = AMM_CON_SCALE_Y;
			break;
		    case 'z':
			if (STATE == ST_S_EDIT && mged_variables->mv_transform == 'e' &&
			    ZERO(acc_sc_sol))
			    acc_sc_sol = 1.0;
			else if (STATE == ST_O_EDIT && mged_variables->mv_transform == 'e') {
			    edit_absolute_scale = acc_sc[2] - 1.0;
			    if (edit_absolute_scale > 0.0)
				edit_absolute_scale /= 3.0;
			}

			am_mode = AMM_CON_SCALE_Z;
			break;
		    default:
			Tcl_AppendResult(INTERP, "dm con: unrecognized parameter - ", argv[2],
					 "\ndm con r|t|s x|y|z xpos ypos\n", (char *)NULL);
			return TCL_ERROR;
		}
		break;
	    default:
		Tcl_AppendResult(INTERP, "dm con: unrecognized parameter - ", argv[1],
				 "\ndm con r|t|s x|y|z xpos ypos\n", (char *)NULL);
		return TCL_ERROR;
	}

	return TCL_OK;
    }

    if (BU_STR_EQUAL(argv[0], "size")) {
	int width, height;

	/* get the window size */
	if (argc == 1) {
	    bu_vls_printf(&vls, "%d %d", dmp->dm_width, dmp->dm_height);
	    Tcl_AppendResult(INTERP, bu_vls_addr(&vls), (char *)NULL);
	    bu_vls_free(&vls);

	    return TCL_OK;
	}

	/* set the window size */
	if (argc == 3) {
	    width = atoi(argv[1]);
	    height = atoi(argv[2]);

	    dmp->dm_width = width;
	    dmp->dm_height = height;

#if defined(DM_X) || defined(DM_TK) || defined(DM_OGL) || defined(DM_WGL)
#  if 0
	    Tk_ResizeWindow(((struct dm_xvars *)dmp->dm_vars.pub_vars)->xtkwin, width, height);
#  else
#if defined(HAVE_TK)
	    Tk_GeometryRequest(((struct dm_xvars *)dmp->dm_vars.pub_vars)->xtkwin, width, height);
#endif
#  endif
#endif

	    return TCL_OK;
	}

	Tcl_AppendResult(INTERP, "Usage: dm size [width height]\n", (char *)NULL);
	return TCL_ERROR;
    }

#if defined(DM_X) || defined(DM_TK) || defined(DM_OGL) || defined(DM_WGL)
    if (BU_STR_EQUAL(argv[0], "getx")) {
	if (argc == 1) {
	    struct bu_vls tmp_vls = BU_VLS_INIT_ZERO;

	    /* Bare set command, print out current settings */
	    bu_vls_struct_print2(&tmp_vls, "dm internal X variables", dm_xvars_vparse,
				 (const char *)dmp->dm_vars.pub_vars);
	    Tcl_AppendResult(INTERP, bu_vls_addr(&tmp_vls), (char *)NULL);
	    bu_vls_free(&tmp_vls);
	} else if (argc == 2) {
	    bu_vls_struct_item_named(&vls, dm_xvars_vparse, argv[1], (const char *)dmp->dm_vars.pub_vars, COMMA);
	    Tcl_AppendResult(INTERP, bu_vls_addr(&vls), (char *)NULL);
	    bu_vls_free(&vls);
	}

	return TCL_OK;
    }
#endif

    if (BU_STR_EQUAL(argv[0], "bg")) {
	int r, g, b;

	if (argc != 1 && argc != 4) {
	    bu_vls_printf(&vls, "Usage: dm bg [r g b]");
	    Tcl_AppendResult(INTERP, bu_vls_addr(&vls), (char *)NULL);
	    bu_vls_free(&vls);

	    return TCL_ERROR;
	}

	/* return background color of current display manager */
	if (argc == 1) {
	    bu_vls_printf(&vls, "%d %d %d",
			  dmp->dm_bg[0],
			  dmp->dm_bg[1],
			  dmp->dm_bg[2]);
	    Tcl_AppendResult(INTERP, bu_vls_addr(&vls), (char *)NULL);
	    bu_vls_free(&vls);

	    return TCL_OK;
	}

	if (sscanf(argv[1], "%d", &r) != 1 ||
	    sscanf(argv[2], "%d", &g) != 1 ||
	    sscanf(argv[3], "%d", &b) != 1) {
	    bu_vls_printf(&vls, "Usage: dm bg r g b");
	    Tcl_AppendResult(INTERP, bu_vls_addr(&vls), (char *)NULL);
	    bu_vls_free(&vls);

	    return TCL_ERROR;
	}

	dirty = 1;
	return DM_SET_BGCOLOR(dmp, r, g, b);
    }

    Tcl_AppendResult(INTERP, "dm: bad command - ", argv[0], "\n", (char *)NULL);
    return TCL_ERROR;
}
Ejemplo n.º 13
0
static void
create_object_button_press(CreateObjectTool *tool, GdkEventButton *event,
			   DDisplay *ddisp)
{
  Point clickedpoint, origpoint;
  Handle *handle1;
  Handle *handle2;
  DiaObject *obj;
  real click_distance;

  ddisplay_untransform_coords(ddisp,
			      (int)event->x, (int)event->y,
			      &clickedpoint.x, &clickedpoint.y);

  origpoint = clickedpoint;

  snap_to_grid(ddisp, &clickedpoint.x, &clickedpoint.y);

  click_distance = ddisplay_untransform_length(ddisp, 3.0);

  obj = dia_object_default_create (tool->objtype, &clickedpoint,
                                   tool->user_data,
                                   &handle1, &handle2);

  tool->obj = obj; /* ensure that tool->obj is initialised in case we
		      return early. */
  if (!obj) {
    tool->moving = FALSE;
    tool->handle = NULL;
    message_error(_("'%s' creation failed"), tool->objtype ? tool->objtype->name : "NULL");
    return;
  }

  diagram_add_object(ddisp->diagram, obj);

  /* Try a connect */
  if (handle1 != NULL &&
      handle1->connect_type != HANDLE_NONCONNECTABLE) {
    ConnectionPoint *connectionpoint;
    connectionpoint =
      object_find_connectpoint_display(ddisp, &origpoint, obj, TRUE);
    if (connectionpoint != NULL) {
      (obj->ops->move)(obj, &origpoint);
    }
  }
  
  if (!(event->state & GDK_SHIFT_MASK)) {
    /* Not Multi-select => remove current selection */
    diagram_remove_all_selected(ddisp->diagram, TRUE);
  }
  diagram_select(ddisp->diagram, obj);

  /* Connect first handle if possible: */
  if ((handle1!= NULL) &&
      (handle1->connect_type != HANDLE_NONCONNECTABLE)) {
    object_connect_display(ddisp, obj, handle1, TRUE);
  }

  object_add_updates(obj, ddisp->diagram);
  ddisplay_do_update_menu_sensitivity(ddisp);
  diagram_flush(ddisp->diagram);
  
  if (handle2 != NULL) {
    tool->handle = handle2;
    tool->moving = TRUE;
    tool->last_to = handle2->pos;
    
    gdk_pointer_grab (gtk_widget_get_window(ddisp->canvas), FALSE,
		      GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
		      NULL, NULL, event->time);
    ddisplay_set_all_cursor(get_cursor(CURSOR_SCROLL));
  } else {
    diagram_update_extents(ddisp->diagram);
    tool->moving = FALSE;
  }

}
Ejemplo n.º 14
0
void snap_button(struct dlg *dlg, struct button *bp, bool sizing, int *content)
{
    struct edges h;
    struct edges v;
    void *parent = NULL;

    int snapdist = g_snap_dist;
    int grid     = g_snap_usegrid ? g_snap_gridsize : 0;
    int padding  = g_snap_padding;

    if (snapdist < 1)
        return;

    h.dmin = v.dmin = h.def = v.def = snapdist;
    h.from2 = (h.from1 = bp->x0) + bp->w0;
    v.from2 = (v.from1 = bp->y0) + bp->h0;

    // ------------------------------------------------------
    // snap to grid
    if (grid > 1)// && (parent || sizing))
    {
        snap_to_grid(&h, &v, sizing, grid, padding);
    }
    else
    {
        struct snap_info si;

        si.h = &h;
        si.v = &v;
        si.sizing = sizing;
        si.same_level = true;
        si.pad = padding;
        si.self = bp;
        si.parent = parent;

        enum_buttons(dlg, snap_enum_proc, &si);

        h.to1 = 0;
        h.to2 = dlg->w;
        v.to1 = 0;
        v.to2 = dlg->h;
        snap_to_edge(&h, &v, sizing, false, padding);

        // -----------------------------------------
        if (sizing)
        {
            // snap to button icons
            if (content)
            {
                // images have to be double padded, since they are centered
                h.to2 = (h.to1 = h.from1) + content[0];
                v.to2 = (v.to1 = v.from1) + content[1];
                snap_to_edge(&h, &v, sizing, false, -2*padding);
            }

        /*
            // snap frame to childs
            si.same_level = false;
            si.pad = -padding;
            si.self = NULL;
            si.parent = self;
            enum_buttons(dlg, snap_enum_proc, &si);
        */
        }
    }

    // -----------------------------------------
    // adjust the window-pos

    if (h.dmin < snapdist) {
        if (sizing)
            bp->w0 += h.omin;
        else
            bp->x0 += h.omin;
    }
    if (v.dmin < snapdist) {
        if (sizing)
            bp->h0 += v.omin;
        else
            bp->y0 += v.omin;
    }
}
Ejemplo n.º 15
0
static void
create_object_motion(CreateObjectTool *tool, GdkEventMotion *event,
		   DDisplay *ddisp)
{
  Point to;
  ConnectionPoint *connectionpoint = NULL;
  gchar *postext;
  GtkStatusbar *statusbar;
  guint context_id;

  if (!tool->moving)
    return;
  
  ddisplay_untransform_coords(ddisp, event->x, event->y, &to.x, &to.y);

  /* make sure the new object is restricted to its parent */
  parent_handle_move_out_check(tool->obj, &to);

  /* Move to ConnectionPoint if near: */
  if (tool->handle != NULL &&
      tool->handle->connect_type != HANDLE_NONCONNECTABLE) {
    connectionpoint =
      object_find_connectpoint_display(ddisp, &to, tool->obj, TRUE);
    
    if (connectionpoint != NULL) {
      to = connectionpoint->pos;
      highlight_object(connectionpoint->object, DIA_HIGHLIGHT_CONNECTIONPOINT, ddisp->diagram);
      ddisplay_set_all_cursor(get_cursor(CURSOR_CONNECT));
    }
  }
  
  if (connectionpoint == NULL) {
    /* No connectionopoint near, then snap to grid (if enabled) */
    snap_to_grid(ddisp, &to.x, &to.y);
    highlight_reset_all(ddisp->diagram);
    ddisplay_set_all_cursor(get_cursor(CURSOR_SCROLL));
  }
      
  object_add_updates(tool->obj, ddisp->diagram);
  tool->obj->ops->move_handle(tool->obj, tool->handle, &to, connectionpoint,
			      HANDLE_MOVE_CREATE, 0);
  object_add_updates(tool->obj, ddisp->diagram);

  /* Put current mouse position in status bar */
  statusbar = GTK_STATUSBAR (ddisp->modified_status);
  context_id = gtk_statusbar_get_context_id (statusbar, "ObjectPos");
    
  postext = g_strdup_printf("%.3f, %.3f - %.3f, %.3f",
			    tool->obj->bounding_box.left,
			    tool->obj->bounding_box.top,
			    tool->obj->bounding_box.right,
			    tool->obj->bounding_box.bottom);
			       
  gtk_statusbar_pop (statusbar, context_id); 
  gtk_statusbar_push (statusbar, context_id, postext);

  g_free(postext);
  
  diagram_flush(ddisp->diagram);

  tool->last_to = to;
  
  return;
}
Ejemplo n.º 16
0
/* ----------------------------------------------------------------------------
 * Handles the events for the area editor.
 */
void area_editor::handle_controls(const ALLEGRO_EVENT &ev) {

    if(fade_mgr.is_fading()) return;
    
    gui->handle_event(ev);
    
    //Update mouse cursor in world coordinates.
    if(
        ev.type == ALLEGRO_EVENT_MOUSE_AXES ||
        ev.type == ALLEGRO_EVENT_MOUSE_WARPED ||
        ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN ||
        ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP
    ) {
        mouse_cursor_x =
            ev.mouse.x / cam_zoom - cam_x - (gui_x / 2 / cam_zoom);
        mouse_cursor_y =
            ev.mouse.y / cam_zoom - cam_y - (scr_h / 2 / cam_zoom);
        lafi::widget* wum;
        if(!is_mouse_in_gui(ev.mouse.x, ev.mouse.y)) {
            wum = NULL;
        } else {
            wum = gui->get_widget_under_mouse(ev.mouse.x, ev.mouse.y);
        }
        ((lafi::label*) gui->widgets["lbl_status_bar"])->text =
            (
                wum ?
                wum->description :
                "(" + i2s(mouse_cursor_x) + "," + i2s(mouse_cursor_y) + ")"
            );
    }
    
    
    //Moving vertexes, camera, etc.
    if(ev.type == ALLEGRO_EVENT_MOUSE_AXES) {
    
        if(
            !is_mouse_in_gui(ev.mouse.x, ev.mouse.y)
            && moving_thing == INVALID && sec_mode != ESM_TEXTURE_VIEW &&
            mode != EDITOR_MODE_OBJECTS
        ) {
            on_sector = get_sector(mouse_cursor_x, mouse_cursor_y, NULL, false);
        } else {
            on_sector = NULL;
        }
        
        //Move guide.
        if(sec_mode == ESM_GUIDE_MOUSE) {
        
            if(holding_m1) {
                guide_x += ev.mouse.dx / cam_zoom;
                guide_y += ev.mouse.dy / cam_zoom;
                
            } else if(holding_m2) {
            
                float new_w = guide_w + ev.mouse.dx / cam_zoom;
                float new_h = guide_h + ev.mouse.dy / cam_zoom;
                
                if(guide_aspect_ratio) {
                    //Find the most significant change.
                    if(ev.mouse.dx != 0 || ev.mouse.dy != 0) {
                        bool most_is_width =
                            fabs((double) ev.mouse.dx) >
                            fabs((double) ev.mouse.dy);
                            
                        if(most_is_width) {
                            float ratio = guide_h / guide_w;
                            guide_w = new_w;
                            guide_h = new_w * ratio;
                        } else {
                            float ratio = guide_w / guide_h;
                            guide_h = new_h;
                            guide_w = new_h * ratio;
                        }
                    }
                } else {
                    guide_w = new_w;
                    guide_h = new_h;
                }
                
            }
            
            guide_to_gui();
            
        } else if(holding_m2) {
            //Move camera.
            cam_x += ev.mouse.dx / cam_zoom;
            cam_y += ev.mouse.dy / cam_zoom;
        }
        
        //Move thing.
        if(moving_thing != INVALID) {
            if(mode == EDITOR_MODE_SECTORS) {
                vertex* v_ptr = cur_area_data.vertexes[moving_thing];
                v_ptr->x = snap_to_grid(mouse_cursor_x);
                v_ptr->y = snap_to_grid(mouse_cursor_y);
            } else if(mode == EDITOR_MODE_OBJECTS) {
                mob_gen* m_ptr = cur_area_data.mob_generators[moving_thing];
                m_ptr->x = snap_to_grid(mouse_cursor_x);
                m_ptr->y = snap_to_grid(mouse_cursor_y);
            } else if(mode == EDITOR_MODE_PATHS) {
                path_stop* s_ptr = cur_area_data.path_stops[moving_thing];
                s_ptr->x = snap_to_grid(mouse_cursor_x);
                s_ptr->y = snap_to_grid(mouse_cursor_y);
                s_ptr->calculate_dists();
                path_preview_timeout.start(false);
            } else if(mode == EDITOR_MODE_SHADOWS) {
                tree_shadow* s_ptr = cur_area_data.tree_shadows[moving_thing];
                s_ptr->x = snap_to_grid(mouse_cursor_x - moving_thing_x);
                s_ptr->y = snap_to_grid(mouse_cursor_y - moving_thing_y);
                shadow_to_gui();
            }
            
            made_changes = true;
        }
        
        //Move path checkpoints.
        if(moving_path_preview_checkpoint != -1) {
            path_preview_checkpoints_x[moving_path_preview_checkpoint] =
                snap_to_grid(mouse_cursor_x);
            path_preview_checkpoints_y[moving_path_preview_checkpoint] =
                snap_to_grid(mouse_cursor_y);
            path_preview_timeout.start(false);
        }
        
        
        if(ev.mouse.dz != 0 && !is_mouse_in_gui(ev.mouse.x, ev.mouse.y)) {
            //Zoom.
            float new_zoom = cam_zoom + (cam_zoom * ev.mouse.dz * 0.1);
            new_zoom = max(ZOOM_MIN_LEVEL_EDITOR, new_zoom);
            new_zoom = min(ZOOM_MAX_LEVEL_EDITOR, new_zoom);
            float new_mc_x =
                ev.mouse.x / new_zoom - cam_x - (gui_x / 2 / new_zoom);
            float new_mc_y =
                ev.mouse.y / new_zoom - cam_y - (scr_h / 2 / new_zoom);
                
            cam_x -= (mouse_cursor_x - new_mc_x);
            cam_y -= (mouse_cursor_y - new_mc_y);
            mouse_cursor_x = new_mc_x;
            mouse_cursor_y = new_mc_y;
            cam_zoom = new_zoom;
        }
        
        if(sec_mode == ESM_NEW_SECTOR) {
            new_sector_valid_line =
                is_new_sector_line_valid(
                    snap_to_grid(mouse_cursor_x),
                    snap_to_grid(mouse_cursor_y)
                );
        }
        
        
    } else if(
        ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN &&
        !is_mouse_in_gui(ev.mouse.x, ev.mouse.y)
    ) {
        //Clicking.
        
        if(ev.mouse.button == 1) holding_m1 = true;
        else if(ev.mouse.button == 2) holding_m2 = true;
        else if(ev.mouse.button == 3) cam_zoom = 1.0;
        
        if(ev.mouse.button != 1) return;
        
        //If the user was editing, save it.
        if(mode == EDITOR_MODE_SECTORS) {
            gui_to_sector();
        } else if(mode == EDITOR_MODE_OBJECTS) {
            gui_to_mob();
        } else if(mode == EDITOR_MODE_SHADOWS) {
            gui_to_shadow();
        }
        
        //Sector-related clicking.
        if(sec_mode == ESM_NONE && mode == EDITOR_MODE_SECTORS) {
        
            moving_thing = INVALID;
            
            edge* clicked_edge_ptr = NULL;
            size_t clicked_edge_nr = INVALID;
            bool created_vertex = false;
            
            for(size_t e = 0; e < cur_area_data.edges.size(); ++e) {
                edge* e_ptr = cur_area_data.edges[e];
                
                if(!is_edge_valid(e_ptr)) continue;
                
                if(
                    circle_intersects_line(
                        mouse_cursor_x, mouse_cursor_y, 8 / cam_zoom,
                        e_ptr->vertexes[0]->x, e_ptr->vertexes[0]->y,
                        e_ptr->vertexes[1]->x, e_ptr->vertexes[1]->y
                    )
                ) {
                    clicked_edge_ptr = e_ptr;
                    clicked_edge_nr = e;
                    break;
                }
            }
            
            if(double_click_time == 0) double_click_time = 0.5;
            else if(clicked_edge_ptr) {
                //Create a new vertex.
                double_click_time = 0;
                
                //New vertex, on the split point.
                //TODO create it on the edge, not on the cursor.
                vertex* new_v_ptr = new vertex(mouse_cursor_x, mouse_cursor_y);
                cur_area_data.vertexes.push_back(new_v_ptr);
                
                //New edge, copied from the original one.
                edge* new_e_ptr = new edge(*clicked_edge_ptr);
                cur_area_data.edges.push_back(new_e_ptr);
                
                //Save the original end vertex for later.
                vertex* end_v_ptr = clicked_edge_ptr->vertexes[1];
                
                //Set vertexes on the new and original edges.
                new_e_ptr->vertex_nrs[0] = cur_area_data.vertexes.size() - 1;
                new_e_ptr->vertexes[0] = new_v_ptr;
                clicked_edge_ptr->vertex_nrs[1] = new_e_ptr->vertex_nrs[0];
                clicked_edge_ptr->vertexes[1] = new_v_ptr;
                
                //Set sectors on the new edge.
                if(new_e_ptr->sectors[0]) {
                    new_e_ptr->sectors[0]->edge_nrs.push_back(
                        cur_area_data.edges.size() - 1
                    );
                    new_e_ptr->sectors[0]->edges.push_back(new_e_ptr);
                }
                if(new_e_ptr->sectors[1]) {
                    new_e_ptr->sectors[1]->edge_nrs.push_back(
                        cur_area_data.edges.size() - 1
                    );
                    new_e_ptr->sectors[1]->edges.push_back(new_e_ptr);
                }
                
                //Set edges of the new vertex.
                new_v_ptr->edge_nrs.push_back(cur_area_data.edges.size() - 1);
                new_v_ptr->edge_nrs.push_back(clicked_edge_nr);
                new_v_ptr->edges.push_back(new_e_ptr);
                new_v_ptr->edges.push_back(clicked_edge_ptr);
                
                //Update edge data on the end vertex of the original edge
                //(it now links to the new edge, not the old).
                for(size_t ve = 0; ve < end_v_ptr->edges.size(); ++ve) {
                    if(end_v_ptr->edges[ve] == clicked_edge_ptr) {
                        end_v_ptr->edges[ve] =
                            new_e_ptr;
                        end_v_ptr->edge_nrs[ve] =
                            cur_area_data.edges.size() - 1;
                        break;
                    }
                }
                
                //Start dragging the new vertex.
                moving_thing = cur_area_data.vertexes.size() - 1;
                
                created_vertex = true;
                made_changes = true;
            }
            
            //Find a vertex to drag.
            if(!created_vertex) {
                for(size_t v = 0; v < cur_area_data.vertexes.size(); ++v) {
                    if(
                        dist(
                            mouse_cursor_x, mouse_cursor_y,
                            cur_area_data.vertexes[v]->x,
                            cur_area_data.vertexes[v]->y
                        ) <= 6.0 / cam_zoom
                    ) {
                        moving_thing = v;
                        break;
                    }
                }
            }
            
            //Find a sector to select.
            if(moving_thing == INVALID) {
                cur_sector =
                    get_sector(mouse_cursor_x, mouse_cursor_y, NULL, false);
                sector_to_gui();
            }
            
            
        } else if(sec_mode == ESM_NONE && mode == EDITOR_MODE_OBJECTS) {
            //Object-related clicking.
            
            cur_mob = NULL;
            moving_thing = INVALID;
            for(size_t m = 0; m < cur_area_data.mob_generators.size(); ++m) {
                mob_gen* m_ptr = cur_area_data.mob_generators[m];
                float radius =
                    m_ptr->type ? m_ptr->type->radius == 0 ? 16 :
                    m_ptr->type->radius : 16;
                if(
                    dist(m_ptr->x, m_ptr->y, mouse_cursor_x, mouse_cursor_y) <=
                    radius
                ) {
                
                    cur_mob = m_ptr;
                    moving_thing = m;
                    break;
                }
            }
            mob_to_gui();
            
        } else if(sec_mode == ESM_NONE && mode == EDITOR_MODE_PATHS) {
            //Path-related clicking.
            
            cur_stop = NULL;
            moving_thing = INVALID;
            for(size_t s = 0; s < cur_area_data.path_stops.size(); ++s) {
                path_stop* s_ptr = cur_area_data.path_stops[s];
                if(
                    dist(s_ptr->x, s_ptr->y, mouse_cursor_x, mouse_cursor_y)
                    <= STOP_RADIUS
                ) {
                
                    cur_stop = s_ptr;
                    moving_thing = s;
                    break;
                }
            }
            
            moving_path_preview_checkpoint = -1;
            if(show_path_preview) {
                for(unsigned char c = 0; c < 2; ++c) {
                    if(
                        bbox_check(
                            path_preview_checkpoints_x[c],
                            path_preview_checkpoints_y[c],
                            mouse_cursor_x, mouse_cursor_y,
                            PATH_PREVIEW_CHECKPOINT_RADIUS / cam_zoom
                        )
                    ) {
                        moving_path_preview_checkpoint = c;
                        break;
                    }
                }
            }
            
        } else if(sec_mode == ESM_NONE && mode == EDITOR_MODE_SHADOWS) {
            //Shadow-related clicking.
            
            cur_shadow = NULL;
            moving_thing = INVALID;
            for(size_t s = 0; s < cur_area_data.tree_shadows.size(); ++s) {
            
                tree_shadow* s_ptr = cur_area_data.tree_shadows[s];
                float min_x, min_y, max_x, max_y;
                get_shadow_bounding_box(s_ptr, &min_x, &min_y, &max_x, &max_y);
                
                if(
                    mouse_cursor_x >= min_x && mouse_cursor_x <= max_x &&
                    mouse_cursor_y >= min_y && mouse_cursor_y <= max_y
                ) {
                    cur_shadow = s_ptr;
                    moving_thing = s;
                    moving_thing_x = mouse_cursor_x - s_ptr->x;
                    moving_thing_y = mouse_cursor_y - s_ptr->y;
                    break;
                }
            }
            shadow_to_gui();
            
        }
        
        if(sec_mode == ESM_NEW_SECTOR) {
            //Next vertex in a new sector.
            float hotspot_x = snap_to_grid(mouse_cursor_x);
            float hotspot_y = snap_to_grid(mouse_cursor_y);
            new_sector_valid_line =
                is_new_sector_line_valid(
                    snap_to_grid(mouse_cursor_x),
                    snap_to_grid(mouse_cursor_y)
                );
                
            if(new_sector_valid_line) {
                if(
                    !new_sector_vertexes.empty() &&
                    dist(
                        hotspot_x, hotspot_y,
                        new_sector_vertexes[0]->x,
                        new_sector_vertexes[0]->y
                    ) <= VERTEX_MERGE_RADIUS
                ) {
                    //Back to the first vertex.
                    sec_mode = ESM_NONE;
                    create_sector();
                    sector_to_gui();
                    made_changes = true;
                } else {
                    //Add a new vertex.
                    vertex* merge =
                        get_merge_vertex(
                            hotspot_x, hotspot_y,
                            cur_area_data.vertexes,
                            VERTEX_MERGE_RADIUS / cam_zoom
                        );
                    if(merge) {
                        new_sector_vertexes.push_back(
                            new vertex(merge->x, merge->y)
                        );
                    } else {
                        new_sector_vertexes.push_back(
                            new vertex(hotspot_x, hotspot_y)
                        );
                    }
                }
            }
            
            
        } else if(sec_mode == ESM_NEW_OBJECT) {
            //Create a mob where the cursor is.
            
            sec_mode = ESM_NONE;
            float hotspot_x = snap_to_grid(mouse_cursor_x);
            float hotspot_y = snap_to_grid(mouse_cursor_y);
            
            cur_area_data.mob_generators.push_back(
                new mob_gen(hotspot_x, hotspot_y)
            );
            
            cur_mob = cur_area_data.mob_generators.back();
            mob_to_gui();
            made_changes = true;
            
        } else if(sec_mode == ESM_DUPLICATE_OBJECT) {
            //Duplicate the current mob to where the cursor is.
            
            sec_mode = ESM_NONE;
            
            if(cur_mob) {
                float hotspot_x = snap_to_grid(mouse_cursor_x);
                float hotspot_y = snap_to_grid(mouse_cursor_y);
                
                mob_gen* new_mg = new mob_gen(*cur_mob);
                new_mg->x = hotspot_x;
                new_mg->y = hotspot_y;
                cur_area_data.mob_generators.push_back(
                    new_mg
                );
                
                cur_mob = new_mg;
                mob_to_gui();
                made_changes = true;
            }
            
        } else if(sec_mode == ESM_NEW_STOP) {
            //Create a new stop where the cursor is.
            
            float hotspot_x = snap_to_grid(mouse_cursor_x);
            float hotspot_y = snap_to_grid(mouse_cursor_y);
            
            cur_area_data.path_stops.push_back(
                new path_stop(hotspot_x, hotspot_y, vector<path_link>())
            );
            
            cur_stop = cur_area_data.path_stops.back();
            made_changes = true;
            
            
        } else if (sec_mode == ESM_NEW_LINK1 || sec_mode == ESM_NEW_1WLINK1) {
            //Pick a stop to start the link on.
            
            for(size_t s = 0; s < cur_area_data.path_stops.size(); ++s) {
                path_stop* s_ptr = cur_area_data.path_stops[s];
                
                if(
                    dist(mouse_cursor_x, mouse_cursor_y, s_ptr->x, s_ptr->y) <=
                    STOP_RADIUS
                ) {
                    new_link_first_stop = s_ptr;
                    sec_mode =
                        sec_mode == ESM_NEW_LINK1 ? ESM_NEW_LINK2 :
                        ESM_NEW_1WLINK2;
                    break;
                }
            }
            
            path_preview_timeout.start(false);
            made_changes = true;
            
        } else if (sec_mode == ESM_NEW_LINK2 || sec_mode == ESM_NEW_1WLINK2) {
            //Pick a stop to end the link on.
            
            for(size_t s = 0; s < cur_area_data.path_stops.size(); ++s) {
                path_stop* s_ptr = cur_area_data.path_stops[s];
                
                if(
                    dist(mouse_cursor_x, mouse_cursor_y, s_ptr->x, s_ptr->y) <=
                    STOP_RADIUS
                ) {
                
                    if(new_link_first_stop == s_ptr) continue;
                    
                    //Check if these two stops already have a link.
                    //Delete it if so.
                    for(
                        size_t l = 0; l < new_link_first_stop->links.size();
                        ++l
                    ) {
                        if(new_link_first_stop->links[l].end_ptr == s_ptr) {
                            new_link_first_stop->links.erase(
                                new_link_first_stop->links.begin() + l
                            );
                            break;
                        }
                    }
                    for(size_t l = 0; l < s_ptr->links.size(); ++l) {
                        if(s_ptr->links[l].end_ptr == new_link_first_stop) {
                            s_ptr->links.erase(s_ptr->links.begin() + l);
                            break;
                        }
                    }
                    
                    
                    new_link_first_stop->links.push_back(
                        path_link(s_ptr, s)
                    );
                    
                    if(sec_mode == ESM_NEW_LINK2) {
                        s_ptr->links.push_back(
                            path_link(new_link_first_stop, INVALID)
                        );
                        s_ptr->fix_nrs(cur_area_data);
                    }
                    
                    new_link_first_stop->calculate_dists();
                    
                    sec_mode =
                        sec_mode == ESM_NEW_LINK2 ? ESM_NEW_LINK1 :
                        ESM_NEW_1WLINK1;
                    break;
                }
            }
            
            path_preview_timeout.start(false);
            made_changes = true;
            
        } else if(sec_mode == ESM_DEL_STOP) {
            //Pick a stop to delete.
            
            for(size_t s = 0; s < cur_area_data.path_stops.size(); ++s) {
                path_stop* s_ptr = cur_area_data.path_stops[s];
                
                if(
                    dist(mouse_cursor_x, mouse_cursor_y, s_ptr->x, s_ptr->y) <=
                    STOP_RADIUS
                ) {
                
                    //Check all links to this stop.
                    for(
                        size_t s2 = 0; s2 < cur_area_data.path_stops.size();
                        ++s2
                    ) {
                        path_stop* s2_ptr = cur_area_data.path_stops[s2];
                        for(size_t l = 0; l < s2_ptr->links.size(); ++l) {
                            if(s2_ptr->links[l].end_ptr == s_ptr) {
                                s2_ptr->links.erase(s2_ptr->links.begin() + l);
                                break;
                            }
                        }
                    }
                    
                    //Finally, delete the stop.
                    delete s_ptr;
                    cur_area_data.path_stops.erase(
                        cur_area_data.path_stops.begin() + s
                    );
                    break;
                }
            }
            
            for(size_t s = 0; s < cur_area_data.path_stops.size(); ++s) {
                cur_area_data.path_stops[s]->fix_nrs(cur_area_data);
            }
            
            path_preview.clear();
            path_preview_timeout.start(false);
            made_changes = true;
            
        } else if(sec_mode == ESM_DEL_LINK) {
            //Pick a link to delete.
            
            bool deleted = false;
            
            for(size_t s = 0; s < cur_area_data.path_stops.size(); ++s) {
                path_stop* s_ptr = cur_area_data.path_stops[s];
                
                for(size_t s2 = 0; s2 < s_ptr->links.size(); ++s2) {
                    path_stop* s2_ptr = s_ptr->links[s2].end_ptr;
                    if(
                        circle_intersects_line(
                            mouse_cursor_x, mouse_cursor_y, 8 / cam_zoom,
                            s_ptr->x, s_ptr->y,
                            s2_ptr->x, s2_ptr->y
                        )
                    ) {
                    
                        s_ptr->links.erase(s_ptr->links.begin() + s2);
                        
                        for(size_t s3 = 0; s3 < s2_ptr->links.size(); ++s3) {
                            if(s2_ptr->links[s3].end_ptr == s_ptr) {
                                s2_ptr->links.erase(
                                    s2_ptr->links.begin() + s3
                                );
                                break;
                            }
                        }
                        
                        deleted = true;
                        break;
                    }
                }
                
                if(deleted) break;
            }
            
            path_preview.clear();
            path_preview_timeout.start(false);
            made_changes = true;
            
        } else if(sec_mode == ESM_NEW_SHADOW) {
            //Create a new shadow where the cursor is.
            
            sec_mode = ESM_NONE;
            float hotspot_x = snap_to_grid(mouse_cursor_x);
            float hotspot_y = snap_to_grid(mouse_cursor_y);
            
            tree_shadow* new_shadow = new tree_shadow(hotspot_x, hotspot_y);
            new_shadow->bitmap = bmp_error;
            
            cur_area_data.tree_shadows.push_back(new_shadow);
            
            cur_shadow = new_shadow;
            shadow_to_gui();
            made_changes = true;
            
        }
        
        
    } else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
        //Mouse button release.
        
        if(ev.mouse.button == 1) holding_m1 = false;
        else if(ev.mouse.button == 2) holding_m2 = false;
        
        if(
            ev.mouse.button == 1 &&
            mode == EDITOR_MODE_SECTORS && sec_mode == ESM_NONE &&
            moving_thing != INVALID
        ) {
            //Release the vertex.
            
            vertex* moved_v_ptr = cur_area_data.vertexes[moving_thing];
            vertex* final_vertex = moved_v_ptr;
            
            unordered_set<sector*> affected_sectors;
            
            //Check if we should merge.
            for(size_t v = 0; v < cur_area_data.vertexes.size(); ++v) {
                vertex* dest_v_ptr = cur_area_data.vertexes[v];
                if(dest_v_ptr == moved_v_ptr) continue;
                
                if(
                    dist(
                        moved_v_ptr->x, moved_v_ptr->y,
                        dest_v_ptr->x, dest_v_ptr->y
                    ) <= (VERTEX_MERGE_RADIUS / cam_zoom)
                ) {
                    merge_vertex(
                        moved_v_ptr, dest_v_ptr, &affected_sectors
                    );
                    final_vertex = dest_v_ptr;
                    break;
                }
            }
            
            //Finally, re-triangulate the affected sectors.
            for(size_t e = 0; e < final_vertex->edges.size(); ++e) {
                edge* e_ptr = final_vertex->edges[e];
                for(size_t s = 0; s < 2; ++s) {
                    if(e_ptr->sectors[s]) {
                        affected_sectors.insert(e_ptr->sectors[s]);
                    }
                }
            }
            for(
                auto s = affected_sectors.begin();
                s != affected_sectors.end(); ++s
            ) {
                if(!(*s)) continue;
                triangulate(*s);
            }
            
            //If somewhere along the line, the current sector
            //got marked for deletion, unselect it.
            if(cur_sector) {
                if(cur_sector->edges.empty()) {
                    cur_sector = NULL;
                    sector_to_gui();
                }
            }
            
            //Check if the edge's vertexes intersect with any other edges.
            //If so, they're marked with red.
            check_edge_intersections(moved_v_ptr);
            
            moving_thing = INVALID;
            
            
            
        } else if(
            ev.mouse.button == 1 && sec_mode == ESM_NONE &&
            moving_thing != INVALID
        ) {
            //Release thing.
            
            moving_thing = INVALID;
            
        }
        
        moving_path_preview_checkpoint = -1;
        
        
    } else if(ev.type == ALLEGRO_EVENT_KEY_DOWN) {
        //Key press.
        
        if(
            ev.keyboard.keycode == ALLEGRO_KEY_LSHIFT ||
            ev.keyboard.keycode == ALLEGRO_KEY_RSHIFT
        ) {
            shift_pressed = true;
        } else if(ev.keyboard.keycode == ALLEGRO_KEY_F1) {
            debug_edge_nrs = !debug_edge_nrs;
        } else if(ev.keyboard.keycode == ALLEGRO_KEY_F2) {
            debug_sector_nrs = !debug_sector_nrs;
        } else if(ev.keyboard.keycode == ALLEGRO_KEY_F3) {
            debug_vertex_nrs = !debug_vertex_nrs;
        } else if(ev.keyboard.keycode == ALLEGRO_KEY_F4) {
            debug_triangulation = !debug_triangulation;
        }
        
        
    } else if(ev.type == ALLEGRO_EVENT_KEY_UP) {
        //Key release.
        
        if(
            ev.keyboard.keycode == ALLEGRO_KEY_LSHIFT ||
            ev.keyboard.keycode == ALLEGRO_KEY_RSHIFT
        ) {
            shift_pressed = false;
        }
    }
}
Ejemplo n.º 17
0
void PixelsMovement::moveImage(const gfx::Point& pos, MoveModifier moveModifier)
{
  gfx::Transformation::Corners oldCorners;
  m_currentData.transformBox(oldCorners);

  ContextWriter writer(m_reader, 1000);
  gfx::RectF bounds = m_initialData.bounds();
  bool updateBounds = false;
  double dx, dy;

  dx = ((pos.x - m_catchPos.x) *  cos(m_currentData.angle()) +
        (pos.y - m_catchPos.y) * -sin(m_currentData.angle()));
  dy = ((pos.x - m_catchPos.x) *  sin(m_currentData.angle()) +
        (pos.y - m_catchPos.y) *  cos(m_currentData.angle()));

  switch (m_handle) {

    case MoveHandle:
      if ((moveModifier & LockAxisMovement) == LockAxisMovement) {
        if (ABS(dx) < ABS(dy))
          dx = 0.0;
        else
          dy = 0.0;
      }

      bounds.offset(dx, dy);
      updateBounds = true;

      if ((moveModifier & SnapToGridMovement) == SnapToGridMovement) {
        // Snap the x1,y1 point to the grid.
        gfx::Rect gridBounds = App::instance()
          ->preferences().document(m_document).grid.bounds();
        gfx::PointF gridOffset(
          snap_to_grid(
            gridBounds,
            gfx::Point(bounds.origin()),
            PreferSnapTo::ClosestGridVertex));

        // Now we calculate the difference from x1,y1 point and we can
        // use it to adjust all coordinates (x1, y1, x2, y2).
        gridOffset -= bounds.origin();
        bounds.offset(gridOffset);
      }
      break;

    case ScaleNWHandle:
    case ScaleNHandle:
    case ScaleNEHandle:
    case ScaleWHandle:
    case ScaleEHandle:
    case ScaleSWHandle:
    case ScaleSHandle:
    case ScaleSEHandle: {
      static double handles[][2] = {
        { 0.0, 0.0 }, { 0.5, 0.0 }, { 1.0, 0.0 },
        { 0.0, 0.5 },               { 1.0, 0.5 },
        { 0.0, 1.0 }, { 0.5, 1.0 }, { 1.0, 1.0 }
      };
      gfx::PointF pivot;
      gfx::PointF handle(
        handles[m_handle-ScaleNWHandle][0],
        handles[m_handle-ScaleNWHandle][1]);

      if ((moveModifier & ScaleFromPivot) == ScaleFromPivot) {
        pivot.x = m_currentData.pivot().x;
        pivot.y = m_currentData.pivot().y;
      }
      else {
        pivot.x = 1.0 - handle.x;
        pivot.y = 1.0 - handle.y;
        pivot.x = bounds.x + bounds.w*pivot.x;
        pivot.y = bounds.y + bounds.h*pivot.y;
      }

      gfx::PointF a = bounds.origin();
      gfx::PointF b = bounds.point2();

      if ((moveModifier & MaintainAspectRatioMovement) == MaintainAspectRatioMovement) {
        auto u = point2Vector(gfx::PointF(m_catchPos) - pivot);
        auto v = point2Vector(gfx::PointF(pos) - pivot);
        auto w = v.projectOn(u);
        double scale = u.magnitude();
        if (scale != 0.0)
          scale = (std::fabs(w.angle()-u.angle()) < PI/2.0 ? 1.0: -1.0) * w.magnitude() / scale;
        else
          scale = 1.0;

        a.x = int((a.x-pivot.x)*scale + pivot.x);
        a.y = int((a.y-pivot.y)*scale + pivot.y);
        b.x = int((b.x-pivot.x)*scale + pivot.x);
        b.y = int((b.y-pivot.y)*scale + pivot.y);
      }
      else {
        handle.x = bounds.x + bounds.w*handle.x;
        handle.y = bounds.y + bounds.h*handle.y;

        double w = (handle.x-pivot.x);
        double h = (handle.y-pivot.y);

        if (m_handle == ScaleNHandle || m_handle == ScaleSHandle) {
          dx = 0.0;
          w = 1.0;              // Any value != 0.0 to avoid div by zero
        }
        else if (m_handle == ScaleWHandle || m_handle == ScaleEHandle) {
          dy = 0.0;
          h = 1.0;
        }

        a.x = int((a.x-pivot.x)*(1.0+dx/w) + pivot.x);
        a.y = int((a.y-pivot.y)*(1.0+dy/h) + pivot.y);
        b.x = int((b.x-pivot.x)*(1.0+dx/w) + pivot.x);
        b.y = int((b.y-pivot.y)*(1.0+dy/h) + pivot.y);
      }

      // Do not use "gfx::Rect(a, b)" here because if a > b we want to
      // keep a rectangle with negative width or height (to know that
      // it was flipped).
      bounds.x = a.x;
      bounds.y = a.y;
      bounds.w = b.x - a.x;
      bounds.h = b.y - a.y;

      updateBounds = true;
      break;
    }

    case RotateNWHandle:
    case RotateNHandle:
    case RotateNEHandle:
    case RotateWHandle:
    case RotateEHandle:
    case RotateSWHandle:
    case RotateSHandle:
    case RotateSEHandle:
      {
        gfx::PointF abs_initial_pivot = m_initialData.pivot();
        gfx::PointF abs_pivot = m_currentData.pivot();

        double newAngle =
          m_initialData.angle()
          + atan2((double)(-pos.y + abs_pivot.y),
                  (double)(+pos.x - abs_pivot.x))
          - atan2((double)(-m_catchPos.y + abs_initial_pivot.y),
                  (double)(+m_catchPos.x - abs_initial_pivot.x));

        // Put the angle in -180 to 180 range.
        while (newAngle < -PI) newAngle += 2*PI;
        while (newAngle > PI) newAngle -= 2*PI;

        // Is the "angle snap" is activated, we've to snap the angle
        // to common (pixel art) angles.
        if ((moveModifier & AngleSnapMovement) == AngleSnapMovement) {
          // TODO make this configurable
          static const double keyAngles[] = {
            0.0, 26.565, 45.0, 63.435, 90.0, 116.565, 135.0, 153.435, 180.0,
            180.0, -153.435, -135.0, -116, -90.0, -63.435, -45.0, -26.565
          };

          double newAngleDegrees = 180.0 * newAngle / PI;

          int closest = 0;
          int last = sizeof(keyAngles) / sizeof(keyAngles[0]) - 1;
          for (int i=0; i<=last; ++i) {
            if (std::fabs(newAngleDegrees-keyAngles[closest]) >
                std::fabs(newAngleDegrees-keyAngles[i]))
              closest = i;
          }

          newAngle = PI * keyAngles[closest] / 180.0;
        }

        m_currentData.angle(newAngle);
      }
      break;

    case PivotHandle:
      {
        // Calculate the new position of the pivot
        gfx::PointF newPivot(m_initialData.pivot().x + (pos.x - m_catchPos.x),
                             m_initialData.pivot().y + (pos.y - m_catchPos.y));

        m_currentData = m_initialData;
        m_currentData.displacePivotTo(newPivot);
      }
      break;
  }

  if (updateBounds) {
    m_currentData.bounds(bounds);
    m_adjustPivot = true;
  }

  redrawExtraImage();

  m_document->setTransformation(m_currentData);

  // Get the new transformed corners
  gfx::Transformation::Corners newCorners;
  m_currentData.transformBox(newCorners);

  // Create a union of all corners, and that will be the bounds to
  // redraw of the sprite.
  gfx::Rect fullBounds;
  for (int i=0; i<gfx::Transformation::Corners::NUM_OF_CORNERS; ++i) {
    fullBounds = fullBounds.createUnion(gfx::Rect((int)oldCorners[i].x, (int)oldCorners[i].y, 1, 1));
    fullBounds = fullBounds.createUnion(gfx::Rect((int)newCorners[i].x, (int)newCorners[i].y, 1, 1));
  }

  // If "fullBounds" is empty is because the cel was not moved
  if (!fullBounds.isEmpty()) {
    // Notify the modified region.
    m_document->notifySpritePixelsModified(m_sprite, gfx::Region(fullBounds),
                                           m_site.frame());
  }
}
Ejemplo n.º 18
0
int
common_dm(int argc, char **argv)
{
    int status;
    struct bu_vls vls;

    if (dbip == DBI_NULL)
	return TCL_OK;

    if (!strcmp(argv[0], "idle")) {
	am_mode = AMM_IDLE;
	scroll_active = 0;
	if (rubber_band->rb_active) {
	    rubber_band->rb_active = 0;

	    if (mged_variables->mv_mouse_behavior == 'p')
		rb_set_dirty_flag();
	    else if (mged_variables->mv_mouse_behavior == 'r')
		rt_rect_area();
	    else if (mged_variables->mv_mouse_behavior == 'z')
		zoom_rect_area();
	}

	return TCL_OK;
    }

    if (!strcmp(argv[0], "m")) {
	int x;
	int y;
	int old_orig_gui;
	int stolen = 0;
	fastf_t fx, fy;

	if (argc < 3) {
	    Tcl_AppendResult(interp, "dm m: need more parameters\n",
			     "dm m xpos ypos\n", (char *)NULL);
	    return TCL_ERROR;
	}

	old_orig_gui = mged_variables->mv_orig_gui;

	fx = dm_Xx2Normal(dmp, atoi(argv[1]));
	fy = dm_Xy2Normal(dmp, atoi(argv[2]), 0);
	x = fx * GED_MAX;
	y = fy * GED_MAX;

	if (mged_variables->mv_faceplate &&
	    mged_variables->mv_orig_gui) {
#define        MENUXLIM        (-1250)

	    if (x >= MENUXLIM && scroll_select(x, y, 0)) {
		stolen = 1;
		goto end;
	    }

	    if (x < MENUXLIM && mmenu_select(y, 0)) {
		stolen = 1;
		goto end;
	    }
	}

	mged_variables->mv_orig_gui = 0;
	fy = dm_Xy2Normal(dmp, atoi(argv[2]), 1);
	y = fy * GED_MAX;

    end:
	bu_vls_init(&vls);
	if (mged_variables->mv_mouse_behavior == 'q' && !stolen) {
	    point_t view_pt;
	    point_t model_pt;

	    if (grid_state->gr_snap)
		snap_to_grid(&fx, &fy);

	    if ( mged_variables->mv_perspective_mode )
		VSET(view_pt, fx, fy, 0.0)
		    else
			VSET(view_pt, fx, fy, 1.0)

			    MAT4X3PNT(model_pt, view_state->vs_vop->vo_view2model, view_pt);
	    VSCALE(model_pt, model_pt, base2local);
	    if (dmp->dm_zclip)
		bu_vls_printf(&vls, "qray_nirt %lf %lf %lf",
			      model_pt[X], model_pt[Y], model_pt[Z]);
	    else
		bu_vls_printf(&vls, "qray_nirt -b %lf %lf %lf",
			      model_pt[X], model_pt[Y], model_pt[Z]);
	} else if ((mged_variables->mv_mouse_behavior == 'p' ||
Ejemplo n.º 19
0
// 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;
}
Ejemplo n.º 20
0
// Event handler for a SheetItem
gboolean
sheet_item_event (GooCanvasItem *sheet_item,
		 GooCanvasItem *sheet_target_item,
		 GdkEvent *event, Sheet *sheet)
{
	// Remember the last position of the mouse cursor.
	static double last_x, last_y;
	GooCanvas *canvas;
	SheetPriv *priv;
	GList *list;
	// 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_item != NULL, FALSE);
	g_return_val_if_fail (sheet != NULL, FALSE);

	priv = sheet->priv;

	canvas = GOO_CANVAS (sheet);
	
	switch (event->type) {
	case GDK_BUTTON_PRESS:
		// Grab focus to sheet for correct use of events
		gtk_widget_grab_focus (GTK_WIDGET (sheet));
		switch (event->button.button) {
		case 1:
			g_signal_stop_emission_by_name (sheet_item, "button_press_event");
			sheet->state = SHEET_STATE_DRAG_START;
			sheet_get_pointer (sheet, &last_x, &last_y);
			break;
		case 3:
			g_signal_stop_emission_by_name (sheet_item, "button_press_event");

			if (sheet->state != SHEET_STATE_NONE)
				return TRUE;

			// Bring up a context menu for right button clicks.
			if (!SHEET_ITEM (sheet_item)->priv->selected &&
				!((event->button.state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK))
					sheet_select_all (sheet, FALSE);

			sheet_item_select (SHEET_ITEM (sheet_item), TRUE);

			sheet_item_run_menu (SHEET_ITEM (sheet_item), sheet, 
			                     (GdkEventButton *) event);
			break;
		default:
			return FALSE;
		}
		break;

	case GDK_2BUTTON_PRESS:
		// Do not interfere with object dragging.
		if (sheet->state == SHEET_STATE_DRAG)
			return FALSE;

		switch (event->button.button) {
		case 1:
			if (sheet->state == SHEET_STATE_DRAG_START)
				sheet->state = SHEET_STATE_NONE;
			g_signal_stop_emission_by_name (sheet_item, "button_press_event");
			g_signal_emit_by_name (sheet_item, "double_clicked");
			break;

		default:
			return FALSE;
		}
		break;

	case GDK_3BUTTON_PRESS:
		g_signal_stop_emission_by_name (sheet_item, "button_press_event");
		return TRUE;

	case GDK_BUTTON_RELEASE:
		switch (event->button.button) {
		case 1:
			if (sheet->state != SHEET_STATE_DRAG &&
				sheet->state != SHEET_STATE_DRAG_START)
				return TRUE;

			g_signal_stop_emission_by_name (sheet_item, "button-release-event");

			if (sheet->state == SHEET_STATE_DRAG_START) {
				sheet->state = SHEET_STATE_NONE;

				if (!(event->button.state & GDK_SHIFT_MASK))
					sheet_select_all (sheet, FALSE);

				if (IS_SHEET_ITEM (sheet_item))
					sheet_item_select (SHEET_ITEM (sheet_item), TRUE);

				return TRUE;
			}

			// Get the mouse motion
			sheet_get_pointer (sheet, &snapped_x, &snapped_y);
			snapped_x -= last_x;
			snapped_y -= last_y;

			sheet->state = SHEET_STATE_NONE;
			goo_canvas_pointer_ungrab (canvas, GOO_CANVAS_ITEM (sheet_item),
			                           event->button.time);

			// Reparent the selected objects to the normal group
			// to have correct behaviour
			for (list = priv->selected_objects; list; list = list->next) {
            	sheet_item_reparent (SHEET_ITEM (list->data), 
	                                 sheet->object_group);
            }

			for (list = priv->selected_objects; list; list = list->next) {
            	ItemData *item_data;
				Coords pos;

                item_data = SHEET_ITEM (list->data)->priv->data;
				pos.x = snapped_x;
				pos.y = snapped_y;
				item_data_move (item_data, &pos);
                item_data_register (item_data);
            }
			g_list_free_full (list, g_object_unref);
				
			break;
		}
			
	case GDK_KEY_PRESS:
		switch (event->key.keyval) {
			case GDK_KEY_r:
				sheet_rotate_selection (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);

					dx = x - (bounds.x1 + bounds.x2) / 2;
					dy = y - (bounds.y1 + bounds.y2) / 2;
                    snap_to_grid (sheet->grid, &dx, &dy);

					goo_canvas_item_translate (
						GOO_CANVAS_ITEM (priv->floating_group), dx, dy);

                    last_x = snapped_x;
                    last_y = snapped_y;
				}
				break;
			default:
				return FALSE;
		}
		return TRUE;

	case GDK_MOTION_NOTIFY:
		if (sheet->state != SHEET_STATE_DRAG &&
			sheet->state != SHEET_STATE_DRAG_START)
			return FALSE;

		if (sheet->state == SHEET_STATE_DRAG_START) {
			sheet->state = SHEET_STATE_DRAG;
			
			// Update the selection if needed. 
			if (IS_SHEET_ITEM (sheet_item)					&&
	    		(!SHEET_ITEM (sheet_item)->priv->selected))	{
				if (!(event->button.state & GDK_SHIFT_MASK)) {
					sheet_select_all (sheet, FALSE);
				}
				sheet_item_select (SHEET_ITEM (sheet_item), TRUE);
			}

			// Reparent the selected objects so that we can move them 
			// efficiently.
			for (list = priv->selected_objects; list; list = list->next) {
				ItemData *item_data;

				item_data = SHEET_ITEM (list->data)->priv->data;
				item_data_unregister (item_data);
				sheet_item_reparent (SHEET_ITEM (list->data), 
                                     priv->selected_group);
			}
			
			goo_canvas_pointer_grab (canvas, GOO_CANVAS_ITEM (sheet_item),
	    		GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
	    		NULL, 
	    		event->button.time);
		}

		// Set last_x & last_y to the pointer position
		sheet_get_pointer (sheet, &snapped_x, &snapped_y);

		dx = snapped_x - last_x;
		dy = snapped_y - last_y;
		
		// Check that we don't move outside the sheet... 
		// Horizontally: 
		/*
		if (cx1 <= 0) {  // leftmost edge 
			dx = dx - x1;
			snap_to_grid (sheet->grid, &dx, NULL);
			snapped_x = last_x + dx;
		} 
		else if (cx2 >= sheet_width) {  // rightmost edge 
			dx = dx - (x2 - sheet_width / priv->zoom);
			snap_to_grid (sheet->grid, &dx, NULL);
			snapped_x = last_x + dx;
		}

		// And vertically:
		if (cy1 <= 0) {  // upper edge
			dy = dy - y1;
			snap_to_grid (sheet->grid, NULL, &dy);
			snapped_y = last_y + dy;
		} 
		else if (cy2 >= sheet_height) {  // lower edge 
			dy = dy - (y2 - sheet_height / priv->zoom);
			snap_to_grid (sheet->grid, NULL, &dy);
			snapped_y = last_y + dy;
		}
		//last_x = snapped_x;
		//last_y = snapped_y;
		*/

		goo_canvas_item_set_transform (GOO_CANVAS_ITEM (priv->selected_group), 
		                               NULL);
		goo_canvas_item_translate (GOO_CANVAS_ITEM (priv->selected_group), 
			                       dx, dy);
		return TRUE;
	
	default:
		return FALSE;
	}
	return TRUE;
}
Ejemplo n.º 21
0
static
int wire_item_event (WireItem *wire_item, const GdkEvent *event, SchematicView *sv)
{
	SheetPos start_pos, length;
	Wire *wire;
	Sheet *sheet;
	GnomeCanvas *canvas;
	static double last_x, last_y;
	double dx, dy, zoom;
	/* The selected group's bounding box in window resp. canvas coordinates. */
	double x1, y1, x2, y2;
	static double bb_x1, bb_y1, bb_x2, bb_y2;
	int cx1, cy1, cx2, cy2;
	double snapped_x, snapped_y;
	int sheet_width, sheet_height;
	SheetPos pos;

	sheet = schematic_view_get_sheet (sv);
	canvas = GNOME_CANVAS (sheet);
	g_object_get (G_OBJECT (wire_item), "data", &wire, NULL);

	wire_get_pos_and_length (WIRE (wire), &start_pos, &length);
	sheet_get_zoom (sheet, &zoom);

	switch (event->type) {
		case GDK_BUTTON_PRESS:
			switch (event->button.button) {
				case 1: {
					g_signal_stop_emission_by_name (G_OBJECT (sheet), "event");
					double x, y;
					x = event->button.x - start_pos.x;
					y = event->button.y - start_pos.y;
					if ((x > -RESIZER_SIZE) && (x < RESIZER_SIZE) &&
						 (y > -RESIZER_SIZE) && (y < RESIZER_SIZE)) {
						gtk_widget_grab_focus (GTK_WIDGET (sheet));
						sheet->state = SHEET_STATE_DRAG_START;
						wire_item->priv->resize_state = WIRE_RESIZER_1;

						last_x = event->button.x;
						last_y = event->button.y;
						item_data_unregister (ITEM_DATA (wire));
						return TRUE;
					}
					if ((x > (length.x-RESIZER_SIZE)) && (x < (length.x+RESIZER_SIZE)) &&
						 (y > (length.y-RESIZER_SIZE)) && (y < (length.y+RESIZER_SIZE))) {
						gtk_widget_grab_focus (GTK_WIDGET (sheet));
						sheet->state = SHEET_STATE_DRAG_START;
						wire_item->priv->resize_state = WIRE_RESIZER_2;

						last_x = event->button.x;
						last_y = event->button.y;
						item_data_unregister (ITEM_DATA (wire));
						return TRUE;
					}
				}
				break;
			}
		break;
		case GDK_MOTION_NOTIFY:
			if (sheet->state != SHEET_STATE_DRAG &&
				sheet->state != SHEET_STATE_DRAG_START)
				break;

			if (wire_item->priv->resize_state == WIRE_RESIZER_NONE)
				break;

			if (sheet->state == SHEET_STATE_DRAG_START || sheet->state == SHEET_STATE_DRAG) {
				sheet->state = SHEET_STATE_DRAG;
		
				snapped_x = event->motion.x;
				snapped_y = event->motion.y;
				snap_to_grid (sheet->grid, &snapped_x, &snapped_y);
		
				dx = snapped_x - last_x;
				dy = snapped_y - last_y;

		
				last_x = snapped_x;
				last_y = snapped_y;

				wire_get_pos_and_length (wire, &pos, &length);

				if (wire_item->priv->resize_state == WIRE_RESIZER_1) {
					switch (wire->priv->direction) {
						case WIRE_DIR_VERT:
							/* Vertical Wire */
							pos.y = last_y;
							length.y -= dy;
						break;
						case WIRE_DIR_HORIZ:
							/* Horizontal Wire */
							pos.x = last_x;
							length.x -= dx;
						break;
						default:
							pos.y = last_y;
							length.y -= dy;
							pos.x = last_x;
							length.x -= dx;
					}
				} else {
					switch (wire->priv->direction) {
						case WIRE_DIR_VERT:
							/* Vertical Wire */
							length.y += dy;
						break;
						case WIRE_DIR_HORIZ:
							/* Horizontal Wire */
							length.x += dx;
						break;
						default:
							length.y += dy;
							length.x += dx;
					}
				}
				snap_to_grid (sheet->grid, &length.x, &length.y);
				item_data_set_pos (sheet_item_get_data (SHEET_ITEM (wire_item)), &pos);
				wire_set_length (wire, &length);
				return TRUE;
			}
		break;
		case GDK_BUTTON_RELEASE:
			switch (event->button.button) {
			case 1:
				if (sheet->state != SHEET_STATE_DRAG &&
					sheet->state != SHEET_STATE_DRAG_START)
					break;
				if (wire_item->priv->resize_state == WIRE_RESIZER_NONE)
					break;

				g_signal_stop_emission_by_name (G_OBJECT (wire_item), "event");

				//gtk_timeout_remove (priv->scroll_timeout_id); // Esto no esta bien.

				sheet->state = SHEET_STATE_NONE;
				gnome_canvas_item_ungrab (GNOME_CANVAS_ITEM (wire_item), event->button.time);

				wire_item->priv->resize_state = WIRE_RESIZER_NONE;
				sheet->state = SHEET_STATE_NONE;
				item_data_register (ITEM_DATA (wire));
				return TRUE;
			}
			break;
		default:
			return sheet_item_event (SHEET_ITEM (wire_item), event, sv);
	}
	return sheet_item_event (SHEET_ITEM (wire_item), event, sv);
}
Ejemplo n.º 22
0
// 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;
}