2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
25 * $XConsortium: abobj_move.c /main/3 1995/11/06 17:17:00 rswiston $
27 * @(#)abobj_move.c 1.25 15 Feb 1994 cde_app_builder/src/ab
29 * RESTRICTED CONFIDENTIAL INFORMATION:
31 * The information in this document is subject to special
32 * restrictions in a confidential disclosure agreement between
33 * HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
34 * document outside HP, IBM, Sun, USL, SCO, or Univel without
35 * Sun's specific written approval. This document and all copies
36 * and derivative works thereof must be returned or destroyed at
39 * Copyright 1993 Sun Microsystems, Inc. All rights reserved.
45 ***********************************************************************
46 * ab_move.c - Implements moving UI objects around
49 ***********************************************************************
52 #include <X11/Intrinsic.h>
53 #include <X11/StringDefs.h>
54 #include <ab_private/x_util.h>
55 #include <ab_private/objxm.h>
56 #include <ab_private/abobj_edit.h>
59 /* XRectangle Transformation macros used for passing rects up/down embedded
62 #define rect_passtoparent(a, b, rect) \
63 {(rect)->x = (unsigned short)(rect)->x + (a); (rect)->y = (unsigned short)(rect)->y + (b);}
65 #define rect_passtochild(a, b, rect) \
66 {(rect)->x = (rect)->x - (a); (rect)->y = (rect)->y - (b);}
68 const int AB_drag_threshold = 4;
71 static void undo_move(
75 /*************************************************************************
79 **************************************************************************/
80 static XRectangle drag_init_rect, orig_rect, move_rect;
81 static Boolean first_move = True;
83 static Widget xy_widget;
85 static ABSelectedRec sel;
87 /*************************************************************************
89 ** Function Definitions **
91 **************************************************************************/
93 abobjP_move_object_outline(
98 static XRectangle parent_rect;
99 static XRectangle last_rect;
100 static int x_offset, y_offset;
101 static Dimension border_w;
103 XRectangle widget_rect;
104 int trans_x, trans_y;
106 /* First time: set up initial move variables */
109 if (obj_is_item(obj))
110 obj = obj_get_parent(obj);
112 obj = obj_get_root(obj);
114 /* Multiple objects might be selected...*/
115 if (obj_is_control(obj) ||
119 abobj_get_selected(obj_get_root(obj_get_parent(obj)), False, False, &sel);
124 sel.list = (ABObj*)util_malloc(sizeof(ABObj));
128 xy_obj = objxm_comp_get_subobj(obj, AB_CFG_POSITION_OBJ);
129 xy_widget = (Widget)xy_obj->ui_handle;
131 if (xy_widget == NULL)
133 if (util_get_verbosity() > 2)
134 fprintf(stderr,"abobjP_move_object_outline: %s :no POSITION widget\n",
135 util_strsafe(obj_get_name(obj)));
139 dpy = XtDisplay(xy_widget);
140 parent = XtParent(xy_widget);
142 x_get_widget_rect(xy_widget, &widget_rect);
143 x_get_widget_rect(parent, &parent_rect);
147 abobj_get_rect_for_objects(sel.list, sel.count, &orig_rect);
151 orig_rect = widget_rect;
152 XtVaGetValues(xy_widget, XtNborderWidth, &border_w, NULL);
153 orig_rect.width += (2*border_w);
154 orig_rect.height += (2*border_w);
158 move_rect = orig_rect;
160 drag_init_rect.x = mevent->x - AB_drag_threshold;
161 drag_init_rect.y = mevent->y - AB_drag_threshold;
162 drag_init_rect.width = drag_init_rect.height = 2 * AB_drag_threshold;
164 x_offset = widget_rect.x - orig_rect.x + mevent->x;
165 y_offset = widget_rect.y - orig_rect.y + mevent->y;
169 rect_zero_out(&last_rect);
171 /* Don't begin rendering move outline until pointer is out of
172 * the drag_init bounding box
174 else if (!rect_includespoint(&drag_init_rect, mevent->x, mevent->y))
178 /* event coords are relative to widget-must translate to parent */
179 XTranslateCoordinates(dpy, XtWindow(xy_widget), XtWindow(parent),
180 mevent->x, mevent->y, &trans_x, &trans_y, &win);
182 move_rect.x = trans_x - x_offset;
183 move_rect.y = trans_y - y_offset;
185 /* Ensure move outline is within the parent's rect */
188 else if ((move_rect.x + (short)move_rect.width + 1) >= (short)parent_rect.width)
189 move_rect.x = parent_rect.width - (move_rect.width + 1);
193 else if ((move_rect.y + (short)move_rect.height + 1) >= (short)parent_rect.height)
194 move_rect.y = parent_rect.height - (move_rect.height + 1);
196 /* If cursor has moved since last event, erase previous outline
197 * and render new one (using XOR function)
199 if (!rect_equal(&move_rect, &last_rect))
201 if (!rect_isnull(&last_rect))
202 x_box_r(parent, &last_rect);
203 x_box_r(parent, &move_rect);
204 last_rect = move_rect;
211 * Move the object to the location of the last drag rect
227 x_box_r(parent, &move_rect);
229 x_delta = move_rect.x - orig_rect.x;
230 y_delta = move_rect.y - orig_rect.y;
233 * Before the move is performed, record undo information
235 (void)abobj_set_undo(sel.list, sel.count, undo_move, AB_UNDO_MOVE);
237 abobj_nudge_selected(sel.list, sel.count, x_delta, y_delta, True);
246 abobj_nudge_selected(
259 for (i=0; i < sel_count; i++)
261 if (obj_is_layers(obj_get_parent(sel_list[i])))
262 moveobj = obj_get_parent(sel_list[i]);
264 moveobj = sel_list[i];
266 xyobj = objxm_comp_get_subobj(moveobj, AB_CFG_POSITION_OBJ);
268 x_get_widget_rect(objxm_get_widget(xyobj), &new_rect);
269 new_rect.x += x_delta;
270 new_rect.y += y_delta;
273 abobj_set_xy(moveobj, new_rect.x, new_rect.y);
276 if (xyobj->attachments)
277 abobj_calculate_new_layout(xyobj, new_rect.x, new_rect.y,
278 new_rect.width, new_rect.height);
281 abobj_tree_instantiate_changes(moveobj);
284 * UGLY WORKAROUND for Motif bug which prevents a 1 pixel move
285 * to the Left from working if only 1 object is being moved...
287 if (sel_count == 1 && x_delta == -1)
288 abobj_force_dang_form_resize(moveobj);
291 abobj_select(sel_list[i]);
310 * Loop through all selected objects with the same owner. Only
311 * move selected objects, groups without anchors, and anchored groups
312 * if the anchor is also selected.
314 /* andy, revisit to add in all the group and anchor stuff */
315 for (i = 0; i < sel_count; i++)
318 x_get_widget_rect(objxm_get_widget(obj), &obj_rect);
319 rect_passtochild(start->x, start->y, &obj_rect);
320 rect_passtoparent(stop->x, stop->y, &obj_rect);
322 undo_record_move(obj);
324 abobj_set_xy(obj, (int)obj_rect.x, (int)obj_rect.y);
325 abobj_instantiate_changes(obj);
330 * Undo function for move
331 * NOTE: may need to change when moving multiple objects is
348 * Set undo to undo this move (undo of undo)
350 (void)abobj_set_undo(undo_rec->list, undo_rec->count,
351 undo_move, AB_UNDO_MOVE);
354 * For each object that was moved previously
356 for (i = 0; i < undo_rec->count; ++i)
359 * If undo record is not the right type, something is WRONG !!
361 if (undo_rec->info_list[i].type != AB_UNDO_MOVE)
365 * Get previous x,y and object taht was moved
367 x = undo_rec->info_list[i].info.move.x;
368 y = undo_rec->info_list[i].info.move.y;
369 obj = undo_rec->list[i];
372 abobj_set_xy(obj, x, y);
374 if (xy_obj->attachments)
375 abobj_calculate_new_layout(xy_obj, x, y,
376 move_rect.width, move_rect.height);
378 abobj_instantiate_changes(obj);
389 AB_CONTAINER_TYPE cont_type;
391 /* If object is a child of a Group and the group has a
392 * defined layout type, then it is not movable
394 pobj = obj_get_root(obj_get_parent(obj));
395 if (obj_is_group(pobj) &&
396 obj_get_group_type(pobj) != AB_GROUP_IGNORE)
399 switch(obj_get_type(obj))
401 case AB_TYPE_TEXT_PANE:
402 case AB_TYPE_TERM_PANE:
403 case AB_TYPE_DRAWING_AREA:
404 case AB_TYPE_CONTAINER:
406 /* If object is child of PanedWindow, it cannot be moved */
407 if (obj_is_paned_win(pobj))
409 else if (obj_is_container(obj))
411 cont_type = obj_get_container_type(obj);
412 if (cont_type == AB_CONT_MENU_BAR ||
413 cont_type == AB_CONT_TOOL_BAR ||
414 cont_type == AB_CONT_FOOTER ||
415 cont_type == AB_CONT_BUTTON_PANEL)