////////////////////////////////////////////////////////////////////////
// Name: nodeops.cc
//
// Description:
//
// This file contains all BDE code responsible for controlling node
// operations. The code has been taken from the BDE 1.0 buttondown.cc,
// buttonup.cc and buttonmoved.cc files.
//
// Routines :node_create();node_delete();node_move();node_resize();
//
// History:
//
// 05/01/93 nlinsky created.
// 08/23/93 hlee modified.
//
//
// $Log: nodeops.cc,v $
//
// Revision 1.5 1995/12/16 phsia
// The node_create() only needs 2 arguments: event and button_op. No
// need to pass state to addno() because no more six states for nodeshapes.
//
// Revision 1.4 1995/05/13 02:31:59 hcpatel
// Implemented corrected state model for node delete operation.
//
// Revision 1.3 1995/05/11 21:31:23 bbarry
// renamed state SRectaingle to SRectangle to make easier to find
//
// Revision 1.2 1995/04/04 04:41:38 cgopal
// File bde20 and others were fixed so that multiple definitions
// of variables were eliminated. All enumarated types were capitializes and give
// n a prefix.
//
// Arguments to XtAddcallback was casted to the right type. Handler.cc
// was also fixed to use right variables.
//
// Revision 1.16 1994/08/23 01:54:36 lechner
// Eliminated obsolete calls to dirdo and to save("wchen")
//
// Revision 1.15 1994/05/07 23:43:12 dgrant
// In routines node_move() and node_resize() changed calls from
// infomessage to displayMessage.
//
// Revision 1.14 1994/05/07 22:00:27 dgrant
// In routine addattr, made required changes so that HA's would
// work in GENV8.
//
// Revision 1.13 1994/04/23 19:04:25 mtorpey
// Cursons now change at the appropriate times.
//
// Revision 1.12 1994/04/22 21:30:48 mtorpey
// Fixed the last remaining bug in node_resize().. :)
//
// Revision 1.11 1994/04/22 19:37:42 mtorpey
// Fixed on more minor bug in node_resize(). Before if you resized a node,
// it left it highlighted, even though at this point you were in the
// unhighlited state. Now it unhighlites the node
//
// Revision 1.10 1994/04/22 00:48:04 mtorpey
// Fixed delete node and resize node to work according to the new state
// machines, ie. they work right.
//
// Revision 1.9 1994/04/21 21:18:28 mtorpey
// Reduce the function node_create() from 134 lines to 46 lines.
//
// Revision 1.8 1994/04/15 19:30:48 mtorpey
// Replaced all occurances of RosterView with 94sbdeview and all occurances
// of RosterReadView with 94sbdedefaultsView. These reflect the new changes
// made to the bdetest.viewdefs file.
//
// Revision 1.7 1994/04/09 18:14:28 dgrant
// CHGEN ver 6 to ver8 updates. DGrant and TSeeley
//
// Revision 1.6 1994/04/01 01:49:58 namin
// version 8 changes (to make it work for version 6)
//
// Revision 1.5 1994/03/31 19:21:14 namin
// version 8 changes
//
// Revision 1.4 1994/03/12 16:44:39 lking
// Added the include file "prototype.h" which contains all the function
// declarations. Removed all external function declarations from this file.
//
// Revision 1.3 1994/03/11 21:16:59 lking
// Reformatted the header comment to make it more readable. Move rcsid
// below the header comment. Removed all debugging printfs from the file.
//
// Revision 1.2 1994/03/09 18:27:48 jrichard
// Added a rcs log replacement statement to all .cc files as part of the
// header comment. THis places all checkin comments directly into the
// header comment.
//
////////////////////////////////////////////////////////////////////////
#ifndef lint
static char rcsid[] =
"$Id: nodeops.cc,v 1.4 1995/05/13 02:31:59 hcpatel Exp $";
#endif
/********************** System include files *******************************/
#include <strings.h>
#include <stdio.h>
#include <math.h>
#include <X11/Xlib.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <Xm/Xm.h>
/********************** Program include files ******************************/
#include "tags.h"
#include "bde.h"
#include "graph.h"
#include "state.h"
#include "prototype.h"
/********************** Macro defines **************************************/
#ifdef GENV6
extern "C" {
void pr_add (char *,char *); /*hlee, should be declared in .h */
char find_view_idx(char *); /*hlee;added this to get rid of
warning <<implicit declaration*/
}
#else
extern "C" {
int find_view_idx(char *);
}
#endif
extern char new_string[30];
extern float nx1,nx2,ny1,ny2;
/********************** Global and external variables **********************/
extern Widget canvas;
extern float selectedx, selectedy;
extern Select selected;
extern float savedx, savedy;
extern graphobject *currentselection;
extern Cursor arrow, dot, addcross,question,textCursor,pirate,movehand;
/***************************************************************************
* Description:
* node_create performs the node creation operation. It does
* this based on the button event and other variables passed
* in to it. All code within this function was lifted from
* the button*.cc files.
*
* Error handling:
* NONE.
* Side effects:
* NONE.
***************************************************************************/
void node_create (XButtonEvent *event,
int button_op) /* BUTTON_UP, BUTTON_DOWN, BUTTON_MOVED */
{
float sx, sy;
/* Xlate into world coordinates */
DCtoWC(event->x, event->y, &sx, &sy);
/* At this point, we are in the Node Create state */
switch (button_op) {
case BUTTON_DOWN_EVENT:
topobject->addnode(sx, sy);
break; /* end of BUTTON_DOWN_EVENT case */
case BUTTON_UP_EVENT:
break;
case BUTTON_MOVED_EVENT:
break;
default: /* illegal value for button_op variable */
//add PostErrorMsg() to handle error message - phsia 12/8/95
PostErrorMsg(SCnode);
break;
}
}
/***************************************************************************
* Name:
* void node_delete(XButtonEvent*, int, node_attributes *, int)
* Added by:
* ???
* Modified by:
* hcpatel & mmaliset - bdesrc 95sbde
* A generic selction routine is used for selecting a Node which searches
* the whole object list till it finds a Node. This routine implements the
* improved state model suggested by Prof.Lechner.
* Description:
* This performs the node deletion operation. It does this based on the
* button event and other variables passed in to it. (Note that attribute
* is not actually used for the delete operation. We don't need to know
* whether the node was a circle or rectangle to delete it.)
* All code within this function was lifted from the button*.cc files.
* button_op is one of: BUTTON_UP, BUTTON_DOWN, BUTTON_MOVED
* Uses:
* DCtoWC(), Ggroup class method select_HN(widget, int, int),
* changeCanvasCursor(), changeAttribState(), docut()
* Side effects:
* NONE
***************************************************************************/
void node_delete (XButtonEvent *event,
int state, /* Canvas State (eventually just NodeCreate)*/
node_attributes *attribute, /* circle, square, etc. */
int button_op /* BUTTON_UP, BUTTON_DOWN, BUTTON_MOVED */
)
{
float sx, sy;
static graphobject *selected_node = NULL;
DCtoWC(event->x, event->y, &sx, &sy);
switch (state) {
/*
Note that once the canvas state has been changed to be more
meaningful, the following state case should eventually
be replaced by a line of the form "case NodeDelete:"
*/
case SDnode1:
switch (button_op) {
case BUTTON_DOWN_EVENT:
topobject->select_HN(canvas, (int)sx, (int)sy);
selected_node = currentselection;
if (currentselection != NULL) {
selected.changeAttribState(SDnode2);
changeCanvasCursor(pirate);
}
break;
case BUTTON_UP_EVENT:
break;
case BUTTON_MOVED_EVENT:
break;
default:
//add PostErrorMsg() to handle error message - phsia 12/8/95
PostErrorMsg(SDnode1);
break;
}
break;
case SDnode2:
switch (button_op) {
case BUTTON_DOWN_EVENT:
topobject->select_HN(canvas, (int)sx, (int)sy);
if(currentselection != NULL
&& selected_node == currentselection) {
docut((Widget) 0,0,0);
selected.changeAttribState(SDnode1);
changeCanvasCursor(arrow);
} else
selected_node = currentselection;
break;
case BUTTON_UP_EVENT:
break;
case BUTTON_MOVED_EVENT:
break;
default: /* illegal value for button_op variable */
//add PostErrorMsg() to handle error message - phsia 12/8/95
PostErrorMsg(SDnode2);
break;
}
break;
default: /* illegal value for state variable */
fprintf(stderr, "Out of State in function node_delete.\n");
fprintf(stderr, "switch on state\n");
fprintf(stderr, "Report this to Professor Lechner.\n");
break;
}
}
// end void node_delete()
/***************************************************************************
* Description:
* node_move performs the node movement operation. It does
* this based on the button event and other variables passed
* in to it. All code within this function was lifted from
* the button*.cc files. Note that we don't actually use
* the attribute information (at least for now).
*
* Error handling:
* NONE.
* Side effects:
* NONE.
***************************************************************************/
void node_move (XButtonEvent *event,
int state, /* Canvas State (eventually just NodeCreate)*/
node_attributes *attribute, /* circle, square, etc. */
int button_op) /* BUTTON_UP, BUTTON_DOWN,BUTTON_MOVED */
{
float sx, sy;
#ifdef GENV6
char *id;
#else
hcg_key id;
#endif
/* Xlate into world coordinates */
DCtoWC(event->x, event->y, &sx, &sy);
switch (state)
{
/*
Note that once the canvas state has been changed to be more
meaningful, the following state case should eventually
be replaced by one line of the form "case NodeMove:"
*/
case SMove:
/* At this point, we are in the Node Move state */
switch (button_op) {
case BUTTON_DOWN_EVENT:
unselect(); /* Unselect any current sel. */
/* Now get the pointed at */
topobject->select_HN(canvas, (int)sx, (int)sy);
if (currentselection != 0) {
#ifdef GENV6
id = currentselection->getid();
#else
id = (hcg_key)currentselection->getid();
#endif
pr_find(HN,HNid,id);
if (HNcurr != NULL) {
selectedx = sx;
selectedy = sy;
savedx = currentselection->getcenterx();
savedy = currentselection->getcentery();
displayMessage("Drag node to new location\n");
} else {
unselect();
currentselection = 0;
displayMessage(
"Link cannot be moved by draging it\n");
}
}
break;
case BUTTON_UP_EVENT:
if(currentselection != 0) {
#ifdef GENV6
topobject->dorecalc(currentselection->getid());
#else
topobject->dorecalc((hcg_key)currentselection->getid());
#endif
unselect();
ReDraw();
}
break;
case BUTTON_MOVED_EVENT:
if(currentselection != 0) {
/* This is the case for moving symbols */
currentselection -> highlight(0);
/* Incremental move of bounding box */
currentselection->setcenterx(savedx + sx - selectedx);
/* Limit movement */
if (currentselection -> getcenterx() < 0)
currentselection -> setcenterx(0);
if (currentselection->getcentery() < 0)
currentselection -> setcentery(0);
currentselection->setcentery(savedy + sy - selectedy);
currentselection -> highlight(1);
}
break;
default: /* illegal value for button_op variable */
//add PostErrorMsg() to handle error message - phsia 12/8/95
PostErrorMsg(SMove);
break;
}
break;
default: /* illegal value for state variable */
fprintf(stderr, "Out of State in function node_move.\n");
fprintf(stderr, "switch on state\n");
fprintf(stderr, "Report this to Professor Lechner.\n");
break;
}
}
//**************************** Begin ************************************
/***************************************************************************
* Description:
* node_resize performs the node resize operation. It does
* this based on the button event and other variables passed
* in to it. All code within this function was lifted from
* the button*.cc files. Note that we don't actually use
* the attribute information (at least for now).
*
* Error handling:
* NONE.
* Side effects:
* NONE.
***************************************************************************/
// This procedure is added by bde3
// Aug,22,93 by Wenchin Chen
//
void node_resize ( XButtonEvent *event,
int state, /* Canvas State (eventually just NodeCreate)*/
node_attributes *attribute, /* circle, square, etc. */
int button_op) /* BUTTON_UP, BUTTON_DOWN,BUTTON_MOVED */
{
/* Stub function, not written yet */
float sx, sy;
#ifdef GENV6
char *id;
#else
hcg_key id;
#endif
char curr_shape[20];
float center_x, center_y, radius;
float temp_x, temp_y, temp_radius;
float diff_x, diff_y;
double squares;
extern int first_time;
static graphobject *selected_node = NULL;
static int Resize = 0;
DCtoWC(event->x, event->y, &sx, &sy);
switch (state)
{
/* Note that once the canvas state has been changed to be more
meaningful, the following state case should eventually be
replaced by a line of the form "case NodeResize:"
*/
case SResize:
switch (button_op) {
case BUTTON_DOWN_EVENT:
unselect();
unselect();
selection(canvas, (int)sx, (int)sy);
selected_node = currentselection;
selected.changeAttribState(SResize_node);
changeCanvasCursor(movehand);
Resize = 0;
break;
case BUTTON_UP_EVENT:
break;
case BUTTON_MOVED_EVENT:
break;
default:
//add PostErrorMsg() to handle error message - phsia 12/8/95
PostErrorMsg(SResize);
break;
}
break;
case SResize_node:
/* At this point, we are in the NodeResize state */
switch (button_op) {
case BUTTON_DOWN_EVENT:
unselect();
selection(canvas, (int)sx, (int)sy);
if (selected_node != currentselection) {
selected_node = currentselection;
break;
}
Resize = 1;
if(currentselection != 0){
#ifdef GENV6
id = currentselection->getid();
#else
id = (hcg_key)currentselection->getid();
#endif
pr_find(HN,HNid,id);
if(HNcurr != NULL){
first_time = TRUE;
selectedx = sx;
selectedy = sy;
savedx = currentselection->getcenterx();
savedy = currentselection->getcentery();
displayMessage("Drag the mouse button to resize\n");
center_x = currentselection->getcenterx();
center_y = currentselection->getcentery();
radius = currentselection->getradius();
}
else{
unselect();
currentselection = 0;
displayMessage("Node cannot be resized\n");
}
}
break;
case BUTTON_MOVED_EVENT:
if (Resize == 1)
doresize ((int)event->x, (int)event->y);
break;
case BUTTON_UP_EVENT:
if (selected_node == NULL) {
selected.changeAttribState(SResize_node);
changeCanvasCursor(arrow);
break;
} else if (Resize == 0)
break;
selected.changeAttribState(SResize);
changeCanvasCursor(arrow);
if(currentselection != 0){
#ifdef GENV6
id = currentselection->getid();
#else
id = (hcg_key)currentselection->getid();
#endif
pr_find(HN,HNid,id);
if(HNcurr == NULL){
return;
}
} else {
return;
}
center_x = currentselection->getcenterx();
center_y = currentselection->getcentery();
temp_x = event->x;
temp_y = event->y;
diff_x = temp_x - center_x;
diff_y = temp_y - center_y;
strcpy(curr_shape, currentselection->getshape());
if((int)curr_shape[0] == 'C' || (int)curr_shape[0] == 'c'){
squares = (double)(diff_x * diff_x + diff_y * diff_y);
temp_radius = (float)sqrt(squares) * 2.0;
currentselection->setradius(temp_radius,temp_radius);
}else{
if(diff_x < 0) diff_x = -diff_x ;
if(diff_y < 0) diff_y = -diff_y ;
currentselection->setradius(diff_x*2.0, diff_y*2.0);
}
#ifdef GENV6
topobject->dorecalc(currentselection->getid());
#else
topobject->dorecalc((hcg_key)currentselection->getid());
#endif
ReDraw();
first_time = TRUE;
unselect();
break;
default: /* illegal value for button_op variable */
fprintf(stderr, "Out of State in function node_resize.\n");
fprintf(stderr, "switch on state\n");
fprintf(stderr, "Report this to Professor Lechner.\n");
break;
}
}
}
/* Routine: doresize() called by case BUTTON_MOVED_EVENT */
void doresize(int x, int y)
{
float curr_x,curr_y,center_x,center_y;
float temp_x,temp_y,diff_x,diff_y;
static float last_radius,last_width,last_height;
double squares;
#ifdef GENV6
char *id;
#else
hcg_key id;
#endif
char curr_shape[20];
extern int first_time;
if(currentselection != 0){
#ifdef GENV6
id = currentselection->getid();
#else
id = (hcg_key)currentselection->getid();
#endif
pr_find(HN,HNid,id);
if(HNcurr == NULL){
return;
}
curr_x = (float)x;
curr_y = (float)y;
temp_x = currentselection->getcenterx();
temp_y = currentselection->getcentery();
strcpy( curr_shape, currentselection->getshape());
if(curr_shape[0] == 'C' || curr_shape[0] == 'c'){
center_x = currentselection->getcenterx();
center_y = currentselection->getcentery();
if(first_time){
last_radius = currentselection->getradius();
drawimage(center_x,center_y,last_radius*2.0,
last_radius*2.0);
first_time = FALSE;
} else{
drawimage(center_x,center_y,last_radius*2.0,
last_radius*2.0);
}
diff_x = curr_x - temp_x;
diff_y = curr_y - temp_y;
squares = (double)(diff_x * diff_x + diff_y *
diff_y);
last_radius = (float)sqrt(squares);
drawimage(center_x,center_y,last_radius*2.0,
last_radius*2.0);
if(diff_x < 0)diff_x = -diff_x;
if(diff_y < 0)diff_y = -diff_y;
} else{
center_x = currentselection->getcenterx();
center_y = currentselection->getcentery();
if(first_time){
last_width = currentselection->getwidth();
last_height = currentselection->getheight();
switch(curr_shape[0]){
case 'E':
case 'e':
drawimage(center_x,center_y,last_width*2.0,
last_height*2.0);
break;
case 'R':
case 'r':
drawrectangular(center_x,center_y,last_width*2.0,
last_height*2.0);
break;
case 'F':
case 'f':
drawfile(center_x,center_y,last_width*2.0,
last_height*2.0);
break;
case 'O':
case 'o':
drawoutput(center_x,center_y,last_width*2.0,
last_height*2.0);
break;
case 'I':
case 'i':
drawinput(center_x,center_y,last_width*2.0,
last_height*2.0);
break;
default:
break;
}
first_time = FALSE;
} else{
switch(curr_shape[0]){
case 'E':
case 'e':
drawimage(center_x,center_y,last_width*2.0,
last_height*2.0);
break;
case 'R':
case 'r':
drawrectangular(center_x,center_y,last_width*2.0,
last_height*2.0);
break;
case 'F':
case 'f':
drawfile(center_x,center_y,last_width*2.0,
last_height*2.0);
break;
case 'O':
case 'o':
drawoutput(center_x,center_y,last_width*2.0,
last_height*2.0);
break;
case 'I':
case 'i':
drawinput(center_x,center_y,last_width*2.0,
last_height*2.0);
break;
default:
break;
}
}
diff_x = curr_x - temp_x;
diff_y = curr_y - temp_y;
last_width = diff_x;
last_height = diff_y;
if(last_width < 0)last_width = -last_width;
if(last_height < 0)last_height = -last_height;
switch(curr_shape[0]){
case 'E':
case 'e':
drawimage(center_x,center_y,last_width*2.0,
last_height*2.0);
break;
case 'R':
case 'r':
drawrectangular(center_x,center_y,last_width*2.0,
last_height*2.0);
break;
case 'F':
case 'f':
drawfile(center_x,center_y,last_width*2.0,
last_height*2.0);
break;
case 'O':
case 'o':
drawoutput(center_x,center_y,last_width*2.0,
last_height*2.0);
break;
case 'I':
case 'i':
drawinput(center_x,center_y,last_width*2.0,
last_height*2.0);
break;
default:
break;
}
if(diff_x < 0)diff_x = -diff_x;
if(diff_y < 0)diff_y = -diff_y;
}
}
}
//****************************** end ***********************************//
//this procedure is to add the attribute of a node
//created by : su93bde2 - hlee 93/08/21
void node::addattr(float x, float y)
{
extern char globalfontname[51];
extern void trim(char *);
extern void load_font(char *,GC);
extern GC copyGC;
float beginx, beginy,heighttmp,newbeginx=0, newbeginy=0;
int width,height;
char *tempid;
#ifdef GENV6
char temp_pkey[9];
char temp_buff[256]; /* constant size */
char *id;
#else
hcg_key temp_pkey;
struct HA *HA_elt;
hcg_key id;
#endif
float origin = 0;
void ReDraw();
#ifdef GENV6
id = currentselection->getid();
#else
id = (hcg_key)currentselection->getid();
#endif
pr_find(HN,HNid,id);
// The node's default in the network database.
tempid = "DA010009";
#ifdef GENV6
pr_gen_pkey("94sbdeview", HA, temp_pkey);
#else
HA_elt = pr_create(HA);
#endif
beginx = currentselection->getcenterx()-x;
beginy = currentselection->getcentery()-y;
trim(globalfontname);
load_font(globalfontname,copyGC);
getDimensions(new_string,globalfontname,&width,&height);
heighttmp = height;
child_loop(HN,HA,HAid,HNid)
{
newbeginx = HAcurr->txtoffsetx ;
newbeginy = HAcurr->txtoffsety ;
origin = HAcurr->HAorigin;
}
if ( newbeginy != 0 ) {
beginy = newbeginy - height ;
beginx = newbeginx;
}
#ifdef GENV6
sprintf (temp_buff, " %s %s %s %8.4f %8.4f %8.4f %d %d %s %s",
temp_pkey, cHN->HNid, tempid,
beginx, beginy,origin,width,height,new_string,globalfontname);
pr_add("94sbdeview",temp_buff);
#else
pr_set_int( HA_elt, HAid, temp_pkey ) ;
pr_set_int( HA_elt, HNid, cHN->HNid ) ;
pr_set_str( HA_elt, DAid, tempid ) ;
pr_set_flt( HA_elt, txtoffsetx, beginx ) ;
pr_set_flt( HA_elt, txtoffsety, beginy ) ;
pr_set_flt( HA_elt, HAorigin, origin ) ;
pr_set_int( HA_elt, txtwidth, width ) ;
pr_set_int( HA_elt, txtheight, height ) ;
//switch txtfont field with hlabel field. - phsia 11/5/95
pr_set_str( HA_elt, txtfont, globalfontname ) ;
pr_set_str( HA_elt, hlabel, new_string ) ;
pr_add( "94sbdeview", HA, HA_elt ) ;
#endif
ReDraw();
}
//this procedure is to change the attribute of a node
//created by : su93bde2 - hlee 93/08/21
void node::chgattr(float x, float y)
{
extern char globalfontname[51];
extern GC copyGC;
float beginx, beginy,heighttmp,newbeginx=0, newbeginy=0;
int width,height;
char *tempid;
#ifdef GENV6
char temp_pkey[9];
char temp_buff[256]; /* constant size */
#else
hcg_key temp_pkey;
struct HN *HN_elt;
struct HA *HA_elt;
#endif
float origin = 0;
void ReDraw();
#ifdef GENV6
pr_find(HN,HNid,id);
#else
pr_find(HN,HNid,pr_get_key(HN_elt,HNid));
#endif
// The node's default in the network database.
tempid = "DA010009";
#ifdef GENV6
pr_gen_pkey("94sbdeview", HA, temp_pkey);
#else
HA_elt = pr_create( HA ) ;
#endif
beginx = currentselection->getcenterx()-x;
beginy = currentselection->getcentery()-y;
trim(globalfontname);
load_font(globalfontname,copyGC);
getDimensions(new_string,globalfontname,&width,&height);
heighttmp = height;
child_loop(HN,HA,HAid,HNid) {
newbeginx = HAcurr->txtoffsetx ;
newbeginy = HAcurr->txtoffsety ;
origin = HAcurr->HAorigin;
}
if ( newbeginy != 0 ) {
beginy = newbeginy - height ;
beginx = newbeginx;
}
#ifdef GENV6
sprintf (temp_buff, " %s %s %s %8.4f %8.4f %8.4f %d %d %s %s",
temp_pkey, cHN->HNid, tempid,
beginx, beginy,origin,width,height,new_string,globalfontname);
pr_add("94sbdeview",temp_buff);
#else
pr_set_int( HA_elt, HAid, temp_pkey ) ;
pr_set_int( HA_elt, HNid, cHN->HNid ) ;
pr_set_str( HA_elt, DAid, tempid ) ;
pr_set_flt( HA_elt, txtoffsetx, beginx ) ;
pr_set_flt( HA_elt, txtoffsety, beginy ) ;
pr_set_flt( HA_elt, HAorigin, origin ) ;
pr_set_int( HA_elt, txtwidth, width ) ;
pr_set_int( HA_elt, txtheight, height ) ;
//switch txtfont field with hlabel field. - phsia 11/5/95
pr_set_str( HA_elt, txtfont, globalfontname ) ;
pr_set_str( HA_elt, hlabel, new_string ) ;
pr_add( "94sbdeview", HA, HA_elt ) ;
#endif
ReDraw();
}