file: util.c
/* util.c - utility routines for XmdvTool */
/* Copyright 1994, Matthew O. Ward
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without fee
* is granted provided that the above copyright notice appears in all copies.
* It is provided "as is" without express or implied warranty.
*/
/* callbacks for canvas processing, some currently empty callbacks for the
keys (later will provide more details on dimensions?), and some useful
utilities. */
#include <X11/Xatom.h>
#include "XmdvTool.h"
#include "hierarchy.h"
#include "scatterplot.h"
#include "parcoord.h"
#include "glyph.h"
#include "glyphtool.h"
#include "stacktool.h"
#include "util.h"
#include "init.h"
#include "brush.h"
#include "data_text.h"
#include "average.h"
#include "multi_select.h"
extern Widget appShell;
extern int dims, data_size, all_dims;
extern char on[MAXDIM];
extern char names[MAXDIM][MAXLABEL];
extern char all_names[MAXDIM][MAXLABEL];
extern double *data_buf;
extern double *br_pos, *br_size;
extern Brush *brush; /* the current brush */
extern Brush brushes[MAXBRUSH]; /* set of brushes */
extern Brush all_brushes[MAXBRUSH]; /* the original set of brushes */
extern int brush_number; /* the current brush number */
extern double dim_min[MAXDIM], dim_max[MAXDIM];
extern int cardinality[MAXDIM];
extern int all_cardinality[MAXDIM];
extern double all_dim_min[MAXDIM], all_dim_max[MAXDIM];
extern unsigned long color_cells[NUM_COLOR_CELLS];
extern XColor outline_col;
extern GC gc, xor_gc;
/* is this a color display? */
extern int COLOR;
extern int X_SIZE, Y_SIZE;
extern int num_topics;
extern char *topics[], *help_file[];
Arg wargs[10];
int n;
/* button defines */
#define BUTTON_DOWN 1
#define BUTTON_DRAG 2
#define BUTTON_UP 3
#define BUTTON_CANCEL 4
void NewDimList(Widget w, caddr_t client, XawListReturnStruct *list_ret)
{
int i, j=0, k, sel;
/* get index of selected dimension */
sel = list_ret->list_index;
if(on[sel] == 1)
on[sel]=0;
else
on[sel] = 1;
for(i = 0;i < all_dims;i++)
if(on[i]) {
dim_min[j] = all_dim_min[i];
dim_max[j] = all_dim_max[i];
cardinality[j] = all_cardinality[i];
strcpy(names[j], all_names[i]);
for(k = 0;k < MAXBRUSH;k++) {
brushes[k].pos[j] = all_brushes[k].pos[i];
brushes[k].size[j] = all_brushes[k].size[i];
brushes[k].bound_offset[j] = all_brushes[k].bound_offset[i];
}
j++;
}
dims = j;
init_glyphkey();
init_hierkey();
init_DimList();
}
void NewHelpList(Widget w, caddr_t client, XawListReturnStruct *list_ret)
{
Widget tw;
int choice;
char filename[100], helpstring[100];
/* get index of selected dimension */
choice = list_ret->list_index;
tw = WcFullNameToWidget(appShell,"*help_mess");
if(tw == NULL)
printf("couldn't get help message widget\n");
else {
n = 0;
/* create a filename, using the absolute path DOCDIR */
sprintf(filename, "%s/doc/%s", DOCDIR, help_file[choice]);
/* set the ascii widget type to file, and set the appropriate file name */
XtSetArg(wargs[n], XtNtype, XawAsciiFile); n++;
XtSetArg(wargs[n], XtNstring, filename); n++;
XtSetValues(tw,wargs,n);
}
/* now set the label of the popped up widget to be the topic line */
tw = WcFullNameToWidget(appShell,"*help2_label");
if(tw == NULL)
printf("couldn't get help label widget\n");
else {
n = 0;
sprintf(helpstring, "Help Topic: %s", topics[choice]);
XtSetArg(wargs[n], XtNlabel, helpstring); n++;
XtSetValues(tw,wargs,n);
}
}
/* on selecting an item from glyph key, do nothing! */
void NewKeyList(Widget w, caddr_t client, XawListReturnStruct *list_ret)
{
}
/* on selecting an item from dimensional stacking key, do nothing! */
void NewKey2List(Widget w, caddr_t client, XawListReturnStruct *list_ret)
{
}
void ResizeCanvasCB(Widget w,
XtPointer params,
XtPointer call_data)
{
/* params as a char pointer */
Widget tw;
char *params_text = (char *)params;
if(!strcmp(params_text, "+big"))
X_SIZE = X_SIZE + X_SIZE / 2;
if(!strcmp(params_text, "+small"))
X_SIZE = X_SIZE + X_SIZE / 10;
if(!strcmp(params_text, "-big"))
X_SIZE = X_SIZE - X_SIZE / 2;
if(!strcmp(params_text, "-small"))
X_SIZE = X_SIZE - X_SIZE / 10;
if(!strcmp(params_text, "Reset"))
X_SIZE = 600;
if(X_SIZE < 600)
X_SIZE = 600;
Y_SIZE = X_SIZE;
tw = WcFullNameToWidget(appShell,"*canvas");
XtSetArg(wargs[0],XtNwidth, X_SIZE);
XtSetArg(wargs[1],XtNheight, Y_SIZE);
XtSetValues(tw,wargs,2);
}
/* redraw canvas if the xexpose count hits 0 - avoids unnecessary redraws */
void ERedrawCanvas(Widget w, caddr_t client_data,
XawDrawingAreaCallbackStruct *call_data)
{
if(call_data->event->xexpose.count != 0 || call_data->reason
!= XawCR_EXPOSE) return;
RedrawCanvas(w, client_data, call_data);
}
/* figure out which display technique is currently selected and call the
required drawing routine */
void RedrawCanvas(Widget w, caddr_t client_data,
XawDrawingAreaCallbackStruct *call_data)
{
do_redraw();
}
void do_redraw(void)
{
Widget canvas_w, choice;
char *str;
canvas_w = WcFullNameToWidget(appShell,"*canvas");
choice = WcFullNameToWidget(appShell,"*togscat");
str = (char *)XawToggleGetCurrent(choice);
XClearWindow(XtDisplay(canvas_w), XtWindow(canvas_w));
if(data_size > 0) {
if(str != NULL && strcmp(str, "togpar") == 0)
do_par(canvas_w);
else if(str != NULL && strcmp(str, "togscat") == 0)
do_scat(canvas_w);
else if(str != NULL && strcmp(str, "toggly") == 0)
do_glyph(canvas_w);
else if(str != NULL && strcmp(str, "toghier") == 0)
do_hier(canvas_w);
}
/* update the brush tools */
GlyphBToolUpdate();
StackBToolUpdate();
StatsUpdate();
/* update the statistics and data text list */
DataTextUpdateList();
StatsDoRedraw();
/* update any average operations */
AverageUpdate();
}
/* several canvas operations currently not supported */
int button_one_down = FALSE;
int button_two_down = FALSE;
int button_three_down = FALSE;
void MotionCanvas(Widget w, caddr_t client_data,
XawDrawingAreaCallbackStruct *call_data)
{
if(button_one_down)
{
interactive_resize_brush(call_data->event->xmotion.x,
call_data->event->xmotion.y,
BUTTON_DRAG); //OVERLOAD CALL: BUTTON_DRAG: glyphtool.c(?), stacktool.c(?), util.c(?)
}
else if(button_two_down)
{
interactive_move_brush(call_data->event->xmotion.x,
call_data->event->xmotion.y,
BUTTON_DRAG); //OVERLOAD CALL: BUTTON_DRAG: glyphtool.c(?), stacktool.c(?), util.c(?)
}
else if(button_three_down)
{
}
}
void InputCanvas(Widget w, caddr_t client_data,
XawDrawingAreaCallbackStruct *call_data)
{
int x, y;
switch (call_data->event->type)
{
/* Process mouse button events */
case ButtonPress:
x = call_data->event->xbutton.x;
y = call_data->event->xbutton.y;
switch (call_data->event->xbutton.button)
{
case 1: /* the resize button */
if(button_two_down)
{
XBell(XtDisplay(w), 0);
button_one_down = button_two_down = button_three_down = FALSE;
interactive_move_brush(x, y, BUTTON_CANCEL); //OVERLOAD CALL: BUTTON_CANCEL: glyphtool.c(?), stacktool.c(?), util.c(?)
break;
}
else if(button_three_down)
{
XBell(XtDisplay(w), 0);
button_one_down = button_two_down = button_three_down = FALSE;
break;
}
button_one_down = TRUE;
interactive_resize_brush(x, y, BUTTON_DOWN); //OVERLOAD CALL: BUTTON_DOWN: glyphtool.c(?), stacktool.c(?), util.c(?)
break;
case 2: /* the move button */
if(button_one_down)
{
XBell(XtDisplay(w), 0);
button_one_down = button_two_down = button_three_down = FALSE;
interactive_resize_brush(x, y, BUTTON_CANCEL); //OVERLOAD CALL: BUTTON_CANCEL: glyphtool.c(?), stacktool.c(?), util.c(?)
break;
}
else if(button_three_down)
{
XBell(XtDisplay(w), 0);
button_one_down = button_two_down = button_three_down = FALSE;
break;
}
button_two_down = TRUE;
interactive_move_brush(x, y, BUTTON_DOWN); //OVERLOAD CALL: BUTTON_DOWN: glyphtool.c(?), stacktool.c(?), util.c(?)
break;
case 3:
if(button_one_down)
{
XBell(XtDisplay(w), 0);
button_one_down = button_two_down = button_three_down = FALSE;
interactive_resize_brush(x, y, BUTTON_CANCEL); //OVERLOAD CALL: BUTTON_CANCEL: glyphtool.c(?), stacktool.c(?), util.c(?)
break;
}
else if(button_two_down)
{
XBell(XtDisplay(w), 0);
button_one_down = button_two_down = button_three_down = FALSE;
interactive_move_brush(x, y, BUTTON_CANCEL); //OVERLOAD CALL: BUTTON_CANCEL: glyphtool.c(?), stacktool.c(?), util.c(?)
break;
}
button_three_down = TRUE;
break;
}
break;
case ButtonRelease:
x = call_data->event->xbutton.x;
y = call_data->event->xbutton.y;
switch (call_data->event->xbutton.button)
{
case 1:
if(!button_one_down)
break;
interactive_resize_brush(x, y, BUTTON_UP); //OVERLOAD CALL: BUTTON_UP: glyphtool.c(?), stacktool.c(?), util.c(?)
button_one_down = FALSE;
break;
case 2:
if(!button_two_down)
break;
interactive_move_brush(x, y, BUTTON_UP); //OVERLOAD CALL: BUTTON_UP: glyphtool.c(?), stacktool.c(?), util.c(?)
button_two_down = FALSE;
break;
case 3:
if(!button_three_down)
break;
button_three_down = FALSE;
break;
}
break;
}
}
void interactive_move_brush(int mouse_x, int mouse_y, int button)
{
Widget canvas_w; /* the canvas widget */
Widget choice; /* radio button choice widget */
char *str; /* radio button label string */
static int axis; /* axis for resize */
double mouse_data_x, /* mose position in data coordinates */
mouse_data_y;
int left_x, left_y, /* locations on neighboring axes */
right_x, right_y;
double left_y_data, /* left/right neighbors in data space */
right_y_data;
int dimwidth, halfwidth; /* dimension variables for parallel coords */
static double old_mouse_data_x,/* old mouse position in data space */
old_mouse_data_y;
int x,y; /* x/y position vars */
int boxwidth, boxheight; /* width/height of scatterplot boxes */
static int dimx, dimy; /* x/y dimensions for scatterplot box */
/* if brushing is not on or not displayed, forget it */
if(brush->display == FALSE || brush->enable == FALSE)
return;
canvas_w = WcFullNameToWidget(appShell,"*canvas");
choice = WcFullNameToWidget(appShell,"*togscat");
str = (char *)XawToggleGetCurrent(choice);
if(str != NULL && strcmp(str, "togpar") == 0)
{
dimwidth = X_SIZE/dims;
halfwidth = dimwidth/2;
/* if this is a button down, determine axis */
if(button == BUTTON_DOWN) //OVERLOAD CALL: BUTTON_DOWN: glyphtool.c(?), stacktool.c(?), util.c(?)
{
axis = map_location_to_axis(mouse_x);
/* sanity check */
if(axis < 0 || axis >= dims)
{
XBell(XtDisplay(canvas_w), 0);
return;
}
}
else
{
/* sanity check */
if(axis < 0 || axis >= dims)
return;
}
/* map mouse y location to data coordinates */
mouse_data_y = (Y_SIZE - mouse_y) *
((dim_max[axis] - dim_min[axis]) / (double)Y_SIZE)
+ dim_min[axis];
/* bound move to display edges */
mouse_data_y = MIN(mouse_data_y, dim_max[axis]-br_size[axis]/2.);
mouse_data_y = MAX(mouse_data_y, dim_min[axis]+br_size[axis]/2.);
/* if this is a drag, release, or cancel then erase the old lines */
if(button == BUTTON_DRAG || button == BUTTON_UP || //OVERLOAD CALL: BUTTON_DRAG: glyphtool.c(?), stacktool.c(?), util.c(?); BUTTON_UP: glyphtool.c(?), stacktool.c(?), util.c(?)
button == BUTTON_CANCEL) //OVERLOAD CALL: BUTTON_CANCEL: glyphtool.c(?), stacktool.c(?), util.c(?)
{
/* erase lines from left axis */
if(axis!=0)
{
/* first the min line */
left_x = (axis-1) * dimwidth + halfwidth;
left_y_data = br_pos[axis-1] - br_size[axis-1]/2.;
/* convert to screen coords */
left_y = Y_SIZE -
((left_y_data - dim_min[axis-1]) *
Y_SIZE / (dim_max[axis-1] - dim_min[axis-1]));
x = axis * dimwidth + halfwidth;
y = Y_SIZE -
((old_mouse_data_y - br_size[axis]/2. - dim_min[axis]) *
Y_SIZE / (dim_max[axis] - dim_min[axis]));
/* erase the old line */
XDrawLine(XtDisplay(canvas_w), XtWindow(canvas_w), xor_gc,
left_x, left_y, x, y);
/* now the max line */
left_y_data = br_pos[axis-1] + br_size[axis-1]/2.;
y = Y_SIZE -
((old_mouse_data_y + br_size[axis]/2. - dim_min[axis]) *
Y_SIZE / (dim_max[axis] - dim_min[axis]));
/* convert to screen coords */
left_y = Y_SIZE -
((left_y_data - dim_min[axis-1]) *
Y_SIZE / (dim_max[axis-1] - dim_min[axis-1]));
/* erase the old line */
XDrawLine(XtDisplay(canvas_w), XtWindow(canvas_w), xor_gc,
left_x, left_y, x, y);
}
/* erase lines from right axis */
if(axis!=dims-1)
{
/* first the min line */
right_x = (axis+1) * dimwidth + halfwidth;
right_y_data = br_pos[axis+1] - br_size[axis+1]/2.;
/* convert to screen coords */
right_y = Y_SIZE -
((right_y_data - dim_min[axis+1]) *
Y_SIZE / (dim_max[axis+1] - dim_min[axis+1]));
x = axis * dimwidth + halfwidth;
y = Y_SIZE -
((old_mouse_data_y - br_size[axis]/2. - dim_min[axis]) *
Y_SIZE / (dim_max[axis] - dim_min[axis]));
/* erase the old line */
XDrawLine(XtDisplay(canvas_w), XtWindow(canvas_w), xor_gc,
right_x, right_y, x, y);
/* now the max line */
right_y_data = br_pos[axis+1] + br_size[axis+1]/2.;
y = Y_SIZE -
((old_mouse_data_y + br_size[axis]/2. - dim_min[axis]) *
Y_SIZE / (dim_max[axis] - dim_min[axis]));
/* convert to screen coords */
right_y = Y_SIZE -
((right_y_data - dim_min[axis+1]) *
Y_SIZE / (dim_max[axis+1] - dim_min[axis+1]));
/* erase the old line */
XDrawLine(XtDisplay(canvas_w), XtWindow(canvas_w), xor_gc,
right_x, right_y, x, y);
}
}
/* if this is a cancel, don't do anything else */
if(button == BUTTON_CANCEL) //OVERLOAD CALL: BUTTON_CANCEL: glyphtool.c(?), stacktool.c(?), util.c(?)
return;
/* if this is not a release, draw the new line */
if(button == BUTTON_DOWN || button == BUTTON_DRAG) //OVERLOAD CALL: BUTTON_DOWN: glyphtool.c(?), stacktool.c(?), util.c(?); BUTTON_DRAG: glyphtool.c(?), stacktool.c(?), util.c(?)
{
/* draw line from left axis */
if(axis !=0)
{
/* first the min line */
left_x = (axis-1) * dimwidth + halfwidth;
left_y_data = br_pos[axis-1] - br_size[axis-1]/2.;
/* convert to screen coords */
left_y = Y_SIZE -
((left_y_data - dim_min[axis-1]) *
Y_SIZE / (dim_max[axis-1] - dim_min[axis-1]));
x = axis * dimwidth + halfwidth;
y = Y_SIZE -
((mouse_data_y - br_size[axis]/2. - dim_min[axis]) *
Y_SIZE / (dim_max[axis] - dim_min[axis]));
/* draw new line */
XDrawLine(XtDisplay(canvas_w), XtWindow(canvas_w), xor_gc,
left_x, left_y, x, y);
/* now the max line */
left_y_data = br_pos[axis-1] + br_size[axis-1]/2.;
y = Y_SIZE -
((mouse_data_y + br_size[axis]/2. - dim_min[axis]) *
Y_SIZE / (dim_max[axis] - dim_min[axis]));
/* convert to screen coords */
left_y = Y_SIZE -
((left_y_data - dim_min[axis-1]) *
Y_SIZE / (dim_max[axis-1] - dim_min[axis-1]));
/* draw new line */
XDrawLine(XtDisplay(canvas_w), XtWindow(canvas_w), xor_gc,
left_x, left_y, x, y);
}
/* draw line from right axis */
if(axis!=dims-1)
{
/* first the min line */
right_x = (axis+1) * dimwidth + halfwidth;
right_y_data = br_pos[axis+1] - br_size[axis+1]/2.;
/* convert to screen coords */
right_y = Y_SIZE -
((right_y_data - dim_min[axis+1])
* Y_SIZE / (dim_max[axis+1] - dim_min[axis+1]));
x = axis * dimwidth + halfwidth;
y = Y_SIZE -
((mouse_data_y - br_size[axis]/2. - dim_min[axis]) *
Y_SIZE / (dim_max[axis] - dim_min[axis]));
/* draw new line */
XDrawLine(XtDisplay(canvas_w), XtWindow(canvas_w), xor_gc,
right_x, right_y, x, y);
/* now the max line */
right_y_data = br_pos[axis+1] + br_size[axis+1]/2.;
y = Y_SIZE -
((mouse_data_y + br_size[axis]/2. - dim_min[axis]) *
Y_SIZE / (dim_max[axis] - dim_min[axis]));
/* convert to screen coords */
right_y = Y_SIZE -
((right_y_data - dim_min[axis+1])
* Y_SIZE / (dim_max[axis+1] - dim_min[axis+1]));
/* draw new line */
XDrawLine(XtDisplay(canvas_w), XtWindow(canvas_w), xor_gc,
right_x, right_y, x, y);
}
}
/* if this is a release then actually perform the move */
if(button == BUTTON_UP) //OVERLOAD CALL: BUTTON_UP: glyphtool.c(?), stacktool.c(?), util.c(?)
{
br_pos[axis] = mouse_data_y;
do_redraw();
}
}
else if(str != NULL && strcmp(str, "togscat") == 0)
{
boxwidth = X_SIZE/dims;
boxheight = Y_SIZE/dims;
/* if this is a button down, determine dimensions */
if(button == BUTTON_DOWN) //OVERLOAD CALL: BUTTON_DOWN: glyphtool.c(?), stacktool.c(?), util.c(?)
{
dimx = mouse_x / boxwidth;
dimy = mouse_y / boxheight;
/* sanity check */
if(dimx < 0 || dimx >= dims || dimy < 0 || dimy >= dims)
{
XBell(XtDisplay(canvas_w), 0);
return;
}
}
else
{
/* sanity check */
if(dimx < 0 || dimx >= dims || dimy < 0 || dimy >= dims)
return;
}
/* map mouse x/y location to data coordinates */
mouse_data_x = (mouse_x - (dimx * boxwidth)) *
((dim_max[dimx] - dim_min[dimx]) / (double)boxwidth)
+ dim_min[dimx];
mouse_data_y = (boxheight - (mouse_y - (dimy * boxheight))) *
((dim_max[dimy] - dim_min[dimy]) / (double)boxheight)
+ dim_min[dimy];
/* if this is a diagonal plot (same dimension on both axes) */
/* then average the x and y positions */
if(dimx == dimy)
mouse_data_x = mouse_data_y = (mouse_data_x + mouse_data_y)/2.;
/* bound mouse to plot edges */
mouse_data_x = MIN(mouse_data_x, dim_max[dimx] - br_size[dimx]/2.);
mouse_data_x = MAX(mouse_data_x, dim_min[dimx] + br_size[dimx]/2.);
mouse_data_y = MIN(mouse_data_y, dim_max[dimy] - br_size[dimy]/2.);
mouse_data_y = MAX(mouse_data_y, dim_min[dimy] + br_size[dimy]/2.);
/* if this is a drag, release, or cancel then erase the old boxes */
if(button == BUTTON_DRAG || button == BUTTON_UP || //OVERLOAD CALL: BUTTON_DRAG: glyphtool.c(?), stacktool.c(?), util.c(?); BUTTON_UP: glyphtool.c(?), stacktool.c(?), util.c(?)
button == BUTTON_CANCEL) //OVERLOAD CALL: BUTTON_CANCEL: glyphtool.c(?), stacktool.c(?), util.c(?)
{
/* do the graph being manipulated */
DrawScatterBrushBox(dimx, dimy, old_mouse_data_x, old_mouse_data_y,
br_size[dimx], br_size[dimy]);
/* do all other graphs along the horizontal */
for(x=0; x<dims; x++)
{
if(x==dimx)
continue;
DrawScatterBrushBox(x, dimy, br_pos[x], old_mouse_data_y,
br_size[x], br_size[dimy]);
}
/* do all other graphs along the vertical */
for(y=0; y<dims; y++)
{
if(y==dimy)
continue;
DrawScatterBrushBox(dimx, y, old_mouse_data_x, br_pos[y],
br_size[dimx], br_size[y]);
}
}
/* if this is a cancel, don't do anything else */
if(button == BUTTON_CANCEL) //OVERLOAD CALL: BUTTON_CANCEL: glyphtool.c(?), stacktool.c(?), util.c(?)
return;
/* if this is not a release, draw the new boxes */
if(button == BUTTON_DOWN || button == BUTTON_DRAG) //OVERLOAD CALL: BUTTON_DOWN: glyphtool.c(?), stacktool.c(?), util.c(?); BUTTON_DRAG: glyphtool.c(?), stacktool.c(?), util.c(?)
{
/* do the graph being manipulated */
DrawScatterBrushBox(dimx, dimy, mouse_data_x, mouse_data_y,
br_size[dimx], br_size[dimy]);
/* do all other graphs along the horizontal */
for(x=0; x<dims; x++)
{
if(x==dimx)
continue;
DrawScatterBrushBox(x, dimy, br_pos[x], mouse_data_y,
br_size[x], br_size[dimy]);
}
/* do all other graphs along the vertical */
for(y=0; y<dims; y++)
{
if(y==dimy)
continue;
DrawScatterBrushBox(dimx, y, mouse_data_x, br_pos[y],
br_size[dimx], br_size[y]);
}
}
/* if this is a release then actually perform the move */
if(button == BUTTON_UP) //OVERLOAD CALL: BUTTON_UP: glyphtool.c(?), stacktool.c(?), util.c(?)
{
br_pos[dimx] = mouse_data_x;
br_pos[dimy] = mouse_data_y;
do_redraw();
}
}
else if(str != NULL && strcmp(str, "toggly") == 0)
{
}
else if(str != NULL && strcmp(str, "toghier") == 0)
{
}
old_mouse_data_x = mouse_data_x;
old_mouse_data_y = mouse_data_y;
}
/*
* DrawScatterBrushBox() - Given x and y dimensions, coordinates of the
* brush center, and brush size in each dimesnion
* draw the corresponding brush outline in xor mode
* on the scatterplot display.
*/
void DrawScatterBrushBox(int dimx, int dimy, double data_x, double data_y,
double size_x, double size_y)
{
int i;
XPoint xpts[5]; /* X Point structure for box */
Widget canvas_w; /* the canvas widget */
int boxwidth, boxheight; /* box width/height */
/* get a pointer to the canvas widget */
canvas_w = WcFullNameToWidget(appShell,"*canvas");
boxwidth = X_SIZE/dims;
boxheight = Y_SIZE/dims;
i = 0;
/* lower left */
xpts[i].x = (data_x - size_x/2. - dim_min[dimx]) *
boxwidth / (dim_max[dimx] - dim_min[dimx]);
xpts[i].x += dimx * boxwidth;
xpts[i].y = (data_y - size_y/2. - dim_min[dimy]) *
boxheight / (dim_max[dimy] - dim_min[dimy]);
xpts[i].y = boxheight - xpts[i].y;
xpts[i].y += dimy * boxheight;
i++;
/* upper left */
xpts[i].x = xpts[i-1].x;
xpts[i].y = (data_y + size_y/2. - dim_min[dimy]) *
boxheight / (dim_max[dimy] - dim_min[dimy]);
xpts[i].y = boxheight - xpts[i].y;
xpts[i].y += dimy * boxheight;
i++;
/* upper right */
xpts[i].x = (data_x + size_x/2. - dim_min[dimx]) *
boxwidth / (dim_max[dimx] - dim_min[dimx]);
xpts[i].x += dimx * boxwidth;
xpts[i].y = xpts[i-1].y;
i++;
/* lower right */
xpts[i].x = xpts[i-1].x;
xpts[i].y = xpts[i-3].y;
i++;
/* back to start point */
xpts[i].x = xpts[0].x;
xpts[i].y = xpts[0].y;
i++;
XDrawLines(XtDisplay(canvas_w), XtWindow(canvas_w), xor_gc,
xpts, i, CoordModeOrigin);
}
/* min/max resize flags */
#define MM_MIN 1
#define MM_MAX 2
/*
* button = BUTTON_DOWN, BUTTON_DRAG, BUTTON_UP //OVERLOAD CALL: BUTTON_DOWN: glyphtool.c(?), stacktool.c(?), util.c(?); BUTTON_DRAG: glyphtool.c(?), stacktool.c(?), util.c(?); BUTTON_UP: glyphtool.c(?), stacktool.c(?), util.c(?)
*/
void interactive_resize_brush(int mouse_x, int mouse_y, int button)
{
Widget canvas_w; /* the canvas widget */
Widget choice; /* radio button choice widget */
char *str; /* radio button label string */
static int axis; /* axis for resize */
double new_min, new_max; /* new brush min/max when resized */
int left_x, left_y, /* locations on neighboring axes */
right_x, right_y;
double left_y_data, /* left/right neighbors in data space */
right_y_data;
int dimwidth, halfwidth; /* dimension variables for parallel coords */
static int min_max; /* are we resizing the min or max? */
int x,y; /* x/y position vars */
int boxwidth, boxheight; /* width/height of scatterplot boxes */
static int dimx, dimy; /* x/y dimensions for scatterplot box */
double mouse_data_x, /* mose position in data coordinates */
mouse_data_y;
static int resize_minx, /* resize minx/max flags */
resize_maxx,
resize_miny,
resize_maxy;
double new_minx, /* new min/max data values */
new_maxx,
new_miny,
new_maxy;
static double old_minx, /* old min/max data values */
old_maxx,
old_miny,
old_maxy;
static double old_mouse_data_x,/* old mouse position in data space */
old_mouse_data_y;
/* if brushing is not on or not displayed, forget it */
if(brush->display == FALSE || brush->enable == FALSE)
return;
canvas_w = WcFullNameToWidget(appShell,"*canvas");
choice = WcFullNameToWidget(appShell,"*togscat");
str = (char *)XawToggleGetCurrent(choice);
if(str != NULL && strcmp(str, "togpar") == 0)
{
dimwidth = X_SIZE/dims;
halfwidth = dimwidth/2;
/* if this is a button down, determine direction of resize and axis */
if(button == BUTTON_DOWN) //OVERLOAD CALL: BUTTON_DOWN: glyphtool.c(?), stacktool.c(?), util.c(?)
{
axis = map_location_to_axis(mouse_x);
/* sanity check */
if(axis < 0 || axis >= dims)
{
XBell(XtDisplay(canvas_w), 0);
return;
}
/* map mouse y location to data coordinates */
mouse_data_y = (Y_SIZE - mouse_y) *
((dim_max[axis] - dim_min[axis]) / (double)Y_SIZE)
+ dim_min[axis];
if(mouse_data_y < br_pos[axis])
min_max = MM_MIN;
else
min_max = MM_MAX;
}
else
{
/* sanity check */
if(axis < 0 || axis >= dims)
return;
/* map mouse y location to data coordinates */
mouse_data_y = (Y_SIZE - mouse_y) *
((dim_max[axis] - dim_min[axis]) / (double)Y_SIZE)
+ dim_min[axis];
}
/* bound mouse to display edges */
mouse_data_y = MIN(mouse_data_y, dim_max[axis]);
mouse_data_y = MAX(mouse_data_y, dim_min[axis]);
/* check if multiple select is on */
if(CheckMultiSelect())
{
int rad = 9; /* radius in screen coords */
int i,y;
double data[MAXDIM];
/* don't do anything on a button up */
if(button == BUTTON_UP) //OVERLOAD CALL: BUTTON_UP: glyphtool.c(?), stacktool.c(?), util.c(?)
return;
/* find all points within circle distance of mouse */
for(i=0; i<data_size; i++)
{
get_data(data, i);
y = (data[axis] - dim_min[axis]) * ((double) Y_SIZE) /
(dim_max[axis] - dim_min[axis]);
y = Y_SIZE - y;
if(ABS(y - mouse_y) < rad)
{
MultiSelectAddPoint(i);
/* redraw */
RedrawSingleParCoord(canvas_w, i);
}
}
return;
}
/* check if boundary drag is on */
if(CheckBoundaryDrag())
{
/* do a full redraw on a button up */
if(button == BUTTON_UP) //OVERLOAD CALL: BUTTON_UP: glyphtool.c(?), stacktool.c(?), util.c(?)
do_redraw();
/* erase the old boundary line */
ParCoordDrawBound(brush_number);
/* axis is the current axis and mouse_y is the mouse */
/* y coordinate and mouse_data_y is the data cooridate */
/* check if top or bottom boundary is being dragged */
if(mouse_data_y > br_pos[axis])
{
brush->bound_offset[axis] = mouse_data_y -
(br_pos[axis] + br_size[axis]/2.0);
brush->bound_offset[axis] = MAX(brush->bound_offset[axis], 0.0);
}
else
{
brush->bound_offset[axis] = (br_pos[axis] - br_size[axis]/2.0) -
mouse_data_y;
brush->bound_offset[axis] = MAX(brush->bound_offset[axis], 0.0);
}
/* draw the new boundary line */
ParCoordDrawBound(brush_number);
return;
}
/* if this is a drag, release, or cancel then erase the old line */
if(button == BUTTON_DRAG || button == BUTTON_UP || //OVERLOAD CALL: BUTTON_DRAG: glyphtool.c(?), stacktool.c(?), util.c(?); BUTTON_UP: glyphtool.c(?), stacktool.c(?), util.c(?)
button == BUTTON_CANCEL) //OVERLOAD CALL: BUTTON_CANCEL: glyphtool.c(?), stacktool.c(?), util.c(?)
{
/* erase line from left axis */
if(axis!=0)
{
left_x = (axis-1) * dimwidth + halfwidth;
if(min_max == MM_MIN)
left_y_data = br_pos[axis-1] - br_size[axis-1]/2.;
else
left_y_data = br_pos[axis-1] + br_size[axis-1]/2.;
/* convert to screen coords */
left_y = Y_SIZE -
((left_y_data - dim_min[axis-1]) *
Y_SIZE / (dim_max[axis-1] - dim_min[axis-1]));
x = axis * dimwidth + halfwidth;
y = Y_SIZE - ((old_mouse_data_y - dim_min[axis]) *
Y_SIZE / (dim_max[axis] - dim_min[axis]));
/* erase the old line */
XDrawLine(XtDisplay(canvas_w), XtWindow(canvas_w), xor_gc,
left_x, left_y, x, y);
}
/* erase line from right axis */
if(axis!=dims-1)
{
right_x = (axis+1) * dimwidth + halfwidth;
if(min_max == MM_MIN)
right_y_data = br_pos[axis+1] - br_size[axis+1]/2.;
else
right_y_data = br_pos[axis+1] + br_size[axis+1]/2.;
/* convert to screen coords */
right_y = Y_SIZE -
((right_y_data - dim_min[axis+1]) *
Y_SIZE / (dim_max[axis+1] - dim_min[axis+1]));
x = axis * dimwidth + halfwidth;
y = Y_SIZE - ((old_mouse_data_y - dim_min[axis]) *
Y_SIZE / (dim_max[axis] - dim_min[axis]));
/* erase the old line */
XDrawLine(XtDisplay(canvas_w), XtWindow(canvas_w), xor_gc,
right_x, right_y, x, y);
}
}
/* if this is a cancel, don't do anything else */
if(button == BUTTON_CANCEL) //OVERLOAD CALL: BUTTON_CANCEL: glyphtool.c(?), stacktool.c(?), util.c(?)
return;
/* if this is not a release, draw the new line */
if(button == BUTTON_DOWN || button == BUTTON_DRAG) //OVERLOAD CALL: BUTTON_DOWN: glyphtool.c(?), stacktool.c(?), util.c(?); BUTTON_DRAG: glyphtool.c(?), stacktool.c(?), util.c(?)
{
/* draw line from left axis */
if(axis !=0)
{
left_x = (axis-1) * dimwidth + halfwidth;
if(min_max == MM_MIN)
left_y_data = br_pos[axis-1] - br_size[axis-1]/2.;
else
left_y_data = br_pos[axis-1] + br_size[axis-1]/2.;
/* convert to screen coords */
left_y = Y_SIZE -
((left_y_data - dim_min[axis-1]) *
Y_SIZE / (dim_max[axis-1] - dim_min[axis-1]));
x = axis * dimwidth + halfwidth;
y = Y_SIZE - ((mouse_data_y - dim_min[axis]) *
Y_SIZE / (dim_max[axis] - dim_min[axis]));
/* draw new line */
XDrawLine(XtDisplay(canvas_w), XtWindow(canvas_w), xor_gc,
left_x, left_y, x, y);
}
/* draw line from right axis */
if(axis!=dims-1)
{
right_x = (axis+1) * dimwidth + halfwidth;
if(min_max == MM_MIN)
right_y_data = br_pos[axis+1] - br_size[axis+1]/2.;
else
right_y_data = br_pos[axis+1] + br_size[axis+1]/2.;
/* convert to screen coords */
right_y = Y_SIZE -
((right_y_data - dim_min[axis+1])
* Y_SIZE / (dim_max[axis+1] - dim_min[axis+1]));
x = axis * dimwidth + halfwidth;
y = Y_SIZE - ((mouse_data_y - dim_min[axis]) *
Y_SIZE / (dim_max[axis] - dim_min[axis]));
/* draw new line */
XDrawLine(XtDisplay(canvas_w), XtWindow(canvas_w), xor_gc,
right_x, right_y, x, y);
}
}
/* if this is a release then actually perform the resize */
if(button == BUTTON_UP) //OVERLOAD CALL: BUTTON_UP: glyphtool.c(?), stacktool.c(?), util.c(?)
{
if(min_max == MM_MIN)
{
new_min = mouse_data_y;
new_max = br_pos[axis] + .5*br_size[axis];
if(new_min >= new_max)
new_max = new_min;
}
else
{
new_min = br_pos[axis] - .5*br_size[axis];
new_max = mouse_data_y;
if(new_max <= new_min)
new_min = new_max;
}
br_pos[axis] = (new_max + new_min) / 2.;
br_size[axis] = new_max - new_min;
do_redraw();
}
}
else if(str != NULL && strcmp(str, "togscat") == 0)
{
boxwidth = X_SIZE/dims;
boxheight = Y_SIZE/dims;
/* if this is a button down, determine dimensions */
if(button == BUTTON_DOWN) //OVERLOAD CALL: BUTTON_DOWN: glyphtool.c(?), stacktool.c(?), util.c(?)
{
dimx = mouse_x / boxwidth;
dimy = mouse_y / boxheight;
/* sanity check */
if(dimx < 0 || dimx >= dims || dimy < 0 || dimy >= dims)
{
XBell(XtDisplay(canvas_w), 0);
return;
}
}
else
{
/* sanity check */
if(dimx < 0 || dimx >= dims || dimy < 0 || dimy >= dims)
return;
}
/* map mouse x/y location to data coordinates */
mouse_data_x = (mouse_x - (dimx * boxwidth)) *
((dim_max[dimx] - dim_min[dimx]) / (double)boxwidth)
+ dim_min[dimx];
mouse_data_y = (boxheight - (mouse_y - (dimy * boxheight))) *
((dim_max[dimy] - dim_min[dimy]) / (double)boxheight)
+ dim_min[dimy];
/* if this is a diagonal plot (same dimension on both axes) */
/* then average the x and y positions */
if(dimx == dimy)
mouse_data_x = mouse_data_y = (mouse_data_x + mouse_data_y)/2.;
/* bound mouse to plot edges */
mouse_data_x = MIN(mouse_data_x, dim_max[dimx]);
mouse_data_x = MAX(mouse_data_x, dim_min[dimx]);
mouse_data_y = MIN(mouse_data_y, dim_max[dimy]);
mouse_data_y = MAX(mouse_data_y, dim_min[dimy]);
/* check if multiple select is on */
if(CheckMultiSelect())
{
int rad2 = 81; /* radius^2 in screen coords */
int i,x,y;
double data[MAXDIM];
/* don't do anything on a button up */
if(button == BUTTON_UP) //OVERLOAD CALL: BUTTON_UP: glyphtool.c(?), stacktool.c(?), util.c(?)
return;
/* find all points within circle distance of mouse */
for(i=0; i<data_size; i++)
{
get_data(data, i);
x = dimx * boxwidth;
x += (data[dimx] - dim_min[dimx]) * ((double) boxwidth) /
(dim_max[dimx] - dim_min[dimx]);
y = dimy*boxheight;
y += (dim_max[dimy] - data[dimy] ) * ((double) boxheight) /
(dim_max[dimy] - dim_min[dimy]);
if((x - mouse_x)*(x - mouse_x) + (y - mouse_y)*(y - mouse_y) <
rad2)
{
MultiSelectAddPoint(i);
/* redraw */
RedrawSingleScatter(canvas_w, i);
}
}
return;
}
/* if a button down, find out what is being resized */
if(button == BUTTON_DOWN) //OVERLOAD CALL: BUTTON_DOWN: glyphtool.c(?), stacktool.c(?), util.c(?)
{
/* there are four different variables that could be resized */
/* (minx, maxx, miny, maxy) the user can resize at most */
/* two at once */
/* reset all resize flags */
resize_minx = resize_maxx = FALSE;
resize_miny = resize_maxy = FALSE;
/* check if user is resizing in x direction */
if(mouse_data_x <= br_pos[dimx] - .25*br_size[dimx])
resize_minx = TRUE;
else if(mouse_data_x >= br_pos[dimx] + .25*br_size[dimx])
resize_maxx = TRUE;
/* check if user is resizing in y direction */
if(mouse_data_y <= br_pos[dimy] - .25*br_size[dimy])
resize_miny = TRUE;
else if(mouse_data_y >= br_pos[dimy] + .25*br_size[dimy])
resize_maxy = TRUE;
/* check if nothing is being resized */
if(!resize_minx && !resize_maxx && !resize_miny && !resize_maxy)
{
XBell(XtDisplay(canvas_w), 0);
return;
}
}
/* check if nothing is being resized */
if(!resize_minx && !resize_maxx && !resize_miny && !resize_maxy)
return;
/* check to make sure min<max */
if(resize_minx && mouse_data_x >= br_pos[dimx]+br_size[dimx]/2.)
mouse_data_x = br_pos[dimx]+br_size[dimx]/2.;
if(resize_maxx && mouse_data_x <= br_pos[dimx]-br_size[dimx]/2.)
mouse_data_x = br_pos[dimx]-br_size[dimx]/2.;
if(resize_miny && mouse_data_y >= br_pos[dimy]+br_size[dimy]/2.)
mouse_data_y = br_pos[dimy]+br_size[dimy]/2.;
if(resize_maxy && mouse_data_y <= br_pos[dimy]-br_size[dimy]/2.)
mouse_data_y = br_pos[dimy]-br_size[dimy]/2.;
/* check if boundary drag is on */
if(CheckBoundaryDrag())
{
/* do a full redraw on a button up */
if(button == BUTTON_UP) //OVERLOAD CALL: BUTTON_UP: glyphtool.c(?), stacktool.c(?), util.c(?)
do_redraw();
/* erase the old boundary line */
ScatterDrawBound(brush_number);
/* resize boundary */
if(resize_minx)
{
if(mouse_data_x > br_pos[dimx] - br_size[dimx]/2.0)
brush->bound_offset[dimx] = 0.0;
else
brush->bound_offset[dimx] = br_pos[dimx] - br_size[dimx]/2.0 -
mouse_data_x;
}
if(resize_maxx)
{
if(mouse_data_x < br_pos[dimx] + br_size[dimx]/2.0)
brush->bound_offset[dimx] = 0.0;
else
brush->bound_offset[dimx] = mouse_data_x - (br_pos[dimx] +
br_size[dimx]/2.0);
}
if(resize_miny)
{
if(mouse_data_y > br_pos[dimy] - br_size[dimy]/2.0)
brush->bound_offset[dimy] = 0.0;
else
brush->bound_offset[dimy] = br_pos[dimy] - br_size[dimy]/2.0 -
mouse_data_y;
}
if(resize_maxy)
{
if(mouse_data_y < br_pos[dimy] + br_size[dimy]/2.0)
brush->bound_offset[dimy] = 0.0;
else
brush->bound_offset[dimy] = mouse_data_y - (br_pos[dimy] +
br_size[dimy]/2.0);
}
/* draw the new boundary line */
ScatterDrawBound(brush_number);
return;
}
/* find the new bounds based on what is being resized */
if(resize_minx)
new_minx = mouse_data_x;
else
new_minx = br_pos[dimx] - br_size[dimx]/2.;
if(resize_maxx)
new_maxx = mouse_data_x;
else
new_maxx = br_pos[dimx] + br_size[dimx]/2.;
if(resize_miny)
new_miny = mouse_data_y;
else
new_miny = br_pos[dimy] - br_size[dimy]/2.;
if(resize_maxy)
new_maxy = mouse_data_y;
else
new_maxy = br_pos[dimy] + br_size[dimy]/2.;
/* if this is a drag, release, or cancel then erase the old boxes */
if(button == BUTTON_DRAG || button == BUTTON_UP || //OVERLOAD CALL: BUTTON_DRAG: glyphtool.c(?), stacktool.c(?), util.c(?); BUTTON_UP: glyphtool.c(?), stacktool.c(?), util.c(?)
button == BUTTON_CANCEL) //OVERLOAD CALL: BUTTON_CANCEL: glyphtool.c(?), stacktool.c(?), util.c(?)
{
/* do the graph being manipulated */
DrawScatterBrushBox(dimx, dimy,
(old_maxx + old_minx)/2.,
(old_maxy + old_miny)/2.,
(old_maxx - old_minx),
(old_maxy - old_miny));
/* do all other graphs along the horizontal */
for(x=0; x<dims; x++)
{
if(x==dimx)
continue;
DrawScatterBrushBox(x, dimy,
br_pos[x],
(old_maxy + old_miny)/2.,
br_size[x],
(old_maxy - old_miny));
}
/* do all other graphs along the vertical */
for(y=0; y<dims; y++)
{
if(y==dimy)
continue;
DrawScatterBrushBox(dimx, y,
(old_maxx + old_minx)/2.,
br_pos[y],
(old_maxx - old_minx),
br_size[y]);
}
}
/* if this is a cancel, don't do anything else */
if(button == BUTTON_CANCEL) //OVERLOAD CALL: BUTTON_CANCEL: glyphtool.c(?), stacktool.c(?), util.c(?)
return;
/* if this is not a release, draw the new boxes */
if(button == BUTTON_DOWN || button == BUTTON_DRAG) //OVERLOAD CALL: BUTTON_DOWN: glyphtool.c(?), stacktool.c(?), util.c(?); BUTTON_DRAG: glyphtool.c(?), stacktool.c(?), util.c(?)
{
/* do the graph being manipulated */
DrawScatterBrushBox(dimx, dimy,
(new_maxx + new_minx)/2.,
(new_maxy + new_miny)/2.,
(new_maxx - new_minx),
(new_maxy - new_miny));
/* do all other graphs along the horizontal */
for(x=0; x<dims; x++)
{
if(x==dimx)
continue;
DrawScatterBrushBox(x, dimy,
br_pos[x],
(new_maxy + new_miny)/2.,
br_size[x],
(new_maxy - new_miny));
}
/* do all other graphs along the vertical */
for(y=0; y<dims; y++)
{
if(y==dimy)
continue;
DrawScatterBrushBox(dimx, y,
(new_maxx + new_minx)/2.,
br_pos[y],
(new_maxx - new_minx),
br_size[y]);
}
}
/* if this is a release then actually perform the move */
if(button == BUTTON_UP) //OVERLOAD CALL: BUTTON_UP: glyphtool.c(?), stacktool.c(?), util.c(?)
{
if(resize_minx || resize_maxx)
{
br_size[dimx] = new_maxx - new_minx;
br_pos[dimx] = (new_minx + new_maxx) / 2.;
}
if(resize_miny || resize_maxy)
{
br_size[dimy] = new_maxy - new_miny;
br_pos[dimy] = (new_miny + new_maxy) / 2.;
}
do_redraw();
}
old_minx = new_minx;
old_maxx = new_maxx;
old_miny = new_miny;
old_maxy = new_maxy;
}
else if(str != NULL && strcmp(str, "toggly") == 0)
{
int blocksize, blockcnt;
int glyph_no;
double data[MAXDIM];
int i;
/* if brushing is not on or not displayed, forget it */
if(brush->display == FALSE || brush->enable == FALSE)
return;
/* figure out how big each glyph will be by dividing up the */
/* drawing area */
blocksize = (double)(X_SIZE)/(1.0 + sqrt((double)data_size));
blockcnt = .5 + sqrt((double)data_size);
/* currently only button up to recenter brush is implemented */
if(button != BUTTON_UP) //OVERLOAD CALL: BUTTON_UP: glyphtool.c(?), stacktool.c(?), util.c(?)
return;
/* check if in range */
if(mouse_y / blocksize >= blockcnt || mouse_x / blocksize >= blockcnt)
{
XBell(XtDisplay(canvas_w), 0);
return;
}
/* map mouse position to glyph */
glyph_no = (mouse_y) / blocksize;
glyph_no *= blockcnt;
glyph_no += (mouse_x) / blocksize;
/* check if multiple select is on */
if(CheckMultiSelect())
{
/* delete point if already there */
if(!MultiSelectDeletePoint(glyph_no))
{
/* redraw */
RedrawSingleGlyph(canvas_w, glyph_no);
}
else
{
/* add this point */
MultiSelectAddPoint(glyph_no);
/* redraw */
RedrawSingleGlyph(canvas_w, glyph_no);
}
return;
}
get_data(data, glyph_no);
for(i=0; i<dims; i++)
br_pos[i] = data[i];
/* check if any of the brush values went out of range */
for(i=0; i<dims; i++)
{
/* don't resize brush, but just move it so it stays in range */
if(br_pos[i] + br_size[i]/2. > dim_max[i])
br_pos[i] = dim_max[i] - br_size[i]/2.;
if(br_pos[i] - br_size[i]/2. < dim_min[i])
br_pos[i] = dim_min[i] + br_size[i]/2.;
}
/* update the brush tool */
do_redraw();
}
else if(str != NULL && strcmp(str, "toghier") == 0)
{
int size[MAXDIM];
int i;
int x = mouse_x; /* local mouse x/y vars */
int y = mouse_y;
int bin, orig_bin; /* the bin number */
double new_center[MAXDIM]; /* new brush center */
int get_pixel_size(int *size);
/* if brushing is not on or not displayed, forget it */
if(brush->display == FALSE || brush->enable == FALSE)
return;
/* currently only button up to recenter is implemented */
if(button != BUTTON_UP) //OVERLOAD CALL: BUTTON_UP: glyphtool.c(?), stacktool.c(?), util.c(?)
return;
/* determine size of each dimension */
get_pixel_size(size);
/* now find the bin that the user clicked in */
for(mouse_data_x = 0., mouse_data_y = 0., i=0; i<dims; i++)
{
/* if odd, it's in the y direction */
if(i%2)
{
bin = y/size[i];
/* invert y */
orig_bin = bin;
bin = cardinality[i] - 1 - bin;
/* check bounds */
if(bin < 0 || bin >= cardinality[i])
{
XBell(XtDisplay(canvas_w), 0);
return;
}
/* increment data coords based on this */
new_center[i] = bin *
(dim_max[i] - dim_min[i])/(double)cardinality[i];
new_center[i] += dim_min[i];
/* use original bin # for y decrement */
y -= orig_bin*size[i];
}
/* if even, it's in the x direction */
else
{
bin = x/size[i];
/* check bounds */
if(bin < 0 || bin >= cardinality[i])
{
XBell(XtDisplay(canvas_w), 0);
return;
}
/* increment data coords based on this */
new_center[i] = bin *
(dim_max[i] - dim_min[i])/(double)cardinality[i];
new_center[i] += dim_min[i];
x -= bin*size[i];
}
}
/* recenter the brush */
for(i=0; i<dims; i++)
br_pos[i] = new_center[i];
/* check if any of the brush values went out of range */
for(i=0; i<dims; i++)
{
/* don't resize brush, but just move it so it stays in range */
if(br_pos[i] + br_size[i]/2. > dim_max[i])
br_pos[i] = dim_max[i] - br_size[i]/2.;
if(br_pos[i] - br_size[i]/2. < dim_min[i])
br_pos[i] = dim_min[i] + br_size[i]/2.;
}
do_redraw();
}
old_mouse_data_y = mouse_data_y;
}
int map_location_to_axis(int mouse_x)
{
int dimwidth;
dimwidth = X_SIZE/dims;
return(mouse_x / dimwidth);
}
void ResizeCanvas(Widget w, caddr_t client_data,
XawDrawingAreaCallbackStruct *call_data)
{
}
/* put a string out to a widget - I don't remember why it needed an array */
void set_ascii_text(Widget w, char *string)
{
int n = 0;
Arg wargs[10];
XtSetArg(wargs[n],XtNstring,string); n++;
XtSetValues(w,wargs,n);
}
/* Make any input in the names widget go to the passed widget */
/* something Dave Nedde wrote which I don't understand! */
void SetInput(Widget w, char *widget_name, caddr_t call_data)
{
Widget form_w;
if(!(form_w = WcFullNameToWidget(w,widget_name)))
{
fprintf(stderr, "Error finding widget \"%s\"\n", widget_name);
return;
}
XtSetKeyboardFocus(form_w,w);
}
/* retrieve a data vector based on an index */
void get_data(double buf[], int n)
{
int i, j=0;
for(i = 0;i < all_dims;i++)
if(on[i])
buf[j++] = data_buf[(all_dims*n) + i];
}
/* check if the brush currently covers this data point */
int covered(double data[])
{
int i;
for(i = 0;i < dims;i++)
if((data[i] < (br_pos[i] - br_size[i]/2.)) ||
(data[i] > (br_pos[i] + br_size[i]/2.)))
return(0);
return(1);
}
/**********************************************************************
* void PlaceWindow(w, place_type, call_data)
*
* A callback that moves the passed widget to a new location on the screen.
*
* Resource File Usage:
* PlaceWindow(pointer|widget|parent|widget_name,x_offset,y_offset)
* pointer - Place widget at pointer position
* widget - Place widget at widget location
* parent - Place widget at widget parent's location
* widget_name - Place widget at the named widget's location
* x_offset - The signed x pixel distance from specified placement point
* y_offset - The signed y pixel distance from specified placement point
**********************************************************************/
void PlaceWindow(Widget w, char *place_type, caddr_t call_data)
{
Widget widget; /* The widget if placing relative to one */
Position rootx_return; /* The root x,y location to put the widget */
Position rooty_return;
char *in_args; /* A copy of the arguments passed in */
int x_offset; /* The offsets passed in */
int y_offset;
char *type; /* First resource file argument */
/* Parse the 3 arguments into type, x/y_offset */
in_args = XtNewString(place_type);
type = strtok(in_args,",");
x_offset = (int)atol(strtok((char *)NULL,","));
y_offset = (int)atol(strtok((char *)NULL,","));
if (!strcmp(type,"pointer"))
{
/* Place widget offset from the pointer position */
Window root_return, child_return;
unsigned int mask;
int win_x,win_y;
int root_x,root_y;
XQueryPointer(XtDisplay(w),DefaultRootWindow(XtDisplay(w)),
&root_return,&child_return,
&root_x,&root_y,&win_x,&win_y,&mask);
rootx_return = root_x;
rooty_return = root_y;
}
else
if (!strcmp(type,"widget"))
/* Place widget at an offset from calling widget */
XtTranslateCoords(w,(Position)0,(Position)0,
&rootx_return,&rooty_return);
else
if (!strcmp(type,"parent"))
/* Place widget at an offset from calling widget's parent */
XtTranslateCoords(XtParent(w),(Position)0,(Position)0,
&rootx_return,&rooty_return);
else
{
/* Place widget at an offset from the specified widget */
if(!(widget = WcFullNameToWidget(w,type)))
fprintf(stderr, "Error finding widget in PlaceWindow\n");
XtTranslateCoords(widget,(Position)0,(Position)0,
&rootx_return,&rooty_return);
}
n = 0;
XtSetArg(wargs[n],XtNx,rootx_return+x_offset); n++;
XtSetArg(wargs[n],XtNy,rooty_return+y_offset); n++;
XtSetValues(w,wargs,n);
XtFree(in_args);
}
/*
* GetState() - Get the current display state
*/
int GetState(void)
{
Widget canvas_w, choice;
char *str;
canvas_w = WcFullNameToWidget(appShell,"*canvas");
choice = WcFullNameToWidget(appShell,"*togscat");
str = (char *)XawToggleGetCurrent(choice);
if(!str)
return STATE_NONE;
else if(!strcmp(str, "togscat"))
return STATE_SCATTERPLOT;
else if(!strcmp(str, "togpar"))
return STATE_PARCOORD;
else if(!strcmp(str, "toggly"))
return STATE_GLYPH;
else if(!strcmp(str, "toghier"))
return STATE_HIER;
else
return STATE_NONE;
}
/*
* str_dup() - Some machines have strdup() some don't, so I rely on this
* private version instead. Allocates and copies a string.
*
* PARAMETERS
* str The string to copy
*
* RETURNS
* A copy of the string. May be freed with free().
* Returns NULL on failure.
*/
char *str_dup(char *str)
{
char *copy;
if(!(copy = (char *)malloc(strlen(str) + 1)))
{
fprintf(stderr, "Memory allocation error in str_dup()\n");
return(NULL);
}
strcpy(copy, str);
return(copy);
}
C++ to HTML Conversion by ctoohtml