cdesktopenv/cde/programs/dtappbuilder/src/ab/abobj_layers.c

419 lines
12 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these librararies and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/*
* $XConsortium: abobj_layers.c /main/3 1995/11/06 17:16:01 rswiston $
*
* @(#)abobj_layers.c 1.18 02 Feb 1995 cde_app_builder/src/ab
*
* RESTRICTED CONFIDENTIAL INFORMATION:
*
* The information in this document is subject to special
* restrictions in a confidential disclosure agreement between
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
* document outside HP, IBM, Sun, USL, SCO, or Univel without
* Sun's specific written approval. This document and all copies
* and derivative works thereof must be returned or destroyed at
* Sun's request.
*
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
*
*/
/*
***********************************************************************
* abobj_layers.c - Implements Layered Panes
*
***********************************************************************
*/
#include <stdio.h>
#include <X11/Intrinsic.h>
#include <Xm/Xm.h>
#include <Xm/Form.h>
#include <ab_private/trav.h>
#include <ab_private/obj_notify.h>
#include <ab_private/objxm.h>
#include <ab_private/abobj.h>
#include <ab_private/abobj_set.h>
#include <ab_private/abobj_edit.h>
#include <ab_private/x_util.h>
/*************************************************************************
** **
** Private Function Declarations **
** **
**************************************************************************/
static void set_pane_attachments(
ABObj pane
);
static int obj_destroyedOCB(
ObjEvDestroyInfo info
);
/*************************************************************************
** **
** Private Data **
** **
**************************************************************************/
static AB_COMPASS_POINT attach_dirs[] = { AB_CP_NORTH, AB_CP_WEST,
AB_CP_EAST, AB_CP_SOUTH };
/*************************************************************************
** **
** Function Definitions **
** **
**************************************************************************/
ABObj
abobj_handle_layered_pane(
ABObj newobj,
ABObj pane
)
{
static BOOL first_time = True;
ABObj pane_parent;
ABObj pobj;
ABObj layers;
AB_ATTACH_TYPE atype;
XRectangle p_rect;
void *aval;
int aoffset;
int i, pos;
if (first_time)
{
obj_add_destroy_callback(obj_destroyedOCB, "LAYERS");
first_time = False;
}
pane = obj_get_root(pane);
pane_parent = obj_get_parent(pane);
x_get_widget_rect(objxm_get_widget(pane), &p_rect);
if (!obj_is_layers(pane_parent)) /* Create New Layered pane */
{
pobj = objxm_comp_get_subobj(obj_get_root(pane_parent),
AB_CFG_PARENT_OBJ);
/* Create Layers Object to hold all layered panes.
* Insert the layer obj in the same position as its
* child.
*/
pos = obj_get_child_num(pane);
layers = obj_create(AB_TYPE_LAYERS, NULL);
obj_insert_child(pobj, layers, pos);
obj_set_unique_name(layers, "layers");
obj_set_width(layers, (int)p_rect.width);
obj_set_height(layers, (int)p_rect.height);
/* If the layer is being parented off of a paned window
* then the paned window will take care of positioning
* the layer object, so we don't need to set the x,y
* values. Same applies to the attachments for the new
* layer.
*/
if (!obj_is_paned_win(pane_parent))
{
obj_set_x(layers, obj_get_x(pane));
obj_set_y(layers, obj_get_y(pane));
/* Copy original Pane's attachments to the Layers object */
for (i=0; i < XtNumber(attach_dirs); i++)
{
atype = obj_get_attach_type(pane, attach_dirs[i]);
aval = obj_get_attach_value(pane,attach_dirs[i]);
aoffset = obj_get_attach_offset(pane, attach_dirs[i]);
obj_set_attachment(layers, attach_dirs[i], atype, aval, aoffset);
}
}
else
{
/* Set the correct position for the layer object,
* so that when it is instantiated, it ends up in
* the right position in the paned window.
*/
objxm_obj_set_ui_arg(layers, AB_ARG_INT,
XmNpositionIndex, (short) pos);
}
/* Reset pane's attachment's to be to all sides of the Layers object */
set_pane_attachments(pane);
obj_reparent(pane, layers);
obj_clear_flag(pane, InstantiatedFlag);
abobj_show_tree(layers, FALSE);
}
else /* Layers already exist */
layers = pane_parent;
obj_set_width(newobj, (int)p_rect.width);
obj_set_height(newobj, (int)p_rect.height);
obj_set_x(newobj, 0);
obj_set_y(newobj, 0);
set_pane_attachments(newobj);
obj_clear_flag(pane, VisibleFlag);
XtUnmanageChild(objxm_get_widget(pane));
obj_set_flag(newobj, VisibleFlag);
return layers;
}
int
abobj_layer_show_next(
ABObj layers
)
{
AB_TRAVERSAL trav;
ABObj pane;
ABObj old_top = NULL;
ABObj new_top = NULL;
if (layers == NULL || !obj_is_layers(layers))
return -1;
/* If there is only one pane, do nothing */
if (obj_get_num_salient_children(layers) <= 1)
return 0;
for (trav_open(&trav, layers, AB_TRAV_SALIENT_CHILDREN);
(pane = trav_next(&trav)) != NULL; )
{
/* Search for currently visible pane and mark it */
if (obj_has_flag(pane, VisibleFlag))
old_top = pane;
else if (old_top != NULL) /* previous pane is visible */
{
new_top = pane;
break;
}
}
trav_close(&trav);
if (new_top == NULL) /* wraparound to first pane */
new_top = obj_get_salient_child(layers, 0);
if (old_top)
abobj_deselect(old_top);
XtManageChild(objxm_get_widget(new_top));
obj_set_flag(new_top, VisibleFlag);
if (old_top)
{
XtUnmanageChild(objxm_get_widget(old_top));
obj_clear_flag(old_top, VisibleFlag);
}
abobj_select(new_top);
return 0;
}
void
abobj_layer_set_size(
ABObj layers,
int new_width,
int new_height
)
{
ABObj pane;
ABObj szObj, xyObj;
Widget szWidget, xyWidget;
XRectangle sz_rect, xy_rect;
int border_w;
AB_TRAVERSAL trav;
util_dprintf(3,"abobj_layer_set_size: %s: %d x %d\n",
obj_get_name(layers), new_width, new_height);
/* If a dimension is -1, then that dimension is not being modified */
if (new_width == -1)
new_width = obj_get_width(layers);
if (new_height == -1)
new_height = obj_get_height(layers);
abobj_set_pixel_size(layers, new_width, new_height, 0);
for (trav_open(&trav, layers, AB_TRAV_SALIENT_CHILDREN);
(pane = trav_next(&trav)) != NULL; )
{
if (obj_has_border_frame(pane))
{
szObj = objxm_comp_get_subobj(pane, AB_CFG_SIZE_OBJ);
xyObj = objxm_comp_get_subobj(pane, AB_CFG_POSITION_OBJ);
szWidget = objxm_get_widget(szObj);
xyWidget = objxm_get_widget(xyObj);
x_get_widget_rect(szWidget, &sz_rect);
x_get_widget_rect(xyWidget, &xy_rect);
border_w = ((int)(xy_rect.width - sz_rect.width))/2;
}
else
border_w = 0;
if ((obj_is_text(pane) || obj_is_term_pane(pane)) &&
obj_get_num_columns(pane) != -1)
/* TextPane, TermPane with Character-based Sizing */
abobj_set_text_size(pane, new_width, new_height);
/* If Pane has "Fit Contents" size-policy, then don't set new size */
else if (obj_get_width(pane) != -1 && obj_get_height(pane) != -1)
abobj_set_pixel_size(pane, new_width, new_height, border_w);
}
trav_close(&trav);
}
/*
* Manage the visible pane in the layer, and unmanage the rest
*/
int
abobj_layer_manage_visible(
ABObj layer
)
{
AB_TRAVERSAL trav;
ABObj pane;
if (layer == NULL || !obj_is_layers(layer))
return -1;
/* manage the visible pane, unmanage the rest */
for (trav_open(&trav, layer, AB_TRAV_SALIENT_CHILDREN);
(pane = trav_next(&trav)) != NULL; )
{
if (obj_has_flag(pane, VisibleFlag))
{
if (!XtIsManaged(objxm_get_widget(pane)))
XtManageChild(objxm_get_widget(pane));
}
else
{
if (XtIsManaged(objxm_get_widget(pane)))
XtUnmanageChild(objxm_get_widget(pane));
}
}
trav_close(&trav);
return 0;
}
/*
* Make all 4 sides of pane attached to Layers object
*/
static void
set_pane_attachments(
ABObj pane
)
{
obj_set_attachment(pane, AB_CP_NORTH, AB_ATTACH_GRIDLINE, 0, 0);
obj_set_attachment(pane, AB_CP_WEST, AB_ATTACH_GRIDLINE, 0, 0);
obj_set_attachment(pane, AB_CP_EAST, AB_ATTACH_GRIDLINE, (void*)100, 0);
obj_set_attachment(pane, AB_CP_SOUTH, AB_ATTACH_GRIDLINE, (void*)100, 0);
}
/*
* obj-callback: object is being destroyed - remove from Prop dialog lists
*/
static int
obj_destroyedOCB(
ObjEvDestroyInfo info
)
{
static ABObj pane = NULL;
ABObj layers;
ABObj last_pane;
AB_ATTACH_TYPE atype;
void *aval;
int aoffset;
int i;
if (obj_get_parent(info->obj) == NULL)
return 0;
layers = obj_get_root(obj_get_parent(info->obj));
if (obj_is_layers(layers))
{
/* A Pane inside the Layers has been destroyed...*/
pane = info->obj;
/* If it was the one currently visible, then show the next one
*/
if (obj_has_flag(pane, VisibleFlag))
abobj_layer_show_next(layers);
if (obj_get_num_salient_children(layers) == 1)
{
/* Since there is only 1 pane left, we no longer need the layers.
* So, reparent the last pane to the layer's parent and destroy
* the layers object.
*/
last_pane = obj_get_child(layers, 0);
/*
* Update undo buffer to depend on this last pane for undo
* instead of the parent (layer) which is about to be nuked
*/
abobj_setup_undo_cut_layer(layers, last_pane);
/* Reparenting the last layer causes the obj_notify function to
* flush its queue, which in turn causes this function to be
* called again with the same object to destroy. Therefore we
* need to track when we are in the reparent phase so that we
* don't get into an infinite loop...
*/
obj_unparent(last_pane);
obj_append_child(obj_get_parent(layers), last_pane);
/* Copy layers object's attachments back to the last pane
* so that it remains positioned in the same spot.
*/
for (i=0; i < XtNumber(attach_dirs); i++)
{
atype = obj_get_attach_type(layers, attach_dirs[i]);
aval = obj_get_attach_value(layers,attach_dirs[i]);
aoffset = obj_get_attach_offset(layers, attach_dirs[i]);
obj_set_attachment(last_pane, attach_dirs[i], atype, aval, aoffset);
}
obj_destroy(layers);
obj_clear_flag(last_pane, InstantiatedFlag);
abobj_show_tree(last_pane, FALSE);
}
}
return 0;
}