Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtappbuilder / src / ab / abobj_layers.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_layers.c /main/3 1995/11/06 17:16:01 rswiston $
26  *
27  * @(#)abobj_layers.c   1.18 02 Feb 1995      cde_app_builder/src/ab
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  * abobj_layers.c - Implements Layered Panes 
47  *
48  ***********************************************************************
49  */
50 #include <stdio.h>
51 #include <X11/Intrinsic.h>
52 #include <Xm/Xm.h>
53 #include <Xm/Form.h>
54 #include <ab_private/trav.h>
55 #include <ab_private/obj_notify.h>
56 #include <ab_private/objxm.h>
57 #include <ab_private/abobj.h>
58 #include <ab_private/abobj_set.h>
59 #include <ab_private/abobj_edit.h>
60 #include <ab_private/x_util.h>
61
62
63 /*************************************************************************
64 **                                                                      **
65 **       Private Function Declarations                                  **
66 **                                                                      **
67 **************************************************************************/
68
69 static void     set_pane_attachments(
70                     ABObj       pane
71                 );
72
73 static int      obj_destroyedOCB(
74                     ObjEvDestroyInfo    info
75                 );
76
77 /*************************************************************************
78 **                                                                      **
79 **       Private Data                                                   **
80 **                                                                      **
81 **************************************************************************/
82
83 static AB_COMPASS_POINT attach_dirs[] = { AB_CP_NORTH, AB_CP_WEST,
84                                         AB_CP_EAST, AB_CP_SOUTH };
85
86 /*************************************************************************
87 **                                                                      **
88 **       Function Definitions                                           **
89 **                                                                      **
90 **************************************************************************/
91
92 ABObj
93 abobj_handle_layered_pane(
94     ABObj       newobj,
95     ABObj       pane    
96 )
97 {
98     static BOOL         first_time = True;
99     ABObj               pane_parent;
100     ABObj               pobj;
101     ABObj               layers;
102     AB_ATTACH_TYPE      atype;
103     XRectangle          p_rect;
104     void                *aval;
105     int                 aoffset;
106     int                 i, pos;
107
108     if (first_time)
109     {
110         obj_add_destroy_callback(obj_destroyedOCB, "LAYERS");
111         first_time = False;
112     }
113
114     pane = obj_get_root(pane);
115     pane_parent = obj_get_parent(pane);
116
117     x_get_widget_rect(objxm_get_widget(pane), &p_rect);
118
119     if (!obj_is_layers(pane_parent)) /* Create New Layered pane */
120     {
121
122         pobj = objxm_comp_get_subobj(obj_get_root(pane_parent),
123                         AB_CFG_PARENT_OBJ);
124
125         /* Create Layers Object to hold all layered panes.
126          * Insert the layer obj in the same position as its
127          * child.
128          */
129         pos = obj_get_child_num(pane);
130         layers = obj_create(AB_TYPE_LAYERS, NULL);
131         obj_insert_child(pobj, layers, pos);
132         
133         obj_set_unique_name(layers, "layers");
134
135         obj_set_width(layers, (int)p_rect.width);
136         obj_set_height(layers, (int)p_rect.height);
137
138         /* If the layer is being parented off of a paned window
139          * then the paned window will take care of positioning
140          * the layer object, so we don't need to set the x,y
141          * values. Same applies to the attachments for the new
142          * layer.
143          */
144         if (!obj_is_paned_win(pane_parent))
145         {
146             obj_set_x(layers, obj_get_x(pane));
147             obj_set_y(layers, obj_get_y(pane));
148
149             /* Copy original Pane's attachments to the Layers object */
150             for (i=0; i < XtNumber(attach_dirs); i++)
151             {
152                 atype   = obj_get_attach_type(pane, attach_dirs[i]);
153                 aval    = obj_get_attach_value(pane,attach_dirs[i]);
154                 aoffset = obj_get_attach_offset(pane, attach_dirs[i]);
155                 obj_set_attachment(layers, attach_dirs[i], atype, aval, aoffset);
156             }
157         }
158         else
159         {
160             /* Set the correct position for the layer object,
161              * so that when it is instantiated, it ends up in
162              * the right position in the paned window.
163              */
164             objxm_obj_set_ui_arg(layers, AB_ARG_INT, 
165                         XmNpositionIndex, (short) pos); 
166         }
167
168         /* Reset pane's attachment's to be to all sides of the Layers object */
169         set_pane_attachments(pane);
170
171         obj_reparent(pane, layers);
172         obj_clear_flag(pane, InstantiatedFlag);
173         abobj_show_tree(layers, FALSE);
174     }
175     else /* Layers already exist */
176         layers = pane_parent;
177
178     obj_set_width(newobj, (int)p_rect.width);
179     obj_set_height(newobj, (int)p_rect.height);
180     obj_set_x(newobj, 0);
181     obj_set_y(newobj, 0);
182     set_pane_attachments(newobj);
183
184     obj_clear_flag(pane, VisibleFlag);
185     XtUnmanageChild(objxm_get_widget(pane));
186     obj_set_flag(newobj, VisibleFlag);
187
188     return layers;
189 }
190
191 int
192 abobj_layer_show_next(
193     ABObj       layers
194 )
195 {
196     AB_TRAVERSAL        trav;
197     ABObj               pane;
198     ABObj               old_top = NULL;
199     ABObj               new_top = NULL;
200
201     if (layers == NULL || !obj_is_layers(layers))
202         return -1;
203
204     /* If there is only one pane, do nothing */
205     if (obj_get_num_salient_children(layers) <= 1)
206         return 0;
207
208     for (trav_open(&trav, layers, AB_TRAV_SALIENT_CHILDREN);
209         (pane = trav_next(&trav)) != NULL; )
210     {
211         /* Search for currently visible pane and mark it */
212         if (obj_has_flag(pane, VisibleFlag))
213             old_top = pane;
214         else if (old_top != NULL) /* previous pane is visible */
215         {
216             new_top = pane;
217             break;
218         }
219     }
220     trav_close(&trav);
221
222     if (new_top == NULL) /* wraparound to first pane */
223         new_top = obj_get_salient_child(layers, 0);
224
225     if (old_top)
226         abobj_deselect(old_top);
227
228     XtManageChild(objxm_get_widget(new_top));
229     obj_set_flag(new_top, VisibleFlag);
230
231     if (old_top)
232     {
233         XtUnmanageChild(objxm_get_widget(old_top));
234         obj_clear_flag(old_top, VisibleFlag);
235     }
236     abobj_select(new_top); 
237
238     return 0;
239 }
240
241 void
242 abobj_layer_set_size(
243     ABObj       layers,
244     int         new_width,
245     int         new_height
246 )
247 {
248     ABObj               pane;
249     ABObj               szObj, xyObj;
250     Widget              szWidget, xyWidget;
251     XRectangle          sz_rect, xy_rect;
252     int                 border_w;
253     AB_TRAVERSAL        trav;
254
255     util_dprintf(3,"abobj_layer_set_size: %s: %d x %d\n",
256         obj_get_name(layers), new_width, new_height);
257
258     /* If a dimension is -1, then that dimension is not being modified */
259     if (new_width == -1)
260         new_width = obj_get_width(layers);
261     if (new_height == -1)
262         new_height = obj_get_height(layers);
263
264
265     abobj_set_pixel_size(layers, new_width, new_height, 0);
266
267     for (trav_open(&trav, layers, AB_TRAV_SALIENT_CHILDREN);
268         (pane = trav_next(&trav)) != NULL; )
269     {
270         if (obj_has_border_frame(pane))
271         {
272             szObj = objxm_comp_get_subobj(pane, AB_CFG_SIZE_OBJ);
273             xyObj = objxm_comp_get_subobj(pane, AB_CFG_POSITION_OBJ);
274
275             szWidget = objxm_get_widget(szObj);
276             xyWidget = objxm_get_widget(xyObj);
277
278             x_get_widget_rect(szWidget, &sz_rect);
279             x_get_widget_rect(xyWidget, &xy_rect);
280             border_w = ((int)(xy_rect.width - sz_rect.width))/2;
281         }
282         else
283             border_w = 0;
284
285         if ((obj_is_text(pane) || obj_is_term_pane(pane)) &&
286                    obj_get_num_columns(pane) != -1)
287             /* TextPane, TermPane with Character-based Sizing */
288             abobj_set_text_size(pane, new_width, new_height);
289
290         /* If Pane has "Fit Contents" size-policy, then don't set new size */
291         else if (obj_get_width(pane) != -1 && obj_get_height(pane) != -1)
292             abobj_set_pixel_size(pane, new_width, new_height, border_w);
293     }    
294     trav_close(&trav);
295 }
296
297 /*
298  * Manage the visible pane in the layer, and unmanage the rest
299  */
300 int
301 abobj_layer_manage_visible(
302     ABObj       layer
303 )
304 {
305     AB_TRAVERSAL        trav;
306     ABObj               pane;
307
308     if (layer == NULL || !obj_is_layers(layer))
309         return -1;
310
311     /* manage the visible pane, unmanage the rest */
312     for (trav_open(&trav, layer, AB_TRAV_SALIENT_CHILDREN);
313         (pane = trav_next(&trav)) != NULL; )
314     {
315         if (obj_has_flag(pane, VisibleFlag))
316         {
317             if (!XtIsManaged(objxm_get_widget(pane)))
318                 XtManageChild(objxm_get_widget(pane));
319         }
320         else
321         {
322             if (XtIsManaged(objxm_get_widget(pane)))
323                 XtUnmanageChild(objxm_get_widget(pane));
324         }
325     }
326     trav_close(&trav);
327
328     return 0;
329 }
330
331
332 /*
333  * Make all 4 sides of pane attached to Layers object
334  */
335 static void
336 set_pane_attachments(
337     ABObj       pane
338 )
339 {
340     obj_set_attachment(pane, AB_CP_NORTH, AB_ATTACH_GRIDLINE, 0, 0);
341     obj_set_attachment(pane, AB_CP_WEST, AB_ATTACH_GRIDLINE, 0, 0);
342     obj_set_attachment(pane, AB_CP_EAST, AB_ATTACH_GRIDLINE, (void*)100, 0);
343     obj_set_attachment(pane, AB_CP_SOUTH, AB_ATTACH_GRIDLINE, (void*)100, 0);
344
345 }
346
347 /*
348  * obj-callback: object is being destroyed - remove from Prop dialog lists
349  */
350 static int
351 obj_destroyedOCB(
352     ObjEvDestroyInfo    info
353 )
354 {
355     static ABObj        pane = NULL;
356     ABObj               layers;
357     ABObj               last_pane;
358     AB_ATTACH_TYPE      atype;
359     void                *aval;
360     int                 aoffset;
361     int                 i;
362
363     if (obj_get_parent(info->obj) == NULL)
364         return 0;
365
366     layers = obj_get_root(obj_get_parent(info->obj));
367
368     if (obj_is_layers(layers))
369     {
370         /* A Pane inside the Layers has been destroyed...*/
371         pane = info->obj;
372
373         /* If it was the one currently visible, then show the next one
374          */
375         if (obj_has_flag(pane, VisibleFlag))
376             abobj_layer_show_next(layers);
377
378         if (obj_get_num_salient_children(layers) == 1)
379         {
380             /* Since there is only 1 pane left, we no longer need the layers.
381              * So, reparent the last pane to the layer's parent and destroy
382              * the layers object.
383              */
384             last_pane = obj_get_child(layers, 0);
385
386             /*
387              * Update undo buffer to depend on this last pane for undo
388              * instead of the parent (layer) which is about to be nuked
389              */
390             abobj_setup_undo_cut_layer(layers, last_pane);
391
392             /* Reparenting the last layer causes the obj_notify function to
393              * flush its queue, which in turn causes this function to be
394              * called again with the same object to destroy.  Therefore we
395              * need to track when we are in the reparent phase so that we
396              * don't get into an infinite loop...
397              */
398             obj_unparent(last_pane);
399             obj_append_child(obj_get_parent(layers), last_pane);
400
401             /* Copy layers object's attachments back to the last pane
402              * so that it remains positioned in the same spot.
403              */
404             for (i=0; i < XtNumber(attach_dirs); i++)
405             {
406                 atype   = obj_get_attach_type(layers, attach_dirs[i]);
407                 aval    = obj_get_attach_value(layers,attach_dirs[i]);
408                 aoffset = obj_get_attach_offset(layers, attach_dirs[i]);
409                 obj_set_attachment(last_pane, attach_dirs[i], atype, aval, aoffset);
410             }
411             obj_destroy(layers);
412             obj_clear_flag(last_pane, InstantiatedFlag);
413             abobj_show_tree(last_pane, FALSE);
414         }
415     }
416
417     return 0;
418 }