OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tk/] [unix/] [tkUnixScale.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tkUnixScale.c --
3
 *
4
 *      This file implements the X specific portion of the scrollbar
5
 *      widget.
6
 *
7
 * Copyright (c) 1996 by Sun Microsystems, Inc.
8
 *
9
 * See the file "license.terms" for information on usage and redistribution
10
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11
 *
12
 * RCS: @(#) $Id: tkUnixScale.c,v 1.1.1.1 2002-01-16 10:26:01 markom Exp $
13
 */
14
 
15
#include "tkScale.h"
16
#include "tkInt.h"
17
 
18
/*
19
 * Forward declarations for procedures defined later in this file:
20
 */
21
 
22
static void             DisplayHorizontalScale _ANSI_ARGS_((TkScale *scalePtr,
23
                            Drawable drawable, XRectangle *drawnAreaPtr));
24
static void             DisplayHorizontalValue _ANSI_ARGS_((TkScale *scalePtr,
25
                            Drawable drawable, double value, int top));
26
static void             DisplayVerticalScale _ANSI_ARGS_((TkScale *scalePtr,
27
                            Drawable drawable, XRectangle *drawnAreaPtr));
28
static void             DisplayVerticalValue _ANSI_ARGS_((TkScale *scalePtr,
29
                            Drawable drawable, double value, int rightEdge));
30
 
31
/*
32
 *----------------------------------------------------------------------
33
 *
34
 * TkpCreateScale --
35
 *
36
 *      Allocate a new TkScale structure.
37
 *
38
 * Results:
39
 *      Returns a newly allocated TkScale structure.
40
 *
41
 * Side effects:
42
 *      None.
43
 *
44
 *----------------------------------------------------------------------
45
 */
46
 
47
TkScale *
48
TkpCreateScale(tkwin)
49
    Tk_Window tkwin;
50
{
51
    return (TkScale *) ckalloc(sizeof(TkScale));
52
}
53
 
54
/*
55
 *----------------------------------------------------------------------
56
 *
57
 * TkpDestroyScale --
58
 *
59
 *      Destroy a TkScale structure.
60
 *
61
 * Results:
62
 *      None
63
 *
64
 * Side effects:
65
 *      Memory is freed.
66
 *
67
 *----------------------------------------------------------------------
68
 */
69
 
70
void
71
TkpDestroyScale(scalePtr)
72
    TkScale *scalePtr;
73
{
74
    ckfree((char *) scalePtr);
75
}
76
 
77
/*
78
 *--------------------------------------------------------------
79
 *
80
 * DisplayVerticalScale --
81
 *
82
 *      This procedure redraws the contents of a vertical scale
83
 *      window.  It is invoked as a do-when-idle handler, so it only
84
 *      runs when there's nothing else for the application to do.
85
 *
86
 * Results:
87
 *      There is no return value.  If only a part of the scale needs
88
 *      to be redrawn, then drawnAreaPtr is modified to reflect the
89
 *      area that was actually modified.
90
 *
91
 * Side effects:
92
 *      Information appears on the screen.
93
 *
94
 *--------------------------------------------------------------
95
 */
96
 
97
static void
98
DisplayVerticalScale(scalePtr, drawable, drawnAreaPtr)
99
    TkScale *scalePtr;                  /* Widget record for scale. */
100
    Drawable drawable;                  /* Where to display scale (window
101
                                         * or pixmap). */
102
    XRectangle *drawnAreaPtr;           /* Initally contains area of window;
103
                                         * if only a part of the scale is
104
                                         * redrawn, gets modified to reflect
105
                                         * the part of the window that was
106
                                         * redrawn. */
107
{
108
    Tk_Window tkwin = scalePtr->tkwin;
109
    int x, y, width, height, shadowWidth;
110
    double tickValue;
111
    Tk_3DBorder sliderBorder;
112
 
113
    /*
114
     * Display the information from left to right across the window.
115
     */
116
 
117
    if (!(scalePtr->flags & REDRAW_OTHER)) {
118
        drawnAreaPtr->x = scalePtr->vertTickRightX;
119
        drawnAreaPtr->y = scalePtr->inset;
120
        drawnAreaPtr->width = scalePtr->vertTroughX + scalePtr->width
121
                + 2*scalePtr->borderWidth - scalePtr->vertTickRightX;
122
        drawnAreaPtr->height -= 2*scalePtr->inset;
123
    }
124
    Tk_Fill3DRectangle(tkwin, drawable, scalePtr->bgBorder,
125
            drawnAreaPtr->x, drawnAreaPtr->y, drawnAreaPtr->width,
126
            drawnAreaPtr->height, 0, TK_RELIEF_FLAT);
127
    if (scalePtr->flags & REDRAW_OTHER) {
128
        /*
129
         * Display the tick marks.
130
         */
131
 
132
        if (scalePtr->tickInterval != 0) {
133
            for (tickValue = scalePtr->fromValue; ;
134
                    tickValue += scalePtr->tickInterval) {
135
                /*
136
                 * The TkRoundToResolution call gets rid of accumulated
137
                 * round-off errors, if any.
138
                 */
139
 
140
                tickValue = TkRoundToResolution(scalePtr, tickValue);
141
                if (scalePtr->toValue >= scalePtr->fromValue) {
142
                    if (tickValue > scalePtr->toValue) {
143
                        break;
144
                    }
145
                } else {
146
                    if (tickValue < scalePtr->toValue) {
147
                        break;
148
                    }
149
                }
150
                DisplayVerticalValue(scalePtr, drawable, tickValue,
151
                        scalePtr->vertTickRightX);
152
            }
153
        }
154
    }
155
 
156
    /*
157
     * Display the value, if it is desired.
158
     */
159
 
160
    if (scalePtr->showValue) {
161
        DisplayVerticalValue(scalePtr, drawable, scalePtr->value,
162
                scalePtr->vertValueRightX);
163
    }
164
 
165
    /*
166
     * Display the trough and the slider.
167
     */
168
 
169
    Tk_Draw3DRectangle(tkwin, drawable,
170
            scalePtr->bgBorder, scalePtr->vertTroughX, scalePtr->inset,
171
            scalePtr->width + 2*scalePtr->borderWidth,
172
            Tk_Height(tkwin) - 2*scalePtr->inset, scalePtr->borderWidth,
173
            TK_RELIEF_SUNKEN);
174
    XFillRectangle(scalePtr->display, drawable, scalePtr->troughGC,
175
            scalePtr->vertTroughX + scalePtr->borderWidth,
176
            scalePtr->inset + scalePtr->borderWidth,
177
            (unsigned) scalePtr->width,
178
            (unsigned) (Tk_Height(tkwin) - 2*scalePtr->inset
179
                - 2*scalePtr->borderWidth));
180
    if (scalePtr->state == tkActiveUid) {
181
        sliderBorder = scalePtr->activeBorder;
182
    } else {
183
        sliderBorder = scalePtr->bgBorder;
184
    }
185
    width = scalePtr->width;
186
    height = scalePtr->sliderLength/2;
187
    x = scalePtr->vertTroughX + scalePtr->borderWidth;
188
    y = TkpValueToPixel(scalePtr, scalePtr->value) - height;
189
    shadowWidth = scalePtr->borderWidth/2;
190
    if (shadowWidth == 0) {
191
        shadowWidth = 1;
192
    }
193
    Tk_Draw3DRectangle(tkwin, drawable, sliderBorder, x, y, width,
194
            2*height, shadowWidth, scalePtr->sliderRelief);
195
    x += shadowWidth;
196
    y += shadowWidth;
197
    width -= 2*shadowWidth;
198
    height -= shadowWidth;
199
    Tk_Fill3DRectangle(tkwin, drawable, sliderBorder, x, y, width,
200
            height, shadowWidth, scalePtr->sliderRelief);
201
    Tk_Fill3DRectangle(tkwin, drawable, sliderBorder, x, y+height,
202
            width, height, shadowWidth, scalePtr->sliderRelief);
203
 
204
    /*
205
     * Draw the label to the right of the scale.
206
     */
207
 
208
    if ((scalePtr->flags & REDRAW_OTHER) && (scalePtr->labelLength != 0)) {
209
        Tk_FontMetrics fm;
210
 
211
        Tk_GetFontMetrics(scalePtr->tkfont, &fm);
212
        Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC,
213
                scalePtr->tkfont, scalePtr->label, scalePtr->labelLength,
214
                scalePtr->vertLabelX, scalePtr->inset + (3*fm.ascent)/2);
215
    }
216
}
217
 
218
/*
219
 *----------------------------------------------------------------------
220
 *
221
 * DisplayVerticalValue --
222
 *
223
 *      This procedure is called to display values (scale readings)
224
 *      for vertically-oriented scales.
225
 *
226
 * Results:
227
 *      None.
228
 *
229
 * Side effects:
230
 *      The numerical value corresponding to value is displayed with
231
 *      its right edge at "rightEdge", and at a vertical position in
232
 *      the scale that corresponds to "value".
233
 *
234
 *----------------------------------------------------------------------
235
 */
236
 
237
static void
238
DisplayVerticalValue(scalePtr, drawable, value, rightEdge)
239
    register TkScale *scalePtr; /* Information about widget in which to
240
                                 * display value. */
241
    Drawable drawable;          /* Pixmap or window in which to draw
242
                                 * the value. */
243
    double value;               /* Y-coordinate of number to display,
244
                                 * specified in application coords, not
245
                                 * in pixels (we'll compute pixels). */
246
    int rightEdge;              /* X-coordinate of right edge of text,
247
                                 * specified in pixels. */
248
{
249
    register Tk_Window tkwin = scalePtr->tkwin;
250
    int y, width, length;
251
    char valueString[PRINT_CHARS];
252
    Tk_FontMetrics fm;
253
 
254
    Tk_GetFontMetrics(scalePtr->tkfont, &fm);
255
    y = TkpValueToPixel(scalePtr, value) + fm.ascent/2;
256
    sprintf(valueString, scalePtr->format, value);
257
    length = strlen(valueString);
258
    width = Tk_TextWidth(scalePtr->tkfont, valueString, length);
259
 
260
    /*
261
     * Adjust the y-coordinate if necessary to keep the text entirely
262
     * inside the window.
263
     */
264
 
265
    if ((y - fm.ascent) < (scalePtr->inset + SPACING)) {
266
        y = scalePtr->inset + SPACING + fm.ascent;
267
    }
268
    if ((y + fm.descent) > (Tk_Height(tkwin) - scalePtr->inset - SPACING)) {
269
        y = Tk_Height(tkwin) - scalePtr->inset - SPACING - fm.descent;
270
    }
271
    Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC,
272
            scalePtr->tkfont, valueString, length, rightEdge - width, y);
273
}
274
 
275
/*
276
 *--------------------------------------------------------------
277
 *
278
 * DisplayHorizontalScale --
279
 *
280
 *      This procedure redraws the contents of a horizontal scale
281
 *      window.  It is invoked as a do-when-idle handler, so it only
282
 *      runs when there's nothing else for the application to do.
283
 *
284
 * Results:
285
 *      There is no return value.  If only a part of the scale needs
286
 *      to be redrawn, then drawnAreaPtr is modified to reflect the
287
 *      area that was actually modified.
288
 *
289
 * Side effects:
290
 *      Information appears on the screen.
291
 *
292
 *--------------------------------------------------------------
293
 */
294
 
295
static void
296
DisplayHorizontalScale(scalePtr, drawable, drawnAreaPtr)
297
    TkScale *scalePtr;                  /* Widget record for scale. */
298
    Drawable drawable;                  /* Where to display scale (window
299
                                         * or pixmap). */
300
    XRectangle *drawnAreaPtr;           /* Initally contains area of window;
301
                                         * if only a part of the scale is
302
                                         * redrawn, gets modified to reflect
303
                                         * the part of the window that was
304
                                         * redrawn. */
305
{
306
    register Tk_Window tkwin = scalePtr->tkwin;
307
    int x, y, width, height, shadowWidth;
308
    double tickValue;
309
    Tk_3DBorder sliderBorder;
310
 
311
    /*
312
     * Display the information from bottom to top across the window.
313
     */
314
 
315
    if (!(scalePtr->flags & REDRAW_OTHER)) {
316
        drawnAreaPtr->x = scalePtr->inset;
317
        drawnAreaPtr->y = scalePtr->horizValueY;
318
        drawnAreaPtr->width -= 2*scalePtr->inset;
319
        drawnAreaPtr->height = scalePtr->horizTroughY + scalePtr->width
320
                + 2*scalePtr->borderWidth - scalePtr->horizValueY;
321
    }
322
    Tk_Fill3DRectangle(tkwin, drawable, scalePtr->bgBorder,
323
            drawnAreaPtr->x, drawnAreaPtr->y, drawnAreaPtr->width,
324
            drawnAreaPtr->height, 0, TK_RELIEF_FLAT);
325
    if (scalePtr->flags & REDRAW_OTHER) {
326
        /*
327
         * Display the tick marks.
328
         */
329
 
330
        if (scalePtr->tickInterval != 0) {
331
            for (tickValue = scalePtr->fromValue; ;
332
                    tickValue += scalePtr->tickInterval) {
333
                /*
334
                 * The TkRoundToResolution call gets rid of accumulated
335
                 * round-off errors, if any.
336
                 */
337
 
338
                tickValue = TkRoundToResolution(scalePtr, tickValue);
339
                if (scalePtr->toValue >= scalePtr->fromValue) {
340
                    if (tickValue > scalePtr->toValue) {
341
                        break;
342
                    }
343
                } else {
344
                    if (tickValue < scalePtr->toValue) {
345
                        break;
346
                    }
347
                }
348
                DisplayHorizontalValue(scalePtr, drawable, tickValue,
349
                        scalePtr->horizTickY);
350
            }
351
        }
352
    }
353
 
354
    /*
355
     * Display the value, if it is desired.
356
     */
357
 
358
    if (scalePtr->showValue) {
359
        DisplayHorizontalValue(scalePtr, drawable, scalePtr->value,
360
                scalePtr->horizValueY);
361
    }
362
 
363
    /*
364
     * Display the trough and the slider.
365
     */
366
 
367
    y = scalePtr->horizTroughY;
368
    Tk_Draw3DRectangle(tkwin, drawable,
369
            scalePtr->bgBorder, scalePtr->inset, y,
370
            Tk_Width(tkwin) - 2*scalePtr->inset,
371
            scalePtr->width + 2*scalePtr->borderWidth,
372
            scalePtr->borderWidth, TK_RELIEF_SUNKEN);
373
    XFillRectangle(scalePtr->display, drawable, scalePtr->troughGC,
374
            scalePtr->inset + scalePtr->borderWidth,
375
            y + scalePtr->borderWidth,
376
            (unsigned) (Tk_Width(tkwin) - 2*scalePtr->inset
377
                - 2*scalePtr->borderWidth),
378
            (unsigned) scalePtr->width);
379
    if (scalePtr->state == tkActiveUid) {
380
        sliderBorder = scalePtr->activeBorder;
381
    } else {
382
        sliderBorder = scalePtr->bgBorder;
383
    }
384
    width = scalePtr->sliderLength/2;
385
    height = scalePtr->width;
386
    x = TkpValueToPixel(scalePtr, scalePtr->value) - width;
387
    y += scalePtr->borderWidth;
388
    shadowWidth = scalePtr->borderWidth/2;
389
    if (shadowWidth == 0) {
390
        shadowWidth = 1;
391
    }
392
    Tk_Draw3DRectangle(tkwin, drawable, sliderBorder,
393
            x, y, 2*width, height, shadowWidth, scalePtr->sliderRelief);
394
    x += shadowWidth;
395
    y += shadowWidth;
396
    width -= shadowWidth;
397
    height -= 2*shadowWidth;
398
    Tk_Fill3DRectangle(tkwin, drawable, sliderBorder, x, y, width, height,
399
            shadowWidth, scalePtr->sliderRelief);
400
    Tk_Fill3DRectangle(tkwin, drawable, sliderBorder, x+width, y,
401
            width, height, shadowWidth, scalePtr->sliderRelief);
402
 
403
    /*
404
     * Draw the label at the top of the scale.
405
     */
406
 
407
    if ((scalePtr->flags & REDRAW_OTHER) && (scalePtr->labelLength != 0)) {
408
        Tk_FontMetrics fm;
409
 
410
        Tk_GetFontMetrics(scalePtr->tkfont, &fm);
411
        Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC,
412
                scalePtr->tkfont, scalePtr->label, scalePtr->labelLength,
413
                scalePtr->inset + fm.ascent/2, scalePtr->horizLabelY + fm.ascent);
414
    }
415
}
416
 
417
/*
418
 *----------------------------------------------------------------------
419
 *
420
 * DisplayHorizontalValue --
421
 *
422
 *      This procedure is called to display values (scale readings)
423
 *      for horizontally-oriented scales.
424
 *
425
 * Results:
426
 *      None.
427
 *
428
 * Side effects:
429
 *      The numerical value corresponding to value is displayed with
430
 *      its bottom edge at "bottom", and at a horizontal position in
431
 *      the scale that corresponds to "value".
432
 *
433
 *----------------------------------------------------------------------
434
 */
435
 
436
static void
437
DisplayHorizontalValue(scalePtr, drawable, value, top)
438
    register TkScale *scalePtr; /* Information about widget in which to
439
                                 * display value. */
440
    Drawable drawable;          /* Pixmap or window in which to draw
441
                                 * the value. */
442
    double value;               /* X-coordinate of number to display,
443
                                 * specified in application coords, not
444
                                 * in pixels (we'll compute pixels). */
445
    int top;                    /* Y-coordinate of top edge of text,
446
                                 * specified in pixels. */
447
{
448
    register Tk_Window tkwin = scalePtr->tkwin;
449
    int x, y, length, width;
450
    char valueString[PRINT_CHARS];
451
    Tk_FontMetrics fm;
452
 
453
    x = TkpValueToPixel(scalePtr, value);
454
    Tk_GetFontMetrics(scalePtr->tkfont, &fm);
455
    y = top + fm.ascent;
456
    sprintf(valueString, scalePtr->format, value);
457
    length = strlen(valueString);
458
    width = Tk_TextWidth(scalePtr->tkfont, valueString, length);
459
 
460
    /*
461
     * Adjust the x-coordinate if necessary to keep the text entirely
462
     * inside the window.
463
     */
464
 
465
    x -= (width)/2;
466
    if (x < (scalePtr->inset + SPACING)) {
467
        x = scalePtr->inset + SPACING;
468
    }
469
    if (x > (Tk_Width(tkwin) - scalePtr->inset)) {
470
        x = Tk_Width(tkwin) - scalePtr->inset - SPACING - width;
471
    }
472
    Tk_DrawChars(scalePtr->display, drawable, scalePtr->textGC,
473
            scalePtr->tkfont, valueString, length, x, y);
474
}
475
 
476
/*
477
 *----------------------------------------------------------------------
478
 *
479
 * TkpDisplayScale --
480
 *
481
 *      This procedure is invoked as an idle handler to redisplay
482
 *      the contents of a scale widget.
483
 *
484
 * Results:
485
 *      None.
486
 *
487
 * Side effects:
488
 *      The scale gets redisplayed.
489
 *
490
 *----------------------------------------------------------------------
491
 */
492
 
493
void
494
TkpDisplayScale(clientData)
495
    ClientData clientData;      /* Widget record for scale. */
496
{
497
    TkScale *scalePtr = (TkScale *) clientData;
498
    Tk_Window tkwin = scalePtr->tkwin;
499
    Tcl_Interp *interp = scalePtr->interp;
500
    Pixmap pixmap;
501
    int result;
502
    char string[PRINT_CHARS];
503
    XRectangle drawnArea;
504
 
505
    if ((scalePtr->tkwin == NULL) || !Tk_IsMapped(scalePtr->tkwin)) {
506
        goto done;
507
    }
508
 
509
    /*
510
     * Invoke the scale's command if needed.
511
     */
512
 
513
    Tcl_Preserve((ClientData) scalePtr);
514
    Tcl_Preserve((ClientData) interp);
515
    if ((scalePtr->flags & INVOKE_COMMAND) && (scalePtr->command != NULL)) {
516
        sprintf(string, scalePtr->format, scalePtr->value);
517
        result = Tcl_VarEval(interp, scalePtr->command, " ", string,
518
                             (char *) NULL);
519
        if (result != TCL_OK) {
520
            Tcl_AddErrorInfo(interp, "\n    (command executed by scale)");
521
            Tcl_BackgroundError(interp);
522
        }
523
    }
524
    Tcl_Release((ClientData) interp);
525
    scalePtr->flags &= ~INVOKE_COMMAND;
526
    if (scalePtr->tkwin == NULL) {
527
        Tcl_Release((ClientData) scalePtr);
528
        return;
529
    }
530
    Tcl_Release((ClientData) scalePtr);
531
 
532
    /*
533
     * In order to avoid screen flashes, this procedure redraws
534
     * the scale in a pixmap, then copies the pixmap to the
535
     * screen in a single operation.  This means that there's no
536
     * point in time where the on-sreen image has been cleared.
537
     */
538
 
539
    pixmap = Tk_GetPixmap(scalePtr->display, Tk_WindowId(tkwin),
540
            Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));
541
    drawnArea.x = 0;
542
    drawnArea.y = 0;
543
    drawnArea.width = Tk_Width(tkwin);
544
    drawnArea.height = Tk_Height(tkwin);
545
 
546
    /*
547
     * Much of the redisplay is done totally differently for
548
     * horizontal and vertical scales.  Handle the part that's
549
     * different.
550
     */
551
 
552
    if (scalePtr->vertical) {
553
        DisplayVerticalScale(scalePtr, pixmap, &drawnArea);
554
    } else {
555
        DisplayHorizontalScale(scalePtr, pixmap, &drawnArea);
556
    }
557
 
558
    /*
559
     * Now handle the part of redisplay that is the same for
560
     * horizontal and vertical scales:  border and traversal
561
     * highlight.
562
     */
563
 
564
    if (scalePtr->flags & REDRAW_OTHER) {
565
        if (scalePtr->relief != TK_RELIEF_FLAT) {
566
            Tk_Draw3DRectangle(tkwin, pixmap, scalePtr->bgBorder,
567
                    scalePtr->highlightWidth, scalePtr->highlightWidth,
568
                    Tk_Width(tkwin) - 2*scalePtr->highlightWidth,
569
                    Tk_Height(tkwin) - 2*scalePtr->highlightWidth,
570
                    scalePtr->borderWidth, scalePtr->relief);
571
        }
572
        if (scalePtr->highlightWidth != 0) {
573
            GC gc;
574
 
575
            if (scalePtr->flags & GOT_FOCUS) {
576
                gc = Tk_GCForColor(scalePtr->highlightColorPtr, pixmap);
577
            } else {
578
                gc = Tk_GCForColor(scalePtr->highlightBgColorPtr, pixmap);
579
            }
580
            Tk_DrawFocusHighlight(tkwin, gc, scalePtr->highlightWidth, pixmap);
581
        }
582
    }
583
 
584
    /*
585
     * Copy the information from the off-screen pixmap onto the screen,
586
     * then delete the pixmap.
587
     */
588
 
589
    XCopyArea(scalePtr->display, pixmap, Tk_WindowId(tkwin),
590
            scalePtr->copyGC, drawnArea.x, drawnArea.y, drawnArea.width,
591
            drawnArea.height, drawnArea.x, drawnArea.y);
592
    Tk_FreePixmap(scalePtr->display, pixmap);
593
 
594
    done:
595
    scalePtr->flags &= ~REDRAW_ALL;
596
}
597
 
598
/*
599
 *----------------------------------------------------------------------
600
 *
601
 * TkpScaleElement --
602
 *
603
 *      Determine which part of a scale widget lies under a given
604
 *      point.
605
 *
606
 * Results:
607
 *      The return value is either TROUGH1, SLIDER, TROUGH2, or
608
 *      OTHER, depending on which of the scale's active elements
609
 *      (if any) is under the point at (x,y).
610
 *
611
 * Side effects:
612
 *      None.
613
 *
614
 *----------------------------------------------------------------------
615
 */
616
 
617
int
618
TkpScaleElement(scalePtr, x, y)
619
    TkScale *scalePtr;          /* Widget record for scale. */
620
    int x, y;                   /* Coordinates within scalePtr's window. */
621
{
622
    int sliderFirst;
623
 
624
    if (scalePtr->vertical) {
625
        if ((x < scalePtr->vertTroughX)
626
                || (x >= (scalePtr->vertTroughX + 2*scalePtr->borderWidth +
627
                scalePtr->width))) {
628
            return OTHER;
629
        }
630
        if ((y < scalePtr->inset)
631
                || (y >= (Tk_Height(scalePtr->tkwin) - scalePtr->inset))) {
632
            return OTHER;
633
        }
634
        sliderFirst = TkpValueToPixel(scalePtr, scalePtr->value)
635
                - scalePtr->sliderLength/2;
636
        if (y < sliderFirst) {
637
            return TROUGH1;
638
        }
639
        if (y < (sliderFirst+scalePtr->sliderLength)) {
640
            return SLIDER;
641
        }
642
        return TROUGH2;
643
    }
644
 
645
    if ((y < scalePtr->horizTroughY)
646
            || (y >= (scalePtr->horizTroughY + 2*scalePtr->borderWidth +
647
            scalePtr->width))) {
648
        return OTHER;
649
    }
650
    if ((x < scalePtr->inset)
651
            || (x >= (Tk_Width(scalePtr->tkwin) - scalePtr->inset))) {
652
        return OTHER;
653
    }
654
    sliderFirst = TkpValueToPixel(scalePtr, scalePtr->value)
655
            - scalePtr->sliderLength/2;
656
    if (x < sliderFirst) {
657
        return TROUGH1;
658
    }
659
    if (x < (sliderFirst+scalePtr->sliderLength)) {
660
        return SLIDER;
661
    }
662
    return TROUGH2;
663
}
664
 
665
/*
666
 *--------------------------------------------------------------
667
 *
668
 * TkpSetScaleValue --
669
 *
670
 *      This procedure changes the value of a scale and invokes
671
 *      a Tcl command to reflect the current position of a scale
672
 *
673
 * Results:
674
 *      None.
675
 *
676
 * Side effects:
677
 *      A Tcl command is invoked, and an additional error-processing
678
 *      command may also be invoked.  The scale's slider is redrawn.
679
 *
680
 *--------------------------------------------------------------
681
 */
682
 
683
void
684
TkpSetScaleValue(scalePtr, value, setVar, invokeCommand)
685
    register TkScale *scalePtr; /* Info about widget. */
686
    double value;               /* New value for scale.  Gets adjusted
687
                                 * if it's off the scale. */
688
    int setVar;                 /* Non-zero means reflect new value through
689
                                 * to associated variable, if any. */
690
    int invokeCommand;          /* Non-zero means invoked -command option
691
                                 * to notify of new value, 0 means don't. */
692
{
693
    char string[PRINT_CHARS];
694
 
695
    value = TkRoundToResolution(scalePtr, value);
696
    if ((value < scalePtr->fromValue)
697
            ^ (scalePtr->toValue < scalePtr->fromValue)) {
698
        value = scalePtr->fromValue;
699
    }
700
    if ((value > scalePtr->toValue)
701
            ^ (scalePtr->toValue < scalePtr->fromValue)) {
702
        value = scalePtr->toValue;
703
    }
704
    if (scalePtr->flags & NEVER_SET) {
705
        scalePtr->flags &= ~NEVER_SET;
706
    } else if (scalePtr->value == value) {
707
        return;
708
    }
709
    scalePtr->value = value;
710
    if (invokeCommand) {
711
        scalePtr->flags |= INVOKE_COMMAND;
712
    }
713
    TkEventuallyRedrawScale(scalePtr, REDRAW_SLIDER);
714
 
715
    if (setVar && (scalePtr->varName != NULL)) {
716
        sprintf(string, scalePtr->format, scalePtr->value);
717
        scalePtr->flags |= SETTING_VAR;
718
        Tcl_SetVar(scalePtr->interp, scalePtr->varName, string,
719
               TCL_GLOBAL_ONLY);
720
        scalePtr->flags &= ~SETTING_VAR;
721
    }
722
}
723
 
724
/*
725
 *----------------------------------------------------------------------
726
 *
727
 * TkpPixelToValue --
728
 *
729
 *      Given a pixel within a scale window, return the scale
730
 *      reading corresponding to that pixel.
731
 *
732
 * Results:
733
 *      A double-precision scale reading.  If the value is outside
734
 *      the legal range for the scale then it's rounded to the nearest
735
 *      end of the scale.
736
 *
737
 * Side effects:
738
 *      None.
739
 *
740
 *----------------------------------------------------------------------
741
 */
742
 
743
double
744
TkpPixelToValue(scalePtr, x, y)
745
    register TkScale *scalePtr;         /* Information about widget. */
746
    int x, y;                           /* Coordinates of point within
747
                                         * window. */
748
{
749
    double value, pixelRange;
750
 
751
    if (scalePtr->vertical) {
752
        pixelRange = Tk_Height(scalePtr->tkwin) - scalePtr->sliderLength
753
                - 2*scalePtr->inset - 2*scalePtr->borderWidth;
754
        value = y;
755
    } else {
756
        pixelRange = Tk_Width(scalePtr->tkwin) - scalePtr->sliderLength
757
                - 2*scalePtr->inset - 2*scalePtr->borderWidth;
758
        value = x;
759
    }
760
 
761
    if (pixelRange <= 0) {
762
        /*
763
         * Not enough room for the slider to actually slide:  just return
764
         * the scale's current value.
765
         */
766
 
767
        return scalePtr->value;
768
    }
769
    value -= scalePtr->sliderLength/2 + scalePtr->inset
770
                + scalePtr->borderWidth;
771
    value /= pixelRange;
772
    if (value < 0) {
773
        value = 0;
774
    }
775
    if (value > 1) {
776
        value = 1;
777
    }
778
    value = scalePtr->fromValue +
779
                value * (scalePtr->toValue - scalePtr->fromValue);
780
    return TkRoundToResolution(scalePtr, value);
781
}
782
 
783
/*
784
 *----------------------------------------------------------------------
785
 *
786
 * TkpValueToPixel --
787
 *
788
 *      Given a reading of the scale, return the x-coordinate or
789
 *      y-coordinate corresponding to that reading, depending on
790
 *      whether the scale is vertical or horizontal, respectively.
791
 *
792
 * Results:
793
 *      An integer value giving the pixel location corresponding
794
 *      to reading.  The value is restricted to lie within the
795
 *      defined range for the scale.
796
 *
797
 * Side effects:
798
 *      None.
799
 *
800
 *----------------------------------------------------------------------
801
 */
802
 
803
int
804
TkpValueToPixel(scalePtr, value)
805
    register TkScale *scalePtr;         /* Information about widget. */
806
    double value;                       /* Reading of the widget. */
807
{
808
    int y, pixelRange;
809
    double valueRange;
810
 
811
    valueRange = scalePtr->toValue - scalePtr->fromValue;
812
    pixelRange = (scalePtr->vertical ? Tk_Height(scalePtr->tkwin)
813
            : Tk_Width(scalePtr->tkwin)) - scalePtr->sliderLength
814
            - 2*scalePtr->inset - 2*scalePtr->borderWidth;
815
    if (valueRange == 0) {
816
        y = 0;
817
    } else {
818
        y = (int) ((value - scalePtr->fromValue) * pixelRange
819
                  / valueRange + 0.5);
820
        if (y < 0) {
821
            y = 0;
822
        } else if (y > pixelRange) {
823
            y = pixelRange;
824
        }
825
    }
826
    y += scalePtr->sliderLength/2 + scalePtr->inset + scalePtr->borderWidth;
827
    return y;
828
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.