Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtappbuilder / src / ab / abobj_align.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
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)
10  * any later version.
11  *
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
16  * details.
17  *
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
22  */
23
24 /*
25  *      $XConsortium: abobj_align.c /main/3 1995/11/06 17:14:58 rswiston $
26  *
27  * @(#)abobj_align.c    1.21 24 May 1994      cde_app_builder/src/libABobj
28  *
29  *      RESTRICTED CONFIDENTIAL INFORMATION:
30  *
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
37  *      Sun's request.
38  *
39  *      Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
40  *
41  */
42
43
44 /*
45  ***********************************************************************
46  * ab_align.c - User-Interface alignment functions. 
47  *      
48  *
49  ***********************************************************************
50  */
51 #include <stdio.h>
52 #include <X11/Intrinsic.h>
53 #include <X11/Composite.h>
54 #include <X11/Shell.h>
55 #include <Xm/Xm.h>
56 #include <Xm/CascadeB.h>
57 #include <Xm/ScrolledW.h>
58 #include <Xm/RowColumn.h>
59 #include <Xm/TextF.h>
60 #include <Xm/Text.h>
61 #include <ab_private/trav.h>
62 #include <ab_private/proj.h>
63 #include <Dt/xpm.h>             /* will this be in include/Dt? */
64 #include "abobjP.h"
65
66
67 static void     align_left_edges(ABObj *sel_list, int sel_count);
68 static void     align_vcenters(ABObj *sel_list, int sel_count);
69 static void     align_right_edges(ABObj *sel_list, int sel_count);
70 static void     align_labels(ABObj *sel_list, int sel_count);
71
72
73 static void     align_top_edges(ABObj *sel_list, int sel_count);
74 static void     align_hcenters(ABObj *sel_list, int sel_count);
75 static void     align_bottom_edges(ABObj *sel_list, int sel_count);
76
77 static void     distribute_horizontal(ABObj *sel_list, int sel_count, int hspacing);
78 static void     distribute_vertical(ABObj *sel_list, int sel_count, int vspacing);
79 static void     center_horizontal(ABObj *sel_list, int sel_count);
80 static void     center_vertical(ABObj *sel_list, int sel_count);
81
82 /*************************************************************************
83 **                                                                      **
84 **       Function Definitions                                           **
85 **                                                                      **
86 **************************************************************************/
87 void
88 abobj_align(
89     unsigned long align_mask
90 )
91 {
92     ABSelectedRec sel;
93     extern int  AB_grid_size;
94     int x = MAXINT;
95
96     if (!align_mask)
97         return;
98
99     abobj_get_selected(proj_get_project(), FALSE, FALSE, &sel);
100     /*
101     * Vertical alignment
102      */
103     if (align_mask & LEFT_EDGES)
104         align_left_edges(sel.list, sel.count);
105     if (align_mask & VCENTERS)
106         align_vcenters(sel.list, sel.count);
107     if (align_mask & RIGHT_EDGES)
108         align_right_edges(sel.list, sel.count);
109     if (align_mask & LABELS)
110         align_labels(sel.list, sel.count);
111
112     /*
113      * Horizonatal alignment
114      */
115     if (align_mask & TOP_EDGES)
116             align_top_edges(sel.list, sel.count);
117     if (align_mask & HCENTERS)
118             align_hcenters(sel.list, sel.count);
119     if (align_mask & BOTTOM_EDGES)
120             align_bottom_edges(sel.list, sel.count);
121
122     /*
123      * Spacing
124      */
125     if (align_mask & HSPACING)
126             distribute_horizontal(sel.list, sel.count, AB_grid_size);
127     if (align_mask & VSPACING)
128             distribute_vertical(sel.list, sel.count, AB_grid_size);
129
130     /*
131      * Centering within parent
132      */
133     if (align_mask & HCENTERED)
134             center_horizontal(sel.list, sel.count);
135     if (align_mask & VCENTERED)
136             center_vertical(sel.list, sel.count);
137 }
138
139
140 /*
141  * align_left_edges
142  */
143 static void
144 align_left_edges(
145     ABObj    *sel_list,
146     int      sel_count
147     )
148 {
149     ABObj    obj;
150     int      i;
151     int      x = MAXINT;
152
153         for (i = 0; i < sel_count; i++) 
154         {
155             obj = sel_list[i];
156             if (obj_get_x(obj) < x)
157                 x = obj_get_x(obj);
158         }
159
160         for (i = 0; i < sel_count; i++) 
161         {
162             obj = sel_list[i];
163             /*
164              undo_record_move(obj);
165             */
166            abobj_set_xy(obj, x, obj_get_y(obj)); 
167            abobj_instantiate_changes(obj); 
168         }
169 }
170
171
172 /*
173  * align_vcenters
174  */
175 static void
176 align_vcenters(
177     ABObj    *sel_list,
178     int      sel_count
179 )
180 {
181     int      i;
182     ABObj    obj;
183     int      x = 0;
184
185     for (i = 0; i < sel_count; i++) 
186     {
187         obj = sel_list[i];
188         x += obj_get_x(obj) + abobj_get_actual_width(obj) / 2;
189     }
190
191         x /= sel_count;
192
193         for (i = 0; i < sel_count; i++) 
194         {
195             obj = sel_list[i];
196             /*
197             undo_record_move(obj);
198             */
199             abobj_set_xy(obj, x - abobj_get_actual_width(obj)/2, obj_get_y(obj));
200             abobj_instantiate_changes(obj); 
201         }
202 }
203
204 /*
205  * align_right_edges
206  */
207 static void
208 align_right_edges(
209     ABObj    *sel_list,
210     int       sel_count
211     )
212 {
213         int     i;
214         ABObj   obj;
215         int     x = -1;
216         int     xtmp;
217
218         for (i = 0; i < sel_count; i++) 
219         {
220             obj = sel_list[i];
221             xtmp = obj_get_x(obj) + abobj_get_actual_width(obj);
222             if (xtmp > x)
223                 x = xtmp;
224         }
225
226         for (i = 0; i < sel_count; i++) 
227         {
228             obj = sel_list[i];
229             /*
230             undo_record_move(obj);
231             */
232             abobj_set_xy(obj, x - abobj_get_actual_width(obj), obj_get_y(obj));
233             abobj_instantiate_changes(obj); 
234         }
235 }
236
237 /*
238  * align_labels
239  *
240  *      Align all selected items to the topmost object's value x.
241  */
242 static void
243 align_labels(
244     ABObj    *sel_list,
245     int      sel_count
246 )
247 {
248     int     i;
249     ABObj   obj;
250     int     new_label_x = 0;
251     int     y = MAXINT;
252
253     for (i = 0; i < sel_count; i++) 
254     {
255         obj = sel_list[i];
256         if (obj_get_y(obj) < y) 
257         {
258                 new_label_x = obj_get_x(obj) +
259                                 abobj_get_label_width(obj);
260                 y = obj_get_y(obj);
261         }
262     }
263
264     for (i = 0; i < sel_count; i++) 
265     {
266         obj = sel_list[i];
267         abobj_set_xy(obj, new_label_x - abobj_get_label_width(obj), 
268                           obj_get_y(obj));
269         abobj_instantiate_changes(obj); 
270     }
271 }
272
273 /*
274  * align_top_edges
275  */
276 static void
277 align_top_edges(
278     ABObj    *sel_list,
279     int       sel_count
280 )
281 {
282         int     i;
283         ABObj   obj;
284         int     y = MAXINT;
285
286         for (i = 0; i < sel_count; i++) 
287         {
288             obj = sel_list[i];
289             if (obj_get_y(obj) < y)
290                 y = obj_get_y(obj);
291         }
292
293         for (i = 0; i < sel_count; i++) 
294         {
295             obj = sel_list[i];
296                 /*
297                 undo_record_move(obj);
298                 */
299             abobj_set_xy(obj, obj_get_x(obj), y);
300             abobj_instantiate_changes(obj); 
301         }
302 }
303
304
305 /*
306  * align_hcenters
307  */
308 static void
309 align_hcenters(
310     ABObj    *sel_list,
311     int      sel_count
312 )
313 {
314     int      i;
315     ABObj    obj;
316     int      y = 0;
317
318     for (i = 0; i < sel_count; i++) 
319     {
320         obj = sel_list[i];
321         y += obj_get_y(obj) + abobj_get_actual_height(obj) / 2;
322     }
323
324     y /= sel_count;
325
326     for (i = 0; i < sel_count; i++) 
327     {
328         obj = sel_list[i];
329         /*
330         undo_record_move(obj);
331         */
332         abobj_set_xy(obj, obj_get_x(obj), y - abobj_get_actual_height(obj)/2);
333         abobj_instantiate_changes(obj); 
334     }
335 }
336
337 /*
338  * align_bottom_edges
339  */
340 static void
341 align_bottom_edges(
342     ABObj    *sel_list,
343     int       sel_count
344 )
345 {
346         int     i;
347         ABObj   obj;
348         int     y = -1;
349         int     ytmp;
350
351         for (i = 0; i < sel_count; i++) 
352         {
353             obj = sel_list[i];
354             ytmp = obj_get_y(obj) + abobj_get_actual_height(obj);
355                 if (ytmp > y)
356                         y = ytmp;
357         }
358
359         for (i = 0; i < sel_count; i++) {
360             obj = sel_list[i];
361                 /*
362                 undo_record_move(obj);
363                 */
364             abobj_set_xy(obj, obj_get_x(obj),  y - abobj_get_actual_height(obj));
365             abobj_instantiate_changes(obj); 
366         }
367 }
368
369
370 /*
371  * distribute_horizontal
372  */
373 static void
374 distribute_horizontal(
375     ABObj    *sel_list,
376     int       sel_count,
377     int       hspacing
378 )
379 {
380     int     i;
381     ABObj          obj;
382     ABObj          prev;
383
384     /*
385      * Sort list of objects based on X values
386      */
387     abobj_sort_sel_list(sel_list, sel_count, XSORT);
388
389     /*
390      * Walk through the list and distribute the objects.
391      */
392     for (i = 1; i < sel_count; i++) 
393     {
394         obj = sel_list[i];
395         prev = sel_list[i-1];
396         /*
397         undo_record_move(obj);
398         */
399         abobj_set_xy(obj, obj_get_x(prev) + abobj_get_actual_width(prev) + 
400                    hspacing, obj_get_y(obj));
401         abobj_instantiate_changes(obj); 
402
403     }
404 }
405
406 /*
407  * distribute_vertical
408  */
409 static void
410 distribute_vertical(
411     ABObj    *sel_list,
412     int       sel_count,
413     int       vspacing
414 )
415 {
416     int i;
417     ABObj       obj;
418     ABObj       prev;
419
420     /*
421      * Sort list of objects based on Y values
422      */
423     abobj_sort_sel_list(sel_list, sel_count, YSORT);
424
425     /*
426      * Walk through the list and distribute the objects.
427      */
428     for (i = 1; i < sel_count; i++) 
429     {
430             obj = sel_list[i];
431             prev = sel_list[i-1];
432             /*
433             undo_record_move(obj);
434             */
435             abobj_set_xy(obj, obj_get_x(obj), obj_get_y(prev) + 
436                       abobj_get_actual_height(prev) + vspacing);
437             abobj_instantiate_changes(obj); 
438     }
439 }
440
441 /*
442  * center_horizontal
443  *
444  * Center selected objects horizontally within their parent
445  */
446 static void
447 center_horizontal(
448     ABObj    *sel_list,
449     int       sel_count
450 )
451 {
452     ABObj       owner_obj = obj_get_parent(sel_list[0]);
453     int         ownerwidth = abobj_get_actual_width(owner_obj);
454     XRectangle  current_rect;
455     XRectangle  new_rect;
456
457     abobj_get_rect_for_objects(sel_list, sel_count, &current_rect);
458
459     new_rect.x = ownerwidth / 2 - current_rect.width / 2;
460     new_rect.y = current_rect.y;
461
462     abobj_move_selected(sel_list, sel_count, &current_rect, &new_rect);
463 }
464
465 /*
466  * center_vertical
467  *
468  * Center selected objects vertically within their parent
469  */
470 static void
471 center_vertical(
472     ABObj    *sel_list,
473     int       sel_count
474 )
475 {
476     ABObj       owner_obj = obj_get_parent(sel_list[0]);
477     int         owneheight = abobj_get_actual_height(owner_obj);
478     XRectangle  current_rect;
479     XRectangle  new_rect;
480
481     abobj_get_rect_for_objects(sel_list, sel_count, &current_rect);
482
483     new_rect.x = current_rect.x;
484     new_rect.y = owneheight / 2 - current_rect.height / 2;
485     abobj_move_selected(sel_list, sel_count, &current_rect, &new_rect);
486 }