file: init.c
/* init.c - initialization 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.
*/
/* initialization functions for XmdvTool. Set up callbacks, colors, and
keys, read data file */
#include "XmdvTool.h"
#include "multi_select.h"
#include "brush.h"
#include "util.h"
#include "color_req.h"
#include "init.h"
#include "brush_oper.h"
#include "bound.h"
#include "fileio.h"
#include "glyphtool.h"
#include "stacktool.h"
#include "stats.h"
extern Widget appShell;
Arg wargs[10];
int n;
/* color variables */
unsigned long color_cells[NUM_COLOR_CELLS];
XColor text_col, data_col, highlight_col, overlap_col;
XColor paint_col, grid1_col, grid2_col, grid3_col;
XColor stat1_col, stat2_col;
extern XColor brush_colors[NUM_BRUSH_CELLS];
/* is this a color display? */
extern int COLOR;
/* data and its attributes (dimensions, size, min, and max) */
int dims, data_size;
double dim_min[MAXDIM], dim_max[MAXDIM], *data_buf=NULL;
/* discretization for each dimension - needed for dimensional stacking */
int cardinality[MAXDIM];
/* structures to hold the original data (as opposed to selected dimensions) */
double all_dim_min[MAXDIM], all_dim_max[MAXDIM];
int all_dims;
int all_cardinality[MAXDIM];
char all_names[MAXDIM][MAXLABEL];
char on[MAXDIM]; /* which dimensions should be shown */
/* the operations */
Operation operations[MAXOPER];
/* strings used for dimension selection and keys */
char names[MAXDIM][MAXLABEL], keys[MAXDIM][MAXLABEL+30],
keys2[MAXDIM+2][MAXLABEL+30];
String mylist[MAXDIM], keylist[MAXDIM], key2list[MAXDIM+2];
char mystring[MAXDIM][MAXLABEL];
/* help topics */
int num_topics = 28;
String helplist[30];
char *topics[] = {"Introduction", "Scatterplots", "Glyphs",
"Parallel Coordinates", "Dimensional Stacking", "File Menu", "Data Menu",
"Display Menu", " Zooming In and Out", " Color Requesting",
" Intro to Brushing", " Direct Brush Manipulation",
" Indirect Brush Manipulation", " Painting", " The Brush Toolbox",
" Global Brush Resizing", " Brush Selection",
" Ramped vs. Step Brush Boundaries", " Brush Operations",
" Brush Operations Toolbox", " Displaying Data Values",
" Key to Interpreting Dimensional Stacking", " Key to Interpreting Glyphs",
" Statistics Display", "Help Menu", "Drawing Area Widget", "Input File Format",
"Hints on Using XmdvTool"};
/* files associated with each topic */
char *help_file[] = { "intro.doc", "scatterplots.doc", "glyphs.doc",
"parcoord.doc", "dimstack.doc", "file.doc", "data.doc", "display.doc",
"zoom.doc", "color_request.doc", "brush.doc", "direct_manip.doc",
"indirect_manip.doc", "painting.doc", "brush_toolbox.doc",
"global_resize.doc", "brush_select.doc", "ramped_brush.doc",
"brush_ops.doc", "op_toolbox.doc", "data_values.doc", "dimstack_key.doc",
"glyph_key.doc", "statistics.doc", "help.doc", "DrawingA.doc",
"Xmdv_format.doc", "hints.doc"};
/* Register all Athena and Public widget classes */
void init_CB(XtAppContext app)
{
XpRegisterAll ( app );
/* DrawingArea widget courtesy of David Nedde */
WcRegisterClassName( app, "DrawingArea", drawingAreaWidgetClass);
WcRegisterClassPtr( app, "drawingAreaWidgetClass", drawingAreaWidgetClass);
/*
* scrollable list courtesy of Richard Hesketh / rlh2@ukc.ac.uk
* Computing Lab. University of Kent at Canterbury, UK
*/
WcRegisterClassName( app, "ukcScrListWidget", ukcScrListWidgetClass);
WcRegisterClassPtr( app, "ukcScrListWidgetClass", ukcScrListWidgetClass);
WcRegisterCallback(app, "NewHelpList", NewHelpList, (caddr_t)0);
WcRegisterCallback(app, "NewDimList", NewDimList, (caddr_t)0);
WcRegisterCallback(app, "NewKeyList", NewKeyList, (caddr_t)0);
WcRegisterCallback(app, "NewKey2List", NewKey2List, (caddr_t)0);
WcRegisterCallback(app, "SetInput", SetInput, (caddr_t)0);
WcRegisterCallback(app, "EnableBrushCB", EnableBrushCB, (caddr_t)0);
WcRegisterCallback(app, "DisplayBrushCB", DisplayBrushCB, (caddr_t)0);
WcRegisterCallback(app, "BoundaryStepCB", BoundaryStepCB, (caddr_t)0);
WcRegisterCallback(app, "BoundaryRampCB", BoundaryRampCB, (caddr_t)0);
WcRegisterCallback(app, "PlaceWindow", PlaceWindow, (caddr_t)0);
WcRegisterCallback(app, "RedrawCanvas", RedrawCanvas, (caddr_t)0);
WcRegisterCallback(app, "ERedrawCanvas", ERedrawCanvas, (caddr_t)0);
WcRegisterCallback(app, "MotionCanvas", MotionCanvas, (caddr_t)0);
WcRegisterCallback(app, "InputCanvas", InputCanvas, (caddr_t)0);
WcRegisterCallback(app, "ResizeCanvas", ResizeCanvas, (caddr_t)0);
WcRegisterCallback(app, "LoadFile", LoadFile, (caddr_t)0);
WcRegisterCallback(app, "GlyphBToolRedrawCanvas",
GlyphBToolRedrawCanvas, (caddr_t)0);
WcRegisterCallback(app, "GlyphBToolMotionCanvas",
GlyphBToolMotionCanvas, (caddr_t)0);
WcRegisterCallback(app, "GlyphBToolInputCanvas",
GlyphBToolInputCanvas, (caddr_t)0);
WcRegisterCallback(app, "GlyphBToolApply", GlyphBToolApply, (caddr_t)0);
WcRegisterCallback(app, "GlyphBToolInit", GlyphBToolInit, (caddr_t)0);
WcRegisterCallback(app, "GlyphBToolPopDown", GlyphBToolPopDown, (caddr_t)0);
WcRegisterCallback(app, "StackBToolRedrawCanvas",
StackBToolRedrawCanvas, (caddr_t)0);
WcRegisterCallback(app, "StackBToolMotionCanvas",
StackBToolMotionCanvas, (caddr_t)0);
WcRegisterCallback(app, "StackBToolInputCanvas",
StackBToolInputCanvas, (caddr_t)0);
WcRegisterCallback(app, "StackBToolApply", StackBToolApply, (caddr_t)0);
WcRegisterCallback(app, "StackBToolInit", StackBToolInit, (caddr_t)0);
WcRegisterCallback(app, "StackBToolPopDown", StackBToolPopDown, (caddr_t)0);
WcRegisterCallback(app, "StatsRedrawCanvas",
StatsRedrawCanvas, (caddr_t)0);
WcRegisterCallback(app, "StatsInit", StatsInit, (caddr_t)0);
WcRegisterCallback(app, "StatsPopDown", StatsPopDown, (caddr_t)0);
WcRegisterCallback(app, "ChangeBrushCB", ChangeBrushCB, (caddr_t)0);
WcRegisterCallback(app, "ResizeBrushCB", ResizeBrushCB, (caddr_t)0);
WcRegisterCallback(app, "ResizeCanvasCB", ResizeCanvasCB, (caddr_t)0);
/* color requester callbacks */
WcRegisterCallback(app, "ColorReqInitCB", ColorReqInitCB, (caddr_t)0);
WcRegisterCallback(app, "ColorReqMenuInitCB",
ColorReqMenuInitCB, (caddr_t)0);
WcRegisterCallback(app, "ColorReqResetCB", ColorReqResetCB, (caddr_t)0);
WcRegisterCallback(app, "ColorReqRedrawCanvasCB",
ColorReqRedrawCanvasCB, (caddr_t)0);
WcRegisterCallback(app, "ColorReqJumpCB", ColorReqJumpCB, (caddr_t)0);
WcRegisterCallback(app, "ColorReqScrollCB", ColorReqScrollCB, (caddr_t)0);
WcRegisterCallback(app, "ColorReqColorSpaceCB",
ColorReqColorSpaceCB, (caddr_t)0);
WcRegisterCallback(app, "ColorReqChooseColorCB",
ColorReqChooseColorCB, (caddr_t)0);
WcRegisterCallback(app, "ColorReqInvalidateColorCB",
ColorReqInvalidateColorCB, (caddr_t)0);
/* brush operation callbacks */
WcRegisterCallback(app, "BrushOperListInitCB",
BrushOperListInitCB, (caddr_t)0);
WcRegisterCallback(app, "BrushOperNewCB", BrushOperNewCB, (caddr_t)0);
WcRegisterCallback(app, "BrushOperDeleteCB", BrushOperDeleteCB, (caddr_t)0);
WcRegisterCallback(app, "BrushOperEditCB", BrushOperEditCB, (caddr_t)0);
WcRegisterCallback(app, "BrushOperResetCB", BrushOperResetCB, (caddr_t)0);
WcRegisterCallback(app, "BrushOperOkCB", BrushOperOkCB, (caddr_t)0);
WcRegisterCallback(app, "BrushOperCancelCB", BrushOperCancelCB, (caddr_t)0);
WcRegisterCallback(app, "BrushOperHighCB", BrushOperHighCB, (caddr_t)0);
WcRegisterCallback(app, "BrushOperLowCB", BrushOperLowCB, (caddr_t)0);
/* register actions */
WcRegisterAction(app, "MultiSelect", MultiSelectACT);
WcRegisterAction(app, "BrushBoundaryACT", BrushBoundaryACT);
}
/* set up colors for text, data display, and brush */
/*
* InitColors() - Initialize the colors to be used in XmdvTool.
* A global array of color cells is allocated
* read/write. Each XColor structure gets it's
* pixel value from the global array. The colors
* may be manipulated with the color requester later.
*
* PARAMETERS
* canvas_w The canvas widget
*
* RETURNS
* void
*/
void InitColors(Widget canvas_w)
{
Colormap cmap; /* the colormap */
int i;
/* get the colormap */
cmap = DefaultColormap(XtDisplay(canvas_w),
DefaultScreen(XtDisplay(canvas_w)));
/* allocate the color cells */
if(!XAllocColorCells(XtDisplay(canvas_w), cmap, True,
NULL, 0, color_cells, NUM_COLOR_CELLS))
{
fprintf(stderr,
"Couldn't allocate colors... going to monochrome mode\n");
COLOR = 0;
return;
}
/* the text color */
text_col.pixel = color_cells[CCELL_TEXT];
text_col.flags = DoRed|DoGreen|DoBlue;
text_col.red = 0; text_col.green = 0; text_col.blue = 0;
XStoreColor(XtDisplay(canvas_w), cmap, &text_col);
/* data color */
data_col.pixel = color_cells[CCELL_DATA];
data_col.flags = DoRed|DoGreen|DoBlue;
data_col.red = 39000; data_col.green = 62000; data_col.blue = 39000;
XStoreColor(XtDisplay(canvas_w), cmap, &data_col);
/* highlight color */
highlight_col.pixel = color_cells[CCELL_HIGHLIGHT];
highlight_col.flags = DoRed|DoGreen|DoBlue;
highlight_col.red = 62000; highlight_col.green = 0; highlight_col.blue = 0;
XStoreColor(XtDisplay(canvas_w), cmap, &highlight_col);
/* paint color */
paint_col.pixel = color_cells[CCELL_PAINT];
paint_col.flags = DoRed|DoGreen|DoBlue;
paint_col.red = 39000; paint_col.green = 0; paint_col.blue = 39000;
XStoreColor(XtDisplay(canvas_w), cmap, &paint_col);
/* lines used for grids on dimensional stacking */
/* grid 1 */
grid1_col.pixel = color_cells[CCELL_GRID1];
grid1_col.flags = DoRed|DoGreen|DoBlue;
grid1_col.red = 4000; grid1_col.green = 4000; grid1_col.blue = 4000;
XStoreColor(XtDisplay(canvas_w), cmap, &grid1_col);
/* grid 2 */
grid2_col.pixel = color_cells[CCELL_GRID2];
grid2_col.flags = DoRed|DoGreen|DoBlue;
grid2_col.red = 45000; grid2_col.green = 45000; grid2_col.blue = 45000;
XStoreColor(XtDisplay(canvas_w), cmap, &grid2_col);
/* grid 3 */
grid3_col.pixel = color_cells[CCELL_GRID3];
grid3_col.flags = DoRed|DoGreen|DoBlue;
grid3_col.red = 60000; grid3_col.green = 60000; grid3_col.blue = 60000;
XStoreColor(XtDisplay(canvas_w), cmap, &grid3_col);
/* stat 1 */
stat1_col.pixel = color_cells[CCELL_STAT1];
stat1_col.flags = DoRed|DoGreen|DoBlue;
stat1_col.red = 60000; stat1_col.green = 0; stat1_col.blue = 0;
XStoreColor(XtDisplay(canvas_w), cmap, &stat1_col);
/* stat 2 */
stat2_col.pixel = color_cells[CCELL_STAT2];
stat2_col.flags = DoRed|DoGreen|DoBlue;
stat2_col.red = 0; stat2_col.green = 0; stat2_col.blue = 50000;
XStoreColor(XtDisplay(canvas_w), cmap, &stat2_col);
/* brush backgrounds */
for(i=0; i<MAXBRUSH; i++)
{
brush_colors[i].pixel = color_cells[i];
brush_colors[i].flags = DoRed|DoGreen|DoBlue;
brush_colors[i].red = 45000;
brush_colors[i].green = 45000;
brush_colors[i].blue = (MAXBRUSH-i)/(double)MAXBRUSH*60000;
/* store it */
XStoreColor(XtDisplay(canvas_w), cmap, &brush_colors[i]);
}
/* update the operations list */
BrushOperUpdateList();
}
/* set up the list of help topics */
void init_HelpList(void)
{
int i;
Widget p_list;
/* not sure why I had to copy it.... */
for(i = 0;i < num_topics;i++)
helplist[i] = topics[i];
helplist[num_topics] = NULL; /* null marks end of list */
p_list = WcFullNameToWidget(appShell,"*help_list");
if(p_list == NULL)
printf("couldn't get help list widget\n");
else
XawListChange(p_list, helplist, 0, 0, True);
}
/* set up the list of dimension selection list */
void init_DimList(void)
{
int i;
Widget p_list;
/* not sure why I had to copy it.... */
for(i = 0;i < all_dims;i++) {
if(on[i])
sprintf(mystring[i], "on %s", all_names[i]);
else
sprintf(mystring[i], "off %s", all_names[i]);
mylist[i] = mystring[i];
}
mylist[all_dims] = NULL; /* null marks end of list */
p_list = WcFullNameToWidget(appShell,"*dim_list");
if(p_list == NULL)
printf("couldn't get dimension list widget\n");
else
XawListChange(p_list, mylist, all_dims, 0, True);
}
/* key to interpreting glyph components - each dimension controls the
length of a ray in a given direction */
void init_glyphkey(void)
{
int i;
Widget p_list;
/* compute text strings and place pointers into keylist */
for(i = 0;i < dims;i++)
sprintf(keys[i], "%s: %d degrees",names[i],((i) * 360)/dims);
for(i = 0;i < dims;i++)
keylist[i] = keys[i];
keylist[dims] = NULL;
p_list = WcFullNameToWidget(appShell,"*keylist");
if(p_list == NULL)
printf("couldn't get glyph key widget\n");
else
XawListChange(p_list, keylist, 0, 0, True);
}
/* key to interpreting dimensional stacking - each dimension has an orientation
(horizontal/vertical) and a level of nesting (speed) */
void init_hierkey(void)
{
int i, j;
Widget p_list;
/* do horizontal dimensions, then vertical, slow speed to high */
sprintf(keys2[0], "Horizontal Dimensions: outer to inner");
j = 1;
for(i = 0;i < dims;i= i+2)
sprintf(keys2[j++], " %s: cardinality %d",names[i], cardinality[i]);
sprintf(keys2[j++], "Vertical Dimensions: outer to inner");
for(i = 1;i < dims;i= i+2)
sprintf(keys2[j++], " %s: cardinality %d",names[i], cardinality[i]);
for(i = 0;i < dims + 2;i++)
key2list[i] = keys2[i];
key2list[dims+2] = NULL;
p_list = WcFullNameToWidget(appShell,"*key2list");
if(p_list == NULL)
printf("couldn't get dimensional stacking key widget\n");
else
XawListChange(p_list, key2list, 0, 0, True);
}
/* read in data file: Format is:
number_of_dimensions number_of_samples (int int)
dimension_name for each dimension (string)
minimum maximum cardinality for each dimension (double double int)
data_samples (doubles) */
void get_head(char *filename)
{
int i, j, ok;
double *f_ptr, dim_diff;
FILE *fp;
Widget label_w; /* filename label widget */
fp = fopen(filename, "r");
if(fp == NULL)
{
printf("data file %s doesn't exist\n", filename);
exit(-1);
}
/* get dimensional info */
if(fscanf(fp, "%d %d\n", &all_dims, &data_size) <= 0) {
printf("error reading first line of file %s!\n", filename);
printf(" Try loading another file!\n");
all_dims = 0;
data_size = 0;
}
if(all_dims >= MAXDIM) {
printf("data has too many dimensions (%d) - limit is %d\n", all_dims,
MAXDIM);
printf(" Try loading another file!\n");
all_dims = 0;
data_size = 0;
}
if(data_size < 0) {
printf("Number of data items is negative (%d)!\n", data_size);
printf(" Try loading another file!\n");
all_dims = 0;
data_size = 0;
}
dims = all_dims;
for(i = 0;i < dims;i++)
{
if(fgets(names[i], MAXLABEL-1, fp) == NULL) {
printf("failed in reading dimension names.\n");
exit(-1);
}
names[i][strlen(names[i])-1] = '\0';
strcpy(all_names[i], names[i]);
}
for(i = 0;i < dims;i++) {
if(fscanf(fp, "%lf %lf %d", &dim_min[i], &dim_max[i], &cardinality[i]) !=3) {
printf("failed in reading dimension ranges.\n");
exit(-1);
}
/* need to handle case when min = max (separate them a bit) */
if(dim_min[i] == dim_max[i])
if(dim_min[i] == 0.0) {
dim_min[i] = -1.0;
dim_max[i] = 1.0;
}
else {
if(dim_min[i] < 0.0) {
dim_min[i] = 2. * dim_min[i];
dim_max[i] = 0.0;
}
else {
dim_max[i] = 2. * dim_min[i];
dim_min[i] = 0.0;
}
}
/* add a bit of space to the bounds to avoid boundary problems */
else {
dim_diff = (dim_max[i] - dim_min[i]) * SPACE;
dim_max[i] += dim_diff;
dim_min[i] -= dim_diff;
}
all_dim_min[i] = dim_min[i];
all_dim_max[i] = dim_max[i];
all_cardinality[i] = cardinality[i];
on[i] = 1;
}
/* free the buffer if it already exists */
if(data_buf)
free(data_buf);
/* allocate space and read data in */
if(data_size > 0) {
data_buf = (double *)malloc(dims*data_size*sizeof(double));
if(data_buf == NULL) {
printf("malloc failed in get_head\n");
exit(-1);
}
f_ptr = data_buf;
for(i = 0;i < data_size;i++)
for(j = 0;j < dims;j++)
if(fscanf(fp, "%lf", f_ptr++) != 1) {
printf("failed in reading data, line %d, item %d.\n", i, j);
}
}
fclose(fp);
/* update the filename label */
if(!(label_w = (Widget)WcFullNameToWidget(appShell, "*file_name")))
{
fprintf(stderr, "Error finding *file_name\n");
exit(-1);
}
/* set the label to be the filename */
n = 0;
XtSetArg(wargs[n], XtNlabel, filename); n++;
XtSetValues(label_w,wargs,n);
}
C++ to HTML Conversion by ctoohtml