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); }
Back to Source File Index
C++ to HTML Conversion by ctoohtml