/* When using the mouse wheel button to zoom in and out, it is more intuitive to maintain the drawing zoom center-point based on the cursor position. This can help orientation and prevent the drawing from "jumping" around while zooming in and out. */ void ddisplay_zoom_centered(DDisplay *ddisp, Point *point, real magnify) { Rectangle *visible; real width, height; /* cursor position ratios */ real rx,ry; if ((ddisp->zoom_factor <= DDISPLAY_MIN_ZOOM) && (magnify<=1.0)) return; if ((ddisp->zoom_factor >= DDISPLAY_MAX_ZOOM) && (magnify>=1.0)) return; visible = &ddisp->visible; /* calculate cursor position ratios */ rx = (point->x-visible->left)/(visible->right - visible->left); ry = (point->y-visible->top)/(visible->bottom - visible->top); width = (visible->right - visible->left)/magnify; height = (visible->bottom - visible->top)/magnify; ddisp->zoom_factor *= magnify; /* set new origin based on the calculated ratios before zooming */ ddisplay_set_origo(ddisp, point->x-(width*rx),point->y-(height*ry)); ddisplay_update_scrollbars(ddisp); ddisplay_add_update_all(ddisp); ddisplay_flush(ddisp); update_zoom_status (ddisp); }
static PyObject * PyDiaDisplay_Flush(PyDiaDisplay *self, PyObject *args) { if (!PyArg_ParseTuple(args, ":Display.flush")) return NULL; ddisplay_flush(self->disp); Py_INCREF(Py_None); return Py_None; }
static void interface_toggle_mainpoint_magnetism(GtkWidget *widget, gpointer data) { DDisplay *ddisp = (DDisplay *)data; ddisplay_set_snap_to_objects(ddisp, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))); ddisplay_add_update_all(ddisp); ddisplay_flush(ddisp); }
static void scroll_motion(ScrollTool *tool, GdkEventMotion *event, DDisplay *ddisp) { Point to; Point delta; /* set the cursor appropriately, and change use_hand if needed */ if (!tool->scrolling) { /* try to minimise the number of cursor type changes */ if ((event->state & GDK_SHIFT_MASK) != 0) { if (!tool->use_hand) { tool->use_hand = TRUE; if (!open_hand_cursor) open_hand_cursor = create_cursor(ddisp->canvas->window, hand_open_data_bits, hand_open_data_width, hand_open_data_height, hand_open_mask_bits, hand_open_data_width/2, hand_open_data_height/2); ddisplay_set_all_cursor(open_hand_cursor); } } else if (tool->use_hand) { tool->use_hand = FALSE; ddisplay_set_all_cursor(scroll_cursor); } return; } ddisplay_untransform_coords(ddisp, event->x, event->y, &to.x, &to.y); if (tool->use_hand) { delta = tool->last_pos; point_sub(&delta, &to); tool->last_pos = to; point_add(&tool->last_pos, &delta); /* we use this so you can scroll past the edge of the image */ point_add(&delta, &ddisp->origo); ddisplay_set_origo(ddisp, delta.x, delta.y); ddisplay_update_scrollbars(ddisp); ddisplay_add_update_all(ddisp); } else { delta = to; point_sub(&delta, &tool->last_pos); point_scale(&delta, 0.5); ddisplay_scroll(ddisp, &delta); tool->last_pos = to; } ddisplay_flush(ddisp); }
static void modify_button_press(ModifyTool *tool, GdkEventButton *event, DDisplay *ddisp) { Point clickedpoint; DiaObject *clicked_obj; gboolean some_selected; ddisplay_untransform_coords(ddisp, (int)event->x, (int)event->y, &clickedpoint.x, &clickedpoint.y); /* don't got to single handle movement if there is more than one object selected */ some_selected = g_list_length (ddisp->diagram->data->selected) > 1; if (!some_selected && do_if_clicked_handle(ddisp, tool, &clickedpoint, event)) return; clicked_obj = click_select_object(ddisp, &clickedpoint, event); if (!some_selected && do_if_clicked_handle(ddisp, tool, &clickedpoint, event)) return; if ( clicked_obj != NULL ) { tool->state = STATE_MOVE_OBJECT; tool->object = clicked_obj; tool->move_compensate = clicked_obj->position; point_sub(&tool->move_compensate, &clickedpoint); tool->break_connections = TRUE; /* unconnect when not grabbing handles, just setting to * FALSE is not enough. Need to refine the move op, too. */ 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); tool->start_at = clickedpoint; tool->start_time = time_micro(); ddisplay_set_all_cursor_name (NULL, "move"); } else { tool->state = STATE_BOX_SELECT; tool->start_box = clickedpoint; tool->end_box = clickedpoint; tool->x1 = tool->x2 = (int) event->x; tool->y1 = tool->y2 = (int) event->y; dia_interactive_renderer_set_selection (ddisp->renderer, TRUE, tool->x1, tool->y1, tool->x2 - tool->x1, tool->y2 - tool->y1); ddisplay_flush (ddisp); 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); } }
/* Got when an area previously obscured need to be redrawn. * Needs GDK_EXPOSURE_MASK. * Gone with gtk+-3.0 or better replaced by "draw". */ static gboolean canvas_expose_event (GtkWidget *widget, GdkEventExpose *event, DDisplay *ddisp) { ddisplay_add_display_area (ddisp, event->area.x, event->area.y, event->area.x + event->area.width, event->area.y + event->area.height); ddisplay_flush(ddisp); return FALSE; }
void diagram_flush(Diagram *dia) { GSList *l; DDisplay *ddisp; l = dia->displays; while (l!=NULL) { ddisp = (DDisplay *) l->data; ddisplay_flush(ddisp); l = g_slist_next(l); } dynobj_refresh_kick(); }
/** Scroll display to where point x,y (window coords) is visible */ gboolean ddisplay_autoscroll(DDisplay *ddisp, int x, int y) { guint16 width, height; Point scroll; if (! ddisp->autoscroll) return FALSE; scroll.x = scroll.y = 0; width = GTK_WIDGET(ddisp->canvas)->allocation.width; height = GTK_WIDGET(ddisp->canvas)->allocation.height; if (x < 0) { scroll.x = x; } else if ( x > width) { scroll.x = x - width; } if (y < 0) { scroll.y = y; } else if (y > height) { scroll.y = y - height; } if ((scroll.x != 0) || (scroll.y != 0)) { gboolean scrolled; scroll.x = ddisplay_untransform_length(ddisp, scroll.x); scroll.y = ddisplay_untransform_length(ddisp, scroll.y); scrolled = ddisplay_scroll(ddisp, &scroll); if (scrolled) { ddisplay_flush(ddisp); return TRUE; } } return FALSE; }
void ddisplay_show_all (DDisplay *ddisp) { Diagram *dia; real magnify_x, magnify_y; int width, height; Point middle; g_return_if_fail (ddisp != NULL); dia = ddisp->diagram; width = dia_renderer_get_width_pixels (ddisp->renderer); height = dia_renderer_get_height_pixels (ddisp->renderer); /* if there is something selected show that instead of all exisiting objects */ if (dia->data->selected) { GList *list = dia->data->selected; Rectangle extents = *dia_object_get_enclosing_box ((DiaObject*)list->data); list = g_list_next(list); while (list) { DiaObject *obj = (DiaObject *)list->data; rectangle_union(&extents, dia_object_get_enclosing_box (obj)); list = g_list_next(list); } magnify_x = (real)width / (extents.right - extents.left) / ddisp->zoom_factor; magnify_y = (real)height / (extents.bottom - extents.top) / ddisp->zoom_factor; middle.x = extents.left + (extents.right - extents.left) / 2.0; middle.y = extents.top + (extents.bottom - extents.top) / 2.0; } else { magnify_x = (real)width / (dia->data->extents.right - dia->data->extents.left) / ddisp->zoom_factor; magnify_y = (real)height / (dia->data->extents.bottom - dia->data->extents.top) / ddisp->zoom_factor; middle.x = dia->data->extents.left + (dia->data->extents.right - dia->data->extents.left) / 2.0; middle.y = dia->data->extents.top + (dia->data->extents.bottom - dia->data->extents.top) / 2.0; } ddisplay_zoom (ddisp, &middle, ((magnify_x<magnify_y)?magnify_x:magnify_y)/1.05); ddisplay_update_scrollbars(ddisp); ddisplay_add_update_all(ddisp); ddisplay_flush(ddisp); }
void ddisplay_resize_canvas(DDisplay *ddisp, int width, int height) { if (ddisp->renderer==NULL) { if (ddisp->aa_renderer) ddisp->renderer = new_aa_renderer (ddisp); else ddisp->renderer = new_gdk_renderer(ddisp); } dia_renderer_set_size(ddisp->renderer, gtk_widget_get_window(ddisp->canvas), width, height); ddisplay_set_origo(ddisp, ddisp->origo.x, ddisp->origo.y); ddisplay_add_update_all(ddisp); ddisplay_flush(ddisp); }
void ddisplay_zoom(DDisplay *ddisp, Point *point, real magnify) { Rectangle *visible; real width, height, old_zoom; visible = &ddisp->visible; if ((ddisp->zoom_factor <= DDISPLAY_MIN_ZOOM) && (magnify<=1.0)) return; if ((ddisp->zoom_factor >= DDISPLAY_MAX_ZOOM) && (magnify>=1.0)) return; old_zoom = ddisp->zoom_factor; ddisp->zoom_factor = old_zoom * magnify; /* clip once more */ if (ddisp->zoom_factor < DDISPLAY_MIN_ZOOM) ddisp->zoom_factor = DDISPLAY_MIN_ZOOM; else if (ddisp->zoom_factor > DDISPLAY_MAX_ZOOM) ddisp->zoom_factor = DDISPLAY_MAX_ZOOM; /* the real one used - after clipping */ magnify = ddisp->zoom_factor / old_zoom; width = (visible->right - visible->left)/magnify; height = (visible->bottom - visible->top)/magnify; ddisplay_set_origo(ddisp, point->x - width/2.0, point->y - height/2.0); ddisplay_update_scrollbars(ddisp); ddisplay_add_update_all(ddisp); ddisplay_flush(ddisp); update_zoom_status (ddisp); }
static void modify_button_release(ModifyTool *tool, GdkEventButton *event, DDisplay *ddisp) { Point *dest_pos, to; GList *list; int i; ObjectChange *objchange; tool->break_connections = FALSE; ddisplay_set_all_cursor(default_cursor); /* remove position from status bar */ { GtkStatusbar *statusbar = GTK_STATUSBAR (ddisp->modified_status); guint context_id = gtk_statusbar_get_context_id (statusbar, "ObjectPos"); gtk_statusbar_pop (statusbar, context_id); } switch (tool->state) { case STATE_MOVE_OBJECT: /* Return to normal state */ gdk_pointer_ungrab (event->time); ddisplay_untransform_coords(ddisp, event->x, event->y, &to.x, &to.y); if (!modify_move_already(tool, ddisp, &to)) { tool->orig_pos = NULL; tool->state = STATE_NONE; return; } diagram_update_connections_selection(ddisp->diagram); if (tool->orig_pos != NULL) { /* consider the non-selected children affected */ list = parent_list_affected(ddisp->diagram->data->selected); dest_pos = g_new(Point, g_list_length(list)); i=0; while (list != NULL) { DiaObject *obj = (DiaObject *) list->data; dest_pos[i] = obj->position; list = g_list_next(list); i++; } undo_move_objects(ddisp->diagram, tool->orig_pos, dest_pos, parent_list_affected(ddisp->diagram->data->selected)); } ddisplay_connect_selected(ddisp); /* pushes UNDO info */ diagram_update_extents(ddisp->diagram); diagram_modified(ddisp->diagram); diagram_flush(ddisp->diagram); undo_set_transactionpoint(ddisp->diagram->undo); tool->orig_pos = NULL; tool->state = STATE_NONE; break; case STATE_MOVE_HANDLE: gdk_pointer_ungrab (event->time); tool->state = STATE_NONE; if (tool->orig_pos != NULL) { undo_move_handle(ddisp->diagram, tool->handle, tool->object, *tool->orig_pos, tool->last_to, gdk_event_to_dia_ModifierKeys(event->state)); } /* Final move: */ object_add_updates(tool->object, ddisp->diagram); objchange = tool->object->ops->move_handle(tool->object, tool->handle, &tool->last_to, NULL, HANDLE_MOVE_USER_FINAL,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); /* Connect if possible: */ if (tool->handle->connect_type != HANDLE_NONCONNECTABLE) { object_connect_display(ddisp, tool->object, tool->handle, TRUE); /* pushes UNDO info */ diagram_update_connections_selection(ddisp->diagram); } highlight_reset_all(ddisp->diagram); diagram_flush(ddisp->diagram); diagram_modified(ddisp->diagram); diagram_update_extents(ddisp->diagram); undo_set_transactionpoint(ddisp->diagram->undo); if (tool->orig_pos != NULL) { g_free(tool->orig_pos); tool->orig_pos = NULL; } break; case STATE_BOX_SELECT: gdk_pointer_ungrab (event->time); /* Remove last box: */ dia_interactive_renderer_set_selection (ddisp->renderer, FALSE, 0, 0, 0, 0); { GList *list, *list_to_free; list = list_to_free = find_selected_objects(ddisp, tool); if (selection_style == SELECT_REPLACE && !(event->state & GDK_SHIFT_MASK)) { /* Not Multi-select => Remove all selected */ diagram_remove_all_selected(ddisp->diagram, TRUE); } if (selection_style == SELECT_INTERSECTION) { GList *intersection = NULL; while (list != NULL) { DiaObject *obj = (DiaObject *)list->data; if (diagram_is_selected(ddisp->diagram, obj)) { intersection = g_list_append(intersection, obj); } list = g_list_next(list); } list = intersection; diagram_remove_all_selected(ddisp->diagram, TRUE); while (list != NULL) { DiaObject *obj = (DiaObject *)list->data; diagram_select(ddisp->diagram, obj); list = g_list_next(list); } g_list_free(intersection); } else { while (list != NULL) { DiaObject *obj = (DiaObject *)list->data; if (selection_style == SELECT_REMOVE) { if (diagram_is_selected(ddisp->diagram, obj)) diagram_unselect_object(ddisp->diagram, obj); } else if (selection_style == SELECT_INVERT) { if (diagram_is_selected(ddisp->diagram, obj)) diagram_unselect_object(ddisp->diagram, obj); else diagram_select(ddisp->diagram, obj); } else { if (!diagram_is_selected(ddisp->diagram, obj)) diagram_select(ddisp->diagram, obj); } list = g_list_next(list); } } g_list_free(list_to_free); } ddisplay_do_update_menu_sensitivity(ddisp); ddisplay_flush(ddisp); tool->state = STATE_NONE; break; case STATE_NONE: break; default: message_error("Internal error: Strange state in modify_tool\n"); } }
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; }