diff options
-rw-r--r-- | generic/tkScale.c | 148 | ||||
-rw-r--r-- | generic/tkScale.h | 4 | ||||
-rw-r--r-- | unix/tkUnixScale.c | 28 |
3 files changed, 114 insertions, 66 deletions
diff --git a/generic/tkScale.c b/generic/tkScale.c index 29f8722..455c656 100644 --- a/generic/tkScale.c +++ b/generic/tkScale.c @@ -157,7 +157,7 @@ enum command { * Forward declarations for procedures defined later in this file: */ -static void ComputeFormat(TkScale *scalePtr); +static void ComputeFormat(TkScale *scalePtr, int forTicks); static void ComputeScaleGeometry(TkScale *scalePtr); static int ConfigureScale(Tcl_Interp *interp, TkScale *scalePtr, int objc, Tcl_Obj *const objv[]); @@ -430,7 +430,7 @@ ScaleWidgetObjCmd( } value = TkScalePixelToValue(scalePtr, x, y); } - Tcl_SetObjResult(interp, Tcl_ObjPrintf(scalePtr->format, value)); + Tcl_SetObjResult(interp, Tcl_ObjPrintf(scalePtr->valueFormat, value)); break; } case COMMAND_IDENTIFY: { @@ -636,7 +636,8 @@ ConfigureScale( scalePtr->tickInterval = -scalePtr->tickInterval; } - ComputeFormat(scalePtr); + ComputeFormat(scalePtr, 0); + ComputeFormat(scalePtr, 1); scalePtr->labelLength = scalePtr->label ? (int)strlen(scalePtr->label) : 0; @@ -764,22 +765,22 @@ ScaleWorldChanged( * * 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. + * This procedure is invoked to recompute the "valueFormat" or + * "tickFormat" field of a scale's widget record, which determines how + * the value of the scale or one of its ticks is converted to a string. * * Results: * None. * - * Side effects: - * The format field of scalePtr is modified. + * Side effects: The valueFormat or tickFormat field of scalePtr is modified. * *---------------------------------------------------------------------- */ static void ComputeFormat( - TkScale *scalePtr) /* Information about scale widget. */ + TkScale *scalePtr, /* Information about scale widget. */ + int forTicks) /* Do for ticks rather than value */ { double maxValue, x; int mostSigDigit, numDigits, leastSigDigit, afterDecimal; @@ -800,46 +801,60 @@ ComputeFormat( } 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 > TCL_MAX_PREC) { - numDigits = 0; - } - if (numDigits <= 0) { - if (scalePtr->resolution > 0) { - /* - * A resolution was specified for the scale, so just use it. - */ + if (forTicks) { + /* + * Display only enough digits to ensure adjacent ticks have different + * values + */ - leastSigDigit = (int) floor(log10(scalePtr->resolution)); + if (scalePtr->tickInterval > 0) { + numDigits = 1 + mostSigDigit - (int) floor(log10(scalePtr->tickInterval)); } else { - /* - * No resolution was specified, so compute the difference in value - * between adjacent pixels and use it for the least significant - * digit. - */ + numDigits = 1; + } + } else { + /* + * 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. + */ - x = fabs(scalePtr->fromValue - scalePtr->toValue); - if (scalePtr->length > 0) { - x /= scalePtr->length; - } - if (x > 0){ - leastSigDigit = (int) floor(log10(x)); + numDigits = scalePtr->digits; + if (numDigits > TCL_MAX_PREC) { + numDigits = 0; + } + 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 { - leastSigDigit = 0; + /* + * 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; } - } - numDigits = mostSigDigit - leastSigDigit + 1; - if (numDigits < 1) { - numDigits = 1; } } @@ -863,10 +878,18 @@ ComputeFormat( if (mostSigDigit < 0) { fDigits++; /* Zero to left of decimal point. */ } - if (fDigits <= eDigits) { - sprintf(scalePtr->format, "%%.%df", afterDecimal); + if (forTicks) { + if (fDigits <= eDigits) { + sprintf(scalePtr->tickFormat, "%%.%df", afterDecimal); + } else { + sprintf(scalePtr->tickFormat, "%%.%de", numDigits-1); + } } else { - sprintf(scalePtr->format, "%%.%de", numDigits-1); + if (fDigits <= eDigits) { + sprintf(scalePtr->valueFormat, "%%.%df", afterDecimal); + } else { + sprintf(scalePtr->valueFormat, "%%.%de", numDigits-1); + } } } @@ -894,7 +917,7 @@ ComputeScaleGeometry( register TkScale *scalePtr) /* Information about widget. */ { char valueString[TCL_DOUBLE_SPACE]; - int tmp, valuePixels, x, y, extraSpace; + int tmp, valuePixels, tickPixels, x, y, extraSpace; Tk_FontMetrics fm; Tk_GetFontMetrics(scalePtr->tkfont, &fm); @@ -940,13 +963,13 @@ ComputeScaleGeometry( * whichever length is longer. */ - if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->format, + if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->valueFormat, scalePtr->fromValue) < 0) { valueString[TCL_DOUBLE_SPACE - 1] = '\0'; } valuePixels = Tk_TextWidth(scalePtr->tkfont, valueString, -1); - if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->format, + if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->valueFormat, scalePtr->toValue) < 0) { valueString[TCL_DOUBLE_SPACE - 1] = '\0'; } @@ -956,18 +979,37 @@ ComputeScaleGeometry( } /* + * Now do the same thing for the tick values + */ + + if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->tickFormat, + scalePtr->fromValue) < 0) { + valueString[TCL_DOUBLE_SPACE - 1] = '\0'; + } + tickPixels = Tk_TextWidth(scalePtr->tkfont, valueString, -1); + + if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->tickFormat, + scalePtr->toValue) < 0) { + valueString[TCL_DOUBLE_SPACE - 1] = '\0'; + } + tmp = Tk_TextWidth(scalePtr->tkfont, valueString, -1); + if (tickPixels < tmp) { + tickPixels = tmp; + } + + /* * Assign x-locations to the elements of the scale, working from left to * right. */ x = scalePtr->inset; if ((scalePtr->tickInterval != 0) && (scalePtr->showValue)) { - scalePtr->vertTickRightX = x + SPACING + valuePixels; + scalePtr->vertTickRightX = x + SPACING + tickPixels; scalePtr->vertValueRightX = scalePtr->vertTickRightX + valuePixels + fm.ascent/2; x = scalePtr->vertValueRightX + SPACING; } else if (scalePtr->tickInterval != 0) { - scalePtr->vertTickRightX = x + SPACING + valuePixels; + scalePtr->vertTickRightX = x + SPACING + tickPixels; scalePtr->vertValueRightX = scalePtr->vertTickRightX; x = scalePtr->vertTickRightX + SPACING; } else if (scalePtr->showValue) { @@ -1350,7 +1392,7 @@ ScaleSetVariable( if (scalePtr->varNamePtr != NULL) { char string[TCL_DOUBLE_SPACE]; - if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->format, + if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->valueFormat, scalePtr->value) < 0) { string[TCL_DOUBLE_SPACE - 1] = '\0'; } diff --git a/generic/tkScale.h b/generic/tkScale.h index d44e65b..4250b06 100644 --- a/generic/tkScale.h +++ b/generic/tkScale.h @@ -73,8 +73,10 @@ typedef struct TkScale { * values. 0 means we get to choose the number * based on resolution and/or the range of the * scale. */ - char format[16]; /* Sprintf conversion specifier computed from + char valueFormat[16]; /* Sprintf conversion specifier computed from * digits and other information. */ + char tickFormat[16]; /* Sprintf conversion specifier computed from + * tick interval. */ double bigIncrement; /* Amount to use for large increments to scale * value. (0 means we pick a value). */ char *command; /* Command prefix to use when invoking Tcl diff --git a/unix/tkUnixScale.c b/unix/tkUnixScale.c index 2009288..f5e3fc2 100644 --- a/unix/tkUnixScale.c +++ b/unix/tkUnixScale.c @@ -24,11 +24,13 @@ static void DisplayHorizontalScale(TkScale *scalePtr, Drawable drawable, XRectangle *drawnAreaPtr); static void DisplayHorizontalValue(TkScale *scalePtr, - Drawable drawable, double value, int top); + Drawable drawable, double value, + int top, char* format); static void DisplayVerticalScale(TkScale *scalePtr, Drawable drawable, XRectangle *drawnAreaPtr); static void DisplayVerticalValue(TkScale *scalePtr, - Drawable drawable, double value, int rightEdge); + Drawable drawable, double value, + int rightEdge, char* format); /* *---------------------------------------------------------------------- @@ -165,7 +167,7 @@ DisplayVerticalScale( } } DisplayVerticalValue(scalePtr, drawable, tickValue, - scalePtr->vertTickRightX); + scalePtr->vertTickRightX, scalePtr->tickFormat); } } } @@ -176,7 +178,7 @@ DisplayVerticalScale( if (scalePtr->showValue) { DisplayVerticalValue(scalePtr, drawable, scalePtr->value, - scalePtr->vertValueRightX); + scalePtr->vertValueRightX, scalePtr->valueFormat); } /* @@ -261,8 +263,9 @@ DisplayVerticalValue( double value, /* Y-coordinate of number to display, * specified in application coords, not in * pixels (we'll compute pixels). */ - int rightEdge) /* X-coordinate of right edge of text, + int rightEdge, /* X-coordinate of right edge of text, * specified in pixels. */ + char* format) /* Format string to use for the value */ { register Tk_Window tkwin = scalePtr->tkwin; int y, width, length; @@ -271,7 +274,7 @@ DisplayVerticalValue( Tk_GetFontMetrics(scalePtr->tkfont, &fm); y = TkScaleValueToPixel(scalePtr, value) + fm.ascent/2; - if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->format, value) < 0) { + if (snprintf(valueString, TCL_DOUBLE_SPACE, format, value) < 0) { valueString[TCL_DOUBLE_SPACE - 1] = '\0'; } length = (int) strlen(valueString); @@ -358,7 +361,7 @@ DisplayHorizontalScale( ticks = fabs((scalePtr->toValue - scalePtr->fromValue) / tickInterval); - if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->format, + if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->tickFormat, scalePtr->fromValue) < 0) { valueString[TCL_DOUBLE_SPACE - 1] = '\0'; } @@ -385,7 +388,7 @@ DisplayHorizontalScale( } } DisplayHorizontalValue(scalePtr, drawable, tickValue, - scalePtr->horizTickY); + scalePtr->horizTickY, scalePtr->tickFormat); } } } @@ -396,7 +399,7 @@ DisplayHorizontalScale( if (scalePtr->showValue) { DisplayHorizontalValue(scalePtr, drawable, scalePtr->value, - scalePtr->horizValueY); + scalePtr->horizValueY, scalePtr->valueFormat); } /* @@ -482,8 +485,9 @@ DisplayHorizontalValue( double value, /* X-coordinate of number to display, * specified in application coords, not in * pixels (we'll compute pixels). */ - int top) /* Y-coordinate of top edge of text, specified + int top, /* Y-coordinate of top edge of text, specified * in pixels. */ + char* format) /* Format string to use for the value */ { register Tk_Window tkwin = scalePtr->tkwin; int x, y, length, width; @@ -493,7 +497,7 @@ DisplayHorizontalValue( x = TkScaleValueToPixel(scalePtr, value); Tk_GetFontMetrics(scalePtr->tkfont, &fm); y = top + fm.ascent; - if (snprintf(valueString, TCL_DOUBLE_SPACE, scalePtr->format, value) < 0) { + if (snprintf(valueString, TCL_DOUBLE_SPACE, format, value) < 0) { valueString[TCL_DOUBLE_SPACE - 1] = '\0'; } length = (int) strlen(valueString); @@ -562,7 +566,7 @@ TkpDisplayScale( Tcl_Preserve(scalePtr); if ((scalePtr->flags & INVOKE_COMMAND) && (scalePtr->command != NULL)) { Tcl_Preserve(interp); - if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->format, + if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->valueFormat, scalePtr->value) < 0) { string[TCL_DOUBLE_SPACE - 1] = '\0'; } |