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 "create_object.h"
19 #include "connectionpoint_ops.h"
20 #include "handle_ops.h"
21 #include "object_ops.h"
22 #include "preferences.h"
25 static void create_object_button_press(CreateObjectTool
*tool
, GdkEventButton
*event
,
27 static void create_object_button_release(CreateObjectTool
*tool
, GdkEventButton
*event
,
29 static void create_object_motion(CreateObjectTool
*tool
, GdkEventMotion
*event
,
31 static void create_object_double_click(CreateObjectTool
*tool
, GdkEventMotion
*event
,
36 create_object_button_press(CreateObjectTool
*tool
, GdkEventButton
*event
,
39 Point clickedpoint
, origpoint
;
44 ddisplay_untransform_coords(ddisp
,
45 (int)event
->x
, (int)event
->y
,
46 &clickedpoint
.x
, &clickedpoint
.y
);
48 origpoint
= clickedpoint
;
50 snap_to_grid(ddisp
, &clickedpoint
.x
, &clickedpoint
.y
);
52 obj
= tool
->objtype
->ops
->create(&clickedpoint
, tool
->user_data
,
54 diagram_add_object(ddisp
->diagram
, obj
);
57 if (handle1
!= NULL
&&
58 handle1
->connect_type
!= HANDLE_NONCONNECTABLE
) {
59 ConnectionPoint
*connectionpoint
;
61 object_find_connectpoint_display(ddisp
, &origpoint
);
62 if (connectionpoint
!= NULL
) {
63 (obj
->ops
->move
)(obj
, &origpoint
);
67 if (!(event
->state
& GDK_SHIFT_MASK
)) {
68 /* Not Multi-select => remove current selection */
69 diagram_remove_all_selected(ddisp
->diagram
, TRUE
);
71 diagram_select(ddisp
->diagram
, obj
);
73 obj
->ops
->selectf(obj
, &clickedpoint
,
74 (Renderer
*)ddisp
->renderer
);
78 /* Connect first handle if possible: */
79 if ((handle1
!= NULL
) &&
80 (handle1
->connect_type
!= HANDLE_NONCONNECTABLE
)) {
81 object_connect_display(ddisp
, obj
, handle1
);
84 object_add_updates(obj
, ddisp
->diagram
);
85 diagram_flush(ddisp
->diagram
);
87 if (handle2
!= NULL
) {
88 tool
->handle
= handle2
;
90 tool
->last_to
= handle2
->pos
;
92 gdk_pointer_grab (ddisp
->canvas
->window
, FALSE
,
93 GDK_POINTER_MOTION_HINT_MASK
| GDK_BUTTON1_MOTION_MASK
| GDK_BUTTON_RELEASE_MASK
,
94 NULL
, NULL
, event
->time
);
96 diagram_update_extents(ddisp
->diagram
);
102 create_object_double_click(CreateObjectTool
*tool
, GdkEventMotion
*event
,
108 create_object_button_release(CreateObjectTool
*tool
, GdkEventButton
*event
,
113 gdk_pointer_ungrab (event
->time
);
115 object_add_updates(tool
->obj
, ddisp
->diagram
);
116 tool
->obj
->ops
->move_handle(tool
->obj
, tool
->handle
, &tool
->last_to
,
117 HANDLE_MOVE_CREATE_FINAL
,0);
118 object_add_updates(tool
->obj
, ddisp
->diagram
);
122 list
= g_list_prepend(list
, tool
->obj
);
124 undo_insert_objects(ddisp
->diagram
, list
, 1);
127 if (tool
->handle
->connect_type
!= HANDLE_NONCONNECTABLE
) {
128 object_connect_display(ddisp
, tool
->obj
, tool
->handle
);
129 diagram_update_connections_selection(ddisp
->diagram
);
130 diagram_flush(ddisp
->diagram
);
132 tool
->moving
= FALSE
;
137 diagram_update_extents(ddisp
->diagram
);
138 diagram_modified(ddisp
->diagram
);
140 undo_set_transactionpoint(ddisp
->diagram
->undo
);
142 if (prefs
.reset_tools_after_create
)
146 create_object_motion(CreateObjectTool
*tool
, GdkEventMotion
*event
,
150 ConnectionPoint
*connectionpoint
;
155 ddisplay_untransform_coords(ddisp
, event
->x
, event
->y
, &to
.x
, &to
.y
);
157 /* Move to ConnectionPoint if near: */
158 if ((tool
->handle
!= NULL
&&
159 tool
->handle
->connect_type
!= HANDLE_NONCONNECTABLE
) &&
161 object_find_connectpoint_display(ddisp
, &to
)) != NULL
)) {
162 to
= connectionpoint
->pos
;
164 /* No connectionopoint near, then snap to grid (if enabled) */
165 snap_to_grid(ddisp
, &to
.x
, &to
.y
);
168 object_add_updates(tool
->obj
, ddisp
->diagram
);
169 tool
->obj
->ops
->move_handle(tool
->obj
, tool
->handle
, &to
,
170 HANDLE_MOVE_CREATE
, 0);
171 object_add_updates(tool
->obj
, ddisp
->diagram
);
173 diagram_flush(ddisp
->diagram
);
182 Tool
*create_create_object_tool(ObjectType
*objtype
, void *user_data
)
184 CreateObjectTool
*tool
;
186 tool
= g_new(CreateObjectTool
, 1);
187 tool
->tool
.type
= CREATE_OBJECT_TOOL
;
188 tool
->tool
.button_press_func
= (ButtonPressFunc
) &create_object_button_press
;
189 tool
->tool
.button_release_func
= (ButtonReleaseFunc
) &create_object_button_release
;
190 tool
->tool
.motion_func
= (MotionFunc
) &create_object_motion
;
191 tool
->tool
.double_click_func
= (DoubleClickFunc
) &create_object_double_click
;
193 tool
->objtype
= objtype
;
194 tool
->user_data
= user_data
;
195 tool
->moving
= FALSE
;
197 return (Tool
*) tool
;
200 void free_create_object_tool(Tool
*tool
)