3123 lines
65 KiB
C
3123 lines
65 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: brws.c /main/4 1996/10/02 11:00:07 drk $
|
|
*
|
|
* @(#)brws.c 1.113 22 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.
|
|
*
|
|
*/
|
|
|
|
|
|
/*
|
|
* brws.c
|
|
* This file contains the API/callbacks for the CDE App Builder interface browser.
|
|
* Currently, it is a direct port of the Devguide browser. The contents of
|
|
* this file will change soon...
|
|
*/
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/types.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <X11/Xlib.h>
|
|
#include <Xm/Xm.h>
|
|
#include <Xm/TextF.h>
|
|
#include <Xm/DialogS.h>
|
|
#include <Xm/SelectioB.h>
|
|
#include <Xm/ScrolledW.h>
|
|
#include <Xm/PushB.h>
|
|
#include <ab_private/obj.h>
|
|
#include <ab_private/obj_notify.h>
|
|
#include <ab_private/trav.h>
|
|
#include <ab_private/istr.h>
|
|
#include <ab/util_types.h>
|
|
#include <ab_private/abobj.h>
|
|
#include <ab_private/abobj_edit.h>
|
|
#include <ab_private/ui_util.h>
|
|
#include <ab_private/x_util.h>
|
|
#include <ab_private/prop.h>
|
|
#include <ab_private/proj.h>
|
|
#include <ab_private/brwsP.h>
|
|
#include <ab_private/ab.h>
|
|
#include <ab_private/message.h>
|
|
#include <ab_private/objxm.h>
|
|
|
|
/*************************************************************************
|
|
** **
|
|
** Private Function Declarations **
|
|
** **
|
|
**************************************************************************/
|
|
|
|
/*
|
|
* routines called from Uil file via callbacks
|
|
*/
|
|
static void browser_repaint(
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XtPointer call_data
|
|
);
|
|
|
|
static void browser_resize(
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XtPointer call_data
|
|
);
|
|
|
|
static void browser_orientation(
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XtPointer call_data
|
|
);
|
|
|
|
static void browser_show_view_glyph(
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XtPointer call_data
|
|
);
|
|
|
|
static void browser_show_view_name(
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XtPointer call_data
|
|
);
|
|
|
|
static void browser_show_view_type(
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XtPointer call_data
|
|
);
|
|
|
|
static void browser_show_view_wclass(
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XtPointer call_data
|
|
);
|
|
|
|
static void browser_find_obj(
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XtPointer call_data
|
|
);
|
|
|
|
static void browser_tear_off(
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XtPointer call_data
|
|
);
|
|
|
|
static void browser_destroyCB( /* Browser destroy procedure */
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XtPointer call_data
|
|
);
|
|
|
|
/*
|
|
* Action Procs for module subwindow of the browser.
|
|
*/
|
|
static void browser_bpress(
|
|
Widget w,
|
|
XEvent *ev,
|
|
String *params,
|
|
int nparams
|
|
);
|
|
static void browser_select(
|
|
Widget w,
|
|
XEvent *ev,
|
|
String *params,
|
|
int nparams
|
|
);
|
|
static void browser_toggle_select(
|
|
Widget w,
|
|
XEvent *ev,
|
|
String *params,
|
|
int nparams
|
|
);
|
|
static void browser_invoke_props(
|
|
Widget w,
|
|
XEvent *ev,
|
|
String *params,
|
|
int nparams
|
|
);
|
|
static void browser_popup_menu(
|
|
Widget w,
|
|
XEvent *ev,
|
|
String *params,
|
|
int nparams
|
|
);
|
|
|
|
static void browser_rband(
|
|
Widget widget,
|
|
XEvent *event,
|
|
XRectangle *rb_rect,
|
|
XtPointer client_data
|
|
);
|
|
|
|
/*
|
|
* Action Procs for project subwindow of the browser.
|
|
*/
|
|
static void browser_proj_select(
|
|
Widget w,
|
|
XEvent *ev,
|
|
String *params,
|
|
int nparams
|
|
);
|
|
static void browser_proj_toggle_select(
|
|
Widget w,
|
|
XEvent *ev,
|
|
String *params,
|
|
int nparams
|
|
);
|
|
static void browser_proj_invoke_props(
|
|
Widget w,
|
|
XEvent *ev,
|
|
String *params,
|
|
int nparams
|
|
);
|
|
static void browser_proj_popup_menu(
|
|
Widget w,
|
|
XEvent *ev,
|
|
String *params,
|
|
int nparams
|
|
);
|
|
|
|
/*
|
|
* Object notification callbacks
|
|
*/
|
|
static int brwsP_obj_renameOCB(
|
|
ObjEvAttChangeInfo info
|
|
);
|
|
|
|
static int brwsP_obj_destroyOCB(
|
|
ObjEvDestroyInfo info
|
|
);
|
|
|
|
static int brwsP_obj_reparentedOCB(
|
|
ObjEvReparentInfo info
|
|
);
|
|
|
|
static int brwsP_selectOCB(
|
|
ObjEvAttChangeInfo info
|
|
);
|
|
|
|
static int brwsP_obj_updateOCB(
|
|
ObjEvUpdateInfo info
|
|
);
|
|
|
|
/*
|
|
* Private functions within this file
|
|
*/
|
|
static ABBrowser create_browser_struct();
|
|
static void destroy_browser_struct(
|
|
ABBrowser b
|
|
);
|
|
|
|
static void create_browser_ui_handles(
|
|
ABBrowser b
|
|
);
|
|
|
|
static void destroy_browser_ui_handles(
|
|
ABBrowser b
|
|
);
|
|
|
|
static BrowserProps aob_create_props();
|
|
|
|
static void aob_destroy_ui_obj(
|
|
Vwr b
|
|
);
|
|
|
|
static void brws_view_cascadeCB(
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XtPointer call_data
|
|
);
|
|
|
|
static void aob_destroy_props(
|
|
Vwr b
|
|
);
|
|
|
|
static Widget get_main_window(
|
|
Widget widget
|
|
);
|
|
|
|
static int select_rband(
|
|
VNode vnode
|
|
);
|
|
|
|
static int select_fn(
|
|
VNode vnode
|
|
);
|
|
|
|
static void brwsP_drawarea_button_drag(
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XEvent *event,
|
|
Boolean *cont_dispatch
|
|
);
|
|
|
|
/*************************************************************************
|
|
** **
|
|
** Data **
|
|
** **
|
|
**************************************************************************/
|
|
|
|
/*
|
|
* Browser Actions
|
|
*/
|
|
static XtActionsRec browser_actions[] = {
|
|
{"BrowserButtonPress", (XtActionProc)browser_bpress },
|
|
{"BrowserSelect", (XtActionProc)browser_select },
|
|
{"BrowserToggleSelect", (XtActionProc)browser_toggle_select },
|
|
{"BrowserInvokeProps", (XtActionProc)browser_invoke_props },
|
|
{"BrowserPopupMenu", (XtActionProc)browser_popup_menu },
|
|
{"BrowserProjSelect", (XtActionProc)browser_proj_select },
|
|
{"BrowserProjToggleSelect", (XtActionProc)browser_proj_toggle_select },
|
|
{"BrowserProjInvokeProps", (XtActionProc)browser_proj_invoke_props },
|
|
{"BrowserProjPopupMenu", (XtActionProc)browser_proj_popup_menu }
|
|
};
|
|
|
|
/*
|
|
* Translations for detailed view of browser
|
|
*/
|
|
static String base_translations =
|
|
"Ctrl <Btn1Down>: ObjectDragChord() \n\
|
|
Shift <Btn1Down>: BrowserButtonPress() \n\
|
|
<Btn1Down>: BrowserButtonPress() \n\
|
|
<Btn1Down>,<Btn1Up>: BrowserSelect() \n\
|
|
Shift <Btn1Down>,<Btn1Up>: BrowserToggleSelect() \n\
|
|
<Btn1Up>(2): BrowserInvokeProps() \n"; /* will be appended-to */
|
|
|
|
static String btn2_adjust_translations =
|
|
"<Btn2Down>: BrowserButtonPress() \n\
|
|
<Btn2Down>,<Btn2Up>: BrowserToggleSelect() \n"; /* will be appended-to */
|
|
|
|
static String btn3_menu_translations =
|
|
"<Btn3Down>: BrowserPopupMenu() ";
|
|
|
|
static String btn2_menu_translations =
|
|
"<Btn2Down>: BrowserPopupMenu() ";
|
|
|
|
static XtTranslations browser_transtbl = NULL;
|
|
|
|
/*
|
|
* Translations for top level view of browser
|
|
*/
|
|
static String proj_base_translations =
|
|
"Shift <Btn1Down>,<Btn1Up>: BrowserProjToggleSelect() \n\
|
|
<Btn1Down>,<Btn1Up>: BrowserProjSelect() \n\
|
|
<Btn1Up>(2): BrowserProjInvokeProps() \n"; /* will be appended-to */
|
|
|
|
static String proj_btn2_adjust_translations =
|
|
"<Btn2Down>,<Btn2Up>: BrowserProjToggleSelect() \n"; /* will be appended-to */
|
|
|
|
static XtTranslations browser_proj_transtbl = NULL;
|
|
|
|
|
|
static char *browser_mainwindow = "mainwindow";
|
|
|
|
static char *sm_font_name = "-*-courier-bold-r-normal--12-120-75-75-m-70-iso8859-1";
|
|
|
|
static XtTranslations orig_draw_area_trans;
|
|
static Bool orig_trans_set = False;
|
|
static XRectangle *rband_rect = NULL;
|
|
|
|
static Boolean mselect_adjust = False;
|
|
|
|
extern VMethods brwsP_mod_methods;
|
|
extern VMethods brwsP_proj_methods;
|
|
|
|
|
|
/*
|
|
*********************************************
|
|
* START OF ACTION PROCS FOR PROJECT SUBWINDOW
|
|
*********************************************
|
|
*/
|
|
|
|
/*
|
|
* Action: caused the browser object to become "selected"
|
|
*/
|
|
static void
|
|
browser_proj_select(
|
|
Widget widget,
|
|
XEvent *event,
|
|
String *params,
|
|
int num_params
|
|
)
|
|
{
|
|
ABBrowser ab = NULL;
|
|
Vwr proj_b;
|
|
Vwr mod_b;
|
|
VNode proj_node;
|
|
VNode mod_node;
|
|
AB_OBJ *obj;
|
|
|
|
XtVaGetValues(widget, XmNuserData, &ab, NULL);
|
|
|
|
if (!ab)
|
|
return;
|
|
|
|
proj_b = ab->project;
|
|
mod_b = ab->module;
|
|
|
|
if (!proj_b || !mod_b)
|
|
return;
|
|
|
|
proj_node = vwr_locate_node(proj_b,
|
|
event->xbutton.x,
|
|
event->xbutton.y);
|
|
|
|
if (proj_node)
|
|
{
|
|
ViewerMethods *m;
|
|
|
|
if (!(obj = (AB_OBJ *)proj_node->obj_data))
|
|
return;
|
|
|
|
if (!(mod_node = aob_find_bnode(obj, mod_b)))
|
|
return;
|
|
|
|
/*
|
|
* Deselect all nodes in toplevel view
|
|
*/
|
|
aob_deselect_all_nodes(proj_b, TRUE);
|
|
|
|
m = mod_b->methods;
|
|
|
|
/*
|
|
* Set select state to TRUE for node
|
|
* Hilite node in project subwindow
|
|
*/
|
|
BRWS_NODE_SET_STATE(proj_node, BRWS_NODE_SELECTED);
|
|
(*m->render_node)(proj_node, TRUE);
|
|
|
|
/*
|
|
* Set shown state of node in module subwindow
|
|
*/
|
|
brwsP_sync_views(ab, FALSE);
|
|
|
|
/*
|
|
* Erase and redraw module subwindow
|
|
*/
|
|
erase_viewer(mod_b);
|
|
draw_viewer(mod_b);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Action: toggles the select-state of the browser object
|
|
*/
|
|
static void
|
|
browser_proj_toggle_select(
|
|
Widget widget,
|
|
XEvent *event,
|
|
String *params,
|
|
int num_params
|
|
)
|
|
{
|
|
ABBrowser ab = NULL;
|
|
Vwr proj_b;
|
|
Vwr mod_b;
|
|
VNode proj_node;
|
|
VNode mod_node;
|
|
AB_OBJ *obj;
|
|
|
|
XtVaGetValues(widget, XmNuserData, &ab, NULL);
|
|
|
|
if (!ab)
|
|
return;
|
|
|
|
proj_b = ab->project;
|
|
mod_b = ab->module;
|
|
|
|
if (!proj_b || !mod_b)
|
|
return;
|
|
|
|
proj_node = vwr_locate_node(proj_b,
|
|
event->xbutton.x,
|
|
event->xbutton.y);
|
|
|
|
if (proj_node)
|
|
{
|
|
VMethods m;
|
|
int hilite;
|
|
|
|
obj = (AB_OBJ *)proj_node->obj_data;
|
|
|
|
if (!(obj = (AB_OBJ *)proj_node->obj_data))
|
|
return;
|
|
|
|
if (!(mod_node = aob_find_bnode(obj, mod_b)))
|
|
return;
|
|
|
|
m = mod_b->methods;
|
|
|
|
/*
|
|
* Toggle select state of node in toplevel view and
|
|
* corresponding node in detail view
|
|
*/
|
|
if (BRWS_NODE_STATE_IS_SET(proj_node, BRWS_NODE_SELECTED))
|
|
{
|
|
/*
|
|
* Set select state of node in toplevel view.
|
|
* Set hilite flag to be used later to render node
|
|
*/
|
|
BRWS_NODE_UNSET_STATE(proj_node, BRWS_NODE_SELECTED);
|
|
hilite = FALSE;
|
|
|
|
/*
|
|
* Set select state of node in detailed view
|
|
*/
|
|
BRWS_NODE_UNSET_STATE(mod_node, BRWS_NODE_VISIBLE);
|
|
}
|
|
else
|
|
{
|
|
BRWS_NODE_SET_STATE(proj_node, BRWS_NODE_SELECTED);
|
|
hilite = TRUE;
|
|
|
|
BRWS_NODE_SET_STATE(mod_node, BRWS_NODE_VISIBLE);
|
|
}
|
|
|
|
/*
|
|
* Render node in toplevel view
|
|
*/
|
|
(*m->render_node)(proj_node, hilite);
|
|
|
|
/*
|
|
* Render entire detailed view
|
|
*/
|
|
erase_viewer(mod_b);
|
|
draw_viewer(mod_b);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Action: invokes the property sheet for the browser object
|
|
*/
|
|
static void
|
|
browser_proj_invoke_props(
|
|
Widget widget,
|
|
XEvent *event,
|
|
String *params,
|
|
int num_params
|
|
)
|
|
{
|
|
AB_OBJ *obj;
|
|
ABBrowser ab = NULL;
|
|
Vwr b;
|
|
VNode selected_node;
|
|
|
|
XtVaGetValues(widget, XmNuserData, &ab, NULL);
|
|
|
|
if (!ab)
|
|
return;
|
|
|
|
b = aob_proj_or_module(ab, widget);
|
|
|
|
selected_node = vwr_locate_node(b,
|
|
event->xbutton.x, event->xbutton.y);
|
|
|
|
if (selected_node)
|
|
{
|
|
obj = (AB_OBJ *)selected_node->obj_data;
|
|
|
|
if (!obj)
|
|
return;
|
|
|
|
if (obj_is_message(obj))
|
|
msgEd_show_dialog();
|
|
else
|
|
prop_load_obj(obj, AB_PROP_REVOLVING);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Action: popup the build menu for the browser object
|
|
*/
|
|
static void
|
|
browser_proj_popup_menu(
|
|
Widget widget,
|
|
XEvent *event,
|
|
String *params,
|
|
int num_params
|
|
)
|
|
{
|
|
AB_OBJ *obj;
|
|
ABBrowser ab = NULL;
|
|
Vwr b;
|
|
VNode selected_node;
|
|
|
|
XtVaGetValues(widget, XmNuserData, &ab, NULL);
|
|
|
|
if (!ab)
|
|
return;
|
|
|
|
b = aob_proj_or_module(ab, widget);
|
|
|
|
selected_node = vwr_locate_node(b,
|
|
event->xbutton.x, event->xbutton.y);
|
|
|
|
if (selected_node)
|
|
{
|
|
ABSelectedRec sel;
|
|
|
|
obj = (AB_OBJ *)selected_node->obj_data;
|
|
|
|
if (!obj)
|
|
return;
|
|
|
|
abobj_get_selected(obj_get_project(obj), FALSE, TRUE, &sel);
|
|
|
|
if (event->type == ButtonPress)
|
|
abobj_popup_menu(BROWSER_EDIT_MENU, widget, &sel, (XButtonEvent *)event);
|
|
|
|
XtFree((char *)sel.list);
|
|
}
|
|
}
|
|
|
|
/*
|
|
*******************************************
|
|
* END OF ACTION PROCS FOR PROJECT SUBWINDOW
|
|
*******************************************
|
|
*/
|
|
|
|
/*
|
|
********************************************
|
|
* START OF ACTION PROCS FOR MODULE SUBWINDOW
|
|
********************************************
|
|
*/
|
|
int
|
|
selected_fn(
|
|
VNode v
|
|
)
|
|
{
|
|
if (BRWS_NODE_STATE_IS_SET(v, BRWS_NODE_SELECTED))
|
|
return (1);
|
|
|
|
return (0);
|
|
}
|
|
|
|
static int
|
|
select_rband(
|
|
VNode vnode
|
|
)
|
|
{
|
|
|
|
if (!vnode || !rband_rect)
|
|
return (0);
|
|
|
|
if (((int)rband_rect->x <= vnode->x) &&
|
|
((int)(rband_rect->x + (short)rband_rect->width) >= (vnode->x + vnode->width)) &&
|
|
((int)rband_rect->y <= vnode->y) &&
|
|
((int)(rband_rect->y + (short)rband_rect->height) >= vnode->y + vnode->height))
|
|
return (1);
|
|
|
|
return (0);
|
|
}
|
|
|
|
static void
|
|
browser_rband(
|
|
Widget widget,
|
|
XEvent *event,
|
|
XRectangle *rb_rect,
|
|
XtPointer client_data
|
|
)
|
|
{
|
|
ABBrowser ab = NULL;
|
|
Vwr v = NULL;
|
|
VNode *selected_nodes = NULL;
|
|
VMethods m;
|
|
ABSelectedRec old_sel,
|
|
new_sel;
|
|
XRectangle tmp_rect;
|
|
int num_selected = 0,
|
|
i;
|
|
|
|
XtVaGetValues(widget, XmNuserData, &ab, NULL);
|
|
|
|
if (!ab)
|
|
return;
|
|
|
|
if (!(v = ab->module))
|
|
return;
|
|
|
|
if (!(m = v->methods))
|
|
return;
|
|
|
|
/* If rubberband was drawn from lower-right to upper-left,
|
|
* translate rect so that x,y is upper-left point in rectangle.
|
|
*/
|
|
if (rect_right(rb_rect) < rb_rect->x ||
|
|
rect_bottom(rb_rect) < rb_rect->y)
|
|
{
|
|
tmp_rect.x = rect_right(rb_rect);
|
|
tmp_rect.y = rect_bottom(rb_rect);
|
|
tmp_rect.width = rb_rect->x - tmp_rect.x;
|
|
tmp_rect.height = rb_rect->y - tmp_rect.y;
|
|
rb_rect = &tmp_rect;
|
|
}
|
|
|
|
/*
|
|
* Important: set rband_rect so that
|
|
* the function 'select_rband' can see it.
|
|
*/
|
|
rband_rect = rb_rect;
|
|
|
|
/*
|
|
* Get nodes in browser that are within the
|
|
* rubber band rectangle.
|
|
*/
|
|
vwr_get_cond(v->current_tree, &selected_nodes,
|
|
&num_selected, select_rband);
|
|
|
|
/*
|
|
* Return if no selected nodes
|
|
*/
|
|
if (num_selected == 0)
|
|
return;
|
|
|
|
new_sel.list = (ABObj *)util_malloc(num_selected * sizeof(ABObj));
|
|
new_sel.count = 0;
|
|
|
|
/*
|
|
* For each object enclosed in rubber band rectangle
|
|
*/
|
|
for (i=0; i < num_selected; ++i)
|
|
{
|
|
ABObj obj;
|
|
int j;
|
|
|
|
/*
|
|
* Skip if browser node is not visible or collapsed
|
|
*/
|
|
if (!brwsP_node_is_visible(selected_nodes[i]) ||
|
|
brwsP_node_is_collapsed(selected_nodes[i]))
|
|
continue;
|
|
|
|
/*
|
|
* Get ABObj
|
|
*/
|
|
obj = (ABObj)selected_nodes[i]->obj_data;
|
|
|
|
if (!obj)
|
|
continue;
|
|
|
|
/*
|
|
* Get list of objects selected within the window of this
|
|
* object. Should optimize by caching this.
|
|
*/
|
|
abobj_get_selected(obj_get_window(obj), True, False, &old_sel);
|
|
|
|
/*
|
|
* For each in current/old selected list (of the object's window)
|
|
*/
|
|
for (j = 0; j < old_sel.count; j++)
|
|
{
|
|
/*
|
|
* Deselect object:
|
|
*
|
|
* If RUBBERBAND-SELECT, deselect all other currently selected
|
|
* objects.
|
|
* If RUBBERBAND-ADJUST, deselect only currently selected
|
|
* NON-sibling objects
|
|
*/
|
|
if ((obj != old_sel.list[j]) &&
|
|
(!mselect_adjust ||
|
|
!obj_is_sibling(obj, old_sel.list[j])) )
|
|
{
|
|
abobj_deselect(old_sel.list[j]);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Construct list of new objects to mark as selected
|
|
*
|
|
* Mark this object as selected only if it is a sibling of any object
|
|
* on the same window already on the list.
|
|
*
|
|
* This can be optimized as well.
|
|
*/
|
|
if (new_sel.count == 0)
|
|
{
|
|
/*
|
|
* If list is empty, just add obj to it
|
|
*/
|
|
new_sel.list[new_sel.count] = obj;
|
|
new_sel.count++;
|
|
}
|
|
else
|
|
{
|
|
Bool added_to_list = False,
|
|
window_found = False;
|
|
|
|
/*
|
|
* List is not empty.
|
|
* 2 things to check:
|
|
* - does obj already have a sibling on the list? If yes,
|
|
* insert obj
|
|
* - is there an object on the list that is on the same window
|
|
* as obj? Non-siblings can be selected together if they are
|
|
* not on the same window.
|
|
*/
|
|
for (j = 0; j < new_sel.count; ++j)
|
|
{
|
|
/*
|
|
* Remember if an object on the same window was found
|
|
*/
|
|
if (obj_get_window(obj) == obj_get_window(new_sel.list[j]))
|
|
window_found = True;
|
|
|
|
/*
|
|
* Sibling found! Add obj to list
|
|
*/
|
|
if (obj_is_sibling(obj, new_sel.list[j]))
|
|
{
|
|
new_sel.list[new_sel.count] = obj;
|
|
new_sel.count++;
|
|
added_to_list = True;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Double check: Add obj to list if there is no object in
|
|
* the same window on the list yet.
|
|
*/
|
|
if (!added_to_list && !window_found)
|
|
{
|
|
new_sel.list[new_sel.count] = obj;
|
|
new_sel.count++;
|
|
}
|
|
}
|
|
|
|
util_free(old_sel.list);
|
|
}
|
|
|
|
/*
|
|
* Unset rband_rect
|
|
*/
|
|
rband_rect = NULL;
|
|
|
|
/*
|
|
* Mark new objects as selected
|
|
*/
|
|
for (i = 0; i < new_sel.count; ++i)
|
|
{
|
|
abobj_select(new_sel.list[i]);
|
|
}
|
|
|
|
/*
|
|
* Free list of new selected objects
|
|
*/
|
|
util_free(new_sel.list);
|
|
|
|
/*
|
|
* Free up node list if it contained anything
|
|
*/
|
|
if (selected_nodes)
|
|
util_free(selected_nodes);
|
|
}
|
|
|
|
/*
|
|
* Action: mouse button down on browser
|
|
*/
|
|
static void
|
|
browser_bpress(
|
|
Widget widget,
|
|
XEvent *event,
|
|
String *params,
|
|
int num_params
|
|
)
|
|
{
|
|
XButtonEvent *bevent;
|
|
|
|
if (event->type == ButtonPress)
|
|
{
|
|
bevent = (XButtonEvent*)event;
|
|
|
|
if (bevent->state == 0 && bevent->button == 1)/* RUBBERBAND SELECT */
|
|
{
|
|
if (ui_initiate_rubberband(widget, True,
|
|
browser_rband, (XtPointer)NULL) == ERROR)
|
|
{
|
|
if (util_get_verbosity() > 0)
|
|
fprintf(stderr,"browser: couldn't begin rubberbanding\n");
|
|
}
|
|
else
|
|
mselect_adjust = False;
|
|
}
|
|
else if (bevent->button == 2 || /* RUBBERBAND ADJUST SELECT */
|
|
(bevent->button == 1 && (bevent->state & ShiftMask)))
|
|
{
|
|
if (ui_initiate_rubberband(widget, True,
|
|
browser_rband, (XtPointer)NULL) == ERROR)
|
|
{
|
|
if (util_get_verbosity() > 0)
|
|
fprintf(stderr,"browser: couldn't begin rubberbanding\n");
|
|
}
|
|
else
|
|
mselect_adjust = True;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Action: caused the browser object to become "selected"
|
|
*/
|
|
static void
|
|
browser_select(
|
|
Widget widget,
|
|
XEvent *event,
|
|
String *params,
|
|
int num_params
|
|
)
|
|
{
|
|
ABBrowser ab = NULL;
|
|
Vwr b;
|
|
VNode selected_node;
|
|
AB_OBJ *obj;
|
|
BrowserUiObjects *ui;
|
|
|
|
XtVaGetValues(widget, XmNuserData, &ab, NULL);
|
|
|
|
if (!ab)
|
|
return;
|
|
|
|
b = aob_proj_or_module(ab, widget);
|
|
|
|
ui = aob_ui_from_browser(b);
|
|
|
|
if (!ui)
|
|
return;
|
|
|
|
selected_node = vwr_locate_node(b,
|
|
event->xbutton.x, event->xbutton.y);
|
|
|
|
if (selected_node)
|
|
{
|
|
VMethods m;
|
|
unsigned long elm_selected;
|
|
|
|
m = b->methods;
|
|
|
|
if (!m)
|
|
return;
|
|
|
|
elm_selected = (*m->locate_elements)(selected_node,
|
|
event->xbutton.x, event->xbutton.y);
|
|
|
|
obj = (AB_OBJ *)selected_node->obj_data;
|
|
|
|
if (!obj)
|
|
return;
|
|
|
|
if (util_get_verbosity() > 0)
|
|
{
|
|
util_dprintf(1, "*********************\n");
|
|
util_dprintf(1, "Browser Node Selected - %s\n",
|
|
obj_get_name(obj));
|
|
util_dprintf(1, "Object %s is %s\n",
|
|
obj_get_name(obj),
|
|
obj_is_initially_active(obj) ?
|
|
"initially active" : "NOT initially active");
|
|
if (obj->ui_handle)
|
|
{
|
|
int num_children = 0;
|
|
|
|
util_dprintf(1,
|
|
"Ui handle - %p, Widget name: %s, class: %s\n",
|
|
(objxm_get_widget(obj)),
|
|
XtName(objxm_get_widget(obj)),
|
|
obj_get_class_name(obj));
|
|
|
|
XtVaGetValues(objxm_get_widget(obj),
|
|
XtNnumChildren, &num_children,
|
|
NULL);
|
|
|
|
util_dprintf(1,
|
|
"Widget %s has %d children\n",
|
|
XtName(objxm_get_widget(obj)),
|
|
num_children);
|
|
|
|
objxm_dump_widget_geometry(objxm_get_widget(obj));
|
|
}
|
|
else
|
|
{
|
|
util_dprintf(1, "No ui handle\n");
|
|
}
|
|
util_dprintf(1, "*********************\n\n");
|
|
|
|
}
|
|
|
|
abobj_deselect_all(obj_get_project(obj));
|
|
abobj_select(obj);
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* Action: toggles the select-state of the browser object
|
|
*/
|
|
static void
|
|
browser_toggle_select(
|
|
Widget widget,
|
|
XEvent *event,
|
|
String *params,
|
|
int num_params
|
|
)
|
|
{
|
|
AB_OBJ *obj;
|
|
ABBrowser ab = NULL;
|
|
Vwr b;
|
|
VNode selected_node;
|
|
|
|
XtVaGetValues(widget, XmNuserData, &ab, NULL);
|
|
|
|
if (!ab)
|
|
return;
|
|
|
|
b = aob_proj_or_module(ab, widget);
|
|
|
|
selected_node = vwr_locate_node(b,
|
|
event->xbutton.x, event->xbutton.y);
|
|
|
|
if (selected_node)
|
|
{
|
|
|
|
obj = (AB_OBJ *)selected_node->obj_data;
|
|
|
|
if (!obj)
|
|
return;
|
|
|
|
if (obj_is_selected(obj_get_root(obj)))
|
|
{
|
|
abobj_deselect(obj);
|
|
}
|
|
else
|
|
{
|
|
ABSelectedRec sel;
|
|
BOOL allow = TRUE;
|
|
int i;
|
|
|
|
/* Only objects on the same level (siblings) may be
|
|
* selected at any one time, so deselect any non-sibling
|
|
* objects
|
|
*/
|
|
abobj_get_selected(obj_get_window(obj), True, False, &sel);
|
|
|
|
for(i = 0; i < sel.count; i++)
|
|
{
|
|
if (!obj_is_sibling(obj, sel.list[i]))
|
|
allow = FALSE;
|
|
}
|
|
if (allow)
|
|
abobj_select(obj);
|
|
|
|
util_free(sel.list);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* Action: invokes the property sheet for the browser object
|
|
*/
|
|
static void
|
|
browser_invoke_props(
|
|
Widget widget,
|
|
XEvent *event,
|
|
String *params,
|
|
int num_params
|
|
)
|
|
{
|
|
AB_OBJ *obj;
|
|
ABBrowser ab = NULL;
|
|
Vwr b;
|
|
VNode selected_node;
|
|
|
|
|
|
XtVaGetValues(widget, XmNuserData, &ab, NULL);
|
|
|
|
if (!ab)
|
|
return;
|
|
|
|
b = aob_proj_or_module(ab, widget);
|
|
|
|
selected_node = vwr_locate_node(b,
|
|
event->xbutton.x, event->xbutton.y);
|
|
|
|
if (selected_node)
|
|
{
|
|
obj = (AB_OBJ *)selected_node->obj_data;
|
|
|
|
if (!obj)
|
|
return;
|
|
|
|
if (obj_is_message(obj))
|
|
msgEd_show_dialog();
|
|
else
|
|
prop_load_obj(obj, AB_PROP_REVOLVING);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Action: popup the build menu for the browser object
|
|
*/
|
|
static void
|
|
browser_popup_menu(
|
|
Widget widget,
|
|
XEvent *event,
|
|
String *params,
|
|
int num_params
|
|
)
|
|
{
|
|
AB_OBJ *obj;
|
|
ABBrowser ab = NULL;
|
|
Vwr b;
|
|
VNode selected_node;
|
|
ABSelectedRec sel;
|
|
|
|
XtVaGetValues(widget, XmNuserData, &ab, NULL);
|
|
|
|
if (!ab)
|
|
return;
|
|
|
|
b = aob_proj_or_module(ab, widget);
|
|
|
|
abobj_get_selected(proj_get_project(), FALSE, TRUE, &sel);
|
|
|
|
if (event->type == ButtonPress)
|
|
abobj_popup_menu(BROWSER_EDIT_MENU, widget, &sel, (XButtonEvent *)event);
|
|
|
|
if (sel.list)
|
|
XtFree((char *)sel.list);
|
|
}
|
|
|
|
/*
|
|
******************************************
|
|
* END OF ACTION PROCS FOR MODULE SUBWINDOW
|
|
******************************************
|
|
*/
|
|
|
|
/*
|
|
* Register build actions with Xt
|
|
*/
|
|
void
|
|
brws_register_actions(
|
|
XtAppContext app
|
|
)
|
|
{
|
|
XtAppAddActions(app, browser_actions, XtNumber(browser_actions));
|
|
}
|
|
|
|
/*
|
|
* Enable browser actions for project subwindow
|
|
*/
|
|
static void
|
|
enable_proj_actions(
|
|
Widget widget
|
|
)
|
|
{
|
|
if (!orig_trans_set)
|
|
{
|
|
XtVaGetValues(widget, XtNtranslations, &orig_draw_area_trans, NULL);
|
|
orig_trans_set = True;
|
|
}
|
|
|
|
if (browser_proj_transtbl == NULL)
|
|
{
|
|
int len;
|
|
String translations, menu_translations;
|
|
|
|
/* First time only.
|
|
* Build up translation table based on the number of mouse buttons
|
|
* and the value of the display resource, "enableBtn1Transfer"
|
|
*/
|
|
menu_translations =
|
|
(AB_BMenu == Button3? btn3_menu_translations : btn2_menu_translations);
|
|
|
|
len = strlen(proj_base_translations) + strlen(menu_translations) + 1;
|
|
|
|
if (AB_BMenu == Button3 && AB_btn1_transfer == True)
|
|
/* Button2 can be used for ADJUST */
|
|
len += strlen(proj_btn2_adjust_translations);
|
|
|
|
translations = (String)util_malloc(len*sizeof(char));
|
|
if (translations == NULL)
|
|
return; /* yikes */
|
|
|
|
strcpy(translations, proj_base_translations);
|
|
if (AB_BMenu == Button3 && AB_btn1_transfer == True)
|
|
strcat(translations, proj_btn2_adjust_translations);
|
|
strcat(translations, menu_translations);
|
|
|
|
browser_proj_transtbl = XtParseTranslationTable(translations);
|
|
|
|
util_free(translations);
|
|
}
|
|
|
|
/* enable build mode behavior */
|
|
XtVaSetValues(widget,
|
|
XtNtranslations, browser_proj_transtbl,
|
|
NULL);
|
|
}
|
|
|
|
/*
|
|
* Enable browser actions for module subwindow
|
|
*/
|
|
static void
|
|
enable_actions(
|
|
Widget widget
|
|
)
|
|
{
|
|
if (!orig_trans_set)
|
|
{
|
|
XtVaGetValues(widget, XtNtranslations, &orig_draw_area_trans, NULL);
|
|
orig_trans_set = True;
|
|
}
|
|
|
|
if (browser_transtbl == NULL)
|
|
{
|
|
int len;
|
|
String translations, menu_translations;
|
|
|
|
/* First time only.
|
|
* Build up translation table based on the number of mouse buttons
|
|
* and the value of the display resource, "enableBtn1Transfer"
|
|
*/
|
|
menu_translations = (AB_BMenu == Button3? btn3_menu_translations : btn2_menu_translations);
|
|
|
|
len = strlen(base_translations) + strlen(menu_translations) + 1;
|
|
|
|
if (AB_BMenu == Button3 && AB_btn1_transfer == True)
|
|
/* Button2 can be used for ADJUST */
|
|
len += strlen(btn2_adjust_translations);
|
|
|
|
translations = (String)util_malloc(len*sizeof(char));
|
|
if (translations == NULL)
|
|
return; /* yikes */
|
|
|
|
strcpy(translations, base_translations);
|
|
if (AB_BMenu == Button3 && AB_btn1_transfer == True)
|
|
strcat(translations, btn2_adjust_translations);
|
|
strcat(translations, menu_translations);
|
|
|
|
browser_transtbl = XtParseTranslationTable(translations);
|
|
|
|
util_free(translations);
|
|
}
|
|
|
|
/* enable build mode behavior */
|
|
XtVaSetValues(widget,
|
|
XtNtranslations, browser_transtbl,
|
|
NULL);
|
|
}
|
|
|
|
/*
|
|
* Disable browser actions for project subwindow
|
|
*/
|
|
static void
|
|
disable_proj_actions(
|
|
Widget widget
|
|
)
|
|
{
|
|
if (!orig_trans_set)
|
|
{
|
|
XtVaGetValues(widget, XtNtranslations, &orig_draw_area_trans, NULL);
|
|
orig_trans_set = True;
|
|
}
|
|
|
|
/* enable build mode behavior */
|
|
XtVaSetValues(widget,
|
|
XtNtranslations, orig_draw_area_trans,
|
|
NULL);
|
|
}
|
|
|
|
/*
|
|
* Disable browser actions for module subwindow
|
|
*/
|
|
static void
|
|
disable_actions(
|
|
Widget widget
|
|
)
|
|
{
|
|
if (!orig_trans_set)
|
|
{
|
|
XtVaGetValues(widget, XtNtranslations, &orig_draw_area_trans, NULL);
|
|
orig_trans_set = True;
|
|
}
|
|
|
|
/* enable build mode behavior */
|
|
XtVaSetValues(widget,
|
|
XtNtranslations, orig_draw_area_trans,
|
|
NULL);
|
|
}
|
|
|
|
/*
|
|
* EventHandler: browser draw area drag action ...
|
|
*/
|
|
static void
|
|
brwsP_drawarea_button_drag(
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XEvent *event,
|
|
Boolean *cont_dispatch
|
|
)
|
|
{
|
|
if (event->type == MotionNotify)
|
|
{
|
|
if (((XMotionEvent*)event)->state & Button1Mask) /* RUBBERBAND SELECT */
|
|
{
|
|
ui_button_drag(widget, event, client_data);
|
|
}
|
|
else if (((XMotionEvent*)event)->state & Button2Mask) /* RUBBERBAND ADJUST */
|
|
{
|
|
ui_button_drag(widget, event, client_data);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
setup_callbacks(
|
|
Widget browser_widget,
|
|
ABBrowser browser
|
|
)
|
|
{
|
|
BrowserUiObj proj_ui,
|
|
mod_ui;
|
|
DtbBrwsMainwindowInfo instance;
|
|
|
|
proj_ui = (BrowserUiObj)browser->project->ui_handle;
|
|
instance = (DtbBrwsMainwindowInfo)proj_ui->ip;
|
|
|
|
enable_proj_actions(instance->toplevel_drawarea);
|
|
enable_actions(instance->detailed_drawarea);
|
|
|
|
XtVaSetValues(instance->toplevel_drawarea,
|
|
XmNuserData, (XtPointer)browser, NULL);
|
|
XtVaSetValues(instance->detailed_drawarea,
|
|
XmNuserData, (XtPointer)browser, NULL);
|
|
XtVaSetValues(instance->menubar_items.View_item,
|
|
XmNuserData, (XtPointer)browser, NULL);
|
|
XtVaSetValues(instance->menubar_View_item_view_pulldown_items.Horizontal_item,
|
|
XmNuserData, (XtPointer)browser, NULL);
|
|
XtVaSetValues(instance->menubar_View_item_view_pulldown_items.Hide_Object_Glyph_item,
|
|
XmNuserData, (XtPointer)browser, NULL);
|
|
XtVaSetValues(instance->menubar_View_item_view_pulldown_items.Hide_Object_Name_item,
|
|
XmNuserData, (XtPointer)browser, NULL);
|
|
XtVaSetValues(instance->menubar_View_item_view_pulldown_items.Show_Object_Type_item,
|
|
XmNuserData, (XtPointer)browser, NULL);
|
|
XtVaSetValues(instance->menubar_View_item_view_pulldown_items.Collapse_item,
|
|
XmNuserData, (XtPointer)browser, NULL);
|
|
XtVaSetValues(instance->menubar_View_item_view_pulldown_items.Expand_item,
|
|
XmNuserData, (XtPointer)browser, NULL);
|
|
XtVaSetValues(instance->menubar_View_item_view_pulldown_items.Expand_All_item,
|
|
XmNuserData, (XtPointer)browser, NULL);
|
|
|
|
#ifdef BRWS_WIDGET_CLASS
|
|
XtVaSetValues(instance->obj_wclass,
|
|
XmNuserData, (XtPointer)browser, NULL);
|
|
#endif
|
|
|
|
XtVaSetValues(instance->menubar_View_item_view_pulldown_items.Find_item,
|
|
XmNuserData, (XtPointer)browser, NULL);
|
|
XtVaSetValues(instance->menubar_View_item_view_pulldown_items.Tear_Off_Browser_item,
|
|
XmNuserData, (XtPointer)browser, NULL);
|
|
|
|
XtVaSetValues(instance->menubar_View_item_view_pulldown_items.Module_item,
|
|
XmNuserData, (XtPointer)browser, NULL);
|
|
|
|
XtVaSetValues(instance->menubar_items.Edit_item,
|
|
XmNuserData, (XtPointer)browser, NULL);
|
|
|
|
XtVaSetValues(instance->menubar_View_item_view_pulldown,
|
|
XmNuserData, (XtPointer)browser, NULL);
|
|
|
|
XtVaSetValues(instance->view_pulldown_Module_item_view_module_pulldown2,
|
|
XmNuserData, (XtPointer)browser, NULL);
|
|
|
|
/*
|
|
* Set callbacks
|
|
*/
|
|
XtAddCallback(instance->menubar_items.Edit_item, XmNcascadingCallback,
|
|
brws_edit_cascadeCB, (XtPointer)NULL);
|
|
XtAddCallback(instance->menubar_items.View_item, XmNcascadingCallback,
|
|
brws_view_cascadeCB,
|
|
(XtPointer)instance->menubar_View_item_view_pulldown_items.Module_item);
|
|
|
|
/*
|
|
* Set event handler on draw area for dragging/rubber banding
|
|
*/
|
|
XtAddEventHandler(instance->detailed_drawarea,
|
|
Button1MotionMask | Button2MotionMask, False,
|
|
brwsP_drawarea_button_drag, (XtPointer)NULL);
|
|
|
|
brwsP_make_drawarea_snap(browser->module, instance->detailed_drawarea);
|
|
}
|
|
|
|
static int
|
|
select_fn(
|
|
VNode vnode
|
|
)
|
|
{
|
|
if (BRWS_NODE_STATE_IS_SET(vnode, BRWS_NODE_SELECTED))
|
|
return (1);
|
|
|
|
return (0);
|
|
}
|
|
|
|
void
|
|
brws_add_objects_to_browser
|
|
(
|
|
ABBrowser ab,
|
|
AB_OBJ *obj
|
|
)
|
|
{
|
|
ViewerMethods *m;
|
|
ABObj module;
|
|
|
|
if (!ab)
|
|
return;
|
|
|
|
if (obj)
|
|
{
|
|
VNode *selected_nodes = NULL;
|
|
int num_selected = 0;
|
|
|
|
m = ab->project->methods;
|
|
(*m->insert_tree)(ab->project, obj);
|
|
|
|
m = ab->module->methods;
|
|
(*m->insert_tree)(ab->module, obj);
|
|
|
|
brwsP_sync_views(ab, TRUE);
|
|
}
|
|
|
|
erase_viewer(ab->project);
|
|
draw_viewer(ab->project);
|
|
|
|
erase_viewer(ab->module);
|
|
draw_viewer(ab->module);
|
|
}
|
|
|
|
void
|
|
brws_delete_objects_from_browser (
|
|
ABBrowser ab,
|
|
AB_OBJ *obj
|
|
)
|
|
{
|
|
ViewerMethods *m;
|
|
|
|
if (!ab)
|
|
return;
|
|
|
|
if (obj)
|
|
{
|
|
m = ab->project->methods;
|
|
(*m->remove_tree)(ab->project, obj);
|
|
|
|
m = ab->module->methods;
|
|
(*m->remove_tree)(ab->module, obj);
|
|
}
|
|
|
|
/*
|
|
* Redraw browser if it still contain objects, otherwise
|
|
* destroy the browser
|
|
*/
|
|
if (ab->project->tree && ab->module->tree)
|
|
{
|
|
erase_viewer(ab->project);
|
|
draw_viewer(ab->project);
|
|
|
|
erase_viewer(ab->module);
|
|
draw_viewer(ab->module);
|
|
}
|
|
else
|
|
{
|
|
Widget shell;
|
|
|
|
shell = aob_ui_shell(ab->project);
|
|
|
|
if (shell)
|
|
XtDestroyWidget(shell);
|
|
}
|
|
}
|
|
|
|
void
|
|
brws_add_objects
|
|
(
|
|
AB_OBJ *obj
|
|
)
|
|
{
|
|
AB_OBJ *project,
|
|
*module;
|
|
ABBrowser new_b, cur_b, b_list = NULL;
|
|
|
|
if (!obj)
|
|
return;
|
|
|
|
/*
|
|
* Get project/module object
|
|
*/
|
|
project = obj_get_project(obj);
|
|
module = obj_get_module(obj);
|
|
|
|
if (!project || !module)
|
|
return;
|
|
|
|
/*
|
|
* Get browser list
|
|
*/
|
|
b_list = (ABBrowser)project->info.project.browsers;
|
|
|
|
/*
|
|
* If no browser list, create browser for this project
|
|
*/
|
|
if (!b_list)
|
|
return;
|
|
|
|
/*
|
|
* If the object passed in was a project, we have to
|
|
* insert into the proper browsers the proper modules
|
|
*/
|
|
if (obj == project)
|
|
{
|
|
AB_TRAVERSAL trav;
|
|
AB_OBJ *cur_module;
|
|
|
|
for (trav_open(&trav, project, AB_TRAV_MODULES);
|
|
(cur_module = trav_next(&trav)) != NULL; ) {
|
|
|
|
for (cur_b = b_list; cur_b; cur_b = cur_b->next)
|
|
{
|
|
AB_OBJ *browsed_module;
|
|
|
|
browsed_module = (AB_OBJ *)cur_b->project->obj_data;
|
|
|
|
if (browsed_module == cur_module)
|
|
{
|
|
brws_add_objects_to_browser(cur_b, browsed_module);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Populate the object subtree with browser data for all
|
|
* browsers on the browser list. We do this for:
|
|
* module subwindow
|
|
* tree subwindow
|
|
*/
|
|
for (cur_b = b_list; cur_b; cur_b = cur_b->next)
|
|
{
|
|
ViewerMethods *m;
|
|
|
|
#ifdef POPULATE_EMPTY_BROWSER
|
|
if (!cur_b->project->tree ||
|
|
(cur_b->project->tree &&
|
|
((AB_OBJ *)cur_b->project->tree->obj_data == module)))
|
|
#else
|
|
if (cur_b->project->tree &&
|
|
((AB_OBJ *)cur_b->project->tree->obj_data == module))
|
|
#endif
|
|
brws_add_objects_to_browser(cur_b, obj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
brws_delete_objects
|
|
(
|
|
AB_OBJ *obj
|
|
)
|
|
{
|
|
AB_OBJ *project;
|
|
ABBrowser cur_b, b_list = NULL;
|
|
|
|
if (!obj)
|
|
return;
|
|
|
|
project = obj_get_project(obj);
|
|
|
|
if (!project)
|
|
return;
|
|
|
|
b_list = (ABBrowser)project->info.project.browsers;
|
|
|
|
for (cur_b = b_list; cur_b; cur_b = cur_b->next)
|
|
{
|
|
brws_delete_objects_from_browser(cur_b, obj);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* create_browser_window - creates a new browser main window
|
|
*/
|
|
ABBrowser
|
|
brws_create
|
|
(
|
|
)
|
|
{
|
|
ABBrowser b;
|
|
|
|
b = create_browser_struct();
|
|
create_browser_ui_handles(b);
|
|
|
|
return(b);
|
|
}
|
|
|
|
/*
|
|
* brws_destroy - destroys browser
|
|
*/
|
|
void
|
|
brws_destroy(
|
|
ABBrowser b
|
|
)
|
|
{
|
|
destroy_browser_ui_handles(b);
|
|
destroy_browser_struct(b);
|
|
}
|
|
|
|
/*
|
|
* Map browser
|
|
*/
|
|
void
|
|
brws_popup
|
|
(
|
|
ABBrowser b
|
|
)
|
|
{
|
|
Widget shell;
|
|
WidgetList children;
|
|
|
|
shell = aob_ui_shell(b->module);
|
|
|
|
if (!shell)
|
|
return;
|
|
|
|
XtVaGetValues(shell, XmNchildren, &children, NULL);
|
|
ab_show_window(children[0]);
|
|
}
|
|
|
|
/*
|
|
* Unmap browser
|
|
*/
|
|
void
|
|
brws_popdown
|
|
(
|
|
ABBrowser b
|
|
)
|
|
{
|
|
Widget shell;
|
|
|
|
shell = aob_ui_shell(b->module);
|
|
|
|
if (!shell)
|
|
return;
|
|
|
|
ui_win_show(shell, False, XtGrabNone);
|
|
}
|
|
|
|
/*
|
|
* Create the windows of the browser
|
|
*/
|
|
static void
|
|
create_browser_ui_handles
|
|
(
|
|
ABBrowser b
|
|
)
|
|
{
|
|
DtbBrwsMainwindowInfo instance;
|
|
BrowserUiObj module_ui;
|
|
BrowserUiObj project_ui;
|
|
Widget browser_main = NULL;
|
|
XmString xmlabel;
|
|
char *tmp;
|
|
char title[100];
|
|
|
|
if (!b || !b->module || b->module->ui_handle)
|
|
return;
|
|
|
|
project_ui = aob_create_ui_obj();
|
|
module_ui = aob_create_ui_obj();
|
|
project_ui->shell = module_ui->shell = NULL;
|
|
|
|
/*
|
|
* Create the browser widgets
|
|
*/
|
|
|
|
instance = (DtbBrwsMainwindowInfo)malloc(sizeof(DtbBrwsMainwindowInfoRec));
|
|
(void)dtbBrwsMainwindowInfo_clear(instance);
|
|
|
|
(void)dtb_brws_mainwindow_initialize(instance, AB_toplevel);
|
|
module_ui->shell = project_ui->shell = instance->mainwindow;
|
|
XtVaSetValues(project_ui->shell, XmNmappedWhenManaged, False, NULL);
|
|
|
|
XtVaSetValues(instance->menubar,
|
|
XmNmenuHelpWidget, instance->menubar_items.Help_item,
|
|
NULL);
|
|
|
|
XtAddCallback(project_ui->shell, XtNdestroyCallback,
|
|
browser_destroyCB, (XtPointer)b);
|
|
|
|
browser_main = instance->mainwindow_mainwin;
|
|
|
|
XtVaSetValues(browser_main, XmNuserData, instance, NULL);
|
|
project_ui->ip = module_ui->ip = (void *)instance;
|
|
|
|
XtRealizeWidget(project_ui->shell);
|
|
|
|
b->project->ui_handle = (void *)project_ui;
|
|
b->module->ui_handle = (void *)module_ui;
|
|
|
|
/*
|
|
* Setup callbacks so that the user data passed == the browser
|
|
* pointer
|
|
*/
|
|
setup_callbacks(browser_main, b);
|
|
|
|
/*
|
|
* Register it so that it will participate in the dtbuilder
|
|
* window protocol
|
|
*/
|
|
ab_register_window(browser_main, AB_WIN_WINDOW,
|
|
WindowHidden, AB_toplevel, AB_WPOS_TILE_LEFT,
|
|
NULL, NULL);
|
|
|
|
/* reset the deleteResponse back to the default since a close just
|
|
* means this browser window should be destroyed
|
|
*/
|
|
XtVaSetValues(project_ui->shell, XmNdeleteResponse, XmDESTROY, NULL);
|
|
|
|
/*
|
|
* End of browser widget creation
|
|
*/
|
|
|
|
setup_vwr_graphics(b->module);
|
|
setup_vwr_graphics(b->project);
|
|
|
|
/*
|
|
**********************************
|
|
* Put project name in window title
|
|
**********************************
|
|
*/
|
|
brws_set_module_name(b->module);
|
|
}
|
|
|
|
/*
|
|
* Destroy the UI objects of the browser
|
|
*/
|
|
static void
|
|
destroy_browser_ui_handles(
|
|
ABBrowser b
|
|
)
|
|
{
|
|
BrowserUiObjects *ui;
|
|
DtbBrwsMainwindowInfo instance;
|
|
|
|
if (!b)
|
|
return;
|
|
|
|
/*
|
|
* Free ui handles for project viewer
|
|
*/
|
|
if (b->project && b->project->ui_handle)
|
|
{
|
|
ui = aob_ui_from_browser(b->project);
|
|
|
|
/*
|
|
* Save pointer to instance structure so that we
|
|
* can free it later
|
|
*/
|
|
instance = (DtbBrwsMainwindowInfo)ui->ip;
|
|
|
|
aob_free_graphics(b->project);
|
|
|
|
if (ui->shell)
|
|
{
|
|
/*
|
|
* If the shell is already being destroyed,
|
|
* this will return right away
|
|
*/
|
|
XtDestroyWidget(ui->shell);
|
|
ui->shell = NULL;
|
|
}
|
|
|
|
aob_destroy_ui_obj(b->project);
|
|
}
|
|
|
|
/*
|
|
* Free ui handles for module viewer
|
|
*/
|
|
if (b->module && b->module->ui_handle)
|
|
{
|
|
ui = aob_ui_from_browser(b->module);
|
|
instance = (DtbBrwsMainwindowInfo)ui->ip;
|
|
|
|
aob_free_graphics(b->module);
|
|
|
|
if (ui->find_box)
|
|
{
|
|
brwsP_destroy_find_box(b->module);
|
|
}
|
|
|
|
if (ui->shell)
|
|
{
|
|
XtDestroyWidget(ui->shell);
|
|
ui->shell = NULL;
|
|
}
|
|
|
|
aob_destroy_ui_obj(b->module);
|
|
}
|
|
|
|
/*
|
|
* Free the ip structure
|
|
*/
|
|
if (instance)
|
|
free(instance);
|
|
}
|
|
|
|
|
|
/*
|
|
* Setup the graphics context and stuffs like that.
|
|
* This routine has to be called before any of
|
|
* the browser drawing routines is called.
|
|
*/
|
|
void
|
|
setup_vwr_graphics(
|
|
Viewer *b
|
|
)
|
|
{
|
|
|
|
BrowserUiObjects *ui_handle;
|
|
XGCValues gcvalues;
|
|
Display *dpy;
|
|
Widget draw_area;
|
|
|
|
if (!b || !b->ui_handle)
|
|
return;
|
|
|
|
ui_handle = (BrowserUiObjects*)b->ui_handle;
|
|
draw_area = brws_draw_area(b);
|
|
dpy = XtDisplay(draw_area);
|
|
|
|
if (!ui_handle->bg_font)
|
|
{
|
|
Font font = NULL;
|
|
|
|
XtVaGetValues(draw_area, XtNfont, &font, NULL);
|
|
ui_handle->bg_font = (XFontStruct *)XQueryFont(dpy, font);
|
|
}
|
|
|
|
if (!ui_handle->normal_gc)
|
|
{
|
|
|
|
XtVaGetValues(draw_area,
|
|
XtNbackground, &ui_handle->bg_color,
|
|
XtNforeground, &ui_handle->fg_color,
|
|
NULL);
|
|
|
|
gcvalues.graphics_exposures = False;
|
|
gcvalues.background = ui_handle->bg_color;
|
|
gcvalues.foreground = ui_handle->fg_color;
|
|
gcvalues.line_width = BRWS_ELM_BORDER_WIDTH;
|
|
ui_handle->normal_gc = XCreateGC(dpy, XtWindow(draw_area),
|
|
GCForeground|GCBackground|GCGraphicsExposures|GCLineWidth, &gcvalues);
|
|
}
|
|
|
|
if (!ui_handle->select_gc)
|
|
{
|
|
|
|
gcvalues.graphics_exposures = False;
|
|
gcvalues.background = WhitePixelOfScreen(XtScreen(draw_area));
|
|
gcvalues.foreground = BlackPixelOfScreen(XtScreen(AB_toplevel));
|
|
gcvalues.line_width = BRWS_ELM_BORDER_WIDTH;
|
|
ui_handle->select_gc = XCreateGC(dpy, XtWindow(draw_area),
|
|
GCForeground|GCBackground|GCGraphicsExposures|GCLineWidth, &gcvalues);
|
|
}
|
|
|
|
if (!ui_handle->line_gc)
|
|
{
|
|
|
|
gcvalues.graphics_exposures = False;
|
|
gcvalues.background = ui_handle->bg_color;
|
|
gcvalues.foreground = ui_handle->fg_color;
|
|
gcvalues.line_width = BRWS_LINE_WIDTH;
|
|
ui_handle->line_gc = XCreateGC(dpy, XtWindow(draw_area),
|
|
GCForeground|GCBackground|GCGraphicsExposures|GCLineWidth, &gcvalues);
|
|
}
|
|
|
|
if (!ui_handle->sm_font)
|
|
{
|
|
ui_handle->sm_font = (XFontStruct *)XLoadQueryFont(dpy, sm_font_name);
|
|
XSetFont(dpy, ui_handle->normal_gc, ui_handle->sm_font->fid);
|
|
XSetFont(dpy, ui_handle->select_gc, ui_handle->sm_font->fid);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Free the graphics context, and fonts.
|
|
*/
|
|
void
|
|
aob_free_graphics(
|
|
Viewer *b
|
|
)
|
|
{
|
|
|
|
BrowserUiObjects *ui_handle;
|
|
XGCValues gcvalues;
|
|
Display *dpy;
|
|
Widget draw_area;
|
|
|
|
if (!b || !b->ui_handle)
|
|
return;
|
|
|
|
ui_handle = (BrowserUiObjects*)b->ui_handle;
|
|
draw_area = brws_draw_area(b);
|
|
dpy = XtDisplay(draw_area);
|
|
|
|
if (ui_handle->normal_gc)
|
|
{
|
|
XFreeGC(dpy, ui_handle->normal_gc);
|
|
}
|
|
|
|
if (ui_handle->select_gc)
|
|
{
|
|
XFreeGC(dpy, ui_handle->select_gc);
|
|
}
|
|
|
|
if (ui_handle->line_gc)
|
|
{
|
|
XFreeGC(dpy, ui_handle->line_gc);
|
|
}
|
|
|
|
if (ui_handle->sm_font)
|
|
{
|
|
XFreeFont(dpy, ui_handle->sm_font);
|
|
}
|
|
|
|
if (ui_handle->bg_font)
|
|
{
|
|
XFreeFont(dpy, ui_handle->bg_font);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Allocate a big enough canvas if the current canvas is not
|
|
* big enough.
|
|
*/
|
|
static void
|
|
reallocate_drawarea
|
|
(
|
|
Viewer *v,
|
|
int width,
|
|
int height
|
|
)
|
|
{
|
|
XRectangle w_rect; /* widget width,height,x,y */
|
|
Widget draw_area;
|
|
Boolean resize_needed = False;
|
|
Arg arg[4];
|
|
int num_args = 0;
|
|
|
|
if (!v)
|
|
return;
|
|
|
|
draw_area = brws_draw_area(v);
|
|
|
|
if (!draw_area)
|
|
return;
|
|
|
|
XtVaGetValues(draw_area,
|
|
XtNwidth, &(w_rect.width),
|
|
XtNheight, &(w_rect.height),
|
|
NULL);
|
|
|
|
if (width != w_rect.width)
|
|
{
|
|
XtSetArg(arg[num_args], XtNwidth, width);
|
|
num_args++;
|
|
resize_needed = True;
|
|
}
|
|
|
|
if (height != w_rect.height)
|
|
{
|
|
XtSetArg(arg[num_args], XtNheight, height);
|
|
num_args++;
|
|
resize_needed = True;
|
|
}
|
|
|
|
if (resize_needed)
|
|
{
|
|
BrowserProps props;
|
|
|
|
props = aob_browser_properties(v);
|
|
|
|
if (props)
|
|
{
|
|
props->min_width = (Dimension)width;
|
|
props->min_height = (Dimension)height;
|
|
}
|
|
|
|
XtSetValues(draw_area, arg, num_args);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Recalculates the coordinates of the node of the tree.
|
|
*/
|
|
void
|
|
recompute_viewer(
|
|
Viewer *v
|
|
)
|
|
{
|
|
ViewerMethods *m;
|
|
int end_y = BRWS_Y_ORIGIN,
|
|
end_x = BRWS_X_ORIGIN,
|
|
max_x = BRWS_X_ORIGIN,
|
|
max_y = BRWS_Y_ORIGIN;
|
|
|
|
if (!v)
|
|
return;
|
|
|
|
m = v->methods;
|
|
|
|
(*m->compute_tree)(v, &end_x, &end_y);
|
|
|
|
reallocate_drawarea(v, end_x, end_y);
|
|
}
|
|
|
|
/*
|
|
* browser_show_view_elements
|
|
* This is used by all the callbacks that toggle the hide/show
|
|
* state of the browser node elements. This function toggles
|
|
* the bit (determined by 'mask') in the 'elements_shown' bit
|
|
* vector. The bit vector is hung off the Viewer structure.
|
|
*
|
|
* b Ptr to Viewer.
|
|
* mask Mask to get to the desired field in
|
|
* the bit vector.
|
|
* widget Cascade button widget that activated the
|
|
* callback.
|
|
* set_str String to set if bit is set.
|
|
* unset_str String to set if bit is unset.
|
|
*/
|
|
void
|
|
browser_show_view_elements(
|
|
Viewer *b,
|
|
unsigned long mask,
|
|
Widget widget,
|
|
char *set_str,
|
|
char *unset_str
|
|
)
|
|
{
|
|
BrowserProperties *props;
|
|
XmString xmlabel;
|
|
|
|
if (!b )
|
|
return;
|
|
|
|
props = aob_browser_properties(b);
|
|
|
|
if (!props)
|
|
return;
|
|
|
|
if (props->elements_shown & mask)
|
|
{
|
|
if (!(props->elements_shown & ~mask))
|
|
return;
|
|
|
|
props->elements_shown &= ~mask;
|
|
}
|
|
else
|
|
props->elements_shown |= mask;
|
|
|
|
if (props->elements_shown & mask)
|
|
{
|
|
xmlabel = XmStringCreateLocalized(set_str);
|
|
}
|
|
else
|
|
{
|
|
xmlabel = XmStringCreateLocalized(unset_str);
|
|
}
|
|
|
|
XtVaSetValues(widget, XmNlabelString, xmlabel, NULL);
|
|
|
|
XmStringFree(xmlabel);
|
|
|
|
erase_viewer(b);
|
|
draw_viewer(b);
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
|
|
|
|
/*
|
|
* aob_proj_init_state
|
|
* Initializes the state of a project in the browser.
|
|
* This means:
|
|
* Making all but the first module visible
|
|
* Making the first browser node in the project subwindow
|
|
* selected
|
|
*/
|
|
void
|
|
aob_proj_init_state
|
|
(
|
|
ABBrowser ab
|
|
)
|
|
{
|
|
Vwr proj_b;
|
|
Vwr mod_b;
|
|
VNode top, child;
|
|
ViewerMethods *m;
|
|
int i, num_child, first_found = FALSE;
|
|
|
|
if (!ab)
|
|
return;
|
|
|
|
|
|
proj_b = ab->project;
|
|
mod_b = ab->module;
|
|
|
|
if (!proj_b || !mod_b)
|
|
return;
|
|
|
|
top = proj_b->tree;
|
|
m = proj_b->methods;
|
|
|
|
num_child = (*m->get_num_children)(top);
|
|
|
|
for (i=0, child = (*m->get_child)(top, 0); (i< num_child);
|
|
child = (*m->get_child)(top, ++i))
|
|
{
|
|
AB_OBJ *obj;
|
|
VNode module_node;
|
|
|
|
obj = (AB_OBJ *)child->obj_data;
|
|
module_node = aob_find_bnode(obj, mod_b);
|
|
|
|
if (!first_found)
|
|
{
|
|
if (child)
|
|
{
|
|
BRWS_NODE_SET_STATE(child, BRWS_NODE_SELECTED);
|
|
|
|
BRWS_NODE_SET_STATE(module_node, BRWS_NODE_VISIBLE);
|
|
|
|
first_found = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (child)
|
|
{
|
|
BRWS_NODE_UNSET_STATE(module_node, BRWS_NODE_VISIBLE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Initialize the object browser.
|
|
*/
|
|
static ABBrowser
|
|
create_browser_struct()
|
|
{
|
|
ABBrowser b;
|
|
|
|
/*
|
|
* Create AB browser struct
|
|
*/
|
|
b = (ABBrowser)malloc(sizeof(AB_BROWSER));
|
|
|
|
/*
|
|
* Create browser structs for project/module windows
|
|
*/
|
|
b->project = vwr_create(brwsP_proj_methods);
|
|
b->module = vwr_create(brwsP_mod_methods);
|
|
b->previous = b->next = NULL;
|
|
|
|
return b;
|
|
}
|
|
|
|
/*
|
|
* Destroy the object browser.
|
|
*/
|
|
static void
|
|
destroy_browser_struct(
|
|
ABBrowser b
|
|
)
|
|
{
|
|
|
|
VMethods m;
|
|
VNode top;
|
|
ABObj root;
|
|
|
|
/*
|
|
*********************************
|
|
* Free resources in module viewer
|
|
*********************************
|
|
*/
|
|
m = b->module->methods;
|
|
top = b->module->tree;
|
|
root = top ? (ABObj)top->obj_data : NULL;
|
|
(*m->remove_tree)(b->module, root);
|
|
vwr_destroy(b->module);
|
|
|
|
/*
|
|
**********************************
|
|
* Free resources in project viewer
|
|
**********************************
|
|
*/
|
|
m = b->project->methods;
|
|
top = b->project->tree;
|
|
root = top ? (ABObj)top->obj_data : NULL;
|
|
(*m->remove_tree)(b->project, root);
|
|
vwr_destroy(b->project);
|
|
|
|
/*
|
|
* Free browser
|
|
*/
|
|
free(b);
|
|
}
|
|
|
|
|
|
/*
|
|
* Destroy the interface browser object.
|
|
*/
|
|
void
|
|
aob_destroy(Viewer *b)
|
|
{
|
|
Widget shell;
|
|
|
|
shell = aob_ui_shell(b);
|
|
XtDestroyWidget(shell);
|
|
vwr_destroy(b);
|
|
}
|
|
|
|
|
|
/*
|
|
* Activate an object browser.
|
|
*/
|
|
void
|
|
aob_activate(Viewer *b)
|
|
{
|
|
Widget shell;
|
|
|
|
shell = aob_ui_shell(b);
|
|
|
|
if (b) {
|
|
ui_win_show(shell, True, XtGrabNone);
|
|
aob_redraw(b);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Redraw the browser object. Only draw when the window
|
|
* is visible.
|
|
*/
|
|
void
|
|
aob_redraw
|
|
(
|
|
Viewer *b
|
|
)
|
|
{
|
|
erase_viewer(b);
|
|
draw_viewer(b);
|
|
}
|
|
|
|
|
|
/*
|
|
* (Re)Draw the viewer
|
|
*/
|
|
void
|
|
draw_viewer(Viewer *v)
|
|
{
|
|
ViewerMethods *m;
|
|
ViewerNode *node;
|
|
|
|
if (!v->current_tree || !v->tree)
|
|
return;
|
|
|
|
m = v->methods;
|
|
|
|
recompute_viewer(v);
|
|
|
|
(*m->render_tree)(v->current_tree);
|
|
}
|
|
|
|
|
|
/*
|
|
* Create (malloc) structure to hold browser UI objects
|
|
*/
|
|
BrowserUiObj
|
|
aob_create_ui_obj
|
|
(
|
|
)
|
|
{
|
|
BrowserUiObj ui;
|
|
|
|
ui = (BrowserUiObj)malloc(sizeof(BrowserUiObjects));
|
|
|
|
ui->ip = NULL;
|
|
ui->shell = NULL;
|
|
ui->find_box = NULL;
|
|
ui->normal_gc = NULL;
|
|
ui->select_gc = NULL;
|
|
ui->line_gc = NULL;
|
|
ui->sm_font = NULL;
|
|
ui->bg_font = NULL;
|
|
ui->fg_color = NULL;
|
|
ui->bg_color = NULL;
|
|
|
|
return(ui);
|
|
}
|
|
|
|
/*
|
|
* Create (malloc) structure to hold browser properties
|
|
*/
|
|
static BrowserProps
|
|
aob_create_props
|
|
(
|
|
)
|
|
{
|
|
BrowserProps props;
|
|
|
|
props = (BrowserProps)malloc(sizeof(BrowserProperties));
|
|
|
|
props->elements_shown = 0;
|
|
props->initial_state = 0;
|
|
props->min_width = 0;
|
|
props->min_height = 0;
|
|
props->orientation = BRWS_VERTICAL;
|
|
props->show_mult_trees = FALSE;
|
|
props->active = FALSE;
|
|
|
|
return(props);
|
|
}
|
|
|
|
/*
|
|
* Free structure that holds browser UI objects
|
|
*/
|
|
static void
|
|
aob_destroy_ui_obj
|
|
(
|
|
Vwr v
|
|
)
|
|
{
|
|
if (!v && !v->ui_handle)
|
|
return;
|
|
|
|
free(v->ui_handle);
|
|
|
|
v->ui_handle = (void *)NULL;
|
|
}
|
|
|
|
/*
|
|
* Free structure that holds browser properties
|
|
*/
|
|
static void
|
|
aob_destroy_props
|
|
(
|
|
Vwr b
|
|
)
|
|
{
|
|
if (!b && !b->properties)
|
|
return;
|
|
|
|
free(b->properties);
|
|
}
|
|
|
|
/*
|
|
* browser_destroyCB - destroy callback for browser window
|
|
* Does 2 things:
|
|
* Remove browser from linked list of browsers on project
|
|
* Destroys browser
|
|
*/
|
|
static void
|
|
browser_destroyCB
|
|
(
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XtPointer call_data
|
|
)
|
|
{
|
|
ABBrowser b = (ABBrowser)client_data,
|
|
prev, next;
|
|
ABObj project = NULL;
|
|
|
|
if (!b || !b->module)
|
|
return;
|
|
|
|
project = (AB_OBJ *)b->module->obj_data;
|
|
|
|
/*
|
|
* If obj_data was NULL, the browser is empty.
|
|
* Use the current project instead.
|
|
*/
|
|
if (!project)
|
|
project = proj_get_project();
|
|
|
|
/*
|
|
* Unlink this browser from the list of browsers on
|
|
* the project
|
|
*/
|
|
prev = b->previous;
|
|
next = b->next;
|
|
|
|
if (prev)
|
|
{
|
|
/*
|
|
* Link previous to next browser
|
|
*/
|
|
prev->next = next;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* This browser is the first on the list.
|
|
* Update browser pointer on project
|
|
* Check if the browser pointers match first
|
|
*/
|
|
if (project && (project->info.project.browsers == b))
|
|
project->info.project.browsers = (void *)next;
|
|
}
|
|
|
|
if (next)
|
|
{
|
|
/*
|
|
* Link next to previous browser
|
|
*/
|
|
next->previous = prev;
|
|
}
|
|
|
|
/*
|
|
* Destroy browser
|
|
*/
|
|
brws_destroy(b);
|
|
}
|
|
|
|
Vwr
|
|
aob_proj_or_module
|
|
(
|
|
ABBrowser b,
|
|
Widget w
|
|
)
|
|
{
|
|
|
|
Widget proj_draw_area, draw_area;
|
|
|
|
proj_draw_area = brws_draw_area(b->project);
|
|
draw_area = brws_draw_area(b->module);
|
|
|
|
if (w == proj_draw_area)
|
|
return (b->project);
|
|
|
|
if (w == draw_area)
|
|
return (b->module);
|
|
|
|
return (NULL);
|
|
}
|
|
|
|
int
|
|
aob_is_widget_proj_browser
|
|
(
|
|
ABBrowser b,
|
|
Widget w
|
|
)
|
|
{
|
|
Widget proj_draw_area, draw_area;
|
|
|
|
proj_draw_area = brws_draw_area(b->project);
|
|
draw_area = brws_draw_area(b->module);
|
|
|
|
if (w == proj_draw_area)
|
|
return (TRUE);
|
|
|
|
return (FALSE);
|
|
}
|
|
|
|
int
|
|
aob_is_proj_browser
|
|
(
|
|
ABBrowser ab,
|
|
Vwr b
|
|
)
|
|
{
|
|
if (b == ab->project)
|
|
return (TRUE);
|
|
|
|
return (FALSE);
|
|
}
|
|
|
|
|
|
/*
|
|
* Return the number of nodes selected in the current tree.
|
|
*/
|
|
int
|
|
number_of_selected
|
|
(
|
|
VNode tree
|
|
)
|
|
{
|
|
ViewerMethods *m;
|
|
VNode child;
|
|
int i, num_child, total = 0;
|
|
|
|
if (!tree)
|
|
return (0);
|
|
|
|
m = BNODE_METHODS(tree);
|
|
|
|
num_child = (*m->get_num_children)(tree);
|
|
|
|
/*
|
|
* Recursively count selected nodes of child subtree
|
|
* This proc should check for (child == NULL)
|
|
*/
|
|
for (i=0, child = (*m->get_child)(tree, 0);
|
|
(i < num_child);
|
|
child = (*m->get_child)(tree, ++i))
|
|
{
|
|
total = number_of_selected(child) + total;
|
|
}
|
|
return total + (BRWS_NODE_STATE_IS_SET(tree, BRWS_NODE_SELECTED) ?
|
|
1 : 0);
|
|
}
|
|
|
|
|
|
/*
|
|
* Return the first node selected.
|
|
*/
|
|
VNode
|
|
node_selected
|
|
(
|
|
VNode tree
|
|
)
|
|
{
|
|
ViewerMethods *m;
|
|
VNode child;
|
|
VNode selected_node;
|
|
int i, num_child;
|
|
|
|
if (!tree)
|
|
return (NULL);
|
|
|
|
m = BNODE_METHODS(tree);
|
|
|
|
num_child = (*m->get_num_children)(tree);
|
|
|
|
/*
|
|
* Recursively look in child subtrees
|
|
* This proc should check for (child == NULL)
|
|
*/
|
|
for (i=0, child = (*m->get_child)(tree, 0);
|
|
(i < num_child);
|
|
child = (*m->get_child)(tree, ++i))
|
|
{
|
|
if (selected_node = node_selected(child))
|
|
return selected_node;
|
|
}
|
|
|
|
if (BRWS_NODE_STATE_IS_SET(tree, BRWS_NODE_SELECTED))
|
|
return tree;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* aob_set_mode
|
|
* Hides/Disables or Shows/Enables browsers depending on
|
|
* the value of AB_builder_mode
|
|
*/
|
|
void
|
|
aob_set_mode
|
|
(
|
|
AB_OBJ *project
|
|
)
|
|
{
|
|
ABBrowser new_b, cur_b, b_list = NULL;
|
|
|
|
if (!project)
|
|
return;
|
|
|
|
if (!obj_is_project(project))
|
|
project = obj_get_project(project);
|
|
|
|
if (!project)
|
|
return;
|
|
|
|
b_list = (ABBrowser)project->info.project.browsers;
|
|
|
|
for (cur_b = b_list; cur_b; cur_b = cur_b->next)
|
|
{
|
|
Widget proj_draw_area, draw_area;
|
|
|
|
proj_draw_area = brws_draw_area(cur_b->project);
|
|
draw_area = brws_draw_area(cur_b->module);
|
|
|
|
if (AB_builder_mode == MODE_BUILD)
|
|
{
|
|
/*
|
|
* Enable translations for browser
|
|
*/
|
|
enable_proj_actions(proj_draw_area);
|
|
enable_actions(draw_area);
|
|
|
|
/*
|
|
* Map browser
|
|
*/
|
|
brws_popup(cur_b);
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Disable translations for browser
|
|
*/
|
|
disable_proj_actions(proj_draw_area);
|
|
disable_actions(draw_area);
|
|
|
|
/*
|
|
* Unmap browser
|
|
*/
|
|
brws_popdown(cur_b);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
brws_switch_module(
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XtPointer call_data
|
|
)
|
|
{
|
|
ABBrowser ab = NULL;
|
|
ABObj module = (ABObj)client_data;
|
|
ViewerMethods *m;
|
|
ABSelectedRec sel;
|
|
|
|
XtVaGetValues(widget, XmNuserData, &ab, NULL);
|
|
|
|
if (!ab)
|
|
return;
|
|
|
|
if (ab->project->tree && ab->project->current_tree)
|
|
{
|
|
m = ab->project->methods;
|
|
(*m->remove_tree)(ab->project, ab->project->tree->obj_data);
|
|
ab->project->tree = ab->project->current_tree = NULL;
|
|
}
|
|
|
|
if (ab->module->tree && ab->module->current_tree)
|
|
{
|
|
m = ab->module->methods;
|
|
(*m->remove_tree)(ab->module, ab->module->tree->obj_data);
|
|
ab->module->tree = ab->module->current_tree = NULL;
|
|
}
|
|
|
|
if (!module && ab->project)
|
|
brws_set_module_name(ab->project);
|
|
|
|
brws_add_objects_to_browser(ab, module);
|
|
|
|
/*
|
|
* Get selected objects in this module
|
|
*/
|
|
abobj_get_selected(module, False, False, &sel);
|
|
|
|
/*
|
|
* Center view on first object in sel.list
|
|
*/
|
|
if (sel.count > 0)
|
|
{
|
|
brws_center_on_obj(ab, sel.list[0]);
|
|
util_free(sel.list);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Cascade callback for edit cascade button
|
|
* This function checks the clipboard as well as the number of
|
|
* objects that are currently selected and sets the sensitivity of the
|
|
* edit menu items appropriately.
|
|
*/
|
|
|
|
void
|
|
brws_edit_cascadeCB(
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XtPointer call_data
|
|
)
|
|
{
|
|
ABObj project = proj_get_project();
|
|
ABSelectedRec sel;
|
|
ABBrowser ab = NULL;
|
|
DtbBrwsMainwindowInfo instance;
|
|
BrowserUiObj top_ui;
|
|
|
|
|
|
XtVaGetValues(widget, XmNuserData, &ab, NULL);
|
|
|
|
if (!project || !ab)
|
|
return;
|
|
|
|
top_ui = (BrowserUiObj)ab->project->ui_handle;
|
|
instance = (DtbBrwsMainwindowInfo)top_ui->ip;
|
|
|
|
abobj_get_selected(project, FALSE, FALSE, &sel);
|
|
|
|
if (sel.count == 0)
|
|
{
|
|
XtVaSetValues(instance->menubar_Edit_item_edit_pulldown_items.Cut_item, XmNsensitive, False, NULL);
|
|
XtVaSetValues(instance->menubar_Edit_item_edit_pulldown_items.Copy_item, XmNsensitive, False, NULL);
|
|
XtVaSetValues(instance->menubar_Edit_item_edit_pulldown_items.Paste_item, XmNsensitive, False, NULL);
|
|
XtVaSetValues(instance->menubar_Edit_item_edit_pulldown_items.Delete_item, XmNsensitive, False, NULL);
|
|
}
|
|
else
|
|
{
|
|
XtVaSetValues(instance->menubar_Edit_item_edit_pulldown_items.Cut_item, XmNsensitive, True, NULL);
|
|
XtVaSetValues(instance->menubar_Edit_item_edit_pulldown_items.Copy_item, XmNsensitive, True, NULL);
|
|
XtVaSetValues(instance->menubar_Edit_item_edit_pulldown_items.Delete_item, XmNsensitive, True, NULL);
|
|
|
|
if (abobj_clipboard_is_empty())
|
|
XtVaSetValues(instance->menubar_Edit_item_edit_pulldown_items.Paste_item, XmNsensitive, False, NULL);
|
|
else
|
|
XtVaSetValues(instance->menubar_Edit_item_edit_pulldown_items.Paste_item, XmNsensitive, True, NULL);
|
|
|
|
XtFree((char *)sel.list);
|
|
}
|
|
|
|
if (abobj_undo_active())
|
|
XtVaSetValues(instance->menubar_Edit_item_edit_pulldown_items.Undo_item, XmNsensitive, True, NULL);
|
|
else
|
|
XtVaSetValues(instance->menubar_Edit_item_edit_pulldown_items.Undo_item, XmNsensitive, False, NULL);
|
|
|
|
}
|
|
|
|
|
|
static Widget
|
|
get_main_window(
|
|
Widget widget
|
|
)
|
|
{
|
|
Widget browser_main = NULL,
|
|
cur_widget = widget;
|
|
|
|
while (cur_widget && !browser_main)
|
|
{
|
|
if (!strcmp(XtName(cur_widget), browser_mainwindow))
|
|
browser_main = cur_widget;
|
|
else
|
|
cur_widget = XtParent(cur_widget);
|
|
}
|
|
|
|
return (browser_main);
|
|
}
|
|
|
|
static void
|
|
brws_view_cascadeCB(
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XtPointer call_data
|
|
)
|
|
{
|
|
ABBrowser ab = NULL;
|
|
BrowserUiObj top_ui;
|
|
DtbBrwsMainwindowInfo instance;
|
|
ABObj project = proj_get_project();
|
|
ABSelectedRec sel;
|
|
Widget browse, browse_pulldown;
|
|
|
|
browse = (Widget) client_data;
|
|
XtVaGetValues(widget, XmNuserData, &ab, NULL);
|
|
|
|
if (!browse || !ab)
|
|
return;
|
|
|
|
/*
|
|
* Build view -> module menu
|
|
*/
|
|
XtVaSetValues(browse, XmNsensitive, True, NULL);
|
|
XtVaGetValues(browse, XmNsubMenuId, &browse_pulldown, NULL);
|
|
|
|
brws_build_module_menu(browse_pulldown, brws_switch_module);
|
|
|
|
/*
|
|
* Desensitize collapse/expand menu items
|
|
*/
|
|
top_ui = (BrowserUiObj)ab->project->ui_handle;
|
|
instance = (DtbBrwsMainwindowInfo)top_ui->ip;
|
|
|
|
abobj_get_selected(project, FALSE, FALSE, &sel);
|
|
|
|
|
|
if (sel.count == 0)
|
|
{
|
|
XtVaSetValues(instance->menubar_View_item_view_pulldown_items.Expand_item,
|
|
XmNsensitive, False, NULL);
|
|
XtVaSetValues(instance->menubar_View_item_view_pulldown_items.Collapse_item,
|
|
XmNsensitive, False, NULL);
|
|
}
|
|
else
|
|
{
|
|
XtVaSetValues(instance->menubar_View_item_view_pulldown_items.Expand_item,
|
|
XmNsensitive, True, NULL);
|
|
XtVaSetValues(instance->menubar_View_item_view_pulldown_items.Collapse_item,
|
|
XmNsensitive, True, NULL);
|
|
|
|
XtFree((char *)sel.list);
|
|
}
|
|
}
|
|
|
|
/*****************************************************************
|
|
* This routine creates the pushButtons for the View->Browse
|
|
* menu. The pushButtons contain the modules which are
|
|
* currently in the ABObj tree. This function is called by
|
|
* view_cascadeCB().
|
|
*****************************************************************/
|
|
void
|
|
brws_build_module_menu(
|
|
Widget pulldown,
|
|
XtCallbackProc callback
|
|
)
|
|
{
|
|
ABObj project = proj_get_project();
|
|
Widget menu = NULL, mpb = NULL;
|
|
WidgetList children = NULL;
|
|
AB_TRAVERSAL trav;
|
|
ABObj module = NULL;
|
|
ABBrowser ab = NULL;
|
|
STRING name = NULL;
|
|
XmString label = NULL;
|
|
Cardinal numChildren = 0;
|
|
int i = 0;
|
|
Boolean shown_modules_exist = False;
|
|
|
|
XtVaGetValues(pulldown, XmNuserData, &ab, NULL);
|
|
|
|
XtVaGetValues(pulldown,
|
|
XmNnumChildren, &numChildren,
|
|
XmNchildren, &children,
|
|
NULL);
|
|
for (i=0; i < numChildren; i++)
|
|
{
|
|
XtDestroyWidget(children[i]);
|
|
}
|
|
|
|
/* Traverse ABObj tree for module nodes.
|
|
* Populate the pulldown menu with the names
|
|
* of the module nodes.
|
|
*/
|
|
for (trav_open(&trav, project, AB_TRAV_MODULES);
|
|
(module = trav_next(&trav)) != NULL; )
|
|
{
|
|
/* Can only browse modules that are shown
|
|
* and defined. Undefined modules can occur
|
|
* if a module is imported which references
|
|
* another module that does not exist in the
|
|
* project (i.e. :win-children).
|
|
*/
|
|
if ( !obj_has_flag(module, MappedFlag) ||
|
|
!obj_is_defined(module)
|
|
)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
/* Use the name of the mapped module for the View
|
|
* menu items.
|
|
*/
|
|
name = obj_get_name(module);
|
|
if (!util_strempty(name))
|
|
{
|
|
label = XmStringCreateLocalized(name);
|
|
mpb = XtVaCreateManagedWidget(name,
|
|
xmPushButtonWidgetClass,
|
|
pulldown,
|
|
XmNlabelString, label,
|
|
XmNuserData, ab,
|
|
NULL);
|
|
XtAddCallback(mpb, XmNactivateCallback, callback,(XtPointer)module);
|
|
XmStringFree(label);
|
|
|
|
shown_modules_exist = True;
|
|
}
|
|
}
|
|
trav_close(&trav);
|
|
|
|
if (!shown_modules_exist)
|
|
{
|
|
label = XmStringCreateLocalized(
|
|
catgets(Dtb_project_catd, 100, 229, "No modules to browse"));
|
|
mpb = XtVaCreateManagedWidget(name,
|
|
xmPushButtonWidgetClass,
|
|
pulldown,
|
|
XmNlabelString, label,
|
|
XmNuserData, ab,
|
|
NULL);
|
|
XmStringFree(label);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* brws_show_browser - maps the App Builder Object browser
|
|
* The contents of the mapped browser depends on what is passed as
|
|
* client_data. If it is NULL, an empty browser will be shown. If it
|
|
* is not NULL, it should be a module AB_OBJ. In this case, the module
|
|
* will be loaded into the browser.
|
|
*/
|
|
void
|
|
brws_show_browser(
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XtPointer call_data
|
|
)
|
|
{
|
|
ABObj module = (AB_OBJ *)client_data;
|
|
ABBrowser cur_b;
|
|
|
|
/*
|
|
* Search for browser containing module
|
|
*/
|
|
cur_b = brws_get_browser_for_obj(module);
|
|
|
|
/*
|
|
* Center browser detailed tree view on any object
|
|
* that was selected that is in this module
|
|
*/
|
|
if (module)
|
|
{
|
|
ABSelectedRec sel;
|
|
|
|
/*
|
|
* Get selected objects in this module
|
|
*/
|
|
abobj_get_selected(module, False, False, &sel);
|
|
|
|
/*
|
|
* Center view on first object in sel.list
|
|
*/
|
|
if (sel.count > 0)
|
|
{
|
|
brws_center_on_obj(cur_b, sel.list[0]);
|
|
util_free(sel.list);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Map the browser that as found
|
|
*/
|
|
brws_popup(cur_b);
|
|
}
|
|
|
|
void
|
|
brws_init(
|
|
)
|
|
{
|
|
obj_add_rename_callback(brwsP_obj_renameOCB, "BRWS");
|
|
obj_add_destroy_callback(brwsP_obj_destroyOCB, "BRWS");
|
|
obj_add_reparent_callback(brwsP_obj_reparentedOCB, "BRWS");
|
|
obj_add_selected_change_callback(brwsP_selectOCB, "BRWS");
|
|
obj_add_update_callback(brwsP_obj_updateOCB, "BRWS");
|
|
}
|
|
|
|
/*
|
|
* Object rename callback
|
|
* Update browsers when object is renamed. This is also used for
|
|
* adding newly created objects.
|
|
*/
|
|
static int
|
|
brwsP_obj_renameOCB(
|
|
ObjEvAttChangeInfo info
|
|
)
|
|
{
|
|
ABObj obj = info->obj;
|
|
|
|
if (!obj)
|
|
return (0);
|
|
|
|
/*
|
|
* Update the name only if the old name was not NULL
|
|
* which means that this is a new object. We let the
|
|
* update callback handle that.
|
|
*/
|
|
if (info->old_name != NULL)
|
|
brws_update_node(obj);
|
|
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* Object destroy callback
|
|
* Remove viewer nodes from browsers when object is destroyed.
|
|
*/
|
|
static int
|
|
brwsP_obj_destroyOCB(
|
|
ObjEvDestroyInfo info
|
|
)
|
|
{
|
|
ABObj obj = info->obj;
|
|
|
|
if (!obj)
|
|
return (0);
|
|
|
|
if (obj->browser_data)
|
|
{
|
|
ABObj project;
|
|
|
|
if (!(project = obj_get_project(obj)))
|
|
return (0);
|
|
|
|
if (obj_has_flag(project, BeingDestroyedFlag) &&
|
|
!(obj_is_project(obj) || obj_is_module(obj)))
|
|
return (0);
|
|
|
|
brws_delete_objects(obj);
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* Object reparent callback
|
|
* Resync tree in browsers.
|
|
*/
|
|
static int
|
|
brwsP_obj_reparentedOCB(
|
|
ObjEvReparentInfo info
|
|
)
|
|
{
|
|
ABObj obj = info->obj,
|
|
old_parent = info->old_parent,
|
|
new_parent;
|
|
|
|
if (!obj | !old_parent)
|
|
return (0);
|
|
|
|
new_parent = obj_get_parent(obj);
|
|
|
|
brws_add_objects(new_parent);
|
|
|
|
return (0);
|
|
}
|
|
|
|
static int
|
|
brwsP_selectOCB(
|
|
ObjEvAttChangeInfo info
|
|
)
|
|
{
|
|
ABObj obj = info->obj;
|
|
|
|
/*
|
|
* If NULL object or if object does
|
|
* not belong to a project, return
|
|
* right away
|
|
*/
|
|
if (!obj || !(obj_get_project(obj)))
|
|
return (0);
|
|
|
|
if (obj_is_selected(obj))
|
|
brws_select(obj);
|
|
else
|
|
brws_deselect(obj);
|
|
|
|
return (0);
|
|
}
|
|
|
|
static int
|
|
brwsP_obj_updateOCB(
|
|
ObjEvUpdateInfo info
|
|
)
|
|
{
|
|
ABObj obj = info->obj,
|
|
project = NULL,
|
|
module = NULL;
|
|
ABBrowser b_list = NULL,
|
|
cur_b;
|
|
|
|
if (!obj)
|
|
return (0);
|
|
|
|
brws_add_objects(obj);
|
|
|
|
/*
|
|
* If a module was hidden, hide the browsers
|
|
* associated with it.
|
|
*/
|
|
project = obj_get_project(obj);
|
|
module = obj_get_module(obj);
|
|
if (!project || !module)
|
|
return (0);
|
|
|
|
if (obj_has_flag(module, MappedFlag))
|
|
return (0);
|
|
|
|
b_list = (ABBrowser)project->info.project.browsers;
|
|
|
|
if (!b_list)
|
|
return (0);
|
|
|
|
for (cur_b = b_list; cur_b; cur_b = cur_b->next)
|
|
{
|
|
AB_OBJ *browsed_module;
|
|
|
|
browsed_module = (AB_OBJ *)cur_b->project->tree->obj_data;
|
|
|
|
if (browsed_module == module)
|
|
{
|
|
Widget shell;
|
|
|
|
shell = aob_ui_shell(cur_b->project);
|
|
|
|
/*
|
|
* Destroy shell widget for browser
|
|
* The destroy callbacks will do cleanup...
|
|
*/
|
|
if (shell)
|
|
XtDestroyWidget(shell);
|
|
}
|
|
}
|
|
|
|
return (0);
|
|
}
|