4 * This module implements a scale widgets for the Tk toolkit.
5 * A scale displays a slider that can be adjusted to change a
6 * value; it also displays numeric labels and a textual label,
9 * Copyright 1990 Regents of the University of California.
10 * Permission to use, copy, modify, and distribute this
11 * software and its documentation for any purpose and without
12 * fee is hereby granted, provided that the above copyright
13 * notice appear in all copies. The University of California
14 * makes no representations about the suitability of this
15 * software for any purpose. It is provided "as is" without
16 * express or implied warranty.
20 static char rcsid
[] = "$Header: /user6/ouster/wish/RCS/tkScale.c,v 1.28 92/08/21 11:45:25 ouster Exp $ SPRITE (Berkeley)";
28 * A data structure of the following type is kept for each scale
29 * widget managed by this file:
33 Tk_Window tkwin
; /* Window that embodies the scale. NULL
34 * means that the window has been destroyed
35 * but the data structures haven't yet been
37 Tcl_Interp
*interp
; /* Interpreter associated with scale. */
38 Tk_Uid orientUid
; /* Orientation for window ("vertical" or
40 int vertical
; /* Non-zero means vertical orientation,
41 * zero means horizontal. */
42 int value
; /* Current value of scale. */
43 int fromValue
; /* Value corresponding to left or top of
45 int toValue
; /* Value corresponding to right or bottom
47 int tickInterval
; /* Distance between tick marks; 0 means
48 * don't display any tick marks. */
49 char *command
; /* Command prefix to use when invoking Tcl
50 * commands because the scale value changed.
51 * NULL means don't invoke commands.
53 int commandLength
; /* Number of non-NULL bytes in command. */
54 char *label
; /* Label to display above or to right of
55 * scale; NULL means don't display a
56 * label. Malloc'ed. */
57 int labelLength
; /* Number of non-NULL chars. in label. */
58 Tk_Uid state
; /* Normal or disabled. Value cannot be
59 * changed when scale is disabled. */
62 * Information used when displaying widget:
65 int borderWidth
; /* Width of 3-D border around window. */
66 Tk_3DBorder bgBorder
; /* Used for drawing background. */
67 Tk_3DBorder sliderBorder
; /* Used for drawing slider in normal mode. */
68 Tk_3DBorder activeBorder
; /* Used for drawing slider when active (i.e.
69 * when mouse is in window). */
70 XFontStruct
*fontPtr
; /* Information about text font, or NULL. */
71 XColor
*textColorPtr
; /* Color for drawing text. */
72 GC textGC
; /* GC for drawing text in normal mode. */
73 int width
; /* Desired narrow dimension of scale,
75 int length
; /* Desired long dimension of scale,
77 int relief
; /* Indicates whether window as a whole is
78 * raised, sunken, or flat. */
79 int offset
; /* Zero if relief is TK_RELIEF_FLAT,
80 * borderWidth otherwise. Indicates how
81 * much interior stuff must be offset from
82 * outside edges to leave room for border. */
83 int sliderLength
; /* Length of slider, measured in pixels along
84 * long dimension of scale. */
85 int showValue
; /* Non-zero means to display the scale value
86 * below or to the left of the slider; zero
87 * means don't display the value. */
88 int tickPixels
; /* Number of pixels required for widest tick
89 * mark. 0 means don't display ticks.*/
90 int valuePixels
; /* Number of pixels required for value text. */
91 int labelPixels
; /* Number of pixels required for label. 0
92 * means don't display label. */
95 * Miscellaneous information:
98 Cursor cursor
; /* Current cursor for window, or None. */
99 int flags
; /* Various flags; see below for
104 * Flag bits for scales:
106 * REDRAW_SLIDER - 1 means slider (and numerical readout) need
108 * REDRAW_OTHER - 1 means other stuff besides slider and value
109 * need to be redrawn.
110 * REDRAW_ALL - 1 means the entire widget needs to be redrawn.
111 * ACTIVE - 1 means the widget is active (the mouse is
113 * BUTTON_PRESSED - 1 means a button press is in progress, so
114 * slider should appear depressed and should be
118 #define REDRAW_SLIDER 1
119 #define REDRAW_OTHER 2
122 #define BUTTON_PRESSED 8
125 * Space to leave between scale area and text.
131 * Information used for argv parsing.
135 static Tk_ConfigSpec configSpecs
[] = {
136 {TK_CONFIG_BORDER
, "-activeforeground", "activeForeground", "Background",
137 DEF_SCALE_ACTIVE_FG_COLOR
, Tk_Offset(Scale
, activeBorder
),
138 TK_CONFIG_COLOR_ONLY
},
139 {TK_CONFIG_BORDER
, "-activeforeground", "activeForeground", "Background",
140 DEF_SCALE_ACTIVE_FG_MONO
, Tk_Offset(Scale
, activeBorder
),
141 TK_CONFIG_MONO_ONLY
},
142 {TK_CONFIG_BORDER
, "-background", "background", "Background",
143 DEF_SCALE_BG_COLOR
, Tk_Offset(Scale
, bgBorder
),
144 TK_CONFIG_COLOR_ONLY
},
145 {TK_CONFIG_BORDER
, "-background", "background", "Background",
146 DEF_SCALE_BG_MONO
, Tk_Offset(Scale
, bgBorder
),
147 TK_CONFIG_MONO_ONLY
},
148 {TK_CONFIG_SYNONYM
, "-bd", "borderWidth", (char *) NULL
,
149 (char *) NULL
, 0, 0},
150 {TK_CONFIG_SYNONYM
, "-bg", "background", (char *) NULL
,
151 (char *) NULL
, 0, 0},
152 {TK_CONFIG_PIXELS
, "-borderwidth", "borderWidth", "BorderWidth",
153 DEF_SCALE_BORDER_WIDTH
, Tk_Offset(Scale
, borderWidth
), 0},
154 {TK_CONFIG_STRING
, "-command", "command", "Command",
155 (char *) NULL
, Tk_Offset(Scale
, command
), 0},
156 {TK_CONFIG_ACTIVE_CURSOR
, "-cursor", "cursor", "Cursor",
157 DEF_SCALE_CURSOR
, Tk_Offset(Scale
, cursor
), TK_CONFIG_NULL_OK
},
158 {TK_CONFIG_SYNONYM
, "-fg", "foreground", (char *) NULL
,
159 (char *) NULL
, 0, 0},
160 {TK_CONFIG_FONT
, "-font", "font", "Font",
161 DEF_SCALE_FONT
, Tk_Offset(Scale
, fontPtr
),
163 {TK_CONFIG_COLOR
, "-foreground", "foreground", "Foreground",
164 DEF_SCALE_FG_COLOR
, Tk_Offset(Scale
, textColorPtr
),
165 TK_CONFIG_COLOR_ONLY
},
166 {TK_CONFIG_COLOR
, "-foreground", "foreground", "Foreground",
167 DEF_SCALE_FG_MONO
, Tk_Offset(Scale
, textColorPtr
),
168 TK_CONFIG_MONO_ONLY
},
169 {TK_CONFIG_INT
, "-from", "from", "From",
170 DEF_SCALE_FROM
, Tk_Offset(Scale
, fromValue
), 0},
171 {TK_CONFIG_STRING
, "-label", "label", "Label",
172 DEF_SCALE_LABEL
, Tk_Offset(Scale
, label
), 0},
173 {TK_CONFIG_PIXELS
, "-length", "length", "Length",
174 DEF_SCALE_LENGTH
, Tk_Offset(Scale
, length
), 0},
175 {TK_CONFIG_UID
, "-orient", "orient", "Orient",
176 DEF_SCALE_ORIENT
, Tk_Offset(Scale
, orientUid
), 0},
177 {TK_CONFIG_RELIEF
, "-relief", "relief", "Relief",
178 DEF_SCALE_RELIEF
, Tk_Offset(Scale
, relief
), 0},
179 {TK_CONFIG_BOOLEAN
, "-showvalue", "showValue", "ShowValue",
180 DEF_SCALE_SHOW_VALUE
, Tk_Offset(Scale
, showValue
), 0},
181 {TK_CONFIG_BORDER
, "-sliderforeground", "sliderForeground", "Background",
182 DEF_SCALE_SLIDER_FG_COLOR
, Tk_Offset(Scale
, sliderBorder
),
183 TK_CONFIG_COLOR_ONLY
},
184 {TK_CONFIG_BORDER
, "-sliderforeground", "sliderForeground", "Background",
185 DEF_SCALE_SLIDER_FG_MONO
, Tk_Offset(Scale
, sliderBorder
),
186 TK_CONFIG_MONO_ONLY
},
187 {TK_CONFIG_PIXELS
, "-sliderlength", "sliderLength", "SliderLength",
188 DEF_SCALE_SLIDER_LENGTH
, Tk_Offset(Scale
, sliderLength
), 0},
189 {TK_CONFIG_UID
, "-state", "state", "State",
190 DEF_SCALE_STATE
, Tk_Offset(Scale
, state
), 0},
191 {TK_CONFIG_INT
, "-tickinterval", "tickInterval", "TickInterval",
192 DEF_SCALE_TICK_INTERVAL
, Tk_Offset(Scale
, tickInterval
), 0},
193 {TK_CONFIG_INT
, "-to", "to", "To",
194 DEF_SCALE_TO
, Tk_Offset(Scale
, toValue
), 0},
195 {TK_CONFIG_PIXELS
, "-width", "width", "Width",
196 DEF_SCALE_WIDTH
, Tk_Offset(Scale
, width
), 0},
197 {TK_CONFIG_END
, (char *) NULL
, (char *) NULL
, (char *) NULL
,
202 * Forward declarations for procedures defined later in this file:
205 static void ComputeScaleGeometry
_ANSI_ARGS_((Scale
*scalePtr
));
206 static int ConfigureScale
_ANSI_ARGS_((Tcl_Interp
*interp
,
207 Scale
*scalePtr
, int argc
, char **argv
,
209 static void DestroyScale
_ANSI_ARGS_((ClientData clientData
));
210 static void DisplayHorizontalScale
_ANSI_ARGS_((
211 ClientData clientData
));
212 static void DisplayHorizontalValue
_ANSI_ARGS_((Scale
*scalePtr
,
213 int value
, int bottom
));
214 static void DisplayVerticalScale
_ANSI_ARGS_((
215 ClientData clientData
));
216 static void DisplayVerticalValue
_ANSI_ARGS_((Scale
*scalePtr
,
217 int value
, int rightEdge
));
218 static void EventuallyRedrawScale
_ANSI_ARGS_((Scale
*scalePtr
,
220 static int PixelToValue
_ANSI_ARGS_((Scale
*scalePtr
, int x
,
222 static void ScaleEventProc
_ANSI_ARGS_((ClientData clientData
,
224 static void ScaleMouseProc
_ANSI_ARGS_((ClientData clientData
,
226 static int ScaleWidgetCmd
_ANSI_ARGS_((ClientData clientData
,
227 Tcl_Interp
*interp
, int argc
, char **argv
));
228 static void SetScaleValue
_ANSI_ARGS_((Scale
*scalePtr
,
230 static int ValueToPixel
_ANSI_ARGS_((Scale
*scalePtr
, int value
));
233 *--------------------------------------------------------------
237 * This procedure is invoked to process the "scale" Tcl
238 * command. See the user documentation for details on what
242 * A standard Tcl result.
245 * See the user documentation.
247 *--------------------------------------------------------------
252 ClientData clientData
, /* Main window associated with
254 Tcl_Interp
*interp
, /* Current interpreter. */
255 int argc
, /* Number of arguments. */
256 char **argv
/* Argument strings. */
259 Tk_Window tkwin
= (Tk_Window
) clientData
;
260 register Scale
*scalePtr
;
264 Tcl_AppendResult(interp
, "wrong # args: should be \"",
265 argv
[0], " pathName ?options?\"", (char *) NULL
);
269 new = Tk_CreateWindowFromPath(interp
, tkwin
, argv
[1], (char *) NULL
);
275 * Initialize fields that won't be initialized by ConfigureScale,
276 * or which ConfigureScale expects to have reasonable values
277 * (e.g. resource pointers).
280 scalePtr
= (Scale
*) ckalloc(sizeof(Scale
));
281 scalePtr
->tkwin
= new;
282 scalePtr
->interp
= interp
;
284 scalePtr
->command
= NULL
;
285 scalePtr
->label
= NULL
;
286 scalePtr
->state
= tkNormalUid
;
287 scalePtr
->bgBorder
= NULL
;
288 scalePtr
->sliderBorder
= NULL
;
289 scalePtr
->activeBorder
= NULL
;
290 scalePtr
->fontPtr
= NULL
;
291 scalePtr
->textColorPtr
= NULL
;
292 scalePtr
->textGC
= None
;
293 scalePtr
->cursor
= None
;
296 Tk_SetClass(scalePtr
->tkwin
, "Scale");
297 Tk_CreateEventHandler(scalePtr
->tkwin
, ExposureMask
|StructureNotifyMask
,
298 ScaleEventProc
, (ClientData
) scalePtr
);
299 Tk_CreateEventHandler(scalePtr
->tkwin
, EnterWindowMask
|LeaveWindowMask
300 |PointerMotionMask
|ButtonPressMask
|ButtonReleaseMask
,
301 ScaleMouseProc
, (ClientData
) scalePtr
);
302 Tcl_CreateCommand(interp
, Tk_PathName(scalePtr
->tkwin
), ScaleWidgetCmd
,
303 (ClientData
) scalePtr
, (void (*)(int *)) NULL
);
304 if (ConfigureScale(interp
, scalePtr
, argc
-2, argv
+2, 0) != TCL_OK
) {
308 interp
->result
= Tk_PathName(scalePtr
->tkwin
);
312 Tk_DestroyWindow(scalePtr
->tkwin
);
317 *--------------------------------------------------------------
321 * This procedure is invoked to process the Tcl command
322 * that corresponds to a widget managed by this module.
323 * See the user documentation for details on what it does.
326 * A standard Tcl result.
329 * See the user documentation.
331 *--------------------------------------------------------------
336 ClientData clientData
, /* Information about scale
338 Tcl_Interp
*interp
, /* Current interpreter. */
339 int argc
, /* Number of arguments. */
340 char **argv
/* Argument strings. */
343 register Scale
*scalePtr
= (Scale
*) clientData
;
349 Tcl_AppendResult(interp
, "wrong # args: should be \"",
350 argv
[0], " option ?arg arg ...?\"", (char *) NULL
);
353 Tk_Preserve((ClientData
) scalePtr
);
355 length
= strlen(argv
[1]);
356 if ((c
== 'c') && (strncmp(argv
[1], "configure", length
) == 0)) {
358 result
= Tk_ConfigureInfo(interp
, scalePtr
->tkwin
, configSpecs
,
359 (char *) scalePtr
, (char *) NULL
, 0);
360 } else if (argc
== 3) {
361 result
= Tk_ConfigureInfo(interp
, scalePtr
->tkwin
, configSpecs
,
362 (char *) scalePtr
, argv
[2], 0);
364 result
= ConfigureScale(interp
, scalePtr
, argc
-2, argv
+2,
365 TK_CONFIG_ARGV_ONLY
);
367 } else if ((c
== 'g') && (strncmp(argv
[1], "get", length
) == 0)) {
369 Tcl_AppendResult(interp
, "wrong # args: should be \"",
370 argv
[0], " get\"", (char *) NULL
);
373 sprintf(interp
->result
, "%d", scalePtr
->value
);
374 } else if ((c
== 's') && (strncmp(argv
[1], "set", length
) == 0)) {
378 Tcl_AppendResult(interp
, "wrong # args: should be \"",
379 argv
[0], " set value\"", (char *) NULL
);
382 if (Tcl_GetInt(interp
, argv
[2], &value
) != TCL_OK
) {
385 if (scalePtr
->state
== tkNormalUid
) {
386 if ((value
< scalePtr
->fromValue
)
387 ^ (scalePtr
->toValue
< scalePtr
->fromValue
)) {
388 value
= scalePtr
->fromValue
;
390 if ((value
> scalePtr
->toValue
)
391 ^ (scalePtr
->toValue
< scalePtr
->fromValue
)) {
392 value
= scalePtr
->toValue
;
394 SetScaleValue(scalePtr
, value
);
397 Tcl_AppendResult(interp
, "bad option \"", argv
[1],
398 "\": must be configure, get, or set", (char *) NULL
);
401 Tk_Release((ClientData
) scalePtr
);
405 Tk_Release((ClientData
) scalePtr
);
410 *----------------------------------------------------------------------
414 * This procedure is invoked by Tk_EventuallyFree or Tk_Release
415 * to clean up the internal structure of a button at a safe time
416 * (when no-one is using it anymore).
422 * Everything associated with the scale is freed up.
424 *----------------------------------------------------------------------
429 ClientData clientData
/* Info about scale widget. */
432 register Scale
*scalePtr
= (Scale
*) clientData
;
434 if (scalePtr
->command
!= NULL
) {
435 ckfree(scalePtr
->command
);
437 if (scalePtr
->label
!= NULL
) {
438 ckfree(scalePtr
->label
);
440 if (scalePtr
->bgBorder
!= NULL
) {
441 Tk_Free3DBorder(scalePtr
->bgBorder
);
443 if (scalePtr
->sliderBorder
!= NULL
) {
444 Tk_Free3DBorder(scalePtr
->sliderBorder
);
446 if (scalePtr
->activeBorder
!= NULL
) {
447 Tk_Free3DBorder(scalePtr
->activeBorder
);
449 if (scalePtr
->fontPtr
!= NULL
) {
450 Tk_FreeFontStruct(scalePtr
->fontPtr
);
452 if (scalePtr
->textColorPtr
!= NULL
) {
453 Tk_FreeColor(scalePtr
->textColorPtr
);
455 if (scalePtr
->textGC
!= None
) {
456 Tk_FreeGC(scalePtr
->textGC
);
458 if (scalePtr
->cursor
!= None
) {
459 Tk_FreeCursor(scalePtr
->cursor
);
461 ckfree((char *) scalePtr
);
465 *----------------------------------------------------------------------
469 * This procedure is called to process an argv/argc list, plus
470 * the Tk option database, in order to configure (or
471 * reconfigure) a scale widget.
474 * The return value is a standard Tcl result. If TCL_ERROR is
475 * returned, then interp->result contains an error message.
478 * Configuration information, such as colors, border width,
479 * etc. get set for scalePtr; old resources get freed,
482 *----------------------------------------------------------------------
487 Tcl_Interp
*interp
, /* Used for error reporting. */
488 register Scale
*scalePtr
, /* Information about widget; may or may
489 * not already have values for some fields. */
490 int argc
, /* Number of valid entries in argv. */
491 char **argv
, /* Arguments. */
492 int flags
/* Flags to pass to Tk_ConfigureWidget. */
499 if (Tk_ConfigureWidget(interp
, scalePtr
->tkwin
, configSpecs
,
500 argc
, argv
, (char *) scalePtr
, flags
) != TCL_OK
) {
505 * A few options need special processing, such as parsing the
506 * orientation or setting the background from a 3-D border.
509 length
= strlen(scalePtr
->orientUid
);
510 if (strncmp(scalePtr
->orientUid
, "vertical", length
) == 0) {
511 scalePtr
->vertical
= 1;
512 } else if (strncmp(scalePtr
->orientUid
, "horizontal", length
) == 0) {
513 scalePtr
->vertical
= 0;
515 Tcl_AppendResult(interp
, "bad orientation \"", scalePtr
->orientUid
,
516 "\": must be vertical or horizontal", (char *) NULL
);
520 if ((scalePtr
->state
!= tkNormalUid
)
521 && (scalePtr
->state
!= tkDisabledUid
)) {
522 Tcl_AppendResult(interp
, "bad state value \"", scalePtr
->state
,
523 "\": must be normal or disabled", (char *) NULL
);
524 scalePtr
->state
= tkNormalUid
;
529 * Make sure that the tick interval has the right sign so that
530 * addition moves from fromValue to toValue.
533 if ((scalePtr
->tickInterval
< 0)
534 ^ ((scalePtr
->toValue
- scalePtr
->fromValue
) < 0)) {
535 scalePtr
->tickInterval
= -scalePtr
->tickInterval
;
539 * Set the scale value to itself; all this does is to make sure
540 * that the scale's value is within the new acceptable range for
544 SetScaleValue(scalePtr
, scalePtr
->value
);
546 if (scalePtr
->command
!= NULL
) {
547 scalePtr
->commandLength
= strlen(scalePtr
->command
);
549 scalePtr
->commandLength
= 0;
552 if (scalePtr
->label
!= NULL
) {
553 scalePtr
->labelLength
= strlen(scalePtr
->label
);
555 scalePtr
->labelLength
= 0;
558 Tk_SetBackgroundFromBorder(scalePtr
->tkwin
, scalePtr
->bgBorder
);
560 gcValues
.font
= scalePtr
->fontPtr
->fid
;
561 gcValues
.foreground
= scalePtr
->textColorPtr
->pixel
;
562 newGC
= Tk_GetGC(scalePtr
->tkwin
, GCForeground
|GCFont
, &gcValues
);
563 if (scalePtr
->textGC
!= None
) {
564 Tk_FreeGC(scalePtr
->textGC
);
566 scalePtr
->textGC
= newGC
;
568 if (scalePtr
->relief
!= TK_RELIEF_FLAT
) {
569 scalePtr
->offset
= scalePtr
->borderWidth
;
571 scalePtr
->offset
= 0;
575 * Recompute display-related information, and let the geometry
576 * manager know how much space is needed now.
579 ComputeScaleGeometry(scalePtr
);
581 EventuallyRedrawScale(scalePtr
, REDRAW_ALL
);
586 *----------------------------------------------------------------------
588 * ComputeScaleGeometry --
590 * This procedure is called to compute various geometrical
591 * information for a scale, such as where various things get
592 * displayed. It's called when the window is reconfigured.
598 * Display-related numbers get changed in *scrollPtr. The
599 * geometry manager gets told about the window's preferred size.
601 *----------------------------------------------------------------------
605 ComputeScaleGeometry (
606 register Scale
*scalePtr
/* Information about widget. */
610 char valueString
[30];
611 int dummy
, lineHeight
;
614 * Horizontal scales are simpler than vertical ones because
615 * all sizes are the same (the height of a line of text);
616 * handle them first and then quit.
619 if (!scalePtr
->vertical
) {
620 lineHeight
= scalePtr
->fontPtr
->ascent
+ scalePtr
->fontPtr
->descent
;
621 if (scalePtr
->tickInterval
!= 0) {
622 scalePtr
->tickPixels
= lineHeight
;
624 scalePtr
->tickPixels
= 0;
626 if (scalePtr
->showValue
) {
627 scalePtr
->valuePixels
= lineHeight
+ SPACING
;
629 scalePtr
->valuePixels
= 0;
631 if (scalePtr
->labelLength
!= 0) {
632 scalePtr
->labelPixels
= lineHeight
;
634 scalePtr
->labelPixels
= 0;
637 Tk_GeometryRequest(scalePtr
->tkwin
,
638 scalePtr
->length
+ 2*scalePtr
->offset
,
639 scalePtr
->tickPixels
+ scalePtr
->valuePixels
640 + scalePtr
->width
+ 2*scalePtr
->borderWidth
641 + scalePtr
->labelPixels
+ 2*scalePtr
->offset
);
642 Tk_SetInternalBorder(scalePtr
->tkwin
, scalePtr
->borderWidth
);
647 * Vertical scale: compute the amount of space needed for tick marks
648 * and current value by formatting strings for the two end points;
649 * use whichever length is longer.
652 sprintf(valueString
, "%d", scalePtr
->fromValue
);
653 XTextExtents(scalePtr
->fontPtr
, valueString
, strlen(valueString
),
654 &dummy
, &dummy
, &dummy
, &bbox
);
655 scalePtr
->tickPixels
= bbox
.rbearing
+ bbox
.lbearing
;
656 sprintf(valueString
, "%d", scalePtr
->toValue
);
657 XTextExtents(scalePtr
->fontPtr
, valueString
, strlen(valueString
),
658 &dummy
, &dummy
, &dummy
, &bbox
);
659 if (scalePtr
->tickPixels
< bbox
.rbearing
+ bbox
.lbearing
) {
660 scalePtr
->tickPixels
= bbox
.rbearing
+ bbox
.lbearing
;
664 * Pad the value with a bit of extra space for prettier printing.
667 scalePtr
->tickPixels
+= scalePtr
->fontPtr
->ascent
/2;
668 scalePtr
->valuePixels
= scalePtr
->tickPixels
;
669 if (scalePtr
->tickInterval
== 0) {
670 scalePtr
->tickPixels
= 0;
672 if (!scalePtr
->showValue
) {
673 scalePtr
->valuePixels
= 0;
676 if (scalePtr
->labelLength
== 0) {
677 scalePtr
->labelPixels
= 0;
679 XTextExtents(scalePtr
->fontPtr
, scalePtr
->label
,
680 scalePtr
->labelLength
, &dummy
, &dummy
, &dummy
, &bbox
);
681 scalePtr
->labelPixels
= bbox
.rbearing
+ bbox
.lbearing
682 + scalePtr
->fontPtr
->ascent
;
684 Tk_GeometryRequest(scalePtr
->tkwin
, 4*scalePtr
->borderWidth
685 + scalePtr
->tickPixels
+ scalePtr
->valuePixels
+ SPACING
686 + scalePtr
->width
+ scalePtr
->labelPixels
,
688 Tk_SetInternalBorder(scalePtr
->tkwin
, scalePtr
->borderWidth
);
692 *--------------------------------------------------------------
694 * DisplayVerticalScale --
696 * This procedure redraws the contents of a vertical scale
697 * window. It is invoked as a do-when-idle handler, so it only
698 * runs when there's nothing else for the application to do.
704 * Information appears on the screen.
706 *--------------------------------------------------------------
710 DisplayVerticalScale (
711 ClientData clientData
/* Information about widget. */
714 register Scale
*scalePtr
= (Scale
*) clientData
;
715 register Tk_Window tkwin
= scalePtr
->tkwin
;
716 int tickRightEdge
, valueRightEdge
, labelLeftEdge
, scaleLeftEdge
;
717 int totalPixels
, x
, y
, width
, height
, shadowWidth
, tickValue
;
719 Tk_3DBorder sliderBorder
;
721 if ((scalePtr
->tkwin
== NULL
) || !Tk_IsMapped(tkwin
)) {
726 * Scanning from left to right across the window, the window
727 * will contain four columns: ticks, value, scale, and label.
728 * Compute the x-coordinate for each of the columns.
731 totalPixels
= scalePtr
->tickPixels
+ scalePtr
->valuePixels
732 + 2*scalePtr
->borderWidth
+ scalePtr
->width
733 + 2*SPACING
+ scalePtr
->labelPixels
;
734 tickRightEdge
= (Tk_Width(tkwin
) - totalPixels
)/2 + scalePtr
->tickPixels
;
735 valueRightEdge
= tickRightEdge
+ scalePtr
->valuePixels
;
736 scaleLeftEdge
= valueRightEdge
+ SPACING
;
737 labelLeftEdge
= scaleLeftEdge
+ 2*scalePtr
->borderWidth
738 + scalePtr
->width
+ scalePtr
->fontPtr
->ascent
/2;
741 * Display the information from left to right across the window.
744 if (scalePtr
->flags
& REDRAW_OTHER
) {
745 XClearWindow(Tk_Display(tkwin
), Tk_WindowId(tkwin
));
748 * Display the tick marks.
751 if (scalePtr
->tickPixels
!= 0) {
752 for (tickValue
= scalePtr
->fromValue
; ;
753 tickValue
+= scalePtr
->tickInterval
) {
754 if (scalePtr
->toValue
> scalePtr
->fromValue
) {
755 if (tickValue
> scalePtr
->toValue
) {
759 if (tickValue
< scalePtr
->toValue
) {
763 DisplayVerticalValue(scalePtr
, tickValue
, tickRightEdge
);
769 * Display the value, if it is desired. If not redisplaying the
770 * entire window, clear the area of the value to get rid of the
771 * old value displayed there.
774 if (scalePtr
->showValue
) {
775 if (!(scalePtr
->flags
& REDRAW_OTHER
)) {
776 XClearArea(Tk_Display(tkwin
), Tk_WindowId(tkwin
),
777 valueRightEdge
-scalePtr
->valuePixels
, scalePtr
->offset
,
778 scalePtr
->valuePixels
,
779 Tk_Height(tkwin
) - 2*scalePtr
->offset
, False
);
781 DisplayVerticalValue(scalePtr
, scalePtr
->value
, valueRightEdge
);
785 * Display the scale and the slider. If not redisplaying the
786 * entire window, must clear the trench area to erase the old
787 * slider, but don't need to redraw the border.
790 if (scalePtr
->flags
& REDRAW_OTHER
) {
791 Tk_Draw3DRectangle(Tk_Display(tkwin
), Tk_WindowId(tkwin
),
792 scalePtr
->bgBorder
, scaleLeftEdge
, scalePtr
->offset
,
793 scalePtr
->width
+ 2*scalePtr
->borderWidth
,
794 Tk_Height(tkwin
) - 2*scalePtr
->offset
, scalePtr
->borderWidth
,
797 XClearArea(Tk_Display(tkwin
), Tk_WindowId(tkwin
),
798 scaleLeftEdge
+ scalePtr
->borderWidth
,
799 scalePtr
->offset
+ scalePtr
->borderWidth
,
801 Tk_Height(tkwin
) - 2*scalePtr
->offset
802 - 2*scalePtr
->borderWidth
, False
);
804 if (scalePtr
->flags
& ACTIVE
) {
805 sliderBorder
= scalePtr
->activeBorder
;
807 sliderBorder
= scalePtr
->sliderBorder
;
809 width
= scalePtr
->width
;
810 height
= scalePtr
->sliderLength
/2;
811 x
= scaleLeftEdge
+ scalePtr
->borderWidth
;
812 y
= ValueToPixel(scalePtr
, scalePtr
->value
) - height
;
813 shadowWidth
= scalePtr
->borderWidth
/2;
814 if (shadowWidth
== 0) {
817 relief
= (scalePtr
->flags
& BUTTON_PRESSED
) ? TK_RELIEF_SUNKEN
819 Tk_Draw3DRectangle(Tk_Display(tkwin
), Tk_WindowId(tkwin
), sliderBorder
,
820 x
, y
, width
, 2*height
, shadowWidth
, relief
);
823 width
-= 2*shadowWidth
;
824 height
-= shadowWidth
;
825 Tk_Fill3DRectangle(Tk_Display(tkwin
), Tk_WindowId(tkwin
), sliderBorder
,
826 x
, y
, width
, height
, shadowWidth
, relief
);
827 Tk_Fill3DRectangle(Tk_Display(tkwin
), Tk_WindowId(tkwin
), sliderBorder
,
828 x
, y
+height
, width
, height
, shadowWidth
, relief
);
831 * Draw the label to the right of the scale.
834 if ((scalePtr
->flags
& REDRAW_OTHER
) && (scalePtr
->labelPixels
!= 0)) {
835 XDrawString(Tk_Display(scalePtr
->tkwin
), Tk_WindowId(scalePtr
->tkwin
),
836 scalePtr
->textGC
, labelLeftEdge
,
837 scalePtr
->offset
+ (3*scalePtr
->fontPtr
->ascent
)/2,
838 scalePtr
->label
, scalePtr
->labelLength
);
842 * Draw the window border.
845 if ((scalePtr
->flags
& REDRAW_OTHER
)
846 && (scalePtr
->relief
!= TK_RELIEF_FLAT
)) {
847 Tk_Draw3DRectangle(Tk_Display(tkwin
), Tk_WindowId(tkwin
),
848 scalePtr
->bgBorder
, 0, 0, Tk_Width(tkwin
), Tk_Height(tkwin
),
849 scalePtr
->borderWidth
, scalePtr
->relief
);
853 scalePtr
->flags
&= ~REDRAW_ALL
;
857 *----------------------------------------------------------------------
859 * DisplayVerticalValue --
861 * This procedure is called to display values (scale readings)
862 * for vertically-oriented scales.
868 * The numerical value corresponding to value is displayed with
869 * its right edge at "rightEdge", and at a vertical position in
870 * the scale that corresponds to "value".
872 *----------------------------------------------------------------------
876 DisplayVerticalValue (
877 register Scale
*scalePtr
, /* Information about widget in which to
879 int value
, /* Y-coordinate of number to display,
880 * specified in application coords, not
881 * in pixels (we'll compute pixels). */
882 int rightEdge
/* X-coordinate of right edge of text,
883 * specified in pixels. */
886 register Tk_Window tkwin
= scalePtr
->tkwin
;
887 int y
, dummy
, length
;
888 char valueString
[30];
891 y
= ValueToPixel(scalePtr
, value
) + scalePtr
->fontPtr
->ascent
/2;
892 sprintf(valueString
, "%d", value
);
893 length
= strlen(valueString
);
894 XTextExtents(scalePtr
->fontPtr
, valueString
, length
,
895 &dummy
, &dummy
, &dummy
, &bbox
);
898 * Adjust the y-coordinate if necessary to keep the text entirely
902 if ((y
- bbox
.ascent
) < scalePtr
->offset
) {
903 y
= scalePtr
->offset
+ bbox
.ascent
;
905 if ((y
+ bbox
.descent
) > (Tk_Height(tkwin
) - scalePtr
->offset
)) {
906 y
= Tk_Height(tkwin
) - scalePtr
->offset
- bbox
.descent
;
908 XDrawString(Tk_Display(tkwin
), Tk_WindowId(tkwin
),
909 scalePtr
->textGC
, rightEdge
- bbox
.rbearing
,
910 y
, valueString
, length
);
914 *--------------------------------------------------------------
916 * DisplayHorizontalScale --
918 * This procedure redraws the contents of a horizontal scale
919 * window. It is invoked as a do-when-idle handler, so it only
920 * runs when there's nothing else for the application to do.
926 * Information appears on the screen.
928 *--------------------------------------------------------------
932 DisplayHorizontalScale (
933 ClientData clientData
/* Information about widget. */
936 register Scale
*scalePtr
= (Scale
*) clientData
;
937 register Tk_Window tkwin
= scalePtr
->tkwin
;
938 int tickBottom
, valueBottom
, labelBottom
, scaleBottom
;
939 int totalPixels
, x
, y
, width
, height
, shadowWidth
, tickValue
;
941 Tk_3DBorder sliderBorder
;
943 if ((scalePtr
->tkwin
== NULL
) || !Tk_IsMapped(tkwin
)) {
948 * Scanning from bottom to top across the window, the window
949 * will contain four rows: ticks, value, scale, and label.
950 * Compute the y-coordinate for each of the rows.
953 totalPixels
= scalePtr
->tickPixels
+ scalePtr
->valuePixels
954 + 2*scalePtr
->borderWidth
+ scalePtr
->width
955 + scalePtr
->labelPixels
;
956 tickBottom
= (Tk_Height(tkwin
) + totalPixels
)/2 - 1;
957 valueBottom
= tickBottom
- scalePtr
->tickPixels
;
958 scaleBottom
= valueBottom
- scalePtr
->valuePixels
;
959 labelBottom
= scaleBottom
- 2*scalePtr
->borderWidth
- scalePtr
->width
;
962 * Display the information from bottom to top across the window.
965 if (scalePtr
->flags
& REDRAW_OTHER
) {
966 XClearWindow(Tk_Display(tkwin
), Tk_WindowId(tkwin
));
969 * Display the tick marks.
972 if (scalePtr
->tickPixels
!= 0) {
973 for (tickValue
= scalePtr
->fromValue
; ;
974 tickValue
+= scalePtr
->tickInterval
) {
975 if (scalePtr
->toValue
> scalePtr
->fromValue
) {
976 if (tickValue
> scalePtr
->toValue
) {
980 if (tickValue
< scalePtr
->toValue
) {
984 DisplayHorizontalValue(scalePtr
, tickValue
, tickBottom
);
990 * Display the value, if it is desired. If not redisplaying the
991 * entire window, clear the area of the value to get rid of the
992 * old value displayed there.
995 if (scalePtr
->showValue
) {
996 if (!(scalePtr
->flags
& REDRAW_OTHER
)) {
997 XClearArea(Tk_Display(tkwin
), Tk_WindowId(tkwin
),
998 scalePtr
->offset
, scaleBottom
+ 1,
999 Tk_Width(tkwin
) - 2*scalePtr
->offset
,
1000 valueBottom
- scaleBottom
, False
);
1002 DisplayHorizontalValue(scalePtr
, scalePtr
->value
, valueBottom
);
1006 * Display the scale and the slider. If not redisplaying the
1007 * entire window, must clear the trench area to erase the old
1008 * slider, but don't need to redraw the border.
1011 y
= scaleBottom
- 2*scalePtr
->borderWidth
- scalePtr
->width
+ 1;
1012 if (scalePtr
->flags
& REDRAW_OTHER
) {
1013 Tk_Draw3DRectangle(Tk_Display(tkwin
), Tk_WindowId(tkwin
),
1014 scalePtr
->bgBorder
, scalePtr
->offset
, y
,
1015 Tk_Width(tkwin
) - 2*scalePtr
->offset
,
1016 scalePtr
->width
+ 2*scalePtr
->borderWidth
,
1017 scalePtr
->borderWidth
, TK_RELIEF_SUNKEN
);
1019 XClearArea(Tk_Display(tkwin
), Tk_WindowId(tkwin
),
1020 scalePtr
->offset
+ scalePtr
->borderWidth
,
1021 y
+ scalePtr
->borderWidth
,
1022 Tk_Width(tkwin
) - 2*scalePtr
->offset
- 2*scalePtr
->borderWidth
,
1023 scalePtr
->width
, False
);
1025 if (scalePtr
->flags
& ACTIVE
) {
1026 sliderBorder
= scalePtr
->activeBorder
;
1028 sliderBorder
= scalePtr
->sliderBorder
;
1030 width
= scalePtr
->sliderLength
/2;
1031 height
= scalePtr
->width
;
1032 x
= ValueToPixel(scalePtr
, scalePtr
->value
) - width
;
1033 y
+= scalePtr
->borderWidth
;
1034 shadowWidth
= scalePtr
->borderWidth
/2;
1035 if (shadowWidth
== 0) {
1038 relief
= (scalePtr
->flags
& BUTTON_PRESSED
) ? TK_RELIEF_SUNKEN
1040 Tk_Draw3DRectangle(Tk_Display(tkwin
), Tk_WindowId(tkwin
), sliderBorder
,
1041 x
, y
, 2*width
, height
, shadowWidth
, relief
);
1044 width
-= shadowWidth
;
1045 height
-= 2*shadowWidth
;
1046 Tk_Fill3DRectangle(Tk_Display(tkwin
), Tk_WindowId(tkwin
), sliderBorder
,
1047 x
, y
, width
, height
, shadowWidth
, relief
);
1048 Tk_Fill3DRectangle(Tk_Display(tkwin
), Tk_WindowId(tkwin
), sliderBorder
,
1049 x
+width
, y
, width
, height
, shadowWidth
, relief
);
1052 * Draw the label to the top of the scale.
1055 if ((scalePtr
->flags
& REDRAW_OTHER
) && (scalePtr
->labelPixels
!= 0)) {
1056 XDrawString(Tk_Display(scalePtr
->tkwin
), Tk_WindowId(scalePtr
->tkwin
),
1057 scalePtr
->textGC
, scalePtr
->offset
+ scalePtr
->fontPtr
->ascent
/2,
1058 labelBottom
- scalePtr
->fontPtr
->descent
,
1059 scalePtr
->label
, scalePtr
->labelLength
);
1063 * Draw the window border.
1066 if ((scalePtr
->flags
& REDRAW_OTHER
)
1067 && (scalePtr
->relief
!= TK_RELIEF_FLAT
)) {
1068 Tk_Draw3DRectangle(Tk_Display(tkwin
), Tk_WindowId(tkwin
),
1069 scalePtr
->bgBorder
, 0, 0, Tk_Width(tkwin
), Tk_Height(tkwin
),
1070 scalePtr
->borderWidth
, scalePtr
->relief
);
1074 scalePtr
->flags
&= ~REDRAW_ALL
;
1078 *----------------------------------------------------------------------
1080 * DisplayHorizontalValue --
1082 * This procedure is called to display values (scale readings)
1083 * for horizontally-oriented scales.
1089 * The numerical value corresponding to value is displayed with
1090 * its bottom edge at "bottom", and at a horizontal position in
1091 * the scale that corresponds to "value".
1093 *----------------------------------------------------------------------
1097 DisplayHorizontalValue (
1098 register Scale
*scalePtr
, /* Information about widget in which to
1100 int value
, /* Y-coordinate of number to display,
1101 * specified in application coords, not
1102 * in pixels (we'll compute pixels). */
1103 int bottom
/* Y-coordinate of bottom edge of text,
1104 * specified in pixels. */
1107 register Tk_Window tkwin
= scalePtr
->tkwin
;
1108 int x
, y
, dummy
, length
;
1109 char valueString
[30];
1112 x
= ValueToPixel(scalePtr
, value
);
1113 y
= bottom
- scalePtr
->fontPtr
->descent
;
1114 sprintf(valueString
, "%d", value
);
1115 length
= strlen(valueString
);
1116 XTextExtents(scalePtr
->fontPtr
, valueString
, length
,
1117 &dummy
, &dummy
, &dummy
, &bbox
);
1120 * Adjust the x-coordinate if necessary to keep the text entirely
1121 * inside the window.
1124 x
-= (bbox
.lbearing
+ bbox
.rbearing
)/2;
1125 if ((x
- bbox
.lbearing
) < scalePtr
->offset
) {
1126 x
= scalePtr
->offset
+ bbox
.lbearing
;
1128 if ((y
+ bbox
.rbearing
) > (Tk_Width(tkwin
) - scalePtr
->offset
)) {
1129 x
= Tk_Width(tkwin
) - scalePtr
->offset
- bbox
.rbearing
;
1131 XDrawString(Tk_Display(tkwin
), Tk_WindowId(tkwin
),
1132 scalePtr
->textGC
, x
, y
, valueString
, length
);
1136 *----------------------------------------------------------------------
1140 * Given a pixel within a scale window, return the scale
1141 * reading corresponding to that pixel.
1144 * An integer scale reading.
1149 *----------------------------------------------------------------------
1154 register Scale
*scalePtr
, /* Information about widget. */
1156 int y
/* Coordinates of point within
1160 int value
, pixelRange
;
1162 if (scalePtr
->vertical
) {
1163 pixelRange
= Tk_Height(scalePtr
->tkwin
) - scalePtr
->sliderLength
1164 - 2*scalePtr
->offset
- 2*scalePtr
->borderWidth
;
1167 pixelRange
= Tk_Width(scalePtr
->tkwin
) - scalePtr
->sliderLength
1168 - 2*scalePtr
->offset
- 2*scalePtr
->borderWidth
;
1172 if (pixelRange
<= 0) {
1174 * Not enough room for the slider to actually slide: just return
1175 * the scale's current value.
1178 return scalePtr
->value
;
1180 value
-= scalePtr
->sliderLength
/2 + scalePtr
->offset
1181 + scalePtr
->borderWidth
;
1185 if (value
> pixelRange
) {
1188 if (scalePtr
->toValue
> scalePtr
->fromValue
) {
1189 value
= scalePtr
->fromValue
+
1190 ((value
* (scalePtr
->toValue
- scalePtr
->fromValue
))
1191 + pixelRange
/2)/pixelRange
;
1193 value
= scalePtr
->toValue
+
1194 (((pixelRange
- value
)
1195 * (scalePtr
->fromValue
- scalePtr
->toValue
))
1196 + pixelRange
/2)/pixelRange
;
1202 *----------------------------------------------------------------------
1206 * Given a reading of the scale, return the x-coordinate or
1207 * y-coordinate corresponding to that reading, depending on
1208 * whether the scale is vertical or horizontal, respectively.
1211 * An integer value giving the pixel location corresponding
1212 * to reading. The value is restricted to lie within the
1213 * defined range for the scale.
1218 *----------------------------------------------------------------------
1223 register Scale
*scalePtr
, /* Information about widget. */
1224 int value
/* Reading of the widget. */
1227 int y
, pixelRange
, valueRange
;
1229 valueRange
= scalePtr
->toValue
- scalePtr
->fromValue
;
1230 pixelRange
= (scalePtr
->vertical
? Tk_Height(scalePtr
->tkwin
)
1231 : Tk_Width(scalePtr
->tkwin
)) - scalePtr
->sliderLength
1232 - 2*scalePtr
->offset
- 2*scalePtr
->borderWidth
;
1233 y
= ((value
- scalePtr
->fromValue
) * pixelRange
1234 + valueRange
/2) / valueRange
;
1237 } else if (y
> pixelRange
) {
1240 y
+= scalePtr
->sliderLength
/2 + scalePtr
->offset
+ scalePtr
->borderWidth
;
1245 *--------------------------------------------------------------
1249 * This procedure is invoked by the Tk dispatcher for various
1256 * When the window gets deleted, internal structures get
1257 * cleaned up. When it gets exposed, it is redisplayed.
1259 *--------------------------------------------------------------
1264 ClientData clientData
, /* Information about window. */
1265 XEvent
*eventPtr
/* Information about event. */
1268 Scale
*scalePtr
= (Scale
*) clientData
;
1270 if ((eventPtr
->type
== Expose
) && (eventPtr
->xexpose
.count
== 0)) {
1271 EventuallyRedrawScale(scalePtr
, REDRAW_ALL
);
1272 } else if (eventPtr
->type
== DestroyNotify
) {
1273 Tcl_DeleteCommand(scalePtr
->interp
, Tk_PathName(scalePtr
->tkwin
));
1274 scalePtr
->tkwin
= NULL
;
1275 if (scalePtr
->flags
& REDRAW_ALL
) {
1276 if (scalePtr
->vertical
) {
1277 Tk_CancelIdleCall(DisplayVerticalScale
, (ClientData
) scalePtr
);
1279 Tk_CancelIdleCall(DisplayHorizontalScale
,
1280 (ClientData
) scalePtr
);
1283 Tk_EventuallyFree((ClientData
) scalePtr
, DestroyScale
);
1284 } else if (eventPtr
->type
== ConfigureNotify
) {
1285 ComputeScaleGeometry(scalePtr
);
1290 *--------------------------------------------------------------
1294 * This procedure is called back by Tk in response to
1295 * mouse events such as window entry, window exit, mouse
1296 * motion, and button presses.
1302 * This procedure implements the "feel" of the scale by
1303 * issuing commands in response to button presses and mouse
1306 *--------------------------------------------------------------
1311 ClientData clientData
, /* Information about window. */
1312 register XEvent
*eventPtr
/* Information about event. */
1315 register Scale
*scalePtr
= (Scale
*) clientData
;
1317 if (scalePtr
->state
!= tkNormalUid
) {
1321 Tk_Preserve((ClientData
) scalePtr
);
1322 if (eventPtr
->type
== EnterNotify
) {
1323 scalePtr
->flags
|= ACTIVE
;
1324 EventuallyRedrawScale(scalePtr
, REDRAW_SLIDER
);
1325 } else if (eventPtr
->type
== LeaveNotify
) {
1326 scalePtr
->flags
&= ~ACTIVE
;
1327 EventuallyRedrawScale(scalePtr
, REDRAW_SLIDER
);
1328 } else if ((eventPtr
->type
== MotionNotify
)
1329 && (scalePtr
->flags
& BUTTON_PRESSED
)) {
1330 SetScaleValue(scalePtr
, PixelToValue(scalePtr
,
1331 eventPtr
->xmotion
.x
, eventPtr
->xmotion
.y
));
1332 } else if ((eventPtr
->type
== ButtonPress
)
1333 /* && (eventPtr->xbutton.button == Button1) */
1334 && ((eventPtr
->xbutton
.state
& ALL_BUTTONS
) == 0)) {
1335 scalePtr
->flags
|= BUTTON_PRESSED
;
1336 SetScaleValue(scalePtr
, PixelToValue(scalePtr
,
1337 eventPtr
->xbutton
.x
, eventPtr
->xbutton
.y
));
1338 EventuallyRedrawScale(scalePtr
, REDRAW_SLIDER
);
1339 } else if ((eventPtr
->type
== ButtonRelease
)
1340 /* && (eventPtr->xbutton.button == Button1) */
1341 && (scalePtr
->flags
& BUTTON_PRESSED
)) {
1342 scalePtr
->flags
&= ~BUTTON_PRESSED
;
1343 EventuallyRedrawScale(scalePtr
, REDRAW_SLIDER
);
1345 Tk_Release((ClientData
) scalePtr
);
1349 *--------------------------------------------------------------
1353 * This procedure changes the value of a scale and invokes
1354 * a Tcl command to reflect the current position of a scale
1360 * A Tcl command is invoked, and an additional error-processing
1361 * command may also be invoked. The scale's slider is redrawn.
1363 *--------------------------------------------------------------
1368 register Scale
*scalePtr
, /* Info about widget. */
1369 int value
/* New value for scale. Gets
1370 * adjusted if it's off the scale. */
1376 if ((value
< scalePtr
->fromValue
)
1377 ^ (scalePtr
->toValue
< scalePtr
->fromValue
)) {
1378 value
= scalePtr
->fromValue
;
1380 if ((value
> scalePtr
->toValue
)
1381 ^ (scalePtr
->toValue
< scalePtr
->fromValue
)) {
1382 value
= scalePtr
->toValue
;
1384 if (value
== scalePtr
->value
) {
1387 scalePtr
->value
= value
;
1388 EventuallyRedrawScale(scalePtr
, REDRAW_SLIDER
);
1390 sprintf(string
, " %d", scalePtr
->value
);
1391 result
= Tcl_VarEval(scalePtr
->interp
, scalePtr
->command
, string
,
1393 if (result
!= TCL_OK
) {
1394 TkBindError(scalePtr
->interp
);
1399 *--------------------------------------------------------------
1401 * EventuallyRedrawScale --
1403 * Arrange for part or all of a scale widget to redrawn at
1404 * the next convenient time in the future.
1410 * If "what" is REDRAW_SLIDER then just the slider and the
1411 * value readout will be redrawn; if "what" is REDRAW_ALL
1412 * then the entire widget will be redrawn.
1414 *--------------------------------------------------------------
1418 EventuallyRedrawScale (
1419 register Scale
*scalePtr
, /* Information about widget. */
1420 int what
/* What to redraw: REDRAW_SLIDER
1424 if ((what
== 0) || (scalePtr
->tkwin
== NULL
)
1425 || !Tk_IsMapped(scalePtr
->tkwin
)) {
1428 if ((scalePtr
->flags
& REDRAW_ALL
) == 0) {
1429 if (scalePtr
->vertical
) {
1430 Tk_DoWhenIdle(DisplayVerticalScale
, (ClientData
) scalePtr
);
1432 Tk_DoWhenIdle(DisplayHorizontalScale
, (ClientData
) scalePtr
);
1435 scalePtr
->flags
|= what
;