void diagram_group_selected(Diagram *dia) { GList *list; GList *group_list; DiaObject *group; DiaObject *obj; GList *orig_list; Change *change; if (g_list_length(dia->data->selected) < 1) { message_error(_("Trying to group with no selected objects.")); return; } #if 0 /* the following is wrong as it screws up the selected list, see bug #153525 * I just don't get what was originally intented so please speak up if you know --hb */ dia->data->selected = parent_list_affected(dia->data->selected); #endif orig_list = g_list_copy(dia->data->active_layer->objects); /* We have to rebuild the selection list so that it is the same order as in the Diagram list. */ group_list = diagram_get_sorted_selected_remove(dia); list = group_list; while (list != NULL) { obj = (DiaObject *)list->data; /* Remove connections from obj to objects outside created group. */ /* strip_connections sets up its own undo info. */ /* The connections aren't reattached by ungroup. */ strip_connections(obj, dia->data->selected, dia); list = g_list_next(list); } /* Remove list of selected objects */ textedit_remove_focus_all(dia); data_remove_all_selected(dia->data); group = group_create(group_list); change = undo_group_objects(dia, group_list, group, orig_list); (change->apply)(change, dia); /* Select the created group */ diagram_select(dia, group); diagram_modified(dia); diagram_flush(dia); undo_set_transactionpoint(dia->undo); }
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; }
void Panel::mouseMoveEvent(QMouseEvent *e) { QWidget::mouseMoveEvent(e); if (m_data->state == STATE_NONE) return; // 坐标转换 QPointF clickedPos = untransformCoords(e->posF()); IView *view = m_data->view; switch(m_data->state) { case STATE_MOVE_OBJECT: { Object *obj = m_data->object; IDoc *doc = m_data->doc; Handle *handle = m_data->handle; QPointF pos = clickedPos; std::list<Object *> tmp = m_data->graphData->selectedObjects(); std::list<Object *> list = parent_list_affected( tmp); // 当是包含子对象的图元被移动的时候 // 子对象也一起移动 if (list.size() > 1) { Object::object_add_updates_list(list, doc); //鼠标移动的差值 QPointF offset = pos - m_data->startAt; QPointF targetPos = m_data->origPos + offset; //对象移动的差值 QPointF delta = targetPos - obj->pos(); //qDebug() << delta; Object::object_list_move_delta(list, &delta); Object::object_add_updates_list(list, doc); } else { // 否则,只移动对象本身 obj->addUpdates(doc); //鼠标移动的差值 QPointF offset = pos - m_data->startAt; QPointF targetPos = m_data->origPos + offset; obj->move(&targetPos); obj->addUpdates(doc); } doc->flush(); update(); } break; case STATE_MOVE_HANDLE: { Object *obj = m_data->object; IDoc *doc = m_data->doc; Handle *handle = m_data->handle; QPointF pos = clickedPos; obj->addUpdates(doc); obj->moveHandle(handle, &pos, GraphLib::HANDLE_MOVE_USER); obj->addUpdates(doc); doc->flush(); update(); } break; case STATE_NONE: break; }; }
static void newgroup_update_data(NewGroup *group) { Element *elem = &group->element; /* ElementBBExtras *extra = &elem->extra_spacing; */ DiaObject *obj = &elem->object; /* Update connections: */ group->connections[0].pos.x = elem->corner.x; group->connections[0].pos.y = elem->corner.y; group->connections[1].pos.x = elem->corner.x + elem->width / 2.0; group->connections[1].pos.y = elem->corner.y; group->connections[2].pos.x = elem->corner.x + elem->width; group->connections[2].pos.y = elem->corner.y; group->connections[3].pos.x = elem->corner.x; group->connections[3].pos.y = elem->corner.y + elem->height / 2.0; group->connections[4].pos.x = elem->corner.x + elem->width; group->connections[4].pos.y = elem->corner.y + elem->height / 2.0; group->connections[5].pos.x = elem->corner.x; group->connections[5].pos.y = elem->corner.y + elem->height; group->connections[6].pos.x = elem->corner.x + elem->width / 2.0; group->connections[6].pos.y = elem->corner.y + elem->height; group->connections[7].pos.x = elem->corner.x + elem->width; group->connections[7].pos.y = elem->corner.y + elem->height; group->connections[8].pos.x = elem->corner.x + elem->width / 2.0; group->connections[8].pos.y = elem->corner.y + elem->height / 2.0; group->connections[0].directions = DIR_NORTH|DIR_WEST; group->connections[1].directions = DIR_NORTH; group->connections[2].directions = DIR_NORTH|DIR_EAST; group->connections[3].directions = DIR_WEST; group->connections[4].directions = DIR_EAST; group->connections[5].directions = DIR_SOUTH|DIR_WEST; group->connections[6].directions = DIR_SOUTH; group->connections[7].directions = DIR_SOUTH|DIR_EAST; group->connections[8].directions = DIR_ALL; element_update_boundingbox(elem); obj->position = elem->corner; element_update_handles(elem); if (group->is_open) { obj->flags &= ~DIA_OBJECT_GRABS_CHILD_INPUT; } else { gboolean newlySet = FALSE; Layer *layer; if (!object_flags_set(obj, DIA_OBJECT_GRABS_CHILD_INPUT)) { newlySet = TRUE; } obj->flags |= DIA_OBJECT_GRABS_CHILD_INPUT; if (newlySet) { layer = dia_object_get_parent_layer(obj); if (layer != NULL) { /* Placed in diagram already */ GList *children = g_list_prepend(NULL, obj); children = parent_list_affected(children); /* Remove the group object that stayed at the start of the list, leaving only the children */ children = g_list_remove_link(children, children); #if 0 /* this introduces a crircular dependency, does not work on win32 and is bad style everywhere */ diagram_unselect_objects(layer_get_parent_diagram(layer), children); #else g_warning ("used to call diagram_unselect_objects()"); #endif g_list_free(children); } } } }
/* This function deletes specified objects along with any children they might have. undo_delete_objects() only deletes the objects that are specified. */ Change * undo_delete_objects_children(Diagram *dia, GList *obj_list) { return undo_delete_objects(dia, parent_list_affected(obj_list)); }