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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tk/] [mac/] [tkMacScrlbr.c] - Blame information for rev 1770

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tkMacScrollbar.c --
3
 *
4
 *      This file implements the Macintosh specific portion of the scrollbar
5
 *      widget.  The Macintosh scrollbar may also draw a windows grow
6
 *      region under certain cases.
7
 *
8
 * Copyright (c) 1996 by Sun Microsystems, Inc.
9
 *
10
 * See the file "license.terms" for information on usage and redistribution
11
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12
 *
13
 * RCS: @(#) $Id: tkMacScrlbr.c,v 1.1.1.1 2002-01-16 10:25:57 markom Exp $
14
 */
15
 
16
#include "tkScrollbar.h"
17
#include "tkMacInt.h"
18
#include <Controls.h>
19
 
20
/*
21
 * The following definitions should really be in MacOS
22
 * header files.  They are included here as this is the only
23
 * file that needs the declarations.
24
 */
25
typedef pascal void (*ThumbActionFunc)(void);
26
 
27
#if GENERATINGCFM
28
typedef UniversalProcPtr ThumbActionUPP;
29
#else
30
typedef ThumbActionFunc ThumbActionUPP;
31
#endif
32
 
33
enum {
34
        uppThumbActionProcInfo = kPascalStackBased
35
};
36
 
37
#if GENERATINGCFM
38
#define NewThumbActionProc(userRoutine)         \
39
                (ThumbActionUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppThumbActionProcInfo, GetCurrentArchitecture())
40
#else
41
#define NewThumbActionProc(userRoutine)         \
42
                ((ThumbActionUPP) (userRoutine))
43
#endif
44
 
45
/*
46
 * Minimum slider length, in pixels (designed to make sure that the slider
47
 * is always easy to grab with the mouse).
48
 */
49
 
50
#define MIN_SLIDER_LENGTH       5
51
 
52
/*
53
 * Declaration of Windows specific scrollbar structure.
54
 */
55
 
56
typedef struct MacScrollbar {
57
    TkScrollbar info;           /* Generic scrollbar info. */
58
    ControlRef sbHandle;        /* Handle to the Scrollbar control struct. */
59
    int macFlags;               /* Various flags; see below. */
60
} MacScrollbar;
61
 
62
/*
63
 * Flag bits for scrollbars on the Mac:
64
 *
65
 * ALREADY_DEAD:                Non-zero means this scrollbar has been
66
 *                              destroyed, but has not been cleaned up.
67
 * IN_MODAL_LOOP:               Non-zero means this scrollbar is in the middle
68
 *                              of a modal loop.
69
 * ACTIVE:                      Non-zero means this window is currently
70
 *                              active (in the foreground).
71
 * FLUSH_TOP:                   Flush with top of Mac window.
72
 * FLUSH_BOTTOM:                Flush with bottom of Mac window.
73
 * FLUSH_RIGHT:                 Flush with right of Mac window.
74
 * FLUSH_LEFT:                  Flush with left of Mac window.
75
 * SCROLLBAR_GROW:              Non-zero means this window draws the grow
76
 *                              region for the toplevel window.
77
 * AUTO_ADJUST:                 Non-zero means we automatically adjust
78
 *                              the size of the widget to align correctly
79
 *                              along a Mac window.
80
 * DRAW_GROW:                   Non-zero means we draw the grow region.
81
 */
82
 
83
#define ALREADY_DEAD            1
84
#define IN_MODAL_LOOP           2
85
#define ACTIVE                  4
86
#define FLUSH_TOP               8
87
#define FLUSH_BOTTOM            16
88
#define FLUSH_RIGHT             32
89
#define FLUSH_LEFT              64
90
#define SCROLLBAR_GROW          128
91
#define AUTO_ADJUST             256
92
#define DRAW_GROW               512
93
 
94
/*
95
 * Globals uses locally in this file.
96
 */
97
static ControlActionUPP scrollActionProc = NULL; /* Pointer to func. */
98
static ThumbActionUPP thumbActionProc = NULL;    /* Pointer to func. */
99
static TkScrollbar *activeScrollPtr = NULL;        /* Non-null when in thumb */
100
                                                 /* proc. */
101
/*
102
 * Forward declarations for procedures defined later in this file:
103
 */
104
 
105
static pascal void      ScrollbarActionProc _ANSI_ARGS_((ControlRef theControl,
106
                            ControlPartCode partCode));
107
static int              ScrollbarBindProc _ANSI_ARGS_((ClientData clientData,
108
                            Tcl_Interp *interp, XEvent *eventPtr,
109
                            Tk_Window tkwin, KeySym keySym));
110
static void             ScrollbarEventProc _ANSI_ARGS_((
111
                            ClientData clientData, XEvent *eventPtr));
112
static pascal void      ThumbActionProc _ANSI_ARGS_((void));
113
static void             UpdateControlValues _ANSI_ARGS_((MacScrollbar *macScrollPtr));
114
 
115
/*
116
 * The class procedure table for the scrollbar widget.
117
 */
118
 
119
TkClassProcs tkpScrollbarProcs = {
120
    NULL,                       /* createProc. */
121
    NULL,                       /* geometryProc. */
122
    NULL                        /* modalProc */
123
};
124
 
125
/*
126
 *----------------------------------------------------------------------
127
 *
128
 * TkpCreateScrollbar --
129
 *
130
 *      Allocate a new TkScrollbar structure.
131
 *
132
 * Results:
133
 *      Returns a newly allocated TkScrollbar structure.
134
 *
135
 * Side effects:
136
 *      None.
137
 *
138
 *----------------------------------------------------------------------
139
 */
140
 
141
TkScrollbar *
142
TkpCreateScrollbar(
143
    Tk_Window tkwin)    /* New Tk Window. */
144
{
145
    MacScrollbar * macScrollPtr;
146
    TkWindow *winPtr = (TkWindow *)tkwin;
147
 
148
    if (scrollActionProc == NULL) {
149
        scrollActionProc = NewControlActionProc(ScrollbarActionProc);
150
        thumbActionProc = NewThumbActionProc(ThumbActionProc);
151
    }
152
 
153
    macScrollPtr = (MacScrollbar *) ckalloc(sizeof(MacScrollbar));
154
    macScrollPtr->sbHandle = NULL;
155
    macScrollPtr->macFlags = 0;
156
 
157
    Tk_CreateEventHandler(tkwin, ActivateMask|ExposureMask|
158
            StructureNotifyMask|FocusChangeMask,
159
            ScrollbarEventProc, (ClientData) macScrollPtr);
160
 
161
    if (!Tcl_GetAssocData(winPtr->mainPtr->interp, "TkScrollbar", NULL)) {
162
        Tcl_SetAssocData(winPtr->mainPtr->interp, "TkScrollbar", NULL,
163
                (ClientData)1);
164
        TkCreateBindingProcedure(winPtr->mainPtr->interp,
165
                winPtr->mainPtr->bindingTable,
166
                (ClientData)Tk_GetUid("Scrollbar"), "<ButtonPress>",
167
                ScrollbarBindProc, NULL, NULL);
168
    }
169
 
170
    return (TkScrollbar *) macScrollPtr;
171
}
172
 
173
/*
174
 *--------------------------------------------------------------
175
 *
176
 * TkpDisplayScrollbar --
177
 *
178
 *      This procedure redraws the contents of a scrollbar window.
179
 *      It is invoked as a do-when-idle handler, so it only runs
180
 *      when there's nothing else for the application to do.
181
 *
182
 * Results:
183
 *      None.
184
 *
185
 * Side effects:
186
 *      Information appears on the screen.
187
 *
188
 *--------------------------------------------------------------
189
 */
190
 
191
void
192
TkpDisplayScrollbar(
193
    ClientData clientData)      /* Information about window. */
194
{
195
    register TkScrollbar *scrollPtr = (TkScrollbar *) clientData;
196
    register MacScrollbar *macScrollPtr = (MacScrollbar *) clientData;
197
    register Tk_Window tkwin = scrollPtr->tkwin;
198
 
199
    MacDrawable *macDraw;
200
    CGrafPtr saveWorld;
201
    GDHandle saveDevice;
202
    GWorldPtr destPort;
203
    WindowRef windowRef;
204
 
205
    if ((scrollPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
206
        goto done;
207
    }
208
 
209
    /*
210
     * Draw the focus or any 3D relief we may have.
211
     */
212
    if (scrollPtr->highlightWidth != 0) {
213
        GC gc;
214
 
215
        if (scrollPtr->flags & GOT_FOCUS) {
216
            gc = Tk_GCForColor(scrollPtr->highlightColorPtr,
217
                    Tk_WindowId(tkwin));
218
        } else {
219
            gc = Tk_GCForColor(scrollPtr->highlightBgColorPtr,
220
                    Tk_WindowId(tkwin));
221
        }
222
        Tk_DrawFocusHighlight(tkwin, gc, scrollPtr->highlightWidth,
223
                Tk_WindowId(tkwin));
224
    }
225
    Tk_Draw3DRectangle(tkwin, Tk_WindowId(tkwin), scrollPtr->bgBorder,
226
            scrollPtr->highlightWidth, scrollPtr->highlightWidth,
227
            Tk_Width(tkwin) - 2*scrollPtr->highlightWidth,
228
            Tk_Height(tkwin) - 2*scrollPtr->highlightWidth,
229
            scrollPtr->borderWidth, scrollPtr->relief);
230
 
231
    /*
232
     * Set up port for drawing Macintosh control.
233
     */
234
    macDraw = (MacDrawable *) Tk_WindowId(tkwin);
235
    destPort = TkMacGetDrawablePort(Tk_WindowId(tkwin));
236
    GetGWorld(&saveWorld, &saveDevice);
237
    SetGWorld(destPort, NULL);
238
    TkMacSetUpClippingRgn(Tk_WindowId(tkwin));
239
 
240
    if (macScrollPtr->sbHandle == NULL) {
241
        Rect r;
242
 
243
        r.left = r.top = 0;
244
        r.right = r.bottom = 1;
245
        macScrollPtr->sbHandle = NewControl((WindowRef) destPort, &r, "\p",
246
                false, (short) 500, 0, 1000,
247
                scrollBarProc, (SInt32) scrollPtr);
248
 
249
        /*
250
         * If we are foremost than make us active.
251
         */
252
        if ((WindowPtr) destPort == FrontWindow()) {
253
            macScrollPtr->macFlags |= ACTIVE;
254
        }
255
    }
256
 
257
    /*
258
     * Update the control values before we draw.
259
     */
260
    windowRef  = (**macScrollPtr->sbHandle).contrlOwner;
261
    UpdateControlValues(macScrollPtr);
262
 
263
    if (macScrollPtr->macFlags & ACTIVE) {
264
        Draw1Control(macScrollPtr->sbHandle);
265
        if (macScrollPtr->macFlags & DRAW_GROW) {
266
            DrawGrowIcon(windowRef);
267
        }
268
    } else {
269
        (**macScrollPtr->sbHandle).contrlHilite = 255;
270
        Draw1Control(macScrollPtr->sbHandle);
271
        if (macScrollPtr->macFlags & DRAW_GROW) {
272
            DrawGrowIcon(windowRef);
273
            Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), scrollPtr->bgBorder,
274
                Tk_Width(tkwin) - 13, Tk_Height(tkwin) - 13,
275
                Tk_Width(tkwin), Tk_Height(tkwin),
276
                0, TK_RELIEF_FLAT);
277
        }
278
    }
279
 
280
    SetGWorld(saveWorld, saveDevice);
281
 
282
    done:
283
    scrollPtr->flags &= ~REDRAW_PENDING;
284
}
285
 
286
/*
287
 *----------------------------------------------------------------------
288
 *
289
 * TkpConfigureScrollbar --
290
 *
291
 *      This procedure is called after the generic code has finished
292
 *      processing configuration options, in order to configure
293
 *      platform specific options.
294
 *
295
 * Results:
296
 *      None.
297
 *
298
 * Side effects:
299
 *      None.
300
 *
301
 *----------------------------------------------------------------------
302
 */
303
 
304
void
305
TkpConfigureScrollbar(scrollPtr)
306
    register TkScrollbar *scrollPtr;    /* Information about widget;  may or
307
                                         * may not already have values for
308
                                         * some fields. */
309
{
310
}
311
 
312
/*
313
 *----------------------------------------------------------------------
314
 *
315
 * TkpComputeScrollbarGeometry --
316
 *
317
 *      After changes in a scrollbar's size or configuration, this
318
 *      procedure recomputes various geometry information used in
319
 *      displaying the scrollbar.
320
 *
321
 * Results:
322
 *      None.
323
 *
324
 * Side effects:
325
 *      The scrollbar will be displayed differently.
326
 *
327
 *----------------------------------------------------------------------
328
 */
329
 
330
void
331
TkpComputeScrollbarGeometry(
332
    register TkScrollbar *scrollPtr)    /* Scrollbar whose geometry may
333
                                         * have changed. */
334
{
335
    MacScrollbar *macScrollPtr = (MacScrollbar *) scrollPtr;
336
    int width, fieldLength, adjust = 0;
337
 
338
    if (scrollPtr->highlightWidth < 0) {
339
        scrollPtr->highlightWidth = 0;
340
    }
341
    scrollPtr->inset = scrollPtr->highlightWidth + scrollPtr->borderWidth;
342
    width = (scrollPtr->vertical) ? Tk_Width(scrollPtr->tkwin)
343
            : Tk_Height(scrollPtr->tkwin);
344
    scrollPtr->arrowLength = width - 2*scrollPtr->inset + 1;
345
    fieldLength = (scrollPtr->vertical ? Tk_Height(scrollPtr->tkwin)
346
            : Tk_Width(scrollPtr->tkwin))
347
            - 2*(scrollPtr->arrowLength + scrollPtr->inset);
348
    if (fieldLength < 0) {
349
        fieldLength = 0;
350
    }
351
    scrollPtr->sliderFirst = fieldLength*scrollPtr->firstFraction;
352
    scrollPtr->sliderLast = fieldLength*scrollPtr->lastFraction;
353
 
354
    /*
355
     * Adjust the slider so that some piece of it is always
356
     * displayed in the scrollbar and so that it has at least
357
     * a minimal width (so it can be grabbed with the mouse).
358
     */
359
 
360
    if (scrollPtr->sliderFirst > (fieldLength - 2*scrollPtr->borderWidth)) {
361
        scrollPtr->sliderFirst = fieldLength - 2*scrollPtr->borderWidth;
362
    }
363
    if (scrollPtr->sliderFirst < 0) {
364
        scrollPtr->sliderFirst = 0;
365
    }
366
    if (scrollPtr->sliderLast < (scrollPtr->sliderFirst
367
            + MIN_SLIDER_LENGTH)) {
368
        scrollPtr->sliderLast = scrollPtr->sliderFirst + MIN_SLIDER_LENGTH;
369
    }
370
    if (scrollPtr->sliderLast > fieldLength) {
371
        scrollPtr->sliderLast = fieldLength;
372
    }
373
    scrollPtr->sliderFirst += scrollPtr->arrowLength + scrollPtr->inset;
374
    scrollPtr->sliderLast += scrollPtr->arrowLength + scrollPtr->inset;
375
 
376
    /*
377
     * Register the desired geometry for the window (leave enough space
378
     * for the two arrows plus a minimum-size slider, plus border around
379
     * the whole window, if any).  Then arrange for the window to be
380
     * redisplayed.
381
     */
382
 
383
    if (scrollPtr->vertical) {
384
        if ((macScrollPtr->macFlags & AUTO_ADJUST) &&
385
                (macScrollPtr->macFlags & (FLUSH_RIGHT|FLUSH_LEFT))) {
386
            adjust--;
387
        }
388
        Tk_GeometryRequest(scrollPtr->tkwin,
389
                scrollPtr->width + 2*scrollPtr->inset + adjust,
390
                2*(scrollPtr->arrowLength + scrollPtr->borderWidth
391
                + scrollPtr->inset));
392
    } else {
393
        if ((macScrollPtr->macFlags & AUTO_ADJUST) &&
394
                (macScrollPtr->macFlags & (FLUSH_TOP|FLUSH_BOTTOM))) {
395
            adjust--;
396
        }
397
        Tk_GeometryRequest(scrollPtr->tkwin,
398
                2*(scrollPtr->arrowLength + scrollPtr->borderWidth
399
                + scrollPtr->inset), scrollPtr->width + 2*scrollPtr->inset + adjust);
400
    }
401
    Tk_SetInternalBorder(scrollPtr->tkwin, scrollPtr->inset);
402
}
403
 
404
/*
405
 *----------------------------------------------------------------------
406
 *
407
 * TkpDestroyScrollbar --
408
 *
409
 *      Free data structures associated with the scrollbar control.
410
 *
411
 * Results:
412
 *      None.
413
 *
414
 * Side effects:
415
 *      None.
416
 *
417
 *----------------------------------------------------------------------
418
 */
419
 
420
void
421
TkpDestroyScrollbar(
422
    TkScrollbar *scrollPtr)     /* Scrollbar to destroy. */
423
{
424
    MacScrollbar *macScrollPtr = (MacScrollbar *)scrollPtr;
425
 
426
    if (macScrollPtr->sbHandle != NULL) {
427
        if (!(macScrollPtr->macFlags & IN_MODAL_LOOP)) {
428
            DisposeControl(macScrollPtr->sbHandle);
429
            macScrollPtr->sbHandle = NULL;
430
        }
431
    }
432
    macScrollPtr->macFlags |= ALREADY_DEAD;
433
}
434
 
435
/*
436
 *--------------------------------------------------------------
437
 *
438
 * TkpScrollbarPosition --
439
 *
440
 *      Determine the scrollbar element corresponding to a
441
 *      given position.
442
 *
443
 * Results:
444
 *      One of TOP_ARROW, TOP_GAP, etc., indicating which element
445
 *      of the scrollbar covers the position given by (x, y).  If
446
 *      (x,y) is outside the scrollbar entirely, then OUTSIDE is
447
 *      returned.
448
 *
449
 * Side effects:
450
 *      None.
451
 *
452
 *--------------------------------------------------------------
453
 */
454
 
455
int
456
TkpScrollbarPosition(
457
    TkScrollbar *scrollPtr,     /* Scrollbar widget record. */
458
    int x, int y)               /* Coordinates within scrollPtr's
459
                                 * window. */
460
{
461
    MacScrollbar *macScrollPtr = (MacScrollbar *) scrollPtr;
462
    GWorldPtr destPort;
463
    int length, width, tmp, inactive = false;
464
    ControlPartCode part;
465
    Point where;
466
    Rect bounds;
467
 
468
    if (scrollPtr->vertical) {
469
        length = Tk_Height(scrollPtr->tkwin);
470
        width = Tk_Width(scrollPtr->tkwin);
471
    } else {
472
        tmp = x;
473
        x = y;
474
        y = tmp;
475
        length = Tk_Width(scrollPtr->tkwin);
476
        width = Tk_Height(scrollPtr->tkwin);
477
    }
478
 
479
    if ((x < scrollPtr->inset) || (x >= (width - scrollPtr->inset))
480
            || (y < scrollPtr->inset) || (y >= (length - scrollPtr->inset))) {
481
        return OUTSIDE;
482
    }
483
 
484
    /*
485
     * All of the calculations in this procedure mirror those in
486
     * DisplayScrollbar.  Be sure to keep the two consistent.  On the
487
     * Macintosh we use the OS call TestControl to do this mapping.
488
     * For TestControl to work, the scrollbar must be active and must
489
     * be in the current port.
490
     */
491
 
492
    destPort = TkMacGetDrawablePort(Tk_WindowId(scrollPtr->tkwin));
493
    SetGWorld(destPort, NULL);
494
    UpdateControlValues(macScrollPtr);
495
    if ((**macScrollPtr->sbHandle).contrlHilite == 255) {
496
        inactive = true;
497
        (**macScrollPtr->sbHandle).contrlHilite = 0;
498
    }
499
 
500
    TkMacWinBounds((TkWindow *) scrollPtr->tkwin, &bounds);
501
    where.h = x + bounds.left;
502
    where.v = y + bounds.top;
503
    part = TestControl(((MacScrollbar *) scrollPtr)->sbHandle, where);
504
    if (inactive) {
505
        (**macScrollPtr->sbHandle).contrlHilite = 255;
506
    }
507
    switch (part) {
508
        case inUpButton:
509
            return TOP_ARROW;
510
        case inPageUp:
511
            return TOP_GAP;
512
        case inThumb:
513
            return SLIDER;
514
        case inPageDown:
515
            return BOTTOM_GAP;
516
        case inDownButton:
517
            return BOTTOM_ARROW;
518
        default:
519
            return OUTSIDE;
520
    }
521
}
522
 
523
/*
524
 *--------------------------------------------------------------
525
 *
526
 * ThumbActionProc --
527
 *
528
 *      Callback procedure used by the Macintosh toolbox call
529
 *      TrackControl.  This call is used to track the thumb of
530
 *      the scrollbar.  Unlike the ScrollbarActionProc function
531
 *      this function is called once and basically takes over
532
 *      tracking the scrollbar from the control.  This is done
533
 *      to avoid conflicts with what the control plans to draw.
534
 *
535
 * Results:
536
 *      None.
537
 *
538
 * Side effects:
539
 *      May change the display.
540
 *
541
 *--------------------------------------------------------------
542
 */
543
 
544
static pascal void
545
ThumbActionProc()
546
{
547
    register TkScrollbar *scrollPtr = activeScrollPtr;
548
    register MacScrollbar *macScrollPtr = (MacScrollbar *) activeScrollPtr;
549
    Tcl_DString cmdString;
550
    Rect nullRect = {0,0,0,0};
551
    int origValue, trackBarPin;
552
    double thumbWidth, newFirstFraction, trackBarSize;
553
    char vauleString[40];
554
    Point currentPoint = { 0, 0 };
555
    Point lastPoint = { 0, 0 };
556
    Rect trackRect;
557
    Tcl_Interp *interp;
558
 
559
    if (scrollPtr == NULL) {
560
        return;
561
    }
562
 
563
    Tcl_DStringInit(&cmdString);
564
 
565
    /*
566
     * First compute values that will remain constant during the tracking
567
     * of the thumb.  The variable trackBarSize is the length of the scrollbar
568
     * minus the 2 arrows and half the width of the thumb on both sides
569
     * (3 * arrowLength).  The variable trackBarPin is the lower starting point
570
     * of the drag region.
571
     *
572
     * Note: the arrowLength is equal to the thumb width of a Mac scrollbar.
573
     */
574
    origValue = GetControlValue(macScrollPtr->sbHandle);
575
    trackRect = (**macScrollPtr->sbHandle).contrlRect;
576
    if (scrollPtr->vertical == true) {
577
        trackBarSize = (double) (trackRect.bottom - trackRect.top
578
                - (scrollPtr->arrowLength * 3));
579
        trackBarPin = trackRect.top + scrollPtr->arrowLength
580
            + (scrollPtr->arrowLength / 2);
581
        InsetRect(&trackRect, -25, -113);
582
 
583
    } else {
584
        trackBarSize = (double) (trackRect.right - trackRect.left
585
                - (scrollPtr->arrowLength * 3));
586
        trackBarPin = trackRect.left + scrollPtr->arrowLength
587
            + (scrollPtr->arrowLength / 2);
588
        InsetRect(&trackRect, -113, -25);
589
    }
590
 
591
    /*
592
     * Track the mouse while the button is held down.  If the mouse is moved,
593
     * we calculate the value that should be passed to the "command" part of
594
     * the scrollbar.
595
     */
596
    while (StillDown()) {
597
        GetMouse(&currentPoint);
598
        if (EqualPt(currentPoint, lastPoint)) {
599
            continue;
600
        }
601
        lastPoint = currentPoint;
602
 
603
        /*
604
         * Calculating this value is a little tricky.  We need to calculate a
605
         * value for where the thumb would be in a Motif widget (variable
606
         * thumb).  This value is what the "command" expects and is what will
607
         * be resent to the scrollbar to update its value.
608
         */
609
        thumbWidth = scrollPtr->lastFraction - scrollPtr->firstFraction;
610
        if (PtInRect(currentPoint, &trackRect)) {
611
            if (scrollPtr->vertical == true) {
612
                newFirstFraction =  (1.0 - thumbWidth) *
613
                    ((double) (currentPoint.v - trackBarPin) / trackBarSize);
614
            } else {
615
                newFirstFraction =  (1.0 - thumbWidth) *
616
                    ((double) (currentPoint.h - trackBarPin) / trackBarSize);
617
            }
618
        } else {
619
            newFirstFraction = ((double) origValue / 1000.0)
620
                * (1.0 - thumbWidth);
621
        }
622
 
623
        sprintf(vauleString, "%g", newFirstFraction);
624
 
625
        Tcl_DStringSetLength(&cmdString, 0);
626
        Tcl_DStringAppend(&cmdString, scrollPtr->command,
627
                scrollPtr->commandSize);
628
        Tcl_DStringAppendElement(&cmdString, "moveto");
629
        Tcl_DStringAppendElement(&cmdString, vauleString);
630
 
631
        interp = scrollPtr->interp;
632
        Tcl_Preserve((ClientData) interp);
633
        Tcl_GlobalEval(interp, cmdString.string);
634
        Tcl_Release((ClientData) interp);
635
 
636
        Tcl_DStringSetLength(&cmdString, 0);
637
        Tcl_DStringAppend(&cmdString, "update idletasks",
638
                strlen("update idletasks"));
639
        Tcl_Preserve((ClientData) interp);
640
        Tcl_GlobalEval(interp, cmdString.string);
641
        Tcl_Release((ClientData) interp);
642
    }
643
 
644
    /*
645
     * This next bit of code is a bit of a hack - but needed.  The problem is
646
     * that the control wants to draw the drag outline if the control value
647
     * changes during the drag (which it does).  What we do here is change the
648
     * clip region to hide this drawing from the user.
649
     */
650
    ClipRect(&nullRect);
651
 
652
    Tcl_DStringFree(&cmdString);
653
    return;
654
}
655
 
656
/*
657
 *--------------------------------------------------------------
658
 *
659
 * ScrollbarActionProc --
660
 *
661
 *      Callback procedure used by the Macintosh toolbox call
662
 *      TrackControl.  This call will update the display while
663
 *      the scrollbar is being manipulated by the user.
664
 *
665
 * Results:
666
 *      None.
667
 *
668
 * Side effects:
669
 *      May change the display.
670
 *
671
 *--------------------------------------------------------------
672
 */
673
 
674
static pascal void
675
ScrollbarActionProc(
676
    ControlRef theControl,      /* Handle to scrollbat control */
677
    ControlPartCode partCode)   /* Part of scrollbar that was "hit" */
678
{
679
    register TkScrollbar *scrollPtr = (TkScrollbar *) GetCRefCon(theControl);
680
    Tcl_DString cmdString;
681
 
682
    Tcl_DStringInit(&cmdString);
683
    Tcl_DStringAppend(&cmdString, scrollPtr->command,
684
            scrollPtr->commandSize);
685
 
686
    if (partCode == inUpButton || partCode == inDownButton) {
687
        Tcl_DStringAppendElement(&cmdString, "scroll");
688
        Tcl_DStringAppendElement(&cmdString,
689
                (partCode == inUpButton ) ? "-1" : "1");
690
        Tcl_DStringAppendElement(&cmdString, "unit");
691
    } else if (partCode == inPageUp || partCode == inPageDown) {
692
        Tcl_DStringAppendElement(&cmdString, "scroll");
693
        Tcl_DStringAppendElement(&cmdString,
694
                (partCode == inPageUp ) ? "-1" : "1");
695
        Tcl_DStringAppendElement(&cmdString, "page");
696
    }
697
    Tcl_Preserve((ClientData) scrollPtr->interp);
698
    Tcl_DStringAppend(&cmdString, "; update idletasks",
699
        strlen("; update idletasks"));
700
    Tcl_GlobalEval(scrollPtr->interp, cmdString.string);
701
    Tcl_Release((ClientData) scrollPtr->interp);
702
 
703
    Tcl_DStringFree(&cmdString);
704
}
705
 
706
/*
707
 *--------------------------------------------------------------
708
 *
709
 * ScrollbarBindProc --
710
 *
711
 *      This procedure is invoked when the default <ButtonPress>
712
 *      binding on the Scrollbar bind tag fires.
713
 *
714
 * Results:
715
 *      None.
716
 *
717
 * Side effects:
718
 *      The event enters a modal loop.
719
 *
720
 *--------------------------------------------------------------
721
 */
722
 
723
static int
724
ScrollbarBindProc(
725
    ClientData clientData,      /* Not used. */
726
    Tcl_Interp *interp,         /* Interp with binding. */
727
    XEvent *eventPtr,           /* X event that triggered binding. */
728
    Tk_Window tkwin,            /* Target window for event. */
729
    KeySym keySym)              /* The KeySym if a key event. */
730
{
731
    TkWindow *winPtr = (TkWindow*)tkwin;
732
    TkScrollbar *scrollPtr = (TkScrollbar *) winPtr->instanceData;
733
    MacScrollbar *macScrollPtr = (MacScrollbar *) winPtr->instanceData;
734
 
735
    Tcl_Preserve((ClientData)scrollPtr);
736
    macScrollPtr->macFlags |= IN_MODAL_LOOP;
737
 
738
    if (eventPtr->type == ButtonPress) {
739
        Point where;
740
        Rect bounds;
741
        int part, x, y, dummy;
742
        unsigned int state;
743
        CGrafPtr saveWorld;
744
        GDHandle saveDevice;
745
        GWorldPtr destPort;
746
        Window window;
747
 
748
        /*
749
         * To call Macintosh control routines we must have the port
750
         * set to the window containing the control.  We will then test
751
         * which part of the control was hit and act accordingly.
752
         */
753
        destPort = TkMacGetDrawablePort(Tk_WindowId(scrollPtr->tkwin));
754
        GetGWorld(&saveWorld, &saveDevice);
755
        SetGWorld(destPort, NULL);
756
        TkMacSetUpClippingRgn(Tk_WindowId(scrollPtr->tkwin));
757
 
758
        TkMacWinBounds((TkWindow *) scrollPtr->tkwin, &bounds);
759
        where.h = eventPtr->xbutton.x + bounds.left;
760
        where.v = eventPtr->xbutton.y + bounds.top;
761
        part = TestControl(macScrollPtr->sbHandle, where);
762
        if (part == inThumb && scrollPtr->jump == false) {
763
            /*
764
             * Case 1: In thumb, no jump scrolling.  Call track control
765
             * with the thumb action proc which will do most of the work.
766
             * Set the global activeScrollPtr to the current control
767
             * so the callback may have access to it.
768
             */
769
            activeScrollPtr = scrollPtr;
770
            part = TrackControl(macScrollPtr->sbHandle, where,
771
                    (ControlActionUPP) thumbActionProc);
772
            activeScrollPtr = NULL;
773
        } else if (part == inThumb) {
774
            /*
775
             * Case 2: in thumb with jump scrolling.  Call TrackControl
776
             * with a NULL action proc.  Use the new value of the control
777
             * to set update the control.
778
             */
779
            part = TrackControl(macScrollPtr->sbHandle, where, NULL);
780
            if (part == inThumb) {
781
                double newFirstFraction, thumbWidth;
782
                Tcl_DString cmdString;
783
                char vauleString[TCL_DOUBLE_SPACE];
784
 
785
                /*
786
                 * The following calculation takes the new control
787
                 * value and maps it to what Tk needs for its variable
788
                 * thumb size representation.
789
                 */
790
                thumbWidth = scrollPtr->lastFraction
791
                     - scrollPtr->firstFraction;
792
                newFirstFraction = (1.0 - thumbWidth) *
793
                    ((double) GetControlValue(macScrollPtr->sbHandle) / 1000.0);
794
                sprintf(vauleString, "%g", newFirstFraction);
795
 
796
                Tcl_DStringInit(&cmdString);
797
                Tcl_DStringAppend(&cmdString, scrollPtr->command,
798
                        strlen(scrollPtr->command));
799
                Tcl_DStringAppendElement(&cmdString, "moveto");
800
                Tcl_DStringAppendElement(&cmdString, vauleString);
801
                Tcl_DStringAppend(&cmdString, "; update idletasks",
802
                        strlen("; update idletasks"));
803
 
804
                interp = scrollPtr->interp;
805
                Tcl_Preserve((ClientData) interp);
806
                Tcl_GlobalEval(interp, cmdString.string);
807
                Tcl_Release((ClientData) interp);
808
                Tcl_DStringFree(&cmdString);
809
            }
810
        } else if (part != 0) {
811
            /*
812
             * Case 3: in any other part of the scrollbar.  We call
813
             * TrackControl with the scrollActionProc which will do
814
             * most all the work.
815
             */
816
            TrackControl(macScrollPtr->sbHandle, where, scrollActionProc);
817
            HiliteControl(macScrollPtr->sbHandle, 0);
818
        }
819
 
820
        /*
821
         * The TrackControl call will "eat" the ButtonUp event.  We now
822
         * generate a ButtonUp event so Tk will unset implicit grabs etc.
823
         */
824
        GetMouse(&where);
825
        XQueryPointer(NULL, None, &window, &window, &x,
826
            &y, &dummy, &dummy, &state);
827
        window = Tk_WindowId(scrollPtr->tkwin);
828
        TkGenerateButtonEvent(x, y, window, state);
829
 
830
        SetGWorld(saveWorld, saveDevice);
831
    }
832
 
833
    if (macScrollPtr->sbHandle && (macScrollPtr->macFlags & ALREADY_DEAD)) {
834
        DisposeControl(macScrollPtr->sbHandle);
835
        macScrollPtr->sbHandle = NULL;
836
    }
837
    macScrollPtr->macFlags &= ~IN_MODAL_LOOP;
838
    Tcl_Release((ClientData)scrollPtr);
839
 
840
    return TCL_OK;
841
}
842
 
843
/*
844
 *--------------------------------------------------------------
845
 *
846
 * ScrollbarEventProc --
847
 *
848
 *      This procedure is invoked by the Tk dispatcher for various
849
 *      events on scrollbars.
850
 *
851
 * Results:
852
 *      None.
853
 *
854
 * Side effects:
855
 *      When the window gets deleted, internal structures get
856
 *      cleaned up.  When it gets exposed, it is redisplayed.
857
 *
858
 *--------------------------------------------------------------
859
 */
860
 
861
static void
862
ScrollbarEventProc(
863
    ClientData clientData,      /* Information about window. */
864
    XEvent *eventPtr)           /* Information about event. */
865
{
866
    TkScrollbar *scrollPtr = (TkScrollbar *) clientData;
867
    MacScrollbar *macScrollPtr = (MacScrollbar *) clientData;
868
 
869
    if (eventPtr->type == UnmapNotify) {
870
        TkMacSetScrollbarGrow((TkWindow *) scrollPtr->tkwin, false);
871
    } else if (eventPtr->type == ActivateNotify) {
872
        macScrollPtr->macFlags |= ACTIVE;
873
        TkScrollbarEventuallyRedraw((ClientData) scrollPtr);
874
    } else if (eventPtr->type == DeactivateNotify) {
875
        macScrollPtr->macFlags &= ~ACTIVE;
876
        TkScrollbarEventuallyRedraw((ClientData) scrollPtr);
877
    } else {
878
        TkScrollbarEventProc(clientData, eventPtr);
879
    }
880
}
881
 
882
/*
883
 *--------------------------------------------------------------
884
 *
885
 * UpdateControlValues --
886
 *
887
 *      This procedure updates the Macintosh scrollbar control
888
 *      to display the values defined by the Tk scrollbar.
889
 *
890
 * Results:
891
 *      None.
892
 *
893
 * Side effects:
894
 *      The Macintosh control is updated.
895
 *
896
 *--------------------------------------------------------------
897
 */
898
 
899
static void
900
UpdateControlValues(
901
    MacScrollbar *macScrollPtr)         /* Scrollbar data struct. */
902
{
903
    TkScrollbar *scrollPtr = (TkScrollbar *) macScrollPtr;
904
    Tk_Window tkwin = scrollPtr->tkwin;
905
    MacDrawable * macDraw = (MacDrawable *) Tk_WindowId(scrollPtr->tkwin);
906
    WindowRef windowRef  = (**macScrollPtr->sbHandle).contrlOwner;
907
    double middle;
908
    int drawGrowRgn = false;
909
    int flushRight = false;
910
    int flushBottom = false;
911
 
912
    /*
913
     * We can't use the Macintosh commands SizeControl and MoveControl as these
914
     * calls will also cause a redraw which in our case will also cause
915
     * flicker.  To avoid this we adjust the control record directly.  The
916
     * Draw1Control command appears to just draw where ever the control says to
917
     * draw so this seems right.
918
     *
919
     * NOTE: changing the control record directly may not work when
920
     * Apple releases the Copland version of the MacOS (or when hell is cold).
921
     */
922
 
923
    (**macScrollPtr->sbHandle).contrlRect.left = macDraw->xOff + scrollPtr->inset;
924
    (**macScrollPtr->sbHandle).contrlRect.top = macDraw->yOff + scrollPtr->inset;
925
    (**macScrollPtr->sbHandle).contrlRect.right = macDraw->xOff + Tk_Width(tkwin)
926
        - scrollPtr->inset;
927
    (**macScrollPtr->sbHandle).contrlRect.bottom = macDraw->yOff +
928
        Tk_Height(tkwin) - scrollPtr->inset;
929
 
930
    /*
931
     * To make Tk applications look more like Macintosh applications without
932
     * requiring additional work by the Tk developer we do some cute tricks.
933
     * The first trick plays with the size of the widget to get it to overlap
934
     * with the side of the window by one pixel (we don't do this if the placer
935
     * is the geometry manager).  The second trick shrinks the scrollbar if it
936
     * it covers the area of the grow region ao the scrollbar can also draw
937
     * the grow region if need be.
938
     */
939
    if (!strcmp(macDraw->winPtr->geomMgrPtr->name, "place")) {
940
        macScrollPtr->macFlags &= AUTO_ADJUST;
941
    } else {
942
        macScrollPtr->macFlags |= AUTO_ADJUST;
943
    }
944
    /* TODO: use accessor function!!! */
945
    if (windowRef->portRect.left == (**macScrollPtr->sbHandle).contrlRect.left) {
946
        if (macScrollPtr->macFlags & AUTO_ADJUST) {
947
            (**macScrollPtr->sbHandle).contrlRect.left--;
948
        }
949
        if (!(macScrollPtr->macFlags & FLUSH_LEFT)) {
950
            macScrollPtr->macFlags |= FLUSH_LEFT;
951
            if (scrollPtr->vertical) {
952
                TkpComputeScrollbarGeometry(scrollPtr);
953
            }
954
        }
955
    } else if (macScrollPtr->macFlags & FLUSH_LEFT) {
956
        macScrollPtr->macFlags &= ~FLUSH_LEFT;
957
        if (scrollPtr->vertical) {
958
            TkpComputeScrollbarGeometry(scrollPtr);
959
        }
960
    }
961
 
962
    if (windowRef->portRect.top == (**macScrollPtr->sbHandle).contrlRect.top) {
963
        if (macScrollPtr->macFlags & AUTO_ADJUST) {
964
            (**macScrollPtr->sbHandle).contrlRect.top--;
965
        }
966
        if (!(macScrollPtr->macFlags & FLUSH_TOP)) {
967
            macScrollPtr->macFlags |= FLUSH_TOP;
968
            if (! scrollPtr->vertical) {
969
                TkpComputeScrollbarGeometry(scrollPtr);
970
            }
971
        }
972
    } else if (macScrollPtr->macFlags & FLUSH_TOP) {
973
        macScrollPtr->macFlags &= ~FLUSH_TOP;
974
        if (! scrollPtr->vertical) {
975
            TkpComputeScrollbarGeometry(scrollPtr);
976
        }
977
    }
978
 
979
    if (windowRef->portRect.right == (**macScrollPtr->sbHandle).contrlRect.right) {
980
        flushRight = true;
981
        if (macScrollPtr->macFlags & AUTO_ADJUST) {
982
            (**macScrollPtr->sbHandle).contrlRect.right++;
983
        }
984
        if (!(macScrollPtr->macFlags & FLUSH_RIGHT)) {
985
            macScrollPtr->macFlags |= FLUSH_RIGHT;
986
            if (scrollPtr->vertical) {
987
                TkpComputeScrollbarGeometry(scrollPtr);
988
            }
989
        }
990
    } else if (macScrollPtr->macFlags & FLUSH_RIGHT) {
991
        macScrollPtr->macFlags &= ~FLUSH_RIGHT;
992
        if (scrollPtr->vertical) {
993
            TkpComputeScrollbarGeometry(scrollPtr);
994
        }
995
    }
996
 
997
    if (windowRef->portRect.bottom == (**macScrollPtr->sbHandle).contrlRect.bottom) {
998
        flushBottom = true;
999
        if (macScrollPtr->macFlags & AUTO_ADJUST) {
1000
            (**macScrollPtr->sbHandle).contrlRect.bottom++;
1001
        }
1002
        if (!(macScrollPtr->macFlags & FLUSH_BOTTOM)) {
1003
            macScrollPtr->macFlags |= FLUSH_BOTTOM;
1004
            if (! scrollPtr->vertical) {
1005
                TkpComputeScrollbarGeometry(scrollPtr);
1006
            }
1007
        }
1008
    } else if (macScrollPtr->macFlags & FLUSH_BOTTOM) {
1009
        macScrollPtr->macFlags &= ~FLUSH_BOTTOM;
1010
        if (! scrollPtr->vertical) {
1011
            TkpComputeScrollbarGeometry(scrollPtr);
1012
        }
1013
    }
1014
 
1015
    /*
1016
     * If the scrollbar is flush against the bottom right hand coner then
1017
     * it may need to draw the grow region for the window so we let the
1018
     * wm code know about this scrollbar.  We don't actually draw the grow
1019
     * region, however, unless we are currently resizable.
1020
     */
1021
    macScrollPtr->macFlags &= ~DRAW_GROW;
1022
    if (flushBottom && flushRight) {
1023
        TkMacSetScrollbarGrow((TkWindow *) tkwin, true);
1024
        if (TkMacResizable(macDraw->toplevel->winPtr)) {
1025
            if (scrollPtr->vertical) {
1026
                (**macScrollPtr->sbHandle).contrlRect.bottom -= 14;
1027
            } else {
1028
                (**macScrollPtr->sbHandle).contrlRect.right -= 14;
1029
            }
1030
            macScrollPtr->macFlags |= DRAW_GROW;
1031
        }
1032
    } else {
1033
        TkMacSetScrollbarGrow((TkWindow *) tkwin, false);
1034
    }
1035
 
1036
    /*
1037
     * Given the Tk parameters for the fractions of the start and
1038
     * end of the thumb, the following calculation determines the
1039
     * location for the fixed sized Macintosh thumb.
1040
     */
1041
    middle = scrollPtr->firstFraction / (scrollPtr->firstFraction +
1042
            (1.0 - scrollPtr->lastFraction));
1043
 
1044
    (**macScrollPtr->sbHandle).contrlValue = (short) (middle * 1000);
1045
    if ((**macScrollPtr->sbHandle).contrlHilite == 0 ||
1046
                (**macScrollPtr->sbHandle).contrlHilite == 255) {
1047
        if (scrollPtr->firstFraction == 0.0 &&
1048
                scrollPtr->lastFraction == 1.0) {
1049
            (**macScrollPtr->sbHandle).contrlHilite = 255;
1050
        } else {
1051
            (**macScrollPtr->sbHandle).contrlHilite = 0;
1052
        }
1053
    }
1054
    if ((**macScrollPtr->sbHandle).contrlVis != 255) {
1055
        (**macScrollPtr->sbHandle).contrlVis = 255;
1056
    }
1057
}

powered by: WebSVN 2.1.0

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