📄 tkstripchart.c
字号:
} else { if (StripchartPtr->stripstodisplay == StripchartPtr->num_strips) { if (!StripchartPtr->scrollrequired) StripchartPtr->scrollrequired = TRUE; else ScrollStrips(StripchartPtr); } DrawStripi(StripchartPtr, StripchartPtr->stripstodisplay); } /* * Display the border */ if (StripchartPtr->displaybits & DISPLAY_BORDER) { Tk_Draw3DRectangle(tkwin, Tk_WindowId(tkwin), StripchartPtr->border, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), StripchartPtr->borderWidth, StripchartPtr->relief); }}/* * StripchartEventProc -- * * This procedure is invoked by the Tk dispatcher on * structure changes to a Stripchart. For Stripcharts with 3D * borders, this procedure is also invoked for exposures. * * Results: * None. * * Side effects: * When the window gets deleted, internal structures get * cleaned up. When it gets exposed, it is redisplayed. */static voidStripchartEventProc(ClientData clientData, XEvent *eventPtr) { Stripchart *StripchartPtr = (Stripchart*)clientData; if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) { if ((StripchartPtr->tkwin != NULL) && !(StripchartPtr->displaybits & REDRAW_PENDING)) { EventuallyRedrawStripchart(StripchartPtr, DISPLAY_ALL|CLEAR_NEEDED); /* * A clear isn't technically needed as the bitmap is * clear when the window is exposed. This flag is * used to indicate that all strips need to be drawn, * not just the most recent one. */ } } else if (eventPtr->type == DestroyNotify) { Tcl_DeleteCommand(StripchartPtr->interp, Tk_PathName(StripchartPtr->tkwin)); StripchartPtr->tkwin = NULL; if (StripchartPtr->displaybits & REDRAW_PENDING) { Tk_CancelIdleCall(DisplayStripchart, (ClientData)StripchartPtr); } Tk_EventuallyFree((ClientData)StripchartPtr, DestroyStripchart); } else if (eventPtr->type == ConfigureNotify) { int n = eventPtr->xconfigure.width; n -= 2 * (StripchartPtr->borderWidth + PADDING); n /= StripchartPtr->strip_width; if (n != StripchartPtr->num_strips) { StripchartPtr->num_strips = n; if (StripchartPtr->value == 0) StripchartPtr->value = (double*)calloc(n, sizeof(double)); else StripchartPtr->value = (double*)realloc(StripchartPtr->value, n * sizeof(double)); if (StripchartPtr->stripstodisplay > n) StripchartPtr->stripstodisplay = n; } }}static double chose_range(const double* lim, int n, double range){ double lr = pow(10., floor(log10(range))); double b = range / lr - 0.002; int i; for (i = 0; i < n; ++i) if (b < lim[i]) break; return ((lim[i]) * lr);}/* * choose a 'nice' lower limit for v (one on a 2/5/10 boundary) */static int chose_scale(Stripchart* sp, double min, double max){ const static double rlim[] = { 1.0, 2.0, 5.0, 10.0 }; const static double blim[] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0 }; double range = max - min; if (range < 1e-9) return (0); range = chose_range(blim, 9, range); min = (double)((int)(min / range)) * range; max = chose_range(rlim, 3, max - min) + min; if (max != sp->max_value || min != sp->min_value) { sp->min_value = min; sp->max_value = max; if (sp->rescale_command) { char scmd[1024]; double n = sp->num_ticks - 1; if (n <= 0.) n = 1.; sprintf(scmd, "%s %g %g %g", sp->rescale_command, min, max, (max - min) / n); (void)Tcl_Eval(sp->interp, scmd); } return (1); } return (0);}/* * SetStripchartValue -- * * This procedure changes the value of a Stripchart and invokes * a Tcl command to reflect the current position of a Stripchart * * Results: * None. * * Side effects: * (Re) Sets the scrollrequired flag. */static voidSetStripchartValue(Stripchart *StripchartPtr, double value){ int std = StripchartPtr->stripstodisplay; int maxvalues = StripchartPtr->num_strips; int flags = DISPLAY_STRIPS; if (std != maxvalues) { StripchartPtr->value[std] = value; StripchartPtr->stripstodisplay = ++std; } else { int n = maxvalues - 1; memcpy(StripchartPtr->value, StripchartPtr->value + 1, n * sizeof(*StripchartPtr->value)); StripchartPtr->value[n] = value; } if (StripchartPtr->autoscale) { double min = value; double max = value; double* vp = StripchartPtr->value; int i; for (i = 0; i < std; ++i) { double v = vp[i]; if (v < min) min = v; if (v > max) max = v; } if (StripchartPtr->autoscale == 1) /* only adjust max */ min = StripchartPtr->min_value; if (max != StripchartPtr->data_max || min != StripchartPtr->data_min) { StripchartPtr->data_min = min; StripchartPtr->data_max = max; if (chose_scale(StripchartPtr, min, max)) flags |= DISPLAY_ALL|CLEAR_NEEDED; } } EventuallyRedrawStripchart(StripchartPtr, flags);}/* * EventuallyRedrawStripchart -- * * Arrange for part or all of a stripchart widget to redrawn at * the next convenient time in the future. * * Results: * None. * * Side effects: * None. */static voidEventuallyRedrawStripchart(Stripchart *StripchartPtr, int displaybits){ if (StripchartPtr->tkwin == NULL || !Tk_IsMapped(StripchartPtr->tkwin) || (StripchartPtr->displaybits & REDRAW_PENDING)) return; StripchartPtr->displaybits = displaybits | REDRAW_PENDING; if (StripchartPtr->guarantee_draw) DisplayStripchart((ClientData) StripchartPtr); else Tk_DoWhenIdle(DisplayStripchart, (ClientData)StripchartPtr);}/* * SwapColours -- * * Save the current colour scheme so that it may be * restored at some later stage. * * Results: * None. * * Side effects: * Colour scheme is swapped and Stripchart is redisplayed with * the new colour scheme. */static void SwapColours(Stripchart * StripchartPtr){ Tk_3DBorder tempb; XColor *tempc;#define SWAP(a,b,c) { (c) = (a); (a) = (b); (b) = (c); } SWAP(StripchartPtr->altborder, StripchartPtr->border, tempb); SWAP(StripchartPtr->altstripBorder, StripchartPtr->stripBorder, tempb); SWAP(StripchartPtr->a_textColor, StripchartPtr->textColorPtr, tempc); SWAP(StripchartPtr->a_tickColor, StripchartPtr->tickColorPtr, tempc);#undef SWAP ConfigureStripchart(StripchartPtr->interp, StripchartPtr, 0, NULL, TK_CONFIG_ARGV_ONLY);}/* * ReplaceColours -- * * Store the current colour scheme and replace it with * the new one. * * Results: * None. * * Side effects: * Stripchart is displayed with the new colour scheme. */static void ReplaceColours(Stripchart* StripchartPtr, int argc, char** argv){ StripchartPtr->altborder = Tk_Get3DBorder(StripchartPtr->interp, StripchartPtr->tkwin, Tk_NameOf3DBorder(StripchartPtr->border)); StripchartPtr->altstripBorder = Tk_Get3DBorder(StripchartPtr->interp, StripchartPtr->tkwin, Tk_NameOf3DBorder(StripchartPtr->stripBorder)); StripchartPtr->a_textColor = Tk_GetColorByValue(StripchartPtr->tkwin, StripchartPtr->textColorPtr); StripchartPtr->a_tickColor = Tk_GetColorByValue(StripchartPtr->tkwin, StripchartPtr->tickColorPtr); ConfigureStripchart(StripchartPtr->interp, StripchartPtr, argc, argv, TK_CONFIG_ARGV_ONLY);}/* * DrawStripi -- * * Draw the i-th strip of the stripchart. * * Results: * None. * * Side effects: * A new strip is drawn. */static void DrawStripi(Stripchart* SPtr, int i){ Tk_Window tkwin = SPtr->tkwin; int lineHeight = SPtr->fontPtr->ascent + SPtr->fontPtr->descent; int x = SPtr->borderWidth + PADDING + (i - 1) * SPtr->strip_width; int y = SPtr->borderWidth + PADDING + hasatitle(SPtr) * (lineHeight + PADDING); int w = SPtr->strip_width; int h; double maxv = SPtr->max_value; double minv = SPtr->min_value; if (i < 1 || i > SPtr->num_strips) return; /* Clear any strip that might be below this one */ XClearArea(Tk_Display(tkwin), Tk_WindowId(tkwin), x, y, w, SPtr->max_height, FALSE); /* Calculate the height of the bar */ if (maxv == minv) h = 0; else h = (int)((double)SPtr->max_height * (SPtr->value[i - 1] - minv) / (maxv - minv)); if (h > SPtr->max_height) h = SPtr->max_height; if (h == 0) h = 1; /* Adject the origin of the bars rectangle depending on its origin */ if (SPtr->grow_up) y += (SPtr->max_height - h); /* draw x axis tick mark, if any */ if (SPtr->hticks > 0 && ++SPtr->lasthtick >= SPtr->hticks) { SPtr->lasthtick = 0; XDrawLine(Tk_Display(tkwin), Tk_WindowId(tkwin), SPtr->tickGC, x, SPtr->borderWidth + PADDING + hasatitle(SPtr) * (lineHeight + PADDING), x, SPtr->max_height); } /* Draw the y axis ticks, if any */ if (SPtr->showticks) { XSegment ticks[MAX_TICKS]; for (i = 0; i < SPtr->num_ticks; i++) { ticks[i].x1 = x; ticks[i].x2 = x + SPtr->strip_width - 1; ticks[i].y1 = ticks[i].y2 = SPtr->borderWidth + PADDING + hasatitle(SPtr) * (lineHeight + PADDING) + i * SPtr->max_height / (SPtr->num_ticks-1); } XDrawSegments(Tk_Display(tkwin), Tk_WindowId(tkwin), SPtr->tickGC, ticks, SPtr->num_ticks); } /* Draw the bar */ Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), SPtr->stripBorder, x, y, w, h, SPtr->stripBorderWidth, SPtr->stripRelief);}/* * ScrollStrips -- * * Scroll the strips in the stripchart region to the left * by the width of a strip pixels. * * Results: * None. * * Side effects: * Display changes. */static void ScrollStrips(Stripchart* SPtr){ Tk_Window tkwin = SPtr->tkwin; int lineHeight = SPtr->fontPtr->ascent + SPtr->fontPtr->descent; int src_x = SPtr->borderWidth + PADDING + SPtr->strip_width; int src_y = SPtr->borderWidth + PADDING + hasatitle(SPtr) * (lineHeight + PADDING); int dest_x = src_x - SPtr->strip_width; int dest_y = src_y; int w = (SPtr->num_strips - 1) * SPtr->strip_width; int h = SPtr->max_height; XCopyArea(Tk_Display(tkwin), Tk_WindowId(tkwin), Tk_WindowId(tkwin), Tk_GetGC(tkwin, 0, NULL), src_x, src_y, w, h, dest_x, dest_y);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -