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

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [tk/] [mac/] [tkMacScale.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tkMacScale.c --
3
 *
4
 *      This file implements the Macintosh specific portion of the
5
 *      scale 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: tkMacScale.c,v 1.1.1.1 2002-01-16 10:25:57 markom Exp $
13
 */
14
 
15
#include "tkScale.h"
16
#include "tkInt.h"
17
#include <Controls.h>
18
#include "tkMacInt.h"
19
 
20
/*
21
 * Defines used in this file.
22
 */
23
#define slider          1110
24
#define inSlider        1
25
#define inInc           2
26
#define inDecr          3
27
 
28
/*
29
 * Declaration of Macintosh specific scale structure.
30
 */
31
 
32
typedef struct MacScale {
33
    TkScale info;               /* Generic scale info. */
34
    int flags;                  /* Flags. */
35
    ControlRef scaleHandle;     /* Handle to the Scale control struct. */
36
} MacScale;
37
 
38
/*
39
 * Globals uses locally in this file.
40
 */
41
static ControlActionUPP scaleActionProc = NULL; /* Pointer to func. */
42
 
43
/*
44
 * Forward declarations for procedures defined later in this file:
45
 */
46
 
47
static void             MacScaleEventProc _ANSI_ARGS_((ClientData clientData,
48
                            XEvent *eventPtr));
49
static pascal void      ScaleActionProc _ANSI_ARGS_((ControlRef theControl,
50
                            ControlPartCode partCode));
51
 
52
/*
53
 *----------------------------------------------------------------------
54
 *
55
 * TkpCreateScale --
56
 *
57
 *      Allocate a new TkScale structure.
58
 *
59
 * Results:
60
 *      Returns a newly allocated TkScale structure.
61
 *
62
 * Side effects:
63
 *      None.
64
 *
65
 *----------------------------------------------------------------------
66
 */
67
 
68
TkScale *
69
TkpCreateScale(tkwin)
70
    Tk_Window tkwin;
71
{
72
    MacScale *macScalePtr;;
73
 
74
    macScalePtr = (MacScale *) ckalloc(sizeof(MacScale));
75
    macScalePtr->scaleHandle = NULL;
76
    if (scaleActionProc == NULL) {
77
        scaleActionProc = NewControlActionProc(ScaleActionProc);
78
    }
79
 
80
    Tk_CreateEventHandler(tkwin, ButtonPressMask,
81
            MacScaleEventProc, (ClientData) macScalePtr);
82
 
83
    return (TkScale *) macScalePtr;
84
}
85
 
86
/*
87
 *----------------------------------------------------------------------
88
 *
89
 * TkpDestroyScale --
90
 *
91
 *      Free Macintosh specific resources.
92
 *
93
 * Results:
94
 *      None
95
 *
96
 * Side effects:
97
 *      The slider control is destroyed.
98
 *
99
 *----------------------------------------------------------------------
100
 */
101
 
102
void
103
TkpDestroyScale(scalePtr)
104
    TkScale *scalePtr;
105
{
106
    MacScale *macScalePtr = (MacScale *) scalePtr;
107
 
108
    /*
109
     * Free Macintosh control.
110
     */
111
    if (macScalePtr->scaleHandle != NULL) {
112
        DisposeControl(macScalePtr->scaleHandle);
113
    }
114
}
115
 
116
/*
117
 *----------------------------------------------------------------------
118
 *
119
 * TkpDisplayScale --
120
 *
121
 *      This procedure is invoked as an idle handler to redisplay
122
 *      the contents of a scale widget.
123
 *
124
 * Results:
125
 *      None.
126
 *
127
 * Side effects:
128
 *      The scale gets redisplayed.
129
 *
130
 *----------------------------------------------------------------------
131
 */
132
 
133
void
134
TkpDisplayScale(clientData)
135
    ClientData clientData;      /* Widget record for scale. */
136
{
137
    TkScale *scalePtr = (TkScale *) clientData;
138
    Tk_Window tkwin = scalePtr->tkwin;
139
    Tcl_Interp *interp = scalePtr->interp;
140
    int result;
141
    char string[PRINT_CHARS];
142
    MacScale *macScalePtr = (MacScale *) clientData;
143
    Rect r;
144
    WindowRef windowRef;
145
    GWorldPtr destPort;
146
    CGrafPtr saveWorld;
147
    GDHandle saveDevice;
148
    MacDrawable *macDraw;
149
 
150
    if ((scalePtr->tkwin == NULL) || !Tk_IsMapped(scalePtr->tkwin)) {
151
        goto done;
152
    }
153
 
154
    /*
155
     * Invoke the scale's command if needed.
156
     */
157
 
158
    Tcl_Preserve((ClientData) scalePtr);
159
    if ((scalePtr->flags & INVOKE_COMMAND) && (scalePtr->command != NULL)) {
160
        Tcl_Preserve((ClientData) interp);
161
        sprintf(string, scalePtr->format, scalePtr->value);
162
        result = Tcl_VarEval(interp, scalePtr->command, " ", string,
163
                             (char *) NULL);
164
        if (result != TCL_OK) {
165
            Tcl_AddErrorInfo(interp, "\n    (command executed by scale)");
166
            Tcl_BackgroundError(interp);
167
        }
168
        Tcl_Release((ClientData) interp);
169
    }
170
    scalePtr->flags &= ~INVOKE_COMMAND;
171
    if (scalePtr->tkwin == NULL) {
172
        Tcl_Release((ClientData) scalePtr);
173
        return;
174
    }
175
    Tcl_Release((ClientData) scalePtr);
176
 
177
    /*
178
     * Now handle the part of redisplay that is the same for
179
     * horizontal and vertical scales:  border and traversal
180
     * highlight.
181
     */
182
 
183
    if (scalePtr->highlightWidth != 0) {
184
        GC gc;
185
 
186
        if (scalePtr->flags & GOT_FOCUS) {
187
            gc = Tk_GCForColor(scalePtr->highlightColorPtr, Tk_WindowId(tkwin));
188
        } else {
189
            gc = Tk_GCForColor(scalePtr->highlightBgColorPtr, Tk_WindowId(tkwin));
190
        }
191
        Tk_DrawFocusHighlight(tkwin, gc, scalePtr->highlightWidth, Tk_WindowId(tkwin));
192
    }
193
    Tk_Draw3DRectangle(tkwin, Tk_WindowId(tkwin), scalePtr->bgBorder,
194
            scalePtr->highlightWidth, scalePtr->highlightWidth,
195
            Tk_Width(tkwin) - 2*scalePtr->highlightWidth,
196
            Tk_Height(tkwin) - 2*scalePtr->highlightWidth,
197
            scalePtr->borderWidth, scalePtr->relief);
198
 
199
    /*
200
     * Set up port for drawing Macintosh control.
201
     */
202
    macDraw = (MacDrawable *) Tk_WindowId(tkwin);
203
    destPort = TkMacGetDrawablePort(Tk_WindowId(tkwin));
204
    GetGWorld(&saveWorld, &saveDevice);
205
    SetGWorld(destPort, NULL);
206
    TkMacSetUpClippingRgn(Tk_WindowId(tkwin));
207
 
208
    /*
209
     * Create Macintosh control.
210
     */
211
    if (macScalePtr->scaleHandle == NULL) {
212
        r.left = r.top = 0;
213
        r.right = r.bottom = 1;
214
        /* TODO: initial value. */
215
        /* 16*slider+4 */
216
        macScalePtr->scaleHandle = NewControl((WindowRef) destPort,
217
                &r, "\p", false, (short) 35, 0, 1000,
218
                16*slider, (SInt32) macScalePtr);
219
 
220
        /*
221
         * If we are foremost than make us active.
222
         */
223
        if ((WindowPtr) destPort == FrontWindow()) {
224
            macScalePtr->flags |= ACTIVE;
225
        }
226
    }
227
    windowRef  = (**macScalePtr->scaleHandle).contrlOwner;
228
 
229
    /*
230
     * We can't use the Macintosh commands SizeControl and MoveControl as these
231
     * calls will also cause a redraw which in our case will also cause
232
     * flicker.  To avoid this we adjust the control record directly.  The
233
     * Draw1Control command appears to just draw where ever the control says to
234
     * draw so this seems right.
235
     *
236
     * NOTE: changing the control record directly may not work when
237
     * Apple releases the Copland version of the MacOS in late 1996.
238
     */
239
 
240
    (**macScalePtr->scaleHandle).contrlRect.left = macDraw->xOff + scalePtr->inset;
241
    (**macScalePtr->scaleHandle).contrlRect.top = macDraw->yOff + scalePtr->inset;
242
    (**macScalePtr->scaleHandle).contrlRect.right = macDraw->xOff + Tk_Width(tkwin)
243
        - scalePtr->inset;
244
    (**macScalePtr->scaleHandle).contrlRect.bottom = macDraw->yOff +
245
        Tk_Height(tkwin) - scalePtr->inset;
246
 
247
    /*
248
     * Set the thumb and resolution etc.
249
     */
250
    (**macScalePtr->scaleHandle).contrlMin = (SInt16) scalePtr->toValue;
251
    (**macScalePtr->scaleHandle).contrlMax = (SInt16) scalePtr->fromValue;
252
    (**macScalePtr->scaleHandle).contrlValue = (SInt16) scalePtr->value;
253
 
254
    /*
255
     * Finally draw the control.
256
     */
257
    (**macScalePtr->scaleHandle).contrlVis = 255;
258
    (**macScalePtr->scaleHandle).contrlHilite = 0;
259
    Draw1Control(macScalePtr->scaleHandle);
260
 
261
    SetGWorld(saveWorld, saveDevice);
262
 
263
    done:
264
    scalePtr->flags &= ~REDRAW_ALL;
265
}
266
 
267
/*
268
 *----------------------------------------------------------------------
269
 *
270
 * TkpScaleElement --
271
 *
272
 *      Determine which part of a scale widget lies under a given
273
 *      point.
274
 *
275
 * Results:
276
 *      The return value is either TROUGH1, SLIDER, TROUGH2, or
277
 *      OTHER, depending on which of the scale's active elements
278
 *      (if any) is under the point at (x,y).
279
 *
280
 * Side effects:
281
 *      None.
282
 *
283
 *----------------------------------------------------------------------
284
 */
285
 
286
int
287
TkpScaleElement(scalePtr, x, y)
288
    TkScale *scalePtr;          /* Widget record for scale. */
289
    int x, y;                   /* Coordinates within scalePtr's window. */
290
{
291
    MacScale *macScalePtr = (MacScale *) scalePtr;
292
    ControlPartCode part;
293
    Point where;
294
    Rect bounds;
295
    CGrafPtr saveWorld;
296
    GDHandle saveDevice;
297
    GWorldPtr destPort;
298
 
299
    destPort = TkMacGetDrawablePort(Tk_WindowId(scalePtr->tkwin));
300
    GetGWorld(&saveWorld, &saveDevice);
301
    SetGWorld(destPort, NULL);
302
 
303
    /*
304
     * All of the calculations in this procedure mirror those in
305
     * DisplayScrollbar.  Be sure to keep the two consistent.
306
     */
307
 
308
    TkMacWinBounds((TkWindow *) scalePtr->tkwin, &bounds);
309
    where.h = x + bounds.left;
310
    where.v = y + bounds.top;
311
    part = TestControl(macScalePtr->scaleHandle, where);
312
 
313
    SetGWorld(saveWorld, saveDevice);
314
 
315
    switch (part) {
316
        case inSlider:
317
            return SLIDER;
318
        case inInc:
319
            if (scalePtr->vertical) {
320
                return TROUGH1;
321
            } else {
322
                return TROUGH2;
323
            }
324
        case inDecr:
325
            if (scalePtr->vertical) {
326
                return TROUGH2;
327
            } else {
328
                return TROUGH1;
329
            }
330
        default:
331
            return OTHER;
332
    }
333
}
334
 
335
/*
336
 *--------------------------------------------------------------
337
 *
338
 * TkpSetScaleValue --
339
 *
340
 *      This procedure changes the value of a scale and invokes
341
 *      a Tcl command to reflect the current position of a scale
342
 *
343
 * Results:
344
 *      None.
345
 *
346
 * Side effects:
347
 *      A Tcl command is invoked, and an additional error-processing
348
 *      command may also be invoked.  The scale's slider is redrawn.
349
 *
350
 *--------------------------------------------------------------
351
 */
352
 
353
void
354
TkpSetScaleValue(scalePtr, value, setVar, invokeCommand)
355
    register TkScale *scalePtr; /* Info about widget. */
356
    double value;               /* New value for scale.  Gets adjusted
357
                                 * if it's off the scale. */
358
    int setVar;                 /* Non-zero means reflect new value through
359
                                 * to associated variable, if any. */
360
    int invokeCommand;          /* Non-zero means invoked -command option
361
                                 * to notify of new value, 0 means don't. */
362
{
363
    char string[PRINT_CHARS];
364
 
365
    value = TkRoundToResolution(scalePtr, value);
366
    if ((value < scalePtr->fromValue)
367
            ^ (scalePtr->toValue < scalePtr->fromValue)) {
368
        value = scalePtr->fromValue;
369
    }
370
    if ((value > scalePtr->toValue)
371
            ^ (scalePtr->toValue < scalePtr->fromValue)) {
372
        value = scalePtr->toValue;
373
    }
374
    if (scalePtr->flags & NEVER_SET) {
375
        scalePtr->flags &= ~NEVER_SET;
376
    } else if (scalePtr->value == value) {
377
        return;
378
    }
379
    scalePtr->value = value;
380
    if (invokeCommand) {
381
        scalePtr->flags |= INVOKE_COMMAND;
382
    }
383
    TkEventuallyRedrawScale(scalePtr, REDRAW_SLIDER);
384
 
385
    if (setVar && (scalePtr->varName != NULL)) {
386
        sprintf(string, scalePtr->format, scalePtr->value);
387
        scalePtr->flags |= SETTING_VAR;
388
        Tcl_SetVar(scalePtr->interp, scalePtr->varName, string,
389
               TCL_GLOBAL_ONLY);
390
        scalePtr->flags &= ~SETTING_VAR;
391
    }
392
}
393
 
394
/*
395
 *----------------------------------------------------------------------
396
 *
397
 * TkpPixelToValue --
398
 *
399
 *      Given a pixel within a scale window, return the scale
400
 *      reading corresponding to that pixel.
401
 *
402
 * Results:
403
 *      A double-precision scale reading.  If the value is outside
404
 *      the legal range for the scale then it's rounded to the nearest
405
 *      end of the scale.
406
 *
407
 * Side effects:
408
 *      None.
409
 *
410
 *----------------------------------------------------------------------
411
 */
412
 
413
double
414
TkpPixelToValue(scalePtr, x, y)
415
    register TkScale *scalePtr;         /* Information about widget. */
416
    int x, y;                           /* Coordinates of point within
417
                                         * window. */
418
{
419
    double value, pixelRange;
420
 
421
    if (scalePtr->vertical) {
422
        pixelRange = Tk_Height(scalePtr->tkwin) - scalePtr->sliderLength
423
                - 2*scalePtr->inset - 2*scalePtr->borderWidth;
424
        value = y;
425
    } else {
426
        pixelRange = Tk_Width(scalePtr->tkwin) - scalePtr->sliderLength
427
                - 2*scalePtr->inset - 2*scalePtr->borderWidth;
428
        value = x;
429
    }
430
 
431
    if (pixelRange <= 0) {
432
        /*
433
         * Not enough room for the slider to actually slide:  just return
434
         * the scale's current value.
435
         */
436
 
437
        return scalePtr->value;
438
    }
439
    value -= scalePtr->sliderLength/2 + scalePtr->inset
440
                + scalePtr->borderWidth;
441
    value /= pixelRange;
442
    if (value < 0) {
443
        value = 0;
444
    }
445
    if (value > 1) {
446
        value = 1;
447
    }
448
    value = scalePtr->fromValue +
449
                value * (scalePtr->toValue - scalePtr->fromValue);
450
    return TkRoundToResolution(scalePtr, value);
451
}
452
 
453
/*
454
 *----------------------------------------------------------------------
455
 *
456
 * TkpValueToPixel --
457
 *
458
 *      Given a reading of the scale, return the x-coordinate or
459
 *      y-coordinate corresponding to that reading, depending on
460
 *      whether the scale is vertical or horizontal, respectively.
461
 *
462
 * Results:
463
 *      An integer value giving the pixel location corresponding
464
 *      to reading.  The value is restricted to lie within the
465
 *      defined range for the scale.
466
 *
467
 * Side effects:
468
 *      None.
469
 *
470
 *----------------------------------------------------------------------
471
 */
472
 
473
int
474
TkpValueToPixel(scalePtr, value)
475
    register TkScale *scalePtr;         /* Information about widget. */
476
    double value;                       /* Reading of the widget. */
477
{
478
    int y, pixelRange;
479
    double valueRange;
480
 
481
    valueRange = scalePtr->toValue - scalePtr->fromValue;
482
    pixelRange = (scalePtr->vertical ? Tk_Height(scalePtr->tkwin)
483
            : Tk_Width(scalePtr->tkwin)) - scalePtr->sliderLength
484
            - 2*scalePtr->inset - 2*scalePtr->borderWidth;
485
    if (valueRange == 0) {
486
        y = 0;
487
    } else {
488
        y = (int) ((value - scalePtr->fromValue) * pixelRange
489
                  / valueRange + 0.5);
490
        if (y < 0) {
491
            y = 0;
492
        } else if (y > pixelRange) {
493
            y = pixelRange;
494
        }
495
    }
496
    y += scalePtr->sliderLength/2 + scalePtr->inset + scalePtr->borderWidth;
497
    return y;
498
}
499
 
500
/*
501
 *--------------------------------------------------------------
502
 *
503
 * MacScaleEventProc --
504
 *
505
 *      This procedure is invoked by the Tk dispatcher for
506
 *      ButtonPress events on scales.
507
 *
508
 * Results:
509
 *      None.
510
 *
511
 * Side effects:
512
 *      When the window gets deleted, internal structures get
513
 *      cleaned up.  When it gets exposed, it is redisplayed.
514
 *
515
 *--------------------------------------------------------------
516
 */
517
 
518
static void
519
MacScaleEventProc(clientData, eventPtr)
520
    ClientData clientData;      /* Information about window. */
521
    XEvent *eventPtr;           /* Information about event. */
522
{
523
    MacScale *macScalePtr = (MacScale *) clientData;
524
    Point where;
525
    Rect bounds;
526
    int part, x, y, dummy;
527
    unsigned int state;
528
    CGrafPtr saveWorld;
529
    GDHandle saveDevice;
530
    GWorldPtr destPort;
531
    Window dummyWin;
532
 
533
    /*
534
     * To call Macintosh control routines we must have the port
535
     * set to the window containing the control.  We will then test
536
     * which part of the control was hit and act accordingly.
537
     */
538
    destPort = TkMacGetDrawablePort(Tk_WindowId(macScalePtr->info.tkwin));
539
    GetGWorld(&saveWorld, &saveDevice);
540
    SetGWorld(destPort, NULL);
541
    TkMacSetUpClippingRgn(Tk_WindowId(macScalePtr->info.tkwin));
542
 
543
    TkMacWinBounds((TkWindow *) macScalePtr->info.tkwin, &bounds);
544
    where.h = eventPtr->xbutton.x + bounds.left;
545
    where.v = eventPtr->xbutton.y + bounds.top;
546
    part = TestControl(macScalePtr->scaleHandle, where);
547
    if (part == 0) {
548
        return;
549
    }
550
 
551
    part = TrackControl(macScalePtr->scaleHandle, where, scaleActionProc);
552
 
553
    /*
554
     * Update the value for the widget.
555
     */
556
    macScalePtr->info.value = (**macScalePtr->scaleHandle).contrlValue;
557
    /* TkpSetScaleValue(&macScalePtr->info, macScalePtr->info.value, 1, 0); */
558
 
559
    /*
560
     * The TrackControl call will "eat" the ButtonUp event.  We now
561
     * generate a ButtonUp event so Tk will unset implicit grabs etc.
562
     */
563
    GetMouse(&where);
564
    XQueryPointer(NULL, None, &dummyWin, &dummyWin, &x,
565
        &y, &dummy, &dummy, &state);
566
    TkGenerateButtonEvent(x, y, Tk_WindowId(macScalePtr->info.tkwin), state);
567
 
568
    SetGWorld(saveWorld, saveDevice);
569
}
570
 
571
/*
572
 *--------------------------------------------------------------
573
 *
574
 * ScaleActionProc --
575
 *
576
 *      Callback procedure used by the Macintosh toolbox call
577
 *      TrackControl.  This call will update the display while
578
 *      the scrollbar is being manipulated by the user.
579
 *
580
 * Results:
581
 *      None.
582
 *
583
 * Side effects:
584
 *      May change the display.
585
 *
586
 *--------------------------------------------------------------
587
 */
588
 
589
static pascal void
590
ScaleActionProc(ControlRef theControl, ControlPartCode partCode)
591
    /* ControlRef theControl;   /* Handle to scrollbat control */
592
    /* ControlPartCode partCode;        /* Part of scrollbar that was "hit" */
593
{
594
    register int value;
595
    register TkScale *scalePtr = (TkScale *) GetCRefCon(theControl);
596
 
597
    value = (**theControl).contrlValue;
598
    TkpSetScaleValue(scalePtr, value, 1, 1);
599
    Tcl_Preserve((ClientData) scalePtr);
600
    Tcl_DoOneEvent(TCL_IDLE_EVENTS);
601
    Tcl_Release((ClientData) scalePtr);
602
}
603
 

powered by: WebSVN 2.1.0

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