void diagram_add_object_list(Diagram *dia, GList *list) { layer_add_objects(dia->data->active_layer, list); diagram_modified(dia); }
void diagram_add_object(Diagram *dia, DiaObject *obj) { layer_add_object(dia->data->active_layer, obj); diagram_modified(dia); }
/** Remove the currently selected objects from the diagram's object list. * Returns a newly created list of the selected objects, in order. */ GList * diagram_get_sorted_selected_remove(Diagram *dia) { diagram_modified(dia); return data_get_sorted_selected_remove(dia->data); }
static gint properties_apply(GtkWidget *canvas, gpointer data) { ObjectChange *obj_change = NULL; if ( (current_obj == NULL) || (current_dia == NULL) ) return 0; object_add_updates(current_obj, current_dia); obj_change = current_obj->ops->apply_properties(current_obj); object_add_updates(current_obj, current_dia); diagram_update_connections_object(current_dia, current_obj, TRUE); if (obj_change != NULL) { undo_object_change(current_dia, current_obj, obj_change); } diagram_modified(current_dia); diagram_update_extents(current_dia); if (obj_change != NULL) { undo_set_transactionpoint(current_dia->undo); } else { message_warning(_("This object doesn't support Undo/Redo.\n" "Undo information erased.")); undo_clear(current_dia->undo); } diagram_flush(current_dia); return 0; }
/** Remove all children from the selected parents. */ void diagram_unparent_children_selected(Diagram *dia) { GList *list; DiaObject *obj, *child; gboolean any_unparented = FALSE; for (list = dia->data->selected; list != NULL; list = g_list_next(list)) { obj = (DiaObject *) list->data; if (!object_flags_set(obj, DIA_OBJECT_CAN_PARENT) || !obj->children) continue; any_unparented = TRUE; /* Yes, this creates a whole bunch of Changes. They're lightweight * structures, though, and it's easier to assure correctness this * way. If needed, we can make a parent undo with a list of children. */ while (obj->children != NULL) { Change *change; child = (DiaObject *) obj->children->data; change = undo_parenting(dia, obj, child, FALSE); /* This will remove one item from the list, so the while terminates. */ (change->apply)(change, dia); } if (obj->children != NULL) printf("Obj still has %d children\n", g_list_length(obj->children)); } if (any_unparented) { diagram_modified(dia); diagram_flush(dia); undo_set_transactionpoint(dia->undo); } }
/** Remove all selected objects from their parents (if any). */ void diagram_unparent_selected(Diagram *dia) { GList *list; DiaObject *obj, *parent; Change *change; gboolean any_unparented = FALSE; for (list = dia->data->selected; list != NULL; list = g_list_next(list)) { obj = (DiaObject *) list->data; parent = obj->parent; if (!parent) continue; change = undo_parenting(dia, parent, obj, FALSE); (change->apply)(change, dia); any_unparented = TRUE; /* parent->children = g_list_remove(parent->children, obj); obj->parent = NULL; */ } if (any_unparented) { diagram_modified(dia); diagram_flush(dia); undo_set_transactionpoint(dia->undo); } }
/* Match and replace property values. */ static gboolean _replace (DiaObject *obj, const SearchData *sd, const char *replacement) { ObjectChange *obj_change; GPtrArray *plist = NULL; plist = _match_props (obj, sd, replacement); if (!plist) return FALSE; /* Refresh screen and free the list of modified properties. */ obj_change = object_apply_props (obj, plist); prop_list_free (plist); if (obj_change) undo_object_change(sd->diagram, obj, obj_change); object_add_updates(obj, sd->diagram); diagram_update_connections_object(sd->diagram, obj, TRUE); diagram_modified(sd->diagram); diagram_object_modified(sd->diagram, obj); diagram_update_extents(sd->diagram); diagram_flush(sd->diagram); return TRUE; }
/** Set this diagram explicitly modified. This should not be called * by things that change the undo stack, as those modifications are * noticed through changes in the undo stack. */ void diagram_set_modified(Diagram *dia, int modified) { if (dia->mollified != modified) { dia->mollified = modified; } diagram_modified(dia); }
static gint properties_respond(GtkWidget *widget, gint response_id, gpointer data) { ObjectChange *obj_change = NULL; gboolean set_tp = TRUE; GList *tmp; if ( response_id == GTK_RESPONSE_APPLY || response_id == GTK_RESPONSE_OK) { if ((current_objects != NULL) && (current_dia != NULL)) { object_add_updates_list(current_objects, current_dia); for (tmp = current_objects; tmp != NULL; tmp = tmp->next) { DiaObject *current_obj = (DiaObject*)tmp->data; obj_change = current_obj->ops->apply_properties_from_dialog(current_obj, object_part); object_add_updates(current_obj, current_dia); diagram_update_connections_object(current_dia, current_obj, TRUE); if (obj_change != NULL) { undo_object_change(current_dia, current_obj, obj_change); set_tp = set_tp && TRUE; } else set_tp = FALSE; diagram_object_modified(current_dia, current_obj); } diagram_modified(current_dia); diagram_update_extents(current_dia); if (set_tp) { undo_set_transactionpoint(current_dia->undo); } else { message_warning(_("This object doesn't support Undo/Redo.\n" "Undo information erased.")); undo_clear(current_dia->undo); } diagram_flush(current_dia); } } if (response_id != GTK_RESPONSE_APPLY) { #ifdef G_OS_WIN32 /* on windows we are not hiding the dialog, because shrinking when hidden does * not work (the dialog shows up with the same size as before, bug #333751) */ gtk_widget_destroy (dialog); #else properties_dialog_hide(); #endif } return 0; }
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); }
int diagram_load_into(Diagram *diagram, const char *filename, DiaImportFilter *ifilter) { /* ToDo: move context further up in the callstack and to sth useful with it's content */ DiaContext *ctx = dia_context_new(_("Load Into")); gboolean was_default = diagram->is_default; if (!ifilter) ifilter = filter_guess_import_filter(filename); /* slightly hacked to avoid 'Not a Dia File' for .shape */ if (!ifilter && g_str_has_suffix (filename, ".shape")) ifilter = filter_import_get_by_name ("dia-svg"); if (!ifilter) /* default to native format */ ifilter = &dia_import_filter; dia_context_set_filename (ctx, filename); if (ifilter->import_func(filename, diagram->data, ctx, ifilter->user_data)) { if (ifilter != &dia_import_filter) { /* When loading non-Dia files, change filename to reflect that saving * will produce a Dia file. See bug #440093 */ if (strcmp (diagram->filename, filename) == 0) { /* not a real load into but initial load */ gchar *old_filename = g_strdup (diagram->filename); gchar *suffix_offset = g_utf8_strrchr(old_filename, -1, (gunichar)'.'); gchar *new_filename; if (suffix_offset != NULL) { new_filename = g_strndup(old_filename, suffix_offset - old_filename); g_free(old_filename); } else { new_filename = old_filename; } old_filename = g_strconcat(new_filename, ".dia", NULL); g_free(new_filename); diagram_set_filename(diagram, old_filename); g_free(old_filename); diagram->unsaved = TRUE; diagram_update_for_filename (diagram); diagram_modified(diagram); } } else { /* the initial diagram should have confirmed filename */ diagram->unsaved = strcmp(filename, diagram->filename) == 0 ? FALSE : was_default; } diagram_set_modified(diagram, TRUE); dia_context_release(ctx); return TRUE; } else { dia_context_release(ctx); return FALSE; } }
/* needs faster algorithm -- if we find that parenting is slow. * If it works, don't optimize it until it's a hotspot. */ void diagram_parent_selected(Diagram *dia) { GList *list = dia->data->selected; int length = g_list_length(list); int idx, idx2; ObjectExtent *oe; gboolean any_parented = FALSE; GPtrArray *extents = g_ptr_array_sized_new(length); while (list) { oe = g_new(ObjectExtent, 1); oe->object = list->data; parent_handle_extents(list->data, &oe->extent); g_ptr_array_add(extents, oe); list = g_list_next(list); } /* sort all the objects by their left position */ g_ptr_array_sort(extents, diagram_parent_sort_cb); for (idx = 0; idx < length; idx++) { ObjectExtent *oe1 = g_ptr_array_index(extents, idx); if (oe1->object->parent) continue; for (idx2 = idx + 1; idx2 < length; idx2++) { ObjectExtent *oe2 = g_ptr_array_index(extents, idx2); if (!object_flags_set(oe2->object, DIA_OBJECT_CAN_PARENT)) continue; if (oe1->extent.right <= oe2->extent.right && oe1->extent.bottom <= oe2->extent.bottom) { Change *change; change = undo_parenting(dia, oe2->object, oe1->object, TRUE); (change->apply)(change, dia); any_parented = TRUE; /* oe1->object->parent = oe2->object; oe2->object->children = g_list_append(oe2->object->children, oe1->object); */ break; } } } g_ptr_array_free(extents, TRUE); if (any_parented) { diagram_modified(dia); diagram_flush(dia); undo_set_transactionpoint(dia->undo); } }
void diagram_place_down_selected(Diagram *dia) { GList *sorted_list; GList *orig_list; GList *tmp, *stmp; GList *new_list = NULL; if (g_list_length (dia->data->selected) == 0) return; orig_list = g_list_copy(dia->data->active_layer->objects); sorted_list = diagram_get_sorted_selected(dia); object_add_updates_list(orig_list, dia); /* Sanity check */ g_assert(g_list_length (dia->data->selected) == g_list_length(sorted_list)); new_list = g_list_copy(orig_list); stmp = sorted_list; for (tmp = new_list; tmp != NULL; tmp = g_list_next(tmp)) { if (stmp == NULL) break; if (tmp->next == NULL) break; if (tmp->data == stmp->data) { /* This just takes care of any starting matches */ stmp = g_list_next(stmp); } else if (tmp->next->data == stmp->data) { /* This flips the non-selected element forwards, ala bubblesort */ void *swap = tmp->data; tmp->data = tmp->next->data; tmp->next->data = swap; stmp = g_list_next(stmp); } } layer_set_object_list(dia->data->active_layer, new_list); undo_reorder_objects(dia, g_list_copy(sorted_list), orig_list); diagram_modified(dia); diagram_flush(dia); undo_set_transactionpoint(dia->undo); }
void diagram_ungroup_selected(Diagram *dia) { DiaObject *group; GList *group_list; GList *selected, *selection_copy; int group_index; int any_groups = 0; if (g_list_length(dia->data->selected) < 1) { message_error("Trying to ungroup with no selected objects."); return; } selection_copy = g_list_copy(dia->data->selected); selected = selection_copy; while (selected != NULL) { group = (DiaObject *)selected->data; if (IS_GROUP(group)) { Change *change; /* Fix selection */ diagram_unselect_object(dia, group); group_list = group_objects(group); group_index = layer_object_get_index(dia->data->active_layer, group); change = undo_ungroup_objects(dia, group_list, group, group_index); (change->apply)(change, dia); diagram_select_list(dia, group_list); any_groups = 1; } selected = g_list_next(selected); } g_list_free(selection_copy); if (any_groups) { diagram_modified(dia); diagram_flush(dia); undo_set_transactionpoint(dia->undo); } }
void diagram_place_up_selected(Diagram *dia) { GList *sorted_list; GList *orig_list; GList *tmp, *stmp; GList *new_list = NULL; if (g_list_length (dia->data->selected) == 0) return; orig_list = g_list_copy(dia->data->active_layer->objects); sorted_list = diagram_get_sorted_selected(dia); object_add_updates_list(orig_list, dia); new_list = g_list_copy(orig_list); stmp = g_list_last(sorted_list); for (tmp = g_list_last(new_list); tmp != NULL; tmp = g_list_previous(tmp)) { if (stmp == NULL) break; if (tmp->prev == NULL) break; if (tmp->data == stmp->data) { stmp = g_list_previous(stmp); } else if (tmp->prev->data == stmp->data) { void *swap = tmp->data; tmp->data = tmp->prev->data; tmp->prev->data = swap; stmp = g_list_previous(stmp); } } layer_set_object_list(dia->data->active_layer, new_list); undo_reorder_objects(dia, g_list_copy(sorted_list), orig_list); diagram_modified(dia); diagram_flush(dia); undo_set_transactionpoint(dia->undo); }
static void plugin_callback (GtkWidget *widget, gpointer data) { DiaCallbackFilter *cbf = data; /* check if the callback filter is still available */ if (!g_list_find (filter_get_callbacks (), cbf)) { message_error (_("The function is not available anymore.")); return; } /* and finally invoke it */ if (cbf->callback) { DDisplay *ddisp = NULL; DiagramData* diadata = NULL; ObjectChange *change; /* stuff from the toolbox menu should never get a diagram to modify */ if (strncmp (cbf->menupath, TOOLBOX_MENU, strlen (TOOLBOX_MENU)) != 0) { ddisp = ddisplay_active(); diadata = ddisp ? ddisp->diagram->data : NULL; } change = cbf->callback (diadata, ddisp ? ddisp->diagram->filename : NULL, 0, cbf->user_data); if (change != NULL) { if (ddisp) { undo_object_change(ddisp->diagram, NULL, change); /* * - can not call object_add_update() w/o object * - could call object_add_updates_list() with the selected objects, * but that would just be an educated guess (layout working on selection) */ diagram_add_update_all(ddisp->diagram); diagram_modified(ddisp->diagram); diagram_update_extents(ddisp->diagram); undo_set_transactionpoint(ddisp->diagram->undo); } else { /* no diagram to keep the change, throw it away */ if (change->free) change->free(change); g_free(change); } } } }
void diagram_place_over_selected(Diagram *dia) { GList *sorted_list; GList *orig_list; if (g_list_length (dia->data->selected) == 0) return; orig_list = g_list_copy(dia->data->active_layer->objects); sorted_list = diagram_get_sorted_selected_remove(dia); object_add_updates_list(sorted_list, dia); layer_add_objects(dia->data->active_layer, sorted_list); undo_reorder_objects(dia, g_list_copy(sorted_list), orig_list); 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 create_object_button_release(CreateObjectTool *tool, GdkEventButton *event, DDisplay *ddisp) { GList *list = NULL; DiaObject *obj = tool->obj; gboolean reset; GList *parent_candidates; g_return_if_fail (obj != NULL); if (!obj) /* not sure if this isn't enough */ return; /* could be a legal invariant */ if (tool->moving) { gdk_pointer_ungrab (event->time); object_add_updates(tool->obj, ddisp->diagram); tool->obj->ops->move_handle(tool->obj, tool->handle, &tool->last_to, NULL, HANDLE_MOVE_CREATE_FINAL, 0); object_add_updates(tool->obj, ddisp->diagram); } parent_candidates = layer_find_objects_containing_rectangle(obj->parent_layer, &obj->bounding_box); /* whole object must be within another object to parent it */ for (; parent_candidates != NULL; parent_candidates = g_list_next(parent_candidates)) { DiaObject *parent_obj = (DiaObject *) parent_candidates->data; if (obj != parent_obj && object_within_parent(obj, parent_obj)) { Change *change = undo_parenting(ddisp->diagram, parent_obj, obj, TRUE); (change->apply)(change, ddisp->diagram); break; /* obj->parent = parent_obj; parent_obj->children = g_list_append(parent_obj->children, obj); */ } } g_list_free(parent_candidates); list = g_list_prepend(list, tool->obj); undo_insert_objects(ddisp->diagram, list, 1); if (tool->moving) { if (tool->handle->connect_type != HANDLE_NONCONNECTABLE) { object_connect_display(ddisp, tool->obj, tool->handle, TRUE); diagram_update_connections_selection(ddisp->diagram); diagram_flush(ddisp->diagram); } tool->moving = FALSE; tool->handle = NULL; tool->obj = NULL; } { /* 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); } highlight_reset_all(ddisp->diagram); reset = prefs.reset_tools_after_create != tool->invert_persistence; /* kind of backward: first starting editing to see if it is possible at all, than GUI reflection */ if (textedit_activate_object(ddisp, obj, NULL) && reset) { gtk_action_activate (menus_get_action ("ToolsTextedit")); reset = FALSE; /* don't switch off textedit below */ } diagram_update_extents(ddisp->diagram); diagram_modified(ddisp->diagram); undo_set_transactionpoint(ddisp->diagram->undo); if (reset) tool_reset(); ddisplay_set_all_cursor(default_cursor); ddisplay_do_update_menu_sensitivity(ddisp); }
void display_set_active(DDisplay *ddisp) { if (ddisp != active_display) { active_display = ddisp; /* perform notification here (such as switch layers dialog) */ layer_dialog_set_diagram(ddisp ? ddisp->diagram : NULL); diagram_properties_set_diagram(ddisp ? ddisp->diagram : NULL); if (ddisp) { if (ddisp->is_standalone_window) { display_update_menu_state(ddisp); if (prefs.toolbox_on_top) { gtk_window_set_transient_for(GTK_WINDOW(interface_get_toolbox_shell()), GTK_WINDOW(ddisp->shell)); } else { gtk_window_set_transient_for(GTK_WINDOW(interface_get_toolbox_shell()), NULL); } } else { GtkNotebook *notebook = g_object_get_data (G_OBJECT (ddisp->shell), DIA_MAIN_NOTEBOOK); /* Find the page with ddisp then set the label on the tab */ gint num_pages = gtk_notebook_get_n_pages (notebook); gint num; GtkWidget *page; for (num = 0 ; num < num_pages ; num++) { page = gtk_notebook_get_nth_page (notebook,num); if (g_object_get_data (G_OBJECT (page), "DDisplay") == ddisp) { gtk_notebook_set_current_page (notebook,num); break; } } /* synchronize_ui_to_active_display (ddisp); */ /* updates display title, etc */ diagram_modified(ddisp->diagram); /* ZOOM */ update_zoom_status (ddisp); /* Snap to grid */ ddisplay_set_snap_to_grid (ddisp, ddisp->grid.snap); /* menus */ /* Object snapping */ ddisplay_set_snap_to_objects (ddisp, ddisp->mainpoint_magnetism); display_update_menu_state (ddisp); gtk_window_present (GTK_WINDOW(ddisp->shell)); } } else { /* TODO: Prevent gtk_window_set_transient_for() in Integrated UI case */ gtk_window_set_transient_for(GTK_WINDOW(interface_get_toolbox_shell()), NULL); } } }