file: glyphtool.c

/* util.c - routines for glyph brush tool 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. */ #include <X11/Xatom.h> #include "XmdvTool.h" #include "glyph.h" #include "glyphtool.h" #include "brush.h" extern Widget appShell; extern int dims; extern char names[MAXDIM][MAXLABEL]; extern double *br_pos, *br_size; extern double dim_min[MAXDIM], dim_max[MAXDIM]; extern unsigned long color_cells[NUM_COLOR_CELLS]; extern XColor outline_col; extern GC gc; /* is this a color display? */ extern int COLOR; extern int X_SIZE, Y_SIZE; Arg wargs[10]; int n; /* glyph brush tool brush variables */ int gbt_open = FALSE; double gbt_br_pos[MAXDIM], gbt_br_size[MAXDIM]; Dimension gbt_x, gbt_y; /* Glyph Brush Tool X/Y dims */ /* button defines */ #define BUTTON_DOWN 1 #define BUTTON_DRAG 2 #define BUTTON_UP 3 #define BUTTON_CANCEL 4 void GlyphBToolRedrawCanvas(Widget w, caddr_t client_data, XawDrawingAreaCallbackStruct *call_data) { GlyphBToolDoRedraw(); } /* * GlyphBToolDoRedraw() - Redraw the entire glyph brush tool */ void GlyphBToolDoRedraw(void) { Widget gbt_canvas_w; /* the glyph brush tool canvas */ int i; int n; Arg wargs[10]; /* widget args */ int center_x, center_y; /* canvas center */ int rad; /* axis radius */ int center_offset; /* radial offset from center */ double angle; /* radial axis angle */ int x,y,x2,y2; XPoint xpts[MAXDIM*2+2]; /* polyline brush points */ XFontStruct *font; /* the font to draw text with */ unsigned long font_height; /* the height of the font */ int dummy; /* dummy var passed to XTextExtents() */ XCharStruct overall; /* for finding extents */ int label_len; /* the length of a label */ gbt_canvas_w = WcFullNameToWidget(appShell,"*glyph_btool_canvas"); if(!gbt_canvas_w) { fprintf(stderr, "Error finding *glyph_btool_canvas\n"); return; } /* if brush tool is not open, do nothing */ if(!gbt_open) return; /* get the new x/y dimensions of the brush tool */ n = 0; XtSetArg(wargs[n],XtNwidth,&gbt_x); n++; XtSetArg(wargs[n],XtNheight,&gbt_y); n++; XtGetValues(gbt_canvas_w,wargs,n); center_x = gbt_x/2; center_y = gbt_y/2; /* make radius the smallest half width and scale */ rad = MIN(center_x, center_y); rad *= .65; /* make the center offset 10% of the width */ center_offset = MIN(center_x, center_y); center_offset *= .20; /* clear the canvas */ XClearWindow(XtDisplay(gbt_canvas_w), XtWindow(gbt_canvas_w)); /* draw the brush */ /* add the outside edge points */ for(n=0, i=0, angle=0.; i<dims; i++, angle+=(2.*M_PI)/(double)dims) { xpts[n].x = center_x + center_offset * cos(angle); xpts[n].x += rad * cos(angle) * (gbt_br_pos[i]+gbt_br_size[i]/2.-dim_min[i])/(dim_max[i] - dim_min[i]); xpts[n].y = center_y - center_offset * sin(angle); xpts[n].y -= rad * sin(angle) * (gbt_br_pos[i]+gbt_br_size[i]/2.-dim_min[i])/(dim_max[i] - dim_min[i]); n++; } /* add the first point again */ xpts[n].x = xpts[0].x; xpts[n].y = xpts[0].y; n++; /* add the inside edge points */ for(i=0, angle=0.; i<dims; i++, angle+=(2.*M_PI)/(double)dims) { xpts[n].x = center_x + center_offset * cos(angle); xpts[n].x += rad * cos(angle) * (gbt_br_pos[i]-gbt_br_size[i]/2.-dim_min[i])/(dim_max[i] - dim_min[i]); xpts[n].y = center_y - center_offset * sin(angle); xpts[n].y -= rad * sin(angle) * (gbt_br_pos[i]-gbt_br_size[i]/2.-dim_min[i])/(dim_max[i] - dim_min[i]); n++; } /* add the first inside point again */ xpts[n].x = xpts[dims+1].x; xpts[n].y = xpts[dims+1].y; n++; /* set the brush color */ if(COLOR==1) XSetForeground(XtDisplay(gbt_canvas_w), gc, outline_col.pixel); /* draw the brush */ XFillPolygon(XtDisplay(gbt_canvas_w), XtWindow(gbt_canvas_w), gc, xpts, n, Complex, CoordModeOrigin); /* draw the axes */ /* set the foreground color for drawing axis */ XSetForeground(XtDisplay(gbt_canvas_w), gc, color_cells[CCELL_TEXT]); /* draw the axes radially from the center */ for(i=0, angle=0.; i<dims; i++, angle+=(2.*M_PI)/(double)dims) { x = center_x + center_offset * cos(angle); y = center_y - center_offset * sin(angle); xpts[i].x = x; xpts[i].y = y; x2 = center_x + (rad + center_offset) * cos(angle); y2 = center_y - (rad + center_offset) * sin(angle); XDrawLine(XtDisplay(gbt_canvas_w), XtWindow(gbt_canvas_w), gc, x, y, x2, y2); } /* connect the inner points of the axes */ xpts[i].x = xpts[0].x; xpts[i].y = xpts[0].y; i++; XDrawLines(XtDisplay(gbt_canvas_w), XtWindow(gbt_canvas_w), gc, xpts, i, CoordModeOrigin); #define GBT_TEXT_SPACING 4 /* space between axis and text */ #define GBT_TEXT_MAX_LETTERS 3 /* maximum letters in label */ /* draw the labels */ XSetForeground(XtDisplay(gbt_canvas_w),gc, color_cells[CCELL_TEXT]); /* get the font */ font = XQueryFont(XtDisplay(gbt_canvas_w), XGContextFromGC(gc)); for(i=0, angle=0.; i<dims; i++, angle+=(2.*M_PI)/(double)dims) { /* determine the string length */ label_len = MIN(GBT_TEXT_MAX_LETTERS, strlen(names[i])); /* find the extents of the string */ XTextExtents(font, names[i], label_len, &dummy, &dummy, &dummy, &overall); font_height = overall.ascent + overall.descent; x = center_x + (rad + center_offset) * cos(angle); y = center_y - (rad + center_offset) * sin(angle); /* tweak values to center string */ x += (font_height/3.) * sin(angle+M_PI/2.); y += (font_height/2.) + (font_height/2.) * sin(angle+M_PI); /* if on the left side, move the text over so it ends at the axis */ if(angle > M_PI/2. && angle < 3.*M_PI/2.) x -= overall.width; XDrawString(XtDisplay(gbt_canvas_w), XtWindow(gbt_canvas_w), gc, x, y, names[i], label_len); } } /* glyph brush tool button flags */ int gbt_button_one_down = FALSE; int gbt_button_two_down = FALSE; int gbt_button_three_down = FALSE; void GlyphBToolMotionCanvas(Widget w, caddr_t client_data, XawDrawingAreaCallbackStruct *call_data) { if(gbt_button_one_down) { GlyphBToolInteractiveResize(call_data->event->xmotion.x, call_data->event->xmotion.y, BUTTON_DRAG); //OVERLOAD CALL: BUTTON_DRAG: glyphtool.c(?), stacktool.c(?), util.c(?) } else if(gbt_button_two_down) { GlyphBToolInteractiveMove(call_data->event->xmotion.x, call_data->event->xmotion.y, BUTTON_DRAG); //OVERLOAD CALL: BUTTON_DRAG: glyphtool.c(?), stacktool.c(?), util.c(?) } else if(gbt_button_three_down) { } } void GlyphBToolInputCanvas(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(gbt_button_two_down) { XBell(XtDisplay(w), 0); gbt_button_one_down = gbt_button_two_down = gbt_button_three_down = FALSE; GlyphBToolInteractiveMove(x, y, BUTTON_CANCEL); //OVERLOAD CALL: BUTTON_CANCEL: glyphtool.c(?), stacktool.c(?), util.c(?) break; } else if(gbt_button_three_down) { XBell(XtDisplay(w), 0); gbt_button_one_down = gbt_button_two_down = gbt_button_three_down = FALSE; break; } gbt_button_one_down = TRUE; GlyphBToolInteractiveResize(x, y, BUTTON_DOWN); //OVERLOAD CALL: BUTTON_DOWN: glyphtool.c(?), stacktool.c(?), util.c(?) break; case 2: /* the move button */ if(gbt_button_one_down) { XBell(XtDisplay(w), 0); gbt_button_one_down = gbt_button_two_down = gbt_button_three_down = FALSE; GlyphBToolInteractiveResize(x, y, BUTTON_CANCEL); //OVERLOAD CALL: BUTTON_CANCEL: glyphtool.c(?), stacktool.c(?), util.c(?) break; } else if(gbt_button_three_down) { XBell(XtDisplay(w), 0); gbt_button_one_down = gbt_button_two_down = gbt_button_three_down = FALSE; break; } gbt_button_two_down = TRUE; GlyphBToolInteractiveMove(x, y, BUTTON_DOWN); //OVERLOAD CALL: BUTTON_DOWN: glyphtool.c(?), stacktool.c(?), util.c(?) break; case 3: if(gbt_button_one_down) { XBell(XtDisplay(w), 0); gbt_button_one_down = gbt_button_two_down = gbt_button_three_down = FALSE; GlyphBToolInteractiveResize(x, y, BUTTON_CANCEL); //OVERLOAD CALL: BUTTON_CANCEL: glyphtool.c(?), stacktool.c(?), util.c(?) break; } else if(gbt_button_two_down) { XBell(XtDisplay(w), 0); gbt_button_one_down = gbt_button_two_down = gbt_button_three_down = FALSE; GlyphBToolInteractiveMove(x, y, BUTTON_CANCEL); //OVERLOAD CALL: BUTTON_CANCEL: glyphtool.c(?), stacktool.c(?), util.c(?) break; } gbt_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(!gbt_button_one_down) break; GlyphBToolInteractiveResize(x, y, BUTTON_UP); //OVERLOAD CALL: BUTTON_UP: glyphtool.c(?), stacktool.c(?), util.c(?) gbt_button_one_down = FALSE; break; case 2: if(!gbt_button_two_down) break; GlyphBToolInteractiveMove(x, y, BUTTON_UP); //OVERLOAD CALL: BUTTON_UP: glyphtool.c(?), stacktool.c(?), util.c(?) gbt_button_two_down = FALSE; break; case 3: if(!gbt_button_three_down) break; gbt_button_three_down = FALSE; break; } break; } } void GlyphBToolApply(Widget w, caddr_t client_data, caddr_t call_data) { int i; /* copy the glyph btool brush to the real brush */ for(i=0; i<dims; i++) { br_pos[i] = gbt_br_pos[i]; br_size[i] = gbt_br_size[i]; } do_redraw(); } void GlyphBToolInit(Widget w, caddr_t client_data, caddr_t call_data) { int i; /* set the global tool open flag */ gbt_open = TRUE; /* copy the real brush to the glyph btool brush */ for(i=0; i<dims; i++) { gbt_br_pos[i] = br_pos[i]; gbt_br_size[i] = br_size[i]; } } /* * GlyphBToolPopDown() - Callback when brush tool is popped down. */ void GlyphBToolPopDown(Widget w, caddr_t client_data, caddr_t call_data) { /* reset global tool open flag */ gbt_open = FALSE; } /* * GlyphBToolUpdate() - Update the glyph brush tool so that it matches * the real brush. */ void GlyphBToolUpdate(void) { int i; /* if brush tool is not open, do nothing */ if(!gbt_open) return; for(i = 0;i < dims;i++) { gbt_br_pos[i] = br_pos[i]; gbt_br_size[i] = br_size[i]; } /* GlyphBToolInit(NULL, NULL, NULL); */ GlyphBToolDoRedraw(); } void GlyphBToolInteractiveMove(int mouse_x, int mouse_y, int button) { Widget gbt_canvas_w; /* the glyph brush tool canvas widget */ static int axis; /* axis for resize */ int center_x, center_y, rad; /* brushtool center and axis radius */ int center_offset; /* radial offset from center */ double mouse_angle, angle; /* angle of button press */ double dist; /* distance from center */ double new_pos; /* new brush position */ gbt_canvas_w = WcFullNameToWidget(appShell,"*glyph_btool_canvas"); if(!gbt_canvas_w) { fprintf(stderr, "Error finding *glyph_btool_canvas\n"); return; } /* find the canvas center */ center_x = gbt_x/2; center_y = gbt_y/2; /* make radius the smallest half width and scale */ rad = MIN(center_x, center_y); rad *= .65; /* make the center offset 10% of the width */ center_offset = MIN(center_x, center_y); center_offset *= .20; /* check if user clicked in center (no man's land) */ if((mouse_x - center_x)*(mouse_x - center_x) + (mouse_y - center_y)*(mouse_y - center_y) < (center_offset*.8) * (center_offset*.8)) { if(button == BUTTON_DOWN) //OVERLOAD CALL: BUTTON_DOWN: glyphtool.c(?), stacktool.c(?), util.c(?) XBell(XtDisplay(gbt_canvas_w), 0); return; } /* find the angle of the line from the center to the mouse */ /* position */ mouse_angle = atan2((double)(center_y-mouse_y), (double)(mouse_x - center_x)); /* if this is a button down, determine axis */ if(button == BUTTON_DOWN) //OVERLOAD CALL: BUTTON_DOWN: glyphtool.c(?), stacktool.c(?), util.c(?) { /* add a half wedge to the angle */ angle = mouse_angle + ((2.*M_PI)/(double)dims)/2.; /* wrap angle around if it is negative */ if(angle < 0.) angle += 2.*M_PI; /* map angle to an axis */ axis = dims*(angle/(2.*M_PI)); /* sanity check */ if(axis < 0 || axis >= dims) { XBell(XtDisplay(gbt_canvas_w), 0); return; } /* store old brush position for later retrieval on cancel */ } else { /* sanity check */ if(axis < 0 || axis >= dims) return; } /* map mouse location to data coordinates */ /* calculate distance from center */ dist = sqrt((double)((center_x-mouse_x)*(center_x-mouse_x) + (center_y-mouse_y)*(center_y-mouse_y))); /* normalize */ dist -= center_offset; dist /= rad; /* find angle of axis */ angle = axis * (2.*M_PI/(double)dims); /* calculate new position and bound it */ dist *= cos(mouse_angle - angle); new_pos = dim_min[axis]+dist*(dim_max[axis]-dim_min[axis]); new_pos = MIN(new_pos, dim_max[axis]-gbt_br_size[axis]/2.); new_pos = MAX(new_pos, dim_min[axis]+gbt_br_size[axis]/2.); /* move brush to new location */ gbt_br_pos[axis] = new_pos; /* redraw brush tool */ GlyphBToolDoRedraw(); /* if this is a cancel, retrieve the old brush */ } /* * GlyphBToolInteractiveResize() - Interactively resize the brush * using the glyph brush tool */ void GlyphBToolInteractiveResize(int mouse_x, int mouse_y, int button) { Widget gbt_canvas_w; /* the glyph brush tool canvas widget */ static int axis; /* axis for resize */ int center_x, center_y, rad; /* brushtool center and axis radius */ int center_offset; /* radial offset from center */ double mouse_angle, angle; /* angle of button press */ double dist; /* distance from center */ double new_min, new_max; /* new brush min/max */ double mouse_data; /* mouse in data coords */ static int resize_min, /* resize min/max flags */ resize_max; gbt_canvas_w = WcFullNameToWidget(appShell,"*glyph_btool_canvas"); if(!gbt_canvas_w) { fprintf(stderr, "Error finding *glyph_btool_canvas\n"); return; } /* find the canvas center */ center_x = gbt_x/2; center_y = gbt_y/2; /* make radius the smallest half width and scale */ rad = MIN(center_x, center_y); rad *= .65; /* make the center offset 10% of the width */ center_offset = MIN(center_x, center_y); center_offset *= .20; /* check if user clicked in center (no man's land) */ if((mouse_x - center_x)*(mouse_x - center_x) + (mouse_y - center_y)*(mouse_y - center_y) < (center_offset*.8) * (center_offset*.8)) { if(button == BUTTON_DOWN) //OVERLOAD CALL: BUTTON_DOWN: glyphtool.c(?), stacktool.c(?), util.c(?) XBell(XtDisplay(gbt_canvas_w), 0); return; } /* find the angle of the line from the center to the mouse */ /* position */ mouse_angle = atan2((double)(center_y-mouse_y), (double)(mouse_x - center_x)); /* if this is a button down, determine axis */ if(button == BUTTON_DOWN) //OVERLOAD CALL: BUTTON_DOWN: glyphtool.c(?), stacktool.c(?), util.c(?) { /* add a half wedge to the angle */ angle = mouse_angle + ((2.*M_PI)/(double)dims)/2.; /* wrap angle around if it is negative */ if(angle < 0.) angle += 2.*M_PI; /* map angle to an axis */ axis = dims*(angle/(2.*M_PI)); /* sanity check */ if(axis < 0 || axis >= dims) { XBell(XtDisplay(gbt_canvas_w), 0); return; } /* map mouse location to data coordinates */ /* calculate distance from center */ dist = sqrt((double)((center_x-mouse_x)*(center_x-mouse_x) + (center_y-mouse_y)*(center_y-mouse_y))); /* normalize */ dist -= center_offset; dist /= rad; /* find angle of axis */ angle = axis * (2.*M_PI/(double)dims); /* calculate mouse position in data coords and bound it */ dist *= cos(mouse_angle - angle); mouse_data = dim_min[axis]+dist*(dim_max[axis]-dim_min[axis]); mouse_data = MIN(mouse_data, dim_max[axis]); mouse_data = MAX(mouse_data, dim_min[axis]); /* now determine if min or max is being resized */ resize_min = resize_max = FALSE; if(mouse_data < gbt_br_pos[axis]) resize_min = TRUE; else resize_max = TRUE; } else { /* sanity check */ if(axis < 0 || axis >= dims) return; /* map mouse location to data coordinates */ /* calculate distance from center */ dist = sqrt((double)((center_x-mouse_x)*(center_x-mouse_x) + (center_y-mouse_y)*(center_y-mouse_y))); /* normalize */ dist -= center_offset; dist /= rad; /* find angle of axis */ angle = axis * (2.*M_PI/(double)dims); /* calculate mouse position in data coords and bound it */ dist *= cos(mouse_angle - angle); mouse_data = dim_min[axis]+dist*(dim_max[axis]-dim_min[axis]); mouse_data = MIN(mouse_data, dim_max[axis]); mouse_data = MAX(mouse_data, dim_min[axis]); } /* resize min or max */ if(resize_min) { new_min = mouse_data; new_max = gbt_br_pos[axis]+gbt_br_size[axis]/2.; } else { new_min = gbt_br_pos[axis]-gbt_br_size[axis]/2.; new_max = mouse_data; } /* check if min>max */ if(resize_min && new_min > new_max) new_max = new_min; if(resize_max && new_min > new_max) new_min = new_max; /* assign the new brush */ gbt_br_pos[axis] = (new_min + new_max)/2.; gbt_br_size[axis] = new_max - new_min; /* redraw brush tool */ GlyphBToolDoRedraw(); }


Back to Source File Index


C++ to HTML Conversion by ctoohtml