📄 tkscale.c
字号:
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " identify x y\"", (char *) NULL); goto error; } if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) || (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) { goto error; } thing = TkpScaleElement(scalePtr, x,y); switch (thing) { case TROUGH1: interp->result = "trough1"; break; case SLIDER: interp->result = "slider"; break; case TROUGH2: interp->result = "trough2"; break; } } else if ((c == 's') && (strncmp(argv[1], "set", length) == 0)) { double value; if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " set value\"", (char *) NULL); goto error; } if (Tcl_GetDouble(interp, argv[2], &value) != TCL_OK) { goto error; } if (scalePtr->state != tkDisabledUid) { TkpSetScaleValue(scalePtr, value, 1, 1); } } else { Tcl_AppendResult(interp, "bad option \"", argv[1], "\": must be cget, configure, coords, get, identify, or set", (char *) NULL); goto error; } Tcl_Release((ClientData) scalePtr); return result; error: Tcl_Release((ClientData) scalePtr); return TCL_ERROR;}/* *---------------------------------------------------------------------- * * DestroyScale -- * * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release * to clean up the internal structure of a button at a safe time * (when no-one is using it anymore). * * Results: * None. * * Side effects: * Everything associated with the scale is freed up. * *---------------------------------------------------------------------- */static voidDestroyScale(memPtr) char *memPtr; /* Info about scale widget. */{ register TkScale *scalePtr = (TkScale *) memPtr; /* * Free up all the stuff that requires special handling, then * let Tk_FreeOptions handle all the standard option-related * stuff. */ if (scalePtr->varName != NULL) { Tcl_UntraceVar(scalePtr->interp, scalePtr->varName, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ScaleVarProc, (ClientData) scalePtr); } if (scalePtr->troughGC != None) { Tk_FreeGC(scalePtr->display, scalePtr->troughGC); } if (scalePtr->copyGC != None) { Tk_FreeGC(scalePtr->display, scalePtr->copyGC); } if (scalePtr->textGC != None) { Tk_FreeGC(scalePtr->display, scalePtr->textGC); } Tk_FreeOptions(configSpecs, (char *) scalePtr, scalePtr->display, 0); TkpDestroyScale(scalePtr);}/* *---------------------------------------------------------------------- * * ConfigureScale -- * * This procedure is called to process an argv/argc list, plus * the Tk option database, in order to configure (or * reconfigure) a scale widget. * * Results: * The return value is a standard Tcl result. If TCL_ERROR is * returned, then interp->result contains an error message. * * Side effects: * Configuration information, such as colors, border width, * etc. get set for scalePtr; old resources get freed, * if there were any. * *---------------------------------------------------------------------- */static intConfigureScale(interp, scalePtr, argc, argv, flags) Tcl_Interp *interp; /* Used for error reporting. */ register TkScale *scalePtr; /* Information about widget; may or may * not already have values for some fields. */ int argc; /* Number of valid entries in argv. */ char **argv; /* Arguments. */ int flags; /* Flags to pass to Tk_ConfigureWidget. */{ size_t length; /* * Eliminate any existing trace on a variable monitored by the scale. */ if (scalePtr->varName != NULL) { Tcl_UntraceVar(interp, scalePtr->varName, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ScaleVarProc, (ClientData) scalePtr); } if (Tk_ConfigureWidget(interp, scalePtr->tkwin, configSpecs, argc, argv, (char *) scalePtr, flags) != TCL_OK) { return TCL_ERROR; } /* * If the scale is tied to the value of a variable, then set up * a trace on the variable's value and set the scale's value from * the value of the variable, if it exists. */ if (scalePtr->varName != NULL) { char *stringValue, *end; double value; stringValue = Tcl_GetVar(interp, scalePtr->varName, TCL_GLOBAL_ONLY); if (stringValue != NULL) { value = strtod(stringValue, &end); if ((end != stringValue) && (*end == 0)) { scalePtr->value = TkRoundToResolution(scalePtr, value); } } Tcl_TraceVar(interp, scalePtr->varName, TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, ScaleVarProc, (ClientData) scalePtr); } /* * Several options need special processing, such as parsing the * orientation and creating GCs. */ length = strlen(scalePtr->orientUid); if (strncmp(scalePtr->orientUid, "vertical", length) == 0) { scalePtr->vertical = 1; } else if (strncmp(scalePtr->orientUid, "horizontal", length) == 0) { scalePtr->vertical = 0; } else { Tcl_AppendResult(interp, "bad orientation \"", scalePtr->orientUid, "\": must be vertical or horizontal", (char *) NULL); return TCL_ERROR; } scalePtr->fromValue = TkRoundToResolution(scalePtr, scalePtr->fromValue); scalePtr->toValue = TkRoundToResolution(scalePtr, scalePtr->toValue); scalePtr->tickInterval = TkRoundToResolution(scalePtr, scalePtr->tickInterval); /* * Make sure that the tick interval has the right sign so that * addition moves from fromValue to toValue. */ if ((scalePtr->tickInterval < 0) ^ ((scalePtr->toValue - scalePtr->fromValue) < 0)) { scalePtr->tickInterval = -scalePtr->tickInterval; } /* * Set the scale value to itself; all this does is to make sure * that the scale's value is within the new acceptable range for * the scale and reflect the value in the associated variable, * if any. */ ComputeFormat(scalePtr); TkpSetScaleValue(scalePtr, scalePtr->value, 1, 1); if (scalePtr->label != NULL) { scalePtr->labelLength = strlen(scalePtr->label); } else { scalePtr->labelLength = 0; } if ((scalePtr->state != tkNormalUid) && (scalePtr->state != tkDisabledUid) && (scalePtr->state != tkActiveUid)) { Tcl_AppendResult(interp, "bad state value \"", scalePtr->state, "\": must be normal, active, or disabled", (char *) NULL); scalePtr->state = tkNormalUid; return TCL_ERROR; } Tk_SetBackgroundFromBorder(scalePtr->tkwin, scalePtr->bgBorder); if (scalePtr->highlightWidth < 0) { scalePtr->highlightWidth = 0; } scalePtr->inset = scalePtr->highlightWidth + scalePtr->borderWidth; ScaleWorldChanged((ClientData) scalePtr); return TCL_OK;}/* *--------------------------------------------------------------------------- * * ScaleWorldChanged -- * * This procedure is called when the world has changed in some * way and the widget needs to recompute all its graphics contexts * and determine its new geometry. * * Results: * None. * * Side effects: * Scale will be relayed out and redisplayed. * *--------------------------------------------------------------------------- */ static voidScaleWorldChanged(instanceData) ClientData instanceData; /* Information about widget. */{ XGCValues gcValues; GC gc; TkScale *scalePtr; scalePtr = (TkScale *) instanceData; gcValues.foreground = scalePtr->troughColorPtr->pixel; gc = Tk_GetGC(scalePtr->tkwin, GCForeground, &gcValues); if (scalePtr->troughGC != None) { Tk_FreeGC(scalePtr->display, scalePtr->troughGC); } scalePtr->troughGC = gc; gcValues.font = Tk_FontId(scalePtr->tkfont); gcValues.foreground = scalePtr->textColorPtr->pixel; gc = Tk_GetGC(scalePtr->tkwin, GCForeground | GCFont, &gcValues); if (scalePtr->textGC != None) { Tk_FreeGC(scalePtr->display, scalePtr->textGC); } scalePtr->textGC = gc; if (scalePtr->copyGC == None) { gcValues.graphics_exposures = False; scalePtr->copyGC = Tk_GetGC(scalePtr->tkwin, GCGraphicsExposures, &gcValues); } scalePtr->inset = scalePtr->highlightWidth + scalePtr->borderWidth; /* * Recompute display-related information, and let the geometry * manager know how much space is needed now. */ ComputeScaleGeometry(scalePtr); TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);}/* *---------------------------------------------------------------------- * * ComputeFormat -- * * This procedure is invoked to recompute the "format" field * of a scale's widget record, which determines how the value * of the scale is converted to a string. * * Results: * None. * * Side effects: * The format field of scalePtr is modified. * *---------------------------------------------------------------------- */static voidComputeFormat(scalePtr) TkScale *scalePtr; /* Information about scale widget. */{ double maxValue, x; int mostSigDigit, numDigits, leastSigDigit, afterDecimal; int eDigits, fDigits; /* * Compute the displacement from the decimal of the most significant * digit required for any number in the scale's range. */ maxValue = fabs(scalePtr->fromValue); x = fabs(scalePtr->toValue); if (x > maxValue) { maxValue = x; } if (maxValue == 0) { maxValue = 1; } mostSigDigit = (int) floor(log10(maxValue)); /* * If the number of significant digits wasn't specified explicitly, * compute it. It's the difference between the most significant * digit needed to represent any number on the scale and the * most significant digit of the smallest difference between * numbers on the scale. In other words, display enough digits so * that at least one digit will be different between any two adjacent * positions of the scale. */ numDigits = scalePtr->digits; if (numDigits <= 0) { if (scalePtr->resolution > 0) { /* * A resolution was specified for the scale, so just use it. */ leastSigDigit = (int) floor(log10(scalePtr->resolution)); } else { /* * No resolution was specified, so compute the difference * in value between adjacent pixels and use it for the least * significant digit. */ x = fabs(scalePtr->fromValue - scalePtr->toValue); if (scalePtr->length > 0) { x /= scalePtr->length; } if (x > 0){ leastSigDigit = (int) floor(log10(x)); } else { leastSigDigit = 0; } } numDigits = mostSigDigit - leastSigDigit + 1; if (numDigits < 1) { numDigits = 1; } } /* * Compute the number of characters required using "e" format and * "f" format, and then choose whichever one takes fewer characters. */ eDigits = numDigits + 4; if (numDigits > 1) { eDigits++; /* Decimal point. */ } afterDecimal = numDigits - mostSigDigit - 1; if (afterDecimal < 0) { afterDecimal = 0; } fDigits = (mostSigDigit >= 0) ? mostSigDigit + afterDecimal : afterDecimal;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -