New cisco icons, and a fix in element.h
[dia.git] / app / create_object.c
blobdca025ae17ee29a14f5f2ef920e0b3ad89e49b0d
1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 #include <config.h>
20 #include "create_object.h"
21 #include "connectionpoint_ops.h"
22 #include "handle_ops.h"
23 #include "object_ops.h"
24 #include "preferences.h"
25 #include "undo.h"
26 #include "cursor.h"
27 #include "highlight.h"
28 #include "textedit.h"
30 static void create_object_button_press(CreateObjectTool *tool, GdkEventButton *event,
31 DDisplay *ddisp);
32 static void create_object_button_release(CreateObjectTool *tool, GdkEventButton *event,
33 DDisplay *ddisp);
34 static void create_object_motion(CreateObjectTool *tool, GdkEventMotion *event,
35 DDisplay *ddisp);
36 static void create_object_double_click(CreateObjectTool *tool, GdkEventMotion *event,
37 DDisplay *ddisp);
40 static void
41 create_object_button_press(CreateObjectTool *tool, GdkEventButton *event,
42 DDisplay *ddisp)
44 Point clickedpoint, origpoint;
45 Handle *handle1;
46 Handle *handle2;
47 DiaObject *obj;
48 DiaObject *parent_obj;
49 real click_distance;
50 GList *avoid = NULL;
52 ddisplay_untransform_coords(ddisp,
53 (int)event->x, (int)event->y,
54 &clickedpoint.x, &clickedpoint.y);
56 origpoint = clickedpoint;
58 snap_to_grid(ddisp, &clickedpoint.x, &clickedpoint.y);
60 click_distance = ddisplay_untransform_length(ddisp, 3.0);
62 obj = dia_object_default_create (tool->objtype, &clickedpoint,
63 tool->user_data,
64 &handle1, &handle2);
66 diagram_add_object(ddisp->diagram, obj);
68 /* Make sure to not parent to itself (!) */
69 avoid = g_list_prepend(avoid, obj);
70 /* Try a connect */
71 if (handle1 != NULL &&
72 handle1->connect_type != HANDLE_NONCONNECTABLE) {
73 ConnectionPoint *connectionpoint;
74 connectionpoint =
75 object_find_connectpoint_display(ddisp, &origpoint, obj, TRUE);
76 if (connectionpoint != NULL) {
77 (obj->ops->move)(obj, &origpoint);
78 /* Make sure to not parent to the object connected to */
79 avoid = g_list_prepend(avoid, connectionpoint->object);
84 parent_obj = diagram_find_clicked_object_except(ddisp->diagram,
85 &clickedpoint,
86 click_distance,
87 avoid);
89 g_list_free(avoid);
91 if (parent_obj && parent_obj->can_parent) /* starting point is within another object */
93 Change *change = undo_parenting(ddisp->diagram, parent_obj, obj, TRUE);
94 (change->apply)(change, ddisp->diagram);
96 obj->parent = parent_obj;
97 parent_obj->children = g_list_append(parent_obj->children, obj);
101 if (!(event->state & GDK_SHIFT_MASK)) {
102 /* Not Multi-select => remove current selection */
103 diagram_remove_all_selected(ddisp->diagram, TRUE);
105 diagram_select(ddisp->diagram, obj);
107 tool->obj = obj;
109 /* Connect first handle if possible: */
110 if ((handle1!= NULL) &&
111 (handle1->connect_type != HANDLE_NONCONNECTABLE)) {
112 object_connect_display(ddisp, obj, handle1, TRUE);
115 object_add_updates(obj, ddisp->diagram);
116 ddisplay_do_update_menu_sensitivity(ddisp);
117 diagram_flush(ddisp->diagram);
119 if (handle2 != NULL) {
120 tool->handle = handle2;
121 tool->moving = TRUE;
122 tool->last_to = handle2->pos;
124 gdk_pointer_grab (ddisp->canvas->window, FALSE,
125 GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
126 NULL, NULL, event->time);
127 ddisplay_set_all_cursor(get_cursor(CURSOR_SCROLL));
128 } else {
129 diagram_update_extents(ddisp->diagram);
130 tool->moving = FALSE;
135 static void
136 create_object_double_click(CreateObjectTool *tool, GdkEventMotion *event,
137 DDisplay *ddisp)
141 static void
142 create_object_button_release(CreateObjectTool *tool, GdkEventButton *event,
143 DDisplay *ddisp)
145 GList *list = NULL;
146 DiaObject *obj = tool->obj;
147 if (tool->moving) {
148 gdk_pointer_ungrab (event->time);
150 object_add_updates(tool->obj, ddisp->diagram);
151 tool->obj->ops->move_handle(tool->obj, tool->handle, &tool->last_to,
152 NULL, HANDLE_MOVE_CREATE_FINAL, 0);
153 object_add_updates(tool->obj, ddisp->diagram);
157 list = g_list_prepend(list, tool->obj);
159 undo_insert_objects(ddisp->diagram, list, 1);
161 if (tool->moving) {
162 if (tool->handle->connect_type != HANDLE_NONCONNECTABLE) {
163 object_connect_display(ddisp, tool->obj, tool->handle, TRUE);
164 diagram_update_connections_selection(ddisp->diagram);
165 diagram_flush(ddisp->diagram);
167 tool->moving = FALSE;
168 tool->handle = NULL;
169 tool->obj = NULL;
172 highlight_reset_all(ddisp->diagram);
173 textedit_activate_object(ddisp, obj, NULL);
174 diagram_update_extents(ddisp->diagram);
175 diagram_modified(ddisp->diagram);
177 undo_set_transactionpoint(ddisp->diagram->undo);
179 if (prefs.reset_tools_after_create != tool->invert_persistence)
180 tool_reset();
181 ddisplay_set_all_cursor(default_cursor);
183 static void
184 create_object_motion(CreateObjectTool *tool, GdkEventMotion *event,
185 DDisplay *ddisp)
187 Point to;
188 ConnectionPoint *connectionpoint = NULL;
189 gchar *postext;
190 GtkStatusbar *statusbar;
191 guint context_id;
193 if (!tool->moving)
194 return;
196 ddisplay_untransform_coords(ddisp, event->x, event->y, &to.x, &to.y);
198 /* make sure the new object is restricted to its parent */
199 parent_handle_move_out_check(tool->obj, &to);
201 /* Move to ConnectionPoint if near: */
202 if (tool->handle != NULL &&
203 tool->handle->connect_type != HANDLE_NONCONNECTABLE) {
204 connectionpoint =
205 object_find_connectpoint_display(ddisp, &to, tool->obj, TRUE);
207 if (connectionpoint != NULL) {
208 to = connectionpoint->pos;
209 highlight_object(connectionpoint->object, NULL, ddisp->diagram);
210 ddisplay_set_all_cursor(get_cursor(CURSOR_CONNECT));
214 if (connectionpoint == NULL) {
215 /* No connectionopoint near, then snap to grid (if enabled) */
216 snap_to_grid(ddisp, &to.x, &to.y);
217 highlight_reset_all(ddisp->diagram);
218 ddisplay_set_all_cursor(get_cursor(CURSOR_SCROLL));
221 object_add_updates(tool->obj, ddisp->diagram);
222 tool->obj->ops->move_handle(tool->obj, tool->handle, &to, connectionpoint,
223 HANDLE_MOVE_CREATE, 0);
224 object_add_updates(tool->obj, ddisp->diagram);
226 /* Put current mouse position in status bar */
227 statusbar = GTK_STATUSBAR (ddisp->modified_status);
228 context_id = gtk_statusbar_get_context_id (statusbar, "ObjectPos");
230 postext = g_strdup_printf("%.3f, %.3f - %.3f, %.3f",
231 tool->obj->bounding_box.left,
232 tool->obj->bounding_box.top,
233 tool->obj->bounding_box.right,
234 tool->obj->bounding_box.bottom);
236 gtk_statusbar_pop (statusbar, context_id);
237 gtk_statusbar_push (statusbar, context_id, postext);
239 g_free(postext);
241 diagram_flush(ddisp->diagram);
243 tool->last_to = to;
245 return;
250 Tool *
251 create_create_object_tool(DiaObjectType *objtype, void *user_data,
252 int invert_persistence)
254 CreateObjectTool *tool;
256 tool = g_new0(CreateObjectTool, 1);
257 tool->tool.type = CREATE_OBJECT_TOOL;
258 tool->tool.button_press_func = (ButtonPressFunc) &create_object_button_press;
259 tool->tool.button_release_func = (ButtonReleaseFunc) &create_object_button_release;
260 tool->tool.motion_func = (MotionFunc) &create_object_motion;
261 tool->tool.double_click_func = (DoubleClickFunc) &create_object_double_click;
263 tool->objtype = objtype;
264 tool->user_data = user_data;
265 tool->moving = FALSE;
266 tool->invert_persistence = invert_persistence;
268 return (Tool *) tool;
271 void free_create_object_tool(Tool *tool)
273 g_free(tool);