1871 lines
52 KiB
C
1871 lines
52 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 libraries and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
/*
|
|
* $XConsortium: objxm_inst.c /main/8 1996/10/02 15:26:06 drk $
|
|
*
|
|
* @(#)objxm_inst.c 1.114 19 May 1995
|
|
*
|
|
* 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.
|
|
*
|
|
*/
|
|
|
|
|
|
/*
|
|
***********************************************************************
|
|
* objxm_inst.c - instantiates AB objects into motif widgets
|
|
*
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <ab_private/XmAll.h>
|
|
#include <Dt/TermPrim.h>
|
|
#include <Dt/Term.h>
|
|
#include <Dt/MenuButton.h>
|
|
#include <Dt/SpinBox.h>
|
|
#include <Dt/ComboBox.h>
|
|
#include <ab_private/trav.h>
|
|
#include "objxmP.h"
|
|
|
|
#define MAX_FORMS 24
|
|
|
|
char * const _applicationShell = "applicationShellWidgetClass";
|
|
char * const _dtComboBox = "dtComboBoxWidgetClass";
|
|
char * const _dtMenuButton = "dtMenuButtonWidgetClass";
|
|
char * const _dtSpinBox = "dtSpinBoxWidgetClass";
|
|
char * const _dtTerm = "dtTermWidgetClass";
|
|
char * const _group = "groupWidgetClass";
|
|
char * const _topLevelShell = "topLevelShellWidgetClass";
|
|
char * const _xmArrowButton = "xmArrowButtonWidgetClass";
|
|
char * const _xmBulletinBoard = "xmBulletinBoardWidgetClass";
|
|
char * const _xmCascadeButton = "xmCascadeButtonWidgetClass";
|
|
char * const _xmCommand = "xmCommandWidgetClass";
|
|
char * const _xmDialogShell = "xmDialogShellWidgetClass";
|
|
char * const _xmDrawingArea = "xmDrawingAreaWidgetClass";
|
|
char * const _xmDrawnButton = "xmDrawnButtonWidgetClass";
|
|
char * const _xmFileSelectionBox = "xmFileSelectionBoxWidgetClass";
|
|
/* This is a psuedo widget class */
|
|
char * const _xmFileSelectionDialog = "xmFileSelectionDialogWidgetClass";
|
|
char * const _xmForm = "xmFormWidgetClass";
|
|
char * const _xmFrame = "xmFrameWidgetClass";
|
|
char * const _xmLabel = "xmLabelWidgetClass";
|
|
char * const _xmLabelGadget = "xmLabelGadgetWidgetClass";
|
|
char * const _xmList = "xmListWidgetClass";
|
|
char * const _xmMainWindow = "xmMainWindowWidgetClass";
|
|
char * const _xmManager = "xmManagerWidgetClass";
|
|
char * const _xmMenuShell = "xmMenuShellWidgetClass";
|
|
char * const _xmMessageBox = "xmMessageBoxWidgetClass";
|
|
/* This is a psuedo widget class */
|
|
char * const _xmMessageDialog = "xmMessageDialogWidgetClass";
|
|
char * const _xmPanedWindow = "xmPanedWindowWidgetClass";
|
|
/* xmPopupMenuWidgetClass is a pseudo class name but is supported by UIL */
|
|
char * const _xmPopupMenu = "xmPopupMenuWidgetClass";
|
|
char * const _xmPrimitive = "xmPrimitiveWidgetClass";
|
|
/* xmPulldownMenuWidgetClass is a pseudo class name but is supported by UIL */
|
|
char * const _xmPulldownMenu = "xmPulldownMenuWidgetClass";
|
|
char * const _xmPushButton = "xmPushButtonWidgetClass";
|
|
char * const _xmRowColumn = "xmRowColumnWidgetClass";
|
|
char * const _xmScale = "xmScaleWidgetClass";
|
|
char * const _xmScrollBar = "xmScrollBarWidgetClass";
|
|
/* xmScrolledListWidgetClass is a pseudo class name but is supported by UIL */
|
|
char * const _xmScrolledList = "xmScrolledListWidgetClass";
|
|
char * const _xmScrolledWindow ="xmScrolledWindowWidgetClass";
|
|
char * const _xmSelectionBox = "xmSelectionBoxWidgetClass";
|
|
char * const _xmSeparator = "xmSeparatorWidgetClass";
|
|
char * const _xmSeparatorGadget="xmSeparatorGadgetWidgetClass";
|
|
char * const _xmText = "xmTextWidgetClass";
|
|
char * const _xmTextField = "xmTextFieldWidgetClass";
|
|
char * const _xmToggleButton = "xmToggleButtonWidgetClass";
|
|
char * const _xmToggleButtonGadget = "xmToggleButtonGadgetWidgetClass";
|
|
|
|
/*************************************************************************
|
|
** **
|
|
** Private Function Declarations **
|
|
** **
|
|
**************************************************************************/
|
|
static int xm_instantiate_tree(
|
|
ABObj root,
|
|
BOOL manage
|
|
);
|
|
static int xm_instantiate_obj(
|
|
ABObj obj,
|
|
BOOL manage
|
|
);
|
|
static int post_instantiate_tree(
|
|
ABObj root
|
|
);
|
|
static int post_instantiate_obj(
|
|
ABObj obj
|
|
);
|
|
static int xm_manage_tree(
|
|
ABObj obj
|
|
);
|
|
static Widget instantiate_menu(
|
|
ABObj obj,
|
|
ABObj menu_ref,
|
|
Widget owner,
|
|
Widget parent
|
|
);
|
|
static Widget instantiate_widget(
|
|
ABObj obj,
|
|
Widget parent,
|
|
BOOL manage
|
|
);
|
|
static int xm_map_obj(
|
|
ABObj obj
|
|
);
|
|
static int xm_unmap_obj(
|
|
ABObj obj
|
|
);
|
|
static WidgetClass
|
|
xm_get_class(
|
|
ISTRING class_name
|
|
);
|
|
|
|
static int formlist_append(
|
|
Widget newform
|
|
);
|
|
|
|
static int formlist_force_resize(
|
|
);
|
|
|
|
/*
|
|
* Event Handlers
|
|
*/
|
|
static void xm_popup_menu(
|
|
Widget w,
|
|
XtPointer client_data,
|
|
XEvent *ev,
|
|
Boolean *cont
|
|
);
|
|
|
|
/*
|
|
* Actions
|
|
*/
|
|
static void popup_menu(
|
|
Widget widget,
|
|
XEvent *event,
|
|
String *params,
|
|
int num_params
|
|
);
|
|
|
|
|
|
/*************************************************************************
|
|
** **
|
|
** Global Data **
|
|
** **
|
|
**************************************************************************/
|
|
|
|
static Widget form_list[MAX_FORMS];
|
|
static int form_list_count = 0;
|
|
|
|
static XtTranslations popup_menu_trans = NULL;
|
|
|
|
static XtActionsRec menu_actions[] = {
|
|
{"PopupMenu", (XtActionProc)popup_menu }
|
|
};
|
|
|
|
static String menu_trans =
|
|
"<Btn3Down>: PopupMenu()";
|
|
|
|
/*************************************************************************
|
|
** **
|
|
** Function Definitions **
|
|
** **
|
|
**************************************************************************/
|
|
|
|
/*
|
|
* Instantiate (Create widgets) for all objects in a tree
|
|
* starting at root
|
|
*/
|
|
int
|
|
objxm_tree_instantiate(
|
|
ABObj root,
|
|
BOOL manage_last
|
|
)
|
|
{
|
|
/* Create all widgets
|
|
*/
|
|
xm_instantiate_tree(root, manage_last? FALSE : TRUE);
|
|
|
|
/* Set resources that must be set AFTER all widgets
|
|
* are created.
|
|
*/
|
|
post_instantiate_tree(root);
|
|
|
|
/* Now that ALL resources have been set (attachments)
|
|
* manage the widgets
|
|
*/
|
|
if (manage_last)
|
|
xm_manage_tree(root);
|
|
|
|
/* WORKAROUND for Motif XmForm bug (it ignores child resize request
|
|
* if x,y have not also changed). So, we have to force it.
|
|
*/
|
|
formlist_force_resize();
|
|
|
|
return OK;
|
|
}
|
|
|
|
/*
|
|
* Map/Unmap (display/undisplay on Screen) all objects in a tree
|
|
* starting at root
|
|
*/
|
|
int
|
|
objxm_tree_map(
|
|
ABObj root,
|
|
BOOL map
|
|
)
|
|
{
|
|
AB_TRAVERSAL trav;
|
|
ABObj child = NULL;
|
|
|
|
if (root == NULL)
|
|
return -1;
|
|
|
|
if (map)
|
|
xm_map_obj(root);
|
|
else
|
|
xm_unmap_obj(root);
|
|
|
|
for (trav_open(&trav, root, AB_TRAV_CHILDREN);
|
|
(child = trav_next(&trav)) != NULL; )
|
|
objxm_tree_map(child, map);
|
|
|
|
trav_close(&trav);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
xm_map_obj(
|
|
ABObj obj
|
|
)
|
|
{
|
|
Widget widget;
|
|
|
|
if (!obj_is_ui(obj) && !obj_is_module(obj))
|
|
return 0;
|
|
|
|
if (!obj_has_flag(obj, MappedFlag))
|
|
{
|
|
if (obj_is_module(obj) || obj_is_project(obj))
|
|
{
|
|
util_dprintf(2,"MAPPING %s: %s\n",
|
|
obj_is_project(obj)?"project":"module",
|
|
util_strsafe(obj_get_name(obj)));
|
|
}
|
|
else if ((widget = (Widget)obj->ui_handle) != NULL)
|
|
{
|
|
util_dprintf(2,"MAPPING widget: %s\n", util_strsafe(obj_get_name(obj)));
|
|
|
|
if (XtIsSubclass(widget, applicationShellWidgetClass) ||
|
|
XtIsSubclass(widget, topLevelShellWidgetClass))
|
|
XtPopup(widget, XtGrabNone);
|
|
else if (XtIsSubclass(widget, xmDialogShellWidgetClass))
|
|
{
|
|
XtManageChild(objxm_get_widget(obj_get_child(obj, 0)));
|
|
XtPopup(widget, XtGrabNone);
|
|
}
|
|
}
|
|
obj_set_flag(obj, MappedFlag);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
xm_unmap_obj(
|
|
ABObj obj
|
|
)
|
|
{
|
|
Widget widget;
|
|
|
|
if (!obj_is_ui(obj) && !obj_is_module(obj))
|
|
return 0;
|
|
|
|
if (obj_has_flag(obj, MappedFlag))
|
|
{
|
|
if (obj_is_module(obj) || obj_is_project(obj))
|
|
{
|
|
util_dprintf(2,"UN-MAPPING %s: %s\n",
|
|
obj_is_project(obj)?"project":"module",
|
|
util_strsafe(obj_get_name(obj)));
|
|
}
|
|
else if ((widget = (Widget)obj->ui_handle) != NULL)
|
|
{
|
|
util_dprintf(2,"UN-MAPPING widget: %s\n",
|
|
util_strsafe(obj_get_name(obj)));
|
|
|
|
if (XtIsSubclass(widget, applicationShellWidgetClass) ||
|
|
XtIsSubclass(widget, topLevelShellWidgetClass) ||
|
|
XtIsSubclass(widget, xmDialogShellWidgetClass))
|
|
XtPopdown(widget);
|
|
}
|
|
obj_clear_flag(obj, MappedFlag);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
xm_instantiate_tree(
|
|
ABObj root,
|
|
BOOL manage
|
|
)
|
|
{
|
|
AB_TRAVERSAL trav;
|
|
ABObj child;
|
|
|
|
if (root == NULL)
|
|
return -1;
|
|
|
|
/* Top-down traversal is crucial */
|
|
xm_instantiate_obj(root, manage);
|
|
for (trav_open(&trav, root, AB_TRAV_CHILDREN);
|
|
(child = trav_next(&trav)) != NULL; )
|
|
{
|
|
xm_instantiate_tree(child, manage);
|
|
}
|
|
trav_close(&trav);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
static int
|
|
post_instantiate_tree(
|
|
ABObj root
|
|
)
|
|
{
|
|
AB_TRAVERSAL trav;
|
|
ABObj child;
|
|
|
|
if (root == NULL)
|
|
return -1;
|
|
|
|
post_instantiate_obj(root);
|
|
|
|
/* Bottom-up traversal is crucial*/
|
|
for (trav_open(&trav, root, AB_TRAV_CHILDREN);
|
|
(child = trav_next(&trav)) != NULL; )
|
|
if (obj_is_ui(child))
|
|
post_instantiate_tree(child);
|
|
|
|
trav_close(&trav);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
xm_manage_tree(
|
|
ABObj root
|
|
)
|
|
{
|
|
AB_TRAVERSAL trav;
|
|
static ABObj manage_root = NULL;
|
|
ABObj child;
|
|
ABObj childobj;
|
|
Widget widget;
|
|
WidgetList wchildren;
|
|
int num_children;
|
|
int num_wchildren = 0;
|
|
int i;
|
|
|
|
if (root == NULL)
|
|
return -1;
|
|
|
|
if (manage_root == NULL)
|
|
manage_root = root;
|
|
|
|
/* Bottom-up traversal is crucial*/
|
|
for (trav_open(&trav, root, AB_TRAV_CHILDREN);
|
|
(child = trav_next(&trav)) != NULL; )
|
|
{
|
|
xm_manage_tree(child);
|
|
}
|
|
trav_close(&trav);
|
|
|
|
widget = (Widget)root->ui_handle;
|
|
|
|
/* If this widget has children, manage them all at once.
|
|
*/
|
|
if (widget != NULL && XtIsSubclass(widget, compositeWidgetClass))
|
|
{
|
|
/* Build list of valid widget children */
|
|
num_children = obj_get_num_children(root);
|
|
wchildren = (WidgetList)util_malloc(num_children*sizeof(Widget));
|
|
for (i=0; i < num_children; i++)
|
|
{
|
|
childobj = obj_get_child(root, i);
|
|
if (childobj->ui_handle != NULL &&
|
|
!objxm_is_menu_widget(objxm_get_widget(childobj)))
|
|
wchildren[num_wchildren++] = (Widget)childobj->ui_handle;
|
|
}
|
|
if (num_wchildren > 0 && !XtIsSubclass(widget, xmDialogShellWidgetClass))
|
|
{
|
|
XtManageChildren(wchildren, num_wchildren);
|
|
if (util_get_verbosity() > 3)
|
|
{
|
|
Dimension w,h;
|
|
fprintf(stderr,"MANAGING Children:");
|
|
for (i=0; i < num_wchildren ; i++)
|
|
{
|
|
XtVaGetValues(wchildren[i], XmNwidth, &w, XmNheight, &h, NULL);
|
|
fprintf(stderr,"%s(%dx%d) ", XtName(wchildren[i]),w,h);
|
|
}
|
|
fprintf(stderr,".\n");
|
|
}
|
|
}
|
|
util_free(wchildren);
|
|
}
|
|
/* We are back at the Top of the tree being managed:
|
|
* MUST manage the top one by hand since this function
|
|
* was not called on its parent...
|
|
*/
|
|
if (manage_root == root)
|
|
{
|
|
if (widget != NULL && !XtIsSubclass(widget, shellWidgetClass) &&
|
|
!XtIsSubclass(XtParent(widget), xmDialogShellWidgetClass))
|
|
{
|
|
XtManageChild(widget);
|
|
if (util_get_verbosity() > 3)
|
|
{
|
|
Dimension w,h;
|
|
XtVaGetValues(widget, XmNwidth, &w, XmNheight, &h, NULL);
|
|
fprintf(stderr,"MANAGING root: %s(%dx%d)\n",
|
|
util_strsafe(obj_get_name(root)),w,h);
|
|
}
|
|
}
|
|
manage_root = NULL;
|
|
}
|
|
return 0;
|
|
}
|
|
static int
|
|
xm_instantiate_obj(
|
|
ABObj obj,
|
|
BOOL manage
|
|
)
|
|
{
|
|
ABObj parentobj, temp_parent;
|
|
Widget widget;
|
|
Widget parent;
|
|
|
|
if (!obj_has_flag(obj, XmConfiguredFlag) ||
|
|
obj_has_flag(obj, InstantiatedFlag) ||
|
|
obj_has_flag(obj, BeingDestroyedFlag))
|
|
return OK; /* not considered an error */
|
|
|
|
if (obj_is_virtual(obj) || obj_is_menu_ref(obj))
|
|
{
|
|
objxm_obj_remove_all_ui_args(obj, OBJXM_CONFIG_BUILD);
|
|
obj_clear_flag(obj, CreateAttrsFlag);
|
|
obj_set_flag(obj, InstantiatedFlag);
|
|
obj_clear_flag(obj, AttrChangedFlag);
|
|
return OK;
|
|
}
|
|
|
|
/* List,ComboBox & SpinBox Items are not separate widgets */
|
|
if (obj_is_combo_box_item(obj) ||
|
|
obj_is_list_item(obj) ||
|
|
obj_is_spin_box_item(obj))
|
|
{
|
|
AB_ITEM_TYPE itype;
|
|
XmString xmitem;
|
|
char *obj_name;
|
|
|
|
if ((parent = objxm_get_widget(obj_get_parent(obj))) == NULL)
|
|
{
|
|
obj_name = util_strsafe(obj_get_name(obj));
|
|
util_dprintf(1, "Instantiation ERROR: %s: widget-ID for parent is NULL\n", obj_name);
|
|
return ERROR;
|
|
}
|
|
itype = obj_get_item_type(obj);
|
|
xmitem = XmStringCreateLocalized(obj_get_label(obj));
|
|
|
|
switch(itype)
|
|
{
|
|
case AB_ITEM_FOR_LIST:
|
|
XmListAddItem(parent, xmitem, 0);
|
|
obj_set_flag(obj, InstantiatedFlag);
|
|
break;
|
|
case AB_ITEM_FOR_COMBO_BOX:
|
|
DtComboBoxAddItem(parent, xmitem, 0, False);
|
|
obj_set_flag(obj, InstantiatedFlag);
|
|
break;
|
|
case AB_ITEM_FOR_SPIN_BOX:
|
|
DtSpinBoxAddItem(parent, xmitem, 0);
|
|
obj_set_flag(obj, InstantiatedFlag);
|
|
break;
|
|
default:
|
|
return ERROR;
|
|
}
|
|
XmStringFree(xmitem);
|
|
if (obj_has_flag(obj, InstantiatedFlag))
|
|
return OK;
|
|
}
|
|
/* Determine parent.. */
|
|
/* If obj is a window, parent it off the AB toplevel during
|
|
* build-mode to ensure it's independence during UI editing
|
|
*/
|
|
if (obj_is_window(obj))
|
|
parent = ObjxmP_toplevel;
|
|
else
|
|
{
|
|
parentobj = obj_get_parent(obj);
|
|
|
|
while (parentobj != NULL && obj_is_virtual(parentobj))
|
|
{
|
|
temp_parent = obj_get_parent(parentobj);
|
|
if (temp_parent == NULL)
|
|
break;
|
|
|
|
parentobj = temp_parent;
|
|
}
|
|
|
|
parent = (Widget)parentobj->ui_handle;
|
|
}
|
|
|
|
widget = instantiate_widget(obj, parent, manage);
|
|
|
|
if (widget != NULL)
|
|
{
|
|
/* If we have an OptionMenu menupane, we need to hook it
|
|
* up to the XmOptionMenu (XmRowColumn) in time for the
|
|
* XmOptionMenu's instantiation...ugly, but haven't found
|
|
* a better place to do this yet...
|
|
*/
|
|
if (objxm_is_menu_widget(widget) &&
|
|
XtIsSubclass(widget, xmRowColumnWidgetClass))
|
|
{
|
|
ABObj robj = obj_get_root(obj);
|
|
if (obj_is_choice(robj))
|
|
{
|
|
ABObj o_obj = objxm_comp_get_subobj(robj, AB_CFG_OBJECT_OBJ);
|
|
objxm_obj_set_ui_arg(o_obj, AB_ARG_WIDGET, XmNsubMenuId, widget);
|
|
}
|
|
}
|
|
|
|
/* if widget is being replaced, destroy old one */
|
|
if (obj->ui_handle != NULL)
|
|
objxm_tree_uninstantiate(obj, TRUE);
|
|
|
|
/* Store widget-id in the obj */
|
|
obj->ui_handle = (void*)widget;
|
|
|
|
/* Store the ABObj & the original translations in the widget's
|
|
* userData
|
|
*/
|
|
objxm_store_obj_and_actions(widget, obj);
|
|
|
|
objxm_obj_remove_all_ui_args(obj, OBJXM_CONFIG_BUILD);
|
|
obj_clear_flag(obj, CreateAttrsFlag);
|
|
obj_set_flag(obj, InstantiatedFlag);
|
|
obj_clear_flag(obj, AttrChangedFlag);
|
|
|
|
return OK;
|
|
}
|
|
return ERROR;
|
|
|
|
}
|
|
|
|
|
|
static Widget
|
|
instantiate_widget(
|
|
ABObj obj,
|
|
Widget parent,
|
|
BOOL manage
|
|
)
|
|
{
|
|
Widget widget = NULL;
|
|
WidgetClass xmclass;
|
|
XmCreateFunc xmcreate_func;
|
|
STRING classname;
|
|
String name;
|
|
int num_args;
|
|
ArgList all_args = NULL;
|
|
|
|
name = (String)obj_get_name(obj);
|
|
if (name == NULL)
|
|
{
|
|
util_dprintf(1, "Instantiation ERROR: Object must have a valid name\n");
|
|
return NULL;
|
|
}
|
|
if (parent == NULL)
|
|
{
|
|
char *obj_name = util_strsafe(obj_get_name(obj));
|
|
util_dprintf(1, "Instantiation ERROR: %s: widget-ID for parent is NULL\n", obj_name);
|
|
return NULL;
|
|
}
|
|
if ((classname = obj_get_class_name(obj)) == NULL)
|
|
{
|
|
classname = objxm_obj_get_default_motif_class(obj);
|
|
obj_set_class_name(obj, classname);
|
|
}
|
|
|
|
if (!obj_has_flag(obj, CreateAttrsFlag)) /* Make sure Resources are set */
|
|
objxm_comp_set_ui_args(obj_get_root(obj), OBJXM_CONFIG_BUILD, TRUE);
|
|
|
|
/* Instantiate Widget using class & arglist
|
|
*/
|
|
if (util_streq(obj_get_class_name(obj), _applicationShell))
|
|
{
|
|
all_args = (ArgList)obj->ui_args;
|
|
num_args = objxm_get_num_args(all_args);
|
|
|
|
if (util_get_verbosity() > 3)
|
|
{
|
|
util_dprintf(2,"INSTANTIATING(Shell): %s part_of(%s), parent=%s, class=%s.\n",
|
|
name, obj->part_of? util_strsafe(obj_get_name(obj->part_of)) : name,
|
|
XtName(parent), obj_get_class_name(obj));
|
|
objxm_dump_arglist(obj, all_args, num_args);
|
|
}
|
|
|
|
widget = XtCreatePopupShell(name,
|
|
topLevelShellWidgetClass,
|
|
parent,
|
|
all_args,
|
|
num_args);
|
|
XtVaSetValues(widget, XtNwindowGroup, XtWindow(ObjxmP_toplevel), NULL);
|
|
|
|
}
|
|
else /* Non TopLevel */
|
|
{
|
|
all_args = (ArgList)obj->ui_args;
|
|
num_args = objxm_get_num_args(all_args);
|
|
|
|
if (util_streq(obj_get_class_name(obj), _xmFrame) ||
|
|
XtIsSubclass(parent, xmFrameWidgetClass))
|
|
{
|
|
xmclass = objxm_get_class_ptr(obj_get_class_name(obj));
|
|
widget = XtCreateManagedWidget(name, xmclass, parent, all_args, num_args);
|
|
}
|
|
else
|
|
{
|
|
xmcreate_func = objxm_obj_get_xmcreate_func(obj);
|
|
|
|
if (xmcreate_func != NULL)
|
|
widget = (*xmcreate_func)(parent, name, all_args, num_args);
|
|
else
|
|
{
|
|
xmclass = objxm_get_class_ptr(obj_get_class_name(obj));
|
|
if (xmclass != NULL)
|
|
widget = XtCreateWidget(name, xmclass, parent, all_args, num_args);
|
|
else
|
|
{
|
|
char *obj_name = util_strsafe(obj_get_name(obj));
|
|
util_dprintf(1, "Instantiation ERROR: %s: Object must have widget class\n", obj_name);
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
if (util_get_verbosity() > 3)
|
|
{
|
|
fprintf(stderr,"INSTANTIATING: %s=%p part_of(%s), parent=%s, class=%s.\n",
|
|
name, widget, obj->part_of? util_strsafe(obj_get_name(obj->part_of)) : name,
|
|
XtName(parent), obj_get_class_name(obj));
|
|
objxm_dump_arglist(obj, all_args, num_args);
|
|
}
|
|
|
|
if (manage && !objxm_is_menu_widget(widget))
|
|
{
|
|
XtManageChild(widget);
|
|
if (util_get_verbosity() > 3)
|
|
{
|
|
Dimension w,h;
|
|
XtVaGetValues(widget, XmNwidth, &w, XmNheight, &h, NULL);
|
|
fprintf(stderr,"MANAGING: %s(%dx%d)\n", XtName(widget), w,h);
|
|
}
|
|
}
|
|
|
|
}
|
|
return widget;
|
|
|
|
}
|
|
|
|
static int
|
|
post_instantiate_obj(
|
|
ABObj obj
|
|
)
|
|
{
|
|
Widget widget;
|
|
ABObj parent_obj;
|
|
ArgList args;
|
|
int num_args;
|
|
|
|
widget = (Widget)obj->ui_handle;
|
|
|
|
if (ObjxmP_post_instantiate_cb != NULL)
|
|
ObjxmP_post_instantiate_cb(obj);
|
|
|
|
objxm_obj_set_post_inst_args(obj, OBJXM_CONFIG_BUILD);
|
|
|
|
/* If there is no widget associated with obj, then we are done */
|
|
if (widget == NULL)
|
|
return 0;
|
|
|
|
if (!obj_is_window(obj))
|
|
{
|
|
parent_obj = obj_get_parent(obj);
|
|
|
|
/* This is a workaround for an extremely strange problem where [sometimes]
|
|
* Control Panes do not resize large enough to display all of their children.
|
|
*/
|
|
if (XtIsSubclass(objxm_get_widget(parent_obj), xmFormWidgetClass))
|
|
formlist_append(objxm_get_widget(parent_obj));
|
|
}
|
|
|
|
if (obj_has_flag(obj,AttrChangedFlag))
|
|
{
|
|
args = (ArgList)obj->ui_args;
|
|
num_args = objxm_get_num_args(args);
|
|
|
|
if (util_get_verbosity() > 3)
|
|
{
|
|
fprintf(stderr,"POST-INSTANTIATE SetValues: %s\n", util_strsafe(obj_get_name(obj)));
|
|
objxm_dump_arglist(obj, args, num_args);
|
|
}
|
|
/*
|
|
if (!XtIsManaged(widget))
|
|
XtManageChild(widget);
|
|
*/
|
|
XtSetValues(widget, args, num_args);
|
|
obj_clear_flag(obj, AttrChangedFlag);
|
|
objxm_obj_remove_all_ui_args(obj, OBJXM_CONFIG_BUILD);
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
/*
|
|
* OBJ-callback: called when an object is destroyed so
|
|
* we can destroy the widget associated with it
|
|
*/
|
|
int
|
|
objxmP_destroy(
|
|
ObjEvDestroyInfo info
|
|
)
|
|
{
|
|
ABObj obj = info->obj;
|
|
Widget widget = (Widget)info->obj->ui_handle;
|
|
|
|
if (widget != NULL)
|
|
{
|
|
objxm_free_obj_and_actions(widget);
|
|
/*
|
|
* WORKAROUND UNTIL XtDestroyWidget(combobox) bug
|
|
* is fixed. Isa 2/22/94
|
|
*
|
|
* WORKAROUND Also for XmMainWindow bug - destroying
|
|
* the messageWindow widget causes it to corecump. aim 7/14/94
|
|
*/
|
|
if (obj_is_combo_box(obj) ||
|
|
(obj_is_control_panel(obj) && obj_get_subtype(obj) == AB_CONT_FOOTER))
|
|
{
|
|
XtUnrealizeWidget(widget);
|
|
}
|
|
else
|
|
{
|
|
util_dprintf(2,"WIDGET DESTROY(CB): %s=%p part_of(%s)\n",
|
|
util_strsafe(obj_get_name(obj)), widget,
|
|
obj->part_of? util_strsafe(obj_get_name(obj->part_of)) :
|
|
util_strsafe(obj_get_name(obj)));
|
|
|
|
XtDestroyWidget(widget);
|
|
}
|
|
obj->ui_handle = NULL;
|
|
}
|
|
/* Free the arglist if it exists */
|
|
if (obj->ui_args != NULL)
|
|
{
|
|
util_dprintf(2, "FREEING ARGLIST: %s\n", obj_get_name(obj));
|
|
util_free(obj->ui_args);
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
/*
|
|
* Destroy Widgets AND objects in a tree starting at root
|
|
*/
|
|
int
|
|
objxm_tree_destroy(
|
|
ABObj root
|
|
)
|
|
{
|
|
|
|
if (root == NULL)
|
|
return -1;
|
|
|
|
/* Destroy any existing widgets */
|
|
objxm_tree_uninstantiate(root, TRUE);
|
|
|
|
/* Destroy ABObj tree */
|
|
obj_destroy(root);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Destroy Widgets in a tree starting at root
|
|
* (sets ui_handle to NULL)
|
|
*/
|
|
int
|
|
objxm_tree_uninstantiate(
|
|
ABObj root,
|
|
BOOL topmost
|
|
)
|
|
{
|
|
Widget widget;
|
|
AB_TRAVERSAL trav;
|
|
ABObj child;
|
|
|
|
/*
|
|
* Fix for Bug Ids 1189359 and 1200072
|
|
*
|
|
* Clear the flags first because list, combo box, and spin box items
|
|
* don't actually have a ui_handle associated with them.
|
|
*/
|
|
obj_clear_flag(root, BuildActionsFlag);
|
|
obj_clear_flag(root, InstantiatedFlag);
|
|
obj_clear_flag(root, MappedFlag);
|
|
|
|
widget = (Widget)root->ui_handle;
|
|
|
|
if (widget == NULL)
|
|
return -1;
|
|
|
|
for (trav_open(&trav, root, AB_TRAV_CHILDREN);
|
|
(child = trav_next(&trav)) != NULL; )
|
|
{
|
|
objxm_tree_uninstantiate(child, FALSE);
|
|
}
|
|
|
|
objxm_free_obj_and_actions(widget);
|
|
|
|
/*
|
|
* WORKAROUND UNTIL XtDestroyWidget(combobox) bug
|
|
* is fixed. Isa 2/22/94
|
|
* WORKAROUND Also for XmMainWindow bug - destroying
|
|
* the messageWindow widget causes it to corecump. aim 7/14/94
|
|
*/
|
|
if (obj_is_combo_box(root) ||
|
|
(obj_is_control_panel(root) && obj_get_subtype(root) == AB_CONT_FOOTER))
|
|
{
|
|
XtUnrealizeWidget(widget);
|
|
}
|
|
else
|
|
{
|
|
util_dprintf(2,"WIDGET DESTROY: %s=%p part_of(%s)\n",
|
|
util_strsafe(obj_get_name(root)), widget,
|
|
root->part_of? util_strsafe(obj_get_name(root->part_of)) :
|
|
util_strsafe(obj_get_name(root)));
|
|
|
|
XtDestroyWidget(widget);
|
|
}
|
|
root->ui_handle = NULL;
|
|
|
|
trav_close(&trav);
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
/*
|
|
* Instantiate any changes made to an object tree
|
|
* starting at root
|
|
*/
|
|
int
|
|
objxm_tree_instantiate_changes(
|
|
ABObj root,
|
|
BOOL *new_widgets
|
|
)
|
|
{
|
|
static ABObj chg_root = NULL;
|
|
AB_TRAVERSAL trav;
|
|
ABObj child;
|
|
static BOOL new_w = FALSE;
|
|
|
|
if (root == NULL)
|
|
return -1;
|
|
|
|
if (chg_root == NULL)
|
|
chg_root = root;
|
|
|
|
/* Instantiate changes TOP-DOWN */
|
|
objxm_comp_instantiate_changes(root, new_widgets);
|
|
if (*new_widgets == TRUE)
|
|
new_w = TRUE;
|
|
|
|
for (trav_open(&trav, root, AB_TRAV_SALIENT_CHILDREN);
|
|
(child = trav_next(&trav)) != NULL; )
|
|
{
|
|
objxm_tree_instantiate_changes(child, new_widgets);
|
|
}
|
|
|
|
trav_close(&trav);
|
|
if (chg_root == root) /* We are done */
|
|
{
|
|
chg_root = NULL;
|
|
*new_widgets = new_w;
|
|
new_w = FALSE;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* For a Composite Object, Instantiate any changes made
|
|
* to it's tree using recursion.
|
|
*/
|
|
int
|
|
objxm_comp_instantiate_changes(
|
|
ABObj obj,
|
|
BOOL *new_widgets /* return if new widgets created */
|
|
)
|
|
{
|
|
static ABObj comp_root = NULL; /* Composite RootObj */
|
|
static BOOL args_set = FALSE;
|
|
static BOOL w_created = FALSE;
|
|
AB_TRAVERSAL trav;
|
|
ABObj sub_obj;
|
|
ArgList args;
|
|
int num_args;
|
|
Widget widget;
|
|
BOOL new_w;
|
|
|
|
if (comp_root == NULL) /* Keep track of the Root */
|
|
comp_root = obj;
|
|
|
|
widget = (Widget)obj->ui_handle;
|
|
|
|
/* Re-instantiate obj (if it's not being-destroyed)
|
|
*/
|
|
if (!obj_has_flag(obj, InstantiatedFlag) &&
|
|
!obj_has_flag(obj, BeingDestroyedFlag))
|
|
{
|
|
if (!args_set) /* Set Args ONCE */
|
|
{
|
|
objxm_comp_set_ui_args(obj_get_root(obj),
|
|
OBJXM_CONFIG_BUILD, TRUE);
|
|
args_set = TRUE;
|
|
}
|
|
if (widget != NULL) /* object being re-instantiated */
|
|
XtUnmanageChild(widget);
|
|
|
|
objxm_tree_instantiate(obj, /*False*/True);
|
|
w_created = TRUE;
|
|
}
|
|
/* Change obj's resources (if it's not being destroyed)
|
|
*/
|
|
else if (widget != NULL &&
|
|
obj_has_flag(obj, AttrChangedFlag) &&
|
|
!obj_has_flag(obj, BeingDestroyedFlag))
|
|
{
|
|
args = (ArgList)obj->ui_args;
|
|
num_args = objxm_get_num_args(args);
|
|
|
|
if (util_get_verbosity() > 3)
|
|
{
|
|
fprintf(stderr,"CHANGE-ATTRS SetValues: %s\n",
|
|
util_strsafe(obj_get_name(obj)));
|
|
objxm_dump_arglist(obj, args, num_args);
|
|
}
|
|
XtSetValues(widget, args, num_args);
|
|
|
|
/*
|
|
if (XtIsSubclass(XtParent(widget), xmFormWidgetClass))
|
|
formlist_append(XtParent(widget));
|
|
*/
|
|
|
|
/* If XmNbackground is being set, we must call the Motif
|
|
* routine which re-calculates/sets all other colors in
|
|
* widget (shadow, etc).
|
|
*/
|
|
/*
|
|
REMIND: aim,2/8/94 - revisit why this prevents foreground from being
|
|
changed later...
|
|
|
|
for (i = 0; i < num_args; i++)
|
|
{
|
|
if (args[i].name == XmNbackground)
|
|
XmChangeColor(widget, args[i].value);
|
|
}
|
|
*/
|
|
|
|
obj_clear_flag(obj, AttrChangedFlag);
|
|
objxm_obj_remove_all_ui_args(obj, OBJXM_CONFIG_BUILD);
|
|
}
|
|
|
|
if (obj_has_flag(obj, BeingDestroyedFlag))
|
|
objxm_tree_destroy(obj);
|
|
else
|
|
{
|
|
/* Use recursion to Instantiate changes for any
|
|
* SubObjs or Items of this obj
|
|
* (except for Menu-reference SubObjs)
|
|
*/
|
|
for (trav_open(&trav, obj, AB_TRAV_CHILDREN);
|
|
(sub_obj = trav_next(&trav)) != NULL; )
|
|
{
|
|
if (sub_obj->part_of == comp_root &&
|
|
!obj_is_menu_ref(sub_obj))
|
|
objxm_comp_instantiate_changes(sub_obj, &new_w);
|
|
}
|
|
trav_close(&trav);
|
|
}
|
|
if (obj == comp_root) /* Recursed back up to Root */
|
|
{
|
|
/* Ensure any Non-widget/OptionMenu type items get "selected" if necessary */
|
|
if (obj_is_item(obj))
|
|
objxm_comp_set_item_selection(obj);
|
|
|
|
formlist_force_resize();
|
|
*new_widgets = w_created;
|
|
comp_root = NULL;
|
|
args_set = FALSE;
|
|
w_created = FALSE;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Makes a non-widget type item (List, ComboBox, SpinBox) selected/unselected
|
|
* and makes an OptionMenu item the "selected" item
|
|
*/
|
|
int
|
|
objxm_comp_set_item_selection(
|
|
ABObj obj
|
|
)
|
|
{
|
|
ABObj pobj;
|
|
Widget parent;
|
|
XmString xmitem;
|
|
AB_ITEM_TYPE itype;
|
|
BOOL selected;
|
|
|
|
pobj = obj_get_parent(obj);
|
|
parent = objxm_get_widget(pobj);
|
|
|
|
if (!obj_is_item(obj) || parent == NULL)
|
|
return -1;
|
|
|
|
selected = obj_is_initially_selected(obj);
|
|
itype = obj_get_item_type(obj);
|
|
|
|
if (itype == AB_ITEM_FOR_CHOICE && selected &&
|
|
(obj_get_choice_type(obj_get_root(pobj)) == AB_CHOICE_OPTION_MENU))
|
|
{
|
|
Widget optionbox =
|
|
objxm_get_widget(objxm_comp_get_subobj(obj_get_root(pobj), AB_CFG_OBJECT_OBJ));
|
|
Widget item_w = objxm_get_widget(obj);
|
|
|
|
if (optionbox && item_w) /* Make OptionMenu item selected */
|
|
XtVaSetValues(optionbox, XmNmenuHistory, item_w, NULL);
|
|
}
|
|
else if (itype == AB_ITEM_FOR_LIST ||
|
|
itype == AB_ITEM_FOR_COMBO_BOX ||
|
|
itype == AB_ITEM_FOR_SPIN_BOX)
|
|
{
|
|
Widget combobox;
|
|
int pos = obj_get_child_num(obj);
|
|
|
|
xmitem = XmStringCreateLocalized(obj_get_label(obj));
|
|
|
|
switch(itype)
|
|
{
|
|
case AB_ITEM_FOR_COMBO_BOX:
|
|
if (selected)
|
|
DtComboBoxSetItem(parent, xmitem);
|
|
combobox = parent;
|
|
parent = XtNameToWidget(combobox, "*List");
|
|
/* fall through...*/
|
|
case AB_ITEM_FOR_LIST:
|
|
if (selected)
|
|
XmListSelectPos(parent, ++pos, True);
|
|
else
|
|
XmListDeselectPos(parent, ++pos);
|
|
break;
|
|
case AB_ITEM_FOR_SPIN_BOX:
|
|
if (selected)
|
|
DtSpinBoxSetItem(parent, xmitem);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
XmStringFree(xmitem);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* Store the corresponding ABObj & widget Translations in the
|
|
* userData for the widget
|
|
*/
|
|
int
|
|
objxm_store_obj_and_actions(
|
|
Widget w,
|
|
ABObj obj
|
|
)
|
|
{
|
|
XtTranslations trans;
|
|
ObjxmWidgetInfo *winfo = NULL;
|
|
|
|
if (w == NULL || obj == NULL)
|
|
return -1;
|
|
|
|
winfo = (ObjxmWidgetInfo*)util_malloc(sizeof(ObjxmWidgetInfo));
|
|
|
|
/* Store ABObj & Widget translations in userData of widget
|
|
*/
|
|
winfo->obj = obj;
|
|
|
|
XtVaGetValues(w, XtNtranslations, &trans, NULL);
|
|
winfo->translations = trans;
|
|
|
|
XtVaSetValues(w, XmNuserData, winfo, NULL);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/*
|
|
* Free the data structure used to store the ABObj &
|
|
* original translations for a widget
|
|
*/
|
|
int
|
|
objxm_free_obj_and_actions(
|
|
Widget w
|
|
)
|
|
{
|
|
ObjxmWidgetInfo *winfo = NULL;
|
|
|
|
if (w == NULL)
|
|
return -1;
|
|
|
|
XtVaGetValues(w, XmNuserData, &winfo, NULL);
|
|
|
|
util_free(winfo);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/*
|
|
* Retrieve the ABObj corresponding to a widget
|
|
*/
|
|
ABObj
|
|
objxm_get_obj_from_widget(
|
|
Widget w
|
|
)
|
|
{
|
|
ObjxmWidgetInfo *winfo = NULL;
|
|
|
|
if (w == NULL)
|
|
return NULL;
|
|
|
|
XtVaGetValues(w, XmNuserData, &winfo, NULL);
|
|
|
|
if (winfo != NULL)
|
|
return(winfo->obj);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* Retrieve the original translations corresponding to a widget
|
|
*/
|
|
XtTranslations
|
|
objxm_get_actions_from_widget(
|
|
Widget w
|
|
)
|
|
{
|
|
ObjxmWidgetInfo *winfo = NULL;
|
|
|
|
if (w == NULL)
|
|
return NULL;
|
|
|
|
XtVaGetValues(w, XmNuserData, &winfo, NULL);
|
|
|
|
if (winfo != NULL)
|
|
return(winfo->translations);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
WidgetClass
|
|
objxm_get_class_ptr(
|
|
STRING class_name
|
|
)
|
|
{
|
|
ISTRING class_istr = istr_create(class_name);
|
|
WidgetClass xmclass;
|
|
|
|
xmclass = xm_get_class(class_istr);
|
|
|
|
istr_destroy(class_istr);
|
|
return xmclass;
|
|
}
|
|
|
|
static WidgetClass
|
|
xm_get_class(
|
|
ISTRING class_name
|
|
)
|
|
{
|
|
WidgetClass wclass;
|
|
|
|
if (istr_equal(class_name, istr_const(_applicationShell)))
|
|
wclass = applicationShellWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_topLevelShell)))
|
|
wclass = topLevelShellWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_dtTerm)))
|
|
wclass = dtTermWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmArrowButton)))
|
|
wclass = xmArrowButtonWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmBulletinBoard)))
|
|
wclass = xmBulletinBoardWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmCascadeButton)))
|
|
wclass = xmCascadeButtonWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_dtComboBox)))
|
|
wclass = dtComboBoxWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmCommand)))
|
|
wclass = xmCommandWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmDialogShell)))
|
|
wclass = xmDialogShellWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmDrawingArea)))
|
|
wclass = xmDrawingAreaWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmDrawnButton)))
|
|
wclass = xmDrawnButtonWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmFileSelectionBox)))
|
|
wclass = xmFileSelectionBoxWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmForm)))
|
|
wclass = xmFormWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmFrame)))
|
|
wclass = xmFrameWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmLabel)))
|
|
wclass = xmLabelWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmLabelGadget)))
|
|
wclass = xmLabelGadgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmList)))
|
|
wclass = xmListWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmMainWindow)))
|
|
wclass = xmMainWindowWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmManager)))
|
|
wclass = xmManagerWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_dtMenuButton)))
|
|
wclass = dtMenuButtonWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmMenuShell)))
|
|
wclass = xmMenuShellWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmMessageBox)))
|
|
wclass = xmMessageBoxWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmPanedWindow)))
|
|
wclass = xmPanedWindowWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmPrimitive)))
|
|
wclass = xmPrimitiveWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmPushButton)))
|
|
wclass = xmPushButtonWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmRowColumn)))
|
|
wclass = xmRowColumnWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmScale)))
|
|
wclass = xmScaleWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmScrollBar)))
|
|
wclass = xmScrollBarWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmScrolledWindow)))
|
|
wclass = xmScrolledWindowWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmSelectionBox)))
|
|
wclass = xmSelectionBoxWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmSeparator)))
|
|
wclass = xmSeparatorWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmSeparatorGadget)))
|
|
wclass = xmSeparatorGadgetClass;
|
|
else if (istr_equal(class_name, istr_const(_dtSpinBox)))
|
|
wclass = dtSpinBoxWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmText)))
|
|
wclass = xmTextWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmTextField)))
|
|
wclass = xmTextFieldWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmToggleButton)))
|
|
wclass = xmToggleButtonWidgetClass;
|
|
else if (istr_equal(class_name, istr_const(_xmToggleButtonGadget)))
|
|
wclass = xmToggleButtonGadgetClass;
|
|
|
|
else /* Unknown Widget class */
|
|
wclass = NULL;
|
|
|
|
return(wclass);
|
|
}
|
|
|
|
XmCreateFunc
|
|
objxm_obj_get_xmcreate_func(
|
|
ABObj obj
|
|
)
|
|
{
|
|
ABObj robj = obj_get_root(obj);
|
|
ISTRING class_name = istr_create(obj_get_class_name(obj));
|
|
XmCreateFunc xmcreate_func;
|
|
|
|
if (class_name == NULL)
|
|
return NULL;
|
|
|
|
if (istr_equal(class_name, istr_const(_xmArrowButton)))
|
|
xmcreate_func = XmCreateArrowButton;
|
|
else if (istr_equal(class_name, istr_const(_xmBulletinBoard)))
|
|
xmcreate_func = XmCreateBulletinBoard;
|
|
else if (istr_equal(class_name, istr_const(_xmCascadeButton)))
|
|
xmcreate_func = XmCreateCascadeButton;
|
|
else if (istr_equal(class_name, istr_const(_xmCommand)))
|
|
xmcreate_func = XmCreateCommand;
|
|
else if (istr_equal(class_name, istr_const(_xmDialogShell)))
|
|
xmcreate_func = XmCreateDialogShell;
|
|
else if (istr_equal(class_name, istr_const(_xmDrawingArea)))
|
|
xmcreate_func = XmCreateDrawingArea;
|
|
else if (istr_equal(class_name, istr_const(_xmDrawnButton)))
|
|
xmcreate_func = XmCreateDrawnButton;
|
|
else if (istr_equal(class_name, istr_const(_xmFileSelectionDialog)))
|
|
xmcreate_func = XmCreateFileSelectionDialog;
|
|
else if (istr_equal(class_name, istr_const(_xmForm)))
|
|
xmcreate_func = XmCreateForm;
|
|
else if (istr_equal(class_name, istr_const(_xmFrame)))
|
|
xmcreate_func = XmCreateFrame;
|
|
else if (istr_equal(class_name, istr_const(_xmLabel)))
|
|
xmcreate_func = XmCreateLabel;
|
|
else if (istr_equal(class_name, istr_const(_xmLabelGadget)))
|
|
xmcreate_func = XmCreateLabelGadget;
|
|
else if (istr_equal(class_name, istr_const(_xmList)))
|
|
xmcreate_func = XmCreateList;
|
|
else if (istr_equal(class_name, istr_const(_xmMainWindow)))
|
|
xmcreate_func = XmCreateMainWindow;
|
|
else if (istr_equal(class_name, istr_const(_dtMenuButton)))
|
|
xmcreate_func = DtCreateMenuButton;
|
|
else if (istr_equal(class_name, istr_const(_xmMenuShell)))
|
|
xmcreate_func = XmCreateMenuShell;
|
|
else if (istr_equal(class_name, istr_const(_xmPanedWindow)))
|
|
xmcreate_func = XmCreatePanedWindow;
|
|
else if (istr_equal(class_name, istr_const(_xmPopupMenu)))
|
|
xmcreate_func = XmCreatePopupMenu;
|
|
else if (istr_equal(class_name, istr_const(_xmPulldownMenu)))
|
|
xmcreate_func = XmCreatePulldownMenu;
|
|
else if (istr_equal(class_name, istr_const(_xmPushButton)))
|
|
xmcreate_func = XmCreatePushButton;
|
|
else if (istr_equal(class_name, istr_const(_xmRowColumn)))
|
|
{
|
|
if (obj_is_menubar(obj))
|
|
xmcreate_func = XmCreateMenuBar;
|
|
|
|
else if (obj_is_choice(obj))
|
|
{
|
|
AB_CHOICE_INFO *info = (AB_CHOICE_INFO *)&(robj->info.choice);
|
|
|
|
if (objxm_comp_get_subobj(robj, AB_CFG_OBJECT_OBJ) == obj)
|
|
{
|
|
switch(info->type)
|
|
{
|
|
case AB_CHOICE_EXCLUSIVE:
|
|
xmcreate_func = XmCreateRadioBox;
|
|
break;
|
|
case AB_CHOICE_NONEXCLUSIVE:
|
|
xmcreate_func = XmCreateSimpleCheckBox;
|
|
break;
|
|
case AB_CHOICE_OPTION_MENU:
|
|
xmcreate_func = XmCreateOptionMenu;
|
|
break;
|
|
default:
|
|
xmcreate_func = XmCreateRowColumn;
|
|
}
|
|
}
|
|
else
|
|
xmcreate_func = XmCreateRowColumn;
|
|
}
|
|
else
|
|
xmcreate_func = XmCreateRowColumn;
|
|
}
|
|
|
|
else if (istr_equal(class_name, istr_const(_xmScale)))
|
|
xmcreate_func = XmCreateScale;
|
|
else if (istr_equal(class_name, istr_const(_xmScrollBar)))
|
|
xmcreate_func = XmCreateScrollBar;
|
|
else if (istr_equal(class_name, istr_const(_xmScrolledList)))
|
|
xmcreate_func = XmCreateScrolledList;
|
|
else if (istr_equal(class_name, istr_const(_xmScrolledWindow)))
|
|
xmcreate_func = XmCreateScrolledWindow;
|
|
else if (istr_equal(class_name, istr_const(_xmSelectionBox)))
|
|
xmcreate_func = XmCreateSelectionBox;
|
|
else if (istr_equal(class_name, istr_const(_xmSeparator)))
|
|
xmcreate_func = XmCreateSeparator;
|
|
else if (istr_equal(class_name, istr_const(_xmSeparatorGadget)))
|
|
xmcreate_func = XmCreateSeparatorGadget;
|
|
else if (istr_equal(class_name, istr_const(_xmText)))
|
|
xmcreate_func = XmCreateText;
|
|
else if (istr_equal(class_name, istr_const(_xmTextField)))
|
|
xmcreate_func = XmCreateTextField;
|
|
else if (istr_equal(class_name, istr_const(_xmToggleButton)))
|
|
xmcreate_func = XmCreateToggleButton;
|
|
else if (istr_equal(class_name, istr_const(_xmToggleButtonGadget)))
|
|
xmcreate_func = XmCreateToggleButtonGadget;
|
|
|
|
else /* Unknown Widget class */
|
|
xmcreate_func = NULL;
|
|
|
|
istr_destroy(class_name);
|
|
return(xmcreate_func);
|
|
}
|
|
|
|
/*
|
|
* Store widget-id of XmForm widget which contains children
|
|
* which have changed size
|
|
*/
|
|
static int
|
|
formlist_append(
|
|
Widget newform
|
|
)
|
|
{
|
|
int iRet = 0;
|
|
int i;
|
|
|
|
/* If form is already on list, return */
|
|
for (i=0; i < form_list_count; i++)
|
|
if (form_list[i] == newform)
|
|
return iRet;
|
|
|
|
if (form_list_count < MAX_FORMS)
|
|
form_list[form_list_count++] = newform;
|
|
else
|
|
{
|
|
util_dprintf(3,"formlist_append: form_list FULL\n");
|
|
iRet = -1;
|
|
}
|
|
return iRet;
|
|
|
|
}
|
|
|
|
/*
|
|
* For each XmForm on the form_list, force it to grant it's
|
|
* children's resize requests by 'faking' a geometry change
|
|
* on the XmForm itself.
|
|
*
|
|
* Yes, this is ugly, but is currently the only workaround
|
|
* for the Motif bug where the XmForm refuses childrens'
|
|
* resize requests after they've been already managed.
|
|
*/
|
|
static int
|
|
formlist_force_resize(void)
|
|
{
|
|
Dimension f_width, f_height;
|
|
int i;
|
|
Widget phantom;
|
|
Pixel bgpixel;
|
|
XmString xmlabel;
|
|
|
|
util_dprintf(2,"formlist_force_resize: ");
|
|
|
|
for (i= form_list_count-1; i >= 0; i--)
|
|
{
|
|
/* This is an unfortunate workaround for a strange problem where
|
|
* the XmForm widget does not expand to a size large enough to
|
|
* display all its children.
|
|
*
|
|
* Creating a temporary, invisible widget seems to wake up the
|
|
* Form's geometry manager into resizing itself to the correct
|
|
* geometry.
|
|
*
|
|
* (I agree, this makes little sense, but trust me, it works).
|
|
*/
|
|
XtVaGetValues(form_list[i],
|
|
XmNbackground, &bgpixel,
|
|
NULL);
|
|
|
|
xmlabel = XmStringCreateLocalized(" ");
|
|
util_dprintf(2,"\n Creating phantom child of %s.\n", XtName(form_list[i]));
|
|
phantom = XtVaCreateManagedWidget("phantom", xmLabelWidgetClass,
|
|
form_list[i],
|
|
XmNlabelString, xmlabel,
|
|
XmNbackground, bgpixel,
|
|
NULL);
|
|
XmStringFree(xmlabel);
|
|
XtDestroyWidget(phantom);
|
|
form_list[i] = NULL;
|
|
}
|
|
form_list_count = 0;
|
|
util_dprintf(2, "\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
objxm_create_popup_menu_title(
|
|
ABObj menu_ref,
|
|
OBJXM_CONFIG_TYPE ctype,
|
|
STRING title
|
|
)
|
|
{
|
|
ABObj tobj;
|
|
ABObj menu;
|
|
|
|
if (menu_ref == NULL || !obj_is_menu_ref(menu_ref))
|
|
return -1;
|
|
|
|
menu = obj_get_actual_obj(menu_ref);
|
|
if (menu == NULL)
|
|
return -1;
|
|
|
|
tobj = obj_create(AB_TYPE_LABEL, NULL);
|
|
obj_insert_child(menu_ref, tobj, 0);
|
|
obj_set_unique_name(tobj,
|
|
ab_ident_from_name_and_label(obj_get_name(menu), "title"));
|
|
obj_set_label(tobj, title);
|
|
objxm_obj_configure(tobj, ctype, True);
|
|
|
|
if (ctype == OBJXM_CONFIG_BUILD)
|
|
tobj->ui_handle = instantiate_widget(tobj,
|
|
objxm_get_widget(menu_ref), True);
|
|
|
|
tobj = obj_create(AB_TYPE_SEPARATOR, NULL);
|
|
obj_insert_child(menu_ref, tobj, 1);
|
|
obj_set_unique_name(tobj,
|
|
ab_ident_from_name_and_label(obj_get_name(menu),
|
|
"title_sep"));
|
|
obj_set_line_style(tobj, AB_LINE_DOUBLE_LINE);
|
|
objxm_obj_configure(tobj, ctype, True);
|
|
|
|
if (ctype == OBJXM_CONFIG_BUILD)
|
|
tobj->ui_handle = instantiate_widget(tobj,
|
|
objxm_get_widget(menu_ref), True);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Instantiate (create Widgets) for all Menus connected to
|
|
* objects inside a tree starting at root.
|
|
*/
|
|
int
|
|
objxm_instantiate_menus(
|
|
ABObj root
|
|
)
|
|
{
|
|
AB_TRAVERSAL trav;
|
|
ABObj obj;
|
|
ABObj m_parent;
|
|
ABObj menu_ref;
|
|
|
|
if (root == NULL)
|
|
return -1;
|
|
|
|
for (trav_open(&trav, root, AB_TRAV_UI);
|
|
(obj = trav_next(&trav)) != NULL; )
|
|
/* Instantiate a menu for the object if one exists.
|
|
* NOTE: SubMenus (menus off of other menu-items) are
|
|
* actually instantiated using recursion in instantiate_menu(),
|
|
* thus we do not call instantiate_menu() for them directly.
|
|
*/
|
|
if (obj_is_salient(obj) &&
|
|
obj_get_menu_name(obj) != NULL && !obj_is_menu_item(obj))
|
|
{
|
|
m_parent = objxm_comp_get_subobj(obj, AB_CFG_MENU_PARENT_OBJ);
|
|
menu_ref = objxm_comp_get_subobj(obj, AB_CFG_MENU_OBJ);
|
|
instantiate_menu(obj, menu_ref, (Widget)obj->ui_handle,
|
|
(Widget)m_parent->ui_handle);
|
|
}
|
|
|
|
trav_close(&trav);
|
|
return 0;
|
|
|
|
}
|
|
|
|
/*
|
|
* Since we support the concept of virtual "Sharable" menus (the same Menu
|
|
* object can be attached to multiple objects) and Motif does NOT, we must
|
|
* use special handling when instantiating menus. Although the virtual or
|
|
* "shared" Menu obj is used to determine the structure of the menu, the actual
|
|
* widget ID of the menu is stored in the Menu-Reference obj attached directly
|
|
* to the object which "owns" a copy of the menu. Also, in order to store
|
|
* the widget-IDs of all menu-items & sub-menus, the menu obj hierarchy is
|
|
* temporarily created underneath the Menu-ref obj (this hierarchy is destroyed
|
|
* when the the menus are destroyed).
|
|
*
|
|
* Both "owner" & "parent" are required because for casacdes, Motif requires a
|
|
* menu to be parented off the *parent* of the cascade...
|
|
*
|
|
*/
|
|
static Widget
|
|
instantiate_menu(
|
|
ABObj obj,
|
|
ABObj menu_ref,
|
|
Widget owner,
|
|
Widget parent
|
|
)
|
|
{
|
|
AB_TRAVERSAL trav;
|
|
AB_MENU_TYPE m_type;
|
|
ABObj sub_menu_ref;
|
|
ABObj menu_p;
|
|
ABObj menu;
|
|
ABObj item;
|
|
ABObj tmp_itemobj;
|
|
ABObj tmp_menuref;
|
|
Widget menu_w = NULL;
|
|
Widget submenu_w = NULL;
|
|
Widget item_w;
|
|
|
|
if (menu_ref != NULL)
|
|
{
|
|
/* Get Virtual Menu & object to parent menu off of */
|
|
menu = obj_get_actual_obj(menu_ref);
|
|
|
|
if (menu != NULL && parent != NULL)
|
|
{
|
|
if (obj_is_button(obj) && obj_get_subtype(obj) == AB_BUT_MENU)
|
|
{
|
|
/* MenuButtons already have their Menu created */
|
|
XtVaGetValues((Widget)obj->ui_handle, XmNsubMenuId, &menu_w, NULL);
|
|
menu_ref->ui_handle = (void*)menu_w;
|
|
}
|
|
else
|
|
{
|
|
/* Set Pseudo-class for Menu based on the type
|
|
* of object that owns it
|
|
*/
|
|
if (obj_is_menu_item(obj) || obj_is_menubar_item(obj))
|
|
{
|
|
m_type = AB_MENU_PULLDOWN;
|
|
obj_set_class_name(menu, _xmPulldownMenu);
|
|
}
|
|
else
|
|
{
|
|
m_type = AB_MENU_POPUP;
|
|
obj_set_class_name(menu, _xmPopupMenu);
|
|
}
|
|
menu_w = instantiate_widget(menu, parent, TRUE);
|
|
menu_ref->ui_handle = (void*)menu_w;
|
|
|
|
if (m_type == AB_MENU_PULLDOWN)
|
|
XtVaSetValues(owner, XmNsubMenuId, menu_w, NULL);
|
|
|
|
else /* PopupMenu */
|
|
{
|
|
STRING title;
|
|
|
|
XtInsertEventHandler(parent, ButtonPressMask, False, xm_popup_menu,
|
|
(XtPointer)obj, XtListHead);
|
|
/*
|
|
REMIND: aim, 10/7/94 - In trying to migrate to using translations, it
|
|
messed up the event handling when we returned to BUILD mode.
|
|
For now, going back to event-handling.
|
|
|
|
ABObj tobj;
|
|
|
|
if (popup_menu_trans == NULL)
|
|
{
|
|
XtAppAddActions(XtWidgetToApplicationContext(parent),
|
|
menu_actions, XtNumber(menu_actions));
|
|
popup_menu_trans = XtParseTranslationTable(menu_trans);
|
|
}
|
|
menu_p = objxm_get_obj_from_widget(parent);
|
|
objxm_store_obj_and_actions(parent, menu_p);
|
|
XtOverrideTranslations(parent, popup_menu_trans);
|
|
*/
|
|
|
|
if (!util_strempty((title = obj_get_menu_title(obj))))
|
|
objxm_create_popup_menu_title(menu_ref, OBJXM_CONFIG_BUILD,
|
|
title);
|
|
}
|
|
}
|
|
|
|
/* Instantiate Menu Items */
|
|
for (trav_open(&trav, menu, AB_TRAV_CHILDREN);
|
|
(item = trav_next(&trav)) != NULL; )
|
|
{
|
|
/* Create TEMP copy of Item obj under Menu-ref */
|
|
tmp_itemobj = obj_dup(item);
|
|
obj_append_child(menu_ref, tmp_itemobj);
|
|
item_w = instantiate_widget(item, menu_w, TRUE);
|
|
tmp_itemobj->ui_handle = (void*)item_w;
|
|
|
|
/* If SubMenu exists, instantiate it */
|
|
if ((sub_menu_ref = objxm_comp_get_subobj(item, AB_CFG_MENU_OBJ)) != NULL)
|
|
{
|
|
/* Create TEMP copy of submenu(Menu-ref) under temp Item obj */
|
|
tmp_menuref =
|
|
obj_create_ref(obj_get_actual_obj(sub_menu_ref));
|
|
tmp_menuref->part_of = tmp_itemobj;
|
|
obj_append_child(tmp_itemobj, tmp_menuref);
|
|
submenu_w = instantiate_menu(
|
|
item, tmp_menuref, item_w, menu_w);
|
|
}
|
|
}
|
|
trav_close(&trav);
|
|
}
|
|
else
|
|
{
|
|
char *obj_name = util_strsafe(obj_get_name(obj));
|
|
util_dprintf(1, "Instantiation ERROR: %s: could not instantiate menu\n", obj_name);
|
|
return NULL;
|
|
}
|
|
}
|
|
return menu_w;
|
|
}
|
|
|
|
/*
|
|
* Destroy widgets for all Menus connected to
|
|
* objects inside a tree starting at root.
|
|
*/
|
|
int
|
|
objxm_destroy_menus(
|
|
ABObj root
|
|
)
|
|
{
|
|
AB_TRAVERSAL trav;
|
|
ABObj obj;
|
|
ABObj menu;
|
|
AB_MENU_TYPE m_type;
|
|
ABObj menu_ref;
|
|
ABObj menu_p;
|
|
ABObj *item_array;
|
|
int num_items;
|
|
int i;
|
|
|
|
if (root == NULL)
|
|
return -1;
|
|
|
|
for (trav_open(&trav, root, AB_TRAV_UI);
|
|
(obj = trav_next(&trav)) != NULL; )
|
|
if (obj_is_salient(obj) && !obj_is_menu_item(obj) &&
|
|
(menu_ref = objxm_comp_get_subobj(obj, AB_CFG_MENU_OBJ)) != NULL)
|
|
{
|
|
if (menu_ref->ui_handle != NULL)
|
|
{
|
|
menu = obj_get_actual_obj(menu_ref);
|
|
|
|
/* Destroy Temporary Item objs created ONLY for Test-mode */
|
|
num_items = obj_get_num_children(menu_ref);
|
|
item_array = (ABObj*)util_malloc(num_items*sizeof(ABObj));
|
|
for (i=0; i < num_items; i++)
|
|
item_array[i] = obj_get_child(menu_ref, i);
|
|
|
|
for (i=0; i < num_items; i++)
|
|
obj_destroy(item_array[i]);
|
|
|
|
util_free(item_array);
|
|
|
|
/* Unless the obj is a MenuButton, disconnect & Destroy the Menu
|
|
*/
|
|
if (!(obj_is_button(obj) && obj_get_subtype(obj) == AB_BUT_MENU))
|
|
{
|
|
if (obj_is_item(obj) &&
|
|
(obj->info.item.type == AB_ITEM_FOR_MENU ||
|
|
obj->info.item.type == AB_ITEM_FOR_MENUBAR))
|
|
m_type = AB_MENU_PULLDOWN;
|
|
else
|
|
m_type = AB_MENU_POPUP;
|
|
|
|
if (m_type == AB_MENU_POPUP) /* Remove EventHandler that pops up menu */
|
|
{
|
|
Widget parent;
|
|
XtTranslations orig_trans;
|
|
|
|
menu_p = objxm_comp_get_subobj(obj, AB_CFG_MENU_PARENT_OBJ);
|
|
XtRemoveEventHandler((Widget)menu_p->ui_handle, ButtonPressMask,
|
|
False, xm_popup_menu, (XtPointer)obj);
|
|
/*
|
|
REMIND: aim, 10/7/94 - In trying to migrate to using translations, it
|
|
messed up the event handling when we returned to BUILD mode.
|
|
For now, going back to event-handling.
|
|
|
|
parent = objxm_get_widget(menu_p);
|
|
orig_trans = objxm_get_actions_from_widget(parent);
|
|
XtVaSetValues(parent, XtNtranslations, orig_trans, NULL);
|
|
*/
|
|
|
|
}
|
|
XtDestroyWidget((Widget)menu_ref->ui_handle);
|
|
}
|
|
menu_ref->ui_handle = (void*)NULL;
|
|
}
|
|
}
|
|
trav_close(&trav);
|
|
return 0;
|
|
|
|
}
|
|
|
|
static void
|
|
xm_popup_menu(
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XEvent *event,
|
|
Boolean *cont
|
|
)
|
|
{
|
|
XButtonEvent *bevent = (XButtonEvent*)event;
|
|
ABObj obj = (ABObj)client_data;
|
|
ABObj menu_ref;
|
|
Widget menu;
|
|
|
|
if (bevent->button == 3)
|
|
{
|
|
menu_ref = objxm_comp_get_subobj(obj, AB_CFG_MENU_OBJ);
|
|
|
|
if (menu_ref != NULL && (menu = (Widget)menu_ref->ui_handle) != NULL)
|
|
{
|
|
XmMenuPosition(menu, (XButtonPressedEvent*)bevent);
|
|
XtManageChild(menu);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
popup_menu(
|
|
Widget widget,
|
|
XEvent *event,
|
|
String *params,
|
|
int num_params
|
|
)
|
|
{
|
|
XButtonEvent *bevent;
|
|
ABObj obj, menu_ref;
|
|
Widget menu;
|
|
|
|
if (event->type == ButtonPress)
|
|
{
|
|
bevent = (XButtonEvent*)event;
|
|
obj = objxm_get_obj_from_widget(widget);
|
|
|
|
menu_ref = objxm_comp_get_subobj(obj, AB_CFG_MENU_OBJ);
|
|
|
|
if (menu_ref != NULL && (menu = (Widget)menu_ref->ui_handle) != NULL)
|
|
{
|
|
XmMenuPosition(menu, (XButtonPressedEvent*)bevent);
|
|
XtManageChild(menu);
|
|
}
|
|
}
|
|
}
|