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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [insight/] [tk/] [unix/] [tkUnixScrlbr.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tkUnixScrollbar.c --
3
 *
4
 *      This file implements the Unix 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: tkUnixScrlbr.c,v 1.1.1.1 2002-01-16 10:26:01 markom Exp $
13
 */
14
 
15
#include "tkScrollbar.h"
16
 
17
/*
18
 * Minimum slider length, in pixels (designed to make sure that the slider
19
 * is always easy to grab with the mouse).
20
 */
21
 
22
#define MIN_SLIDER_LENGTH       5
23
 
24
/*
25
 * Declaration of Unix specific scrollbar structure.
26
 */
27
 
28
typedef struct UnixScrollbar {
29
    TkScrollbar info;           /* Generic scrollbar info. */
30
    GC troughGC;                /* For drawing trough. */
31
    GC copyGC;                  /* Used for copying from pixmap onto screen. */
32
} UnixScrollbar;
33
 
34
/*
35
 * The class procedure table for the scrollbar widget.
36
 */
37
 
38
TkClassProcs tkpScrollbarProcs = {
39
    NULL,                       /* createProc. */
40
    NULL,                       /* geometryProc. */
41
    NULL                        /* modalProc. */
42
};
43
 
44
 
45
/*
46
 *----------------------------------------------------------------------
47
 *
48
 * TkpCreateScrollbar --
49
 *
50
 *      Allocate a new TkScrollbar structure.
51
 *
52
 * Results:
53
 *      Returns a newly allocated TkScrollbar structure.
54
 *
55
 * Side effects:
56
 *      Registers an event handler for the widget.
57
 *
58
 *----------------------------------------------------------------------
59
 */
60
 
61
TkScrollbar *
62
TkpCreateScrollbar(tkwin)
63
    Tk_Window tkwin;
64
{
65
    UnixScrollbar *scrollPtr = (UnixScrollbar *)ckalloc(sizeof(UnixScrollbar));
66
    scrollPtr->troughGC = None;
67
    scrollPtr->copyGC = None;
68
 
69
    Tk_CreateEventHandler(tkwin,
70
            ExposureMask|StructureNotifyMask|FocusChangeMask,
71
            TkScrollbarEventProc, (ClientData) scrollPtr);
72
 
73
    return (TkScrollbar *) scrollPtr;
74
}
75
 
76
/*
77
 *--------------------------------------------------------------
78
 *
79
 * TkpDisplayScrollbar --
80
 *
81
 *      This procedure redraws the contents of a scrollbar window.
82
 *      It is invoked as a do-when-idle handler, so it only runs
83
 *      when there's nothing else for the application to do.
84
 *
85
 * Results:
86
 *      None.
87
 *
88
 * Side effects:
89
 *      Information appears on the screen.
90
 *
91
 *--------------------------------------------------------------
92
 */
93
 
94
void
95
TkpDisplayScrollbar(clientData)
96
    ClientData clientData;      /* Information about window. */
97
{
98
    register TkScrollbar *scrollPtr = (TkScrollbar *) clientData;
99
    register Tk_Window tkwin = scrollPtr->tkwin;
100
    XPoint points[7];
101
    Tk_3DBorder border;
102
    int relief, width, elementBorderWidth;
103
    Pixmap pixmap;
104
 
105
    if ((scrollPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
106
        goto done;
107
    }
108
 
109
    if (scrollPtr->vertical) {
110
        width = Tk_Width(tkwin) - 2*scrollPtr->inset;
111
    } else {
112
        width = Tk_Height(tkwin) - 2*scrollPtr->inset;
113
    }
114
    elementBorderWidth = scrollPtr->elementBorderWidth;
115
    if (elementBorderWidth < 0) {
116
        elementBorderWidth = scrollPtr->borderWidth;
117
    }
118
 
119
    /*
120
     * In order to avoid screen flashes, this procedure redraws
121
     * the scrollbar in a pixmap, then copies the pixmap to the
122
     * screen in a single operation.  This means that there's no
123
     * point in time where the on-sreen image has been cleared.
124
     */
125
 
126
    pixmap = Tk_GetPixmap(scrollPtr->display, Tk_WindowId(tkwin),
127
            Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));
128
 
129
    if (scrollPtr->highlightWidth != 0) {
130
        GC gc;
131
 
132
        if (scrollPtr->flags & GOT_FOCUS) {
133
            gc = Tk_GCForColor(scrollPtr->highlightColorPtr, pixmap);
134
        } else {
135
            gc = Tk_GCForColor(scrollPtr->highlightBgColorPtr, pixmap);
136
        }
137
        Tk_DrawFocusHighlight(tkwin, gc, scrollPtr->highlightWidth, pixmap);
138
    }
139
    Tk_Draw3DRectangle(tkwin, pixmap, scrollPtr->bgBorder,
140
            scrollPtr->highlightWidth, scrollPtr->highlightWidth,
141
            Tk_Width(tkwin) - 2*scrollPtr->highlightWidth,
142
            Tk_Height(tkwin) - 2*scrollPtr->highlightWidth,
143
            scrollPtr->borderWidth, scrollPtr->relief);
144
    XFillRectangle(scrollPtr->display, pixmap,
145
            ((UnixScrollbar*)scrollPtr)->troughGC,
146
            scrollPtr->inset, scrollPtr->inset,
147
            (unsigned) (Tk_Width(tkwin) - 2*scrollPtr->inset),
148
            (unsigned) (Tk_Height(tkwin) - 2*scrollPtr->inset));
149
 
150
    /*
151
     * Draw the top or left arrow.  The coordinates of the polygon
152
     * points probably seem odd, but they were carefully chosen with
153
     * respect to X's rules for filling polygons.  These point choices
154
     * cause the arrows to just fill the narrow dimension of the
155
     * scrollbar and be properly centered.
156
     */
157
 
158
    if (scrollPtr->activeField == TOP_ARROW) {
159
        border = scrollPtr->activeBorder;
160
        relief = scrollPtr->activeField == TOP_ARROW ? scrollPtr->activeRelief
161
                : TK_RELIEF_RAISED;
162
    } else {
163
        border = scrollPtr->bgBorder;
164
        relief = TK_RELIEF_RAISED;
165
    }
166
    if (scrollPtr->vertical) {
167
        points[0].x = scrollPtr->inset - 1;
168
        points[0].y = scrollPtr->arrowLength + scrollPtr->inset - 1;
169
        points[1].x = width + scrollPtr->inset;
170
        points[1].y = points[0].y;
171
        points[2].x = width/2 + scrollPtr->inset;
172
        points[2].y = scrollPtr->inset - 1;
173
        Tk_Fill3DPolygon(tkwin, pixmap, border, points, 3,
174
                elementBorderWidth, relief);
175
    } else {
176
        points[0].x = scrollPtr->arrowLength + scrollPtr->inset - 1;
177
        points[0].y = scrollPtr->inset - 1;
178
        points[1].x = scrollPtr->inset;
179
        points[1].y = width/2 + scrollPtr->inset;
180
        points[2].x = points[0].x;
181
        points[2].y = width + scrollPtr->inset;
182
        Tk_Fill3DPolygon(tkwin, pixmap, border, points, 3,
183
                elementBorderWidth, relief);
184
    }
185
 
186
    /*
187
     * Display the bottom or right arrow.
188
     */
189
 
190
    if (scrollPtr->activeField == BOTTOM_ARROW) {
191
        border = scrollPtr->activeBorder;
192
        relief = scrollPtr->activeField == BOTTOM_ARROW
193
                ? scrollPtr->activeRelief : TK_RELIEF_RAISED;
194
    } else {
195
        border = scrollPtr->bgBorder;
196
        relief = TK_RELIEF_RAISED;
197
    }
198
    if (scrollPtr->vertical) {
199
        points[0].x = scrollPtr->inset;
200
        points[0].y = Tk_Height(tkwin) - scrollPtr->arrowLength
201
                - scrollPtr->inset + 1;
202
        points[1].x = width/2 + scrollPtr->inset;
203
        points[1].y = Tk_Height(tkwin) - scrollPtr->inset;
204
        points[2].x = width + scrollPtr->inset;
205
        points[2].y = points[0].y;
206
        Tk_Fill3DPolygon(tkwin, pixmap, border,
207
                points, 3, elementBorderWidth, relief);
208
    } else {
209
        points[0].x = Tk_Width(tkwin) - scrollPtr->arrowLength
210
                - scrollPtr->inset + 1;
211
        points[0].y = scrollPtr->inset - 1;
212
        points[1].x = points[0].x;
213
        points[1].y = width + scrollPtr->inset;
214
        points[2].x = Tk_Width(tkwin) - scrollPtr->inset;
215
        points[2].y = width/2 + scrollPtr->inset;
216
        Tk_Fill3DPolygon(tkwin, pixmap, border,
217
                points, 3, elementBorderWidth, relief);
218
    }
219
 
220
    /*
221
     * Display the slider.
222
     */
223
 
224
    if (scrollPtr->activeField == SLIDER) {
225
        border = scrollPtr->activeBorder;
226
        relief = scrollPtr->activeField == SLIDER ? scrollPtr->activeRelief
227
                : TK_RELIEF_RAISED;
228
    } else {
229
        border = scrollPtr->bgBorder;
230
        relief = TK_RELIEF_RAISED;
231
    }
232
    if (scrollPtr->vertical) {
233
        Tk_Fill3DRectangle(tkwin, pixmap, border,
234
                scrollPtr->inset, scrollPtr->sliderFirst,
235
                width, scrollPtr->sliderLast - scrollPtr->sliderFirst,
236
                elementBorderWidth, relief);
237
    } else {
238
        Tk_Fill3DRectangle(tkwin, pixmap, border,
239
                scrollPtr->sliderFirst, scrollPtr->inset,
240
                scrollPtr->sliderLast - scrollPtr->sliderFirst, width,
241
                elementBorderWidth, relief);
242
    }
243
 
244
    /*
245
     * Copy the information from the off-screen pixmap onto the screen,
246
     * then delete the pixmap.
247
     */
248
 
249
    XCopyArea(scrollPtr->display, pixmap, Tk_WindowId(tkwin),
250
            ((UnixScrollbar*)scrollPtr)->copyGC, 0, 0,
251
            (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin), 0, 0);
252
    Tk_FreePixmap(scrollPtr->display, pixmap);
253
 
254
    done:
255
    scrollPtr->flags &= ~REDRAW_PENDING;
256
}
257
 
258
/*
259
 *----------------------------------------------------------------------
260
 *
261
 * TkpComputeScrollbarGeometry --
262
 *
263
 *      After changes in a scrollbar's size or configuration, this
264
 *      procedure recomputes various geometry information used in
265
 *      displaying the scrollbar.
266
 *
267
 * Results:
268
 *      None.
269
 *
270
 * Side effects:
271
 *      The scrollbar will be displayed differently.
272
 *
273
 *----------------------------------------------------------------------
274
 */
275
 
276
extern void
277
TkpComputeScrollbarGeometry(scrollPtr)
278
    register TkScrollbar *scrollPtr;    /* Scrollbar whose geometry may
279
                                         * have changed. */
280
{
281
    int width, fieldLength;
282
 
283
    if (scrollPtr->highlightWidth < 0) {
284
        scrollPtr->highlightWidth = 0;
285
    }
286
    scrollPtr->inset = scrollPtr->highlightWidth + scrollPtr->borderWidth;
287
    width = (scrollPtr->vertical) ? Tk_Width(scrollPtr->tkwin)
288
            : Tk_Height(scrollPtr->tkwin);
289
    scrollPtr->arrowLength = width - 2*scrollPtr->inset + 1;
290
    fieldLength = (scrollPtr->vertical ? Tk_Height(scrollPtr->tkwin)
291
            : Tk_Width(scrollPtr->tkwin))
292
            - 2*(scrollPtr->arrowLength + scrollPtr->inset);
293
    if (fieldLength < 0) {
294
        fieldLength = 0;
295
    }
296
    scrollPtr->sliderFirst = fieldLength*scrollPtr->firstFraction;
297
    scrollPtr->sliderLast = fieldLength*scrollPtr->lastFraction;
298
 
299
    /*
300
     * Adjust the slider so that some piece of it is always
301
     * displayed in the scrollbar and so that it has at least
302
     * a minimal width (so it can be grabbed with the mouse).
303
     */
304
 
305
    if (scrollPtr->sliderFirst > (fieldLength - 2*scrollPtr->borderWidth)) {
306
        scrollPtr->sliderFirst = fieldLength - 2*scrollPtr->borderWidth;
307
    }
308
    if (scrollPtr->sliderFirst < 0) {
309
        scrollPtr->sliderFirst = 0;
310
    }
311
    if (scrollPtr->sliderLast < (scrollPtr->sliderFirst
312
            + MIN_SLIDER_LENGTH)) {
313
        scrollPtr->sliderLast = scrollPtr->sliderFirst + MIN_SLIDER_LENGTH;
314
    }
315
    if (scrollPtr->sliderLast > fieldLength) {
316
        scrollPtr->sliderLast = fieldLength;
317
    }
318
    scrollPtr->sliderFirst += scrollPtr->arrowLength + scrollPtr->inset;
319
    scrollPtr->sliderLast += scrollPtr->arrowLength + scrollPtr->inset;
320
 
321
    /*
322
     * Register the desired geometry for the window (leave enough space
323
     * for the two arrows plus a minimum-size slider, plus border around
324
     * the whole window, if any).  Then arrange for the window to be
325
     * redisplayed.
326
     */
327
 
328
    if (scrollPtr->vertical) {
329
        Tk_GeometryRequest(scrollPtr->tkwin,
330
                scrollPtr->width + 2*scrollPtr->inset,
331
                2*(scrollPtr->arrowLength + scrollPtr->borderWidth
332
                + scrollPtr->inset));
333
    } else {
334
        Tk_GeometryRequest(scrollPtr->tkwin,
335
                2*(scrollPtr->arrowLength + scrollPtr->borderWidth
336
                + scrollPtr->inset), scrollPtr->width + 2*scrollPtr->inset);
337
    }
338
    Tk_SetInternalBorder(scrollPtr->tkwin, scrollPtr->inset);
339
}
340
 
341
/*
342
 *----------------------------------------------------------------------
343
 *
344
 * TkpDestroyScrollbar --
345
 *
346
 *      Free data structures associated with the scrollbar control.
347
 *
348
 * Results:
349
 *      None.
350
 *
351
 * Side effects:
352
 *      Frees the GCs associated with the scrollbar.
353
 *
354
 *----------------------------------------------------------------------
355
 */
356
 
357
void
358
TkpDestroyScrollbar(scrollPtr)
359
    TkScrollbar *scrollPtr;
360
{
361
    UnixScrollbar *unixScrollPtr = (UnixScrollbar *)scrollPtr;
362
 
363
    if (unixScrollPtr->troughGC != None) {
364
        Tk_FreeGC(scrollPtr->display, unixScrollPtr->troughGC);
365
    }
366
    if (unixScrollPtr->copyGC != None) {
367
        Tk_FreeGC(scrollPtr->display, unixScrollPtr->copyGC);
368
    }
369
}
370
 
371
/*
372
 *----------------------------------------------------------------------
373
 *
374
 * TkpConfigureScrollbar --
375
 *
376
 *      This procedure is called after the generic code has finished
377
 *      processing configuration options, in order to configure
378
 *      platform specific options.
379
 *
380
 * Results:
381
 *      None.
382
 *
383
 * Side effects:
384
 *      Configuration info may get changed.
385
 *
386
 *----------------------------------------------------------------------
387
 */
388
 
389
void
390
TkpConfigureScrollbar(scrollPtr)
391
    register TkScrollbar *scrollPtr;    /* Information about widget;  may or
392
                                         * may not already have values for
393
                                         * some fields. */
394
{
395
    XGCValues gcValues;
396
    GC new;
397
    UnixScrollbar *unixScrollPtr = (UnixScrollbar *) scrollPtr;
398
 
399
    Tk_SetBackgroundFromBorder(scrollPtr->tkwin, scrollPtr->bgBorder);
400
 
401
    gcValues.foreground = scrollPtr->troughColorPtr->pixel;
402
    new = Tk_GetGC(scrollPtr->tkwin, GCForeground, &gcValues);
403
    if (unixScrollPtr->troughGC != None) {
404
        Tk_FreeGC(scrollPtr->display, unixScrollPtr->troughGC);
405
    }
406
    unixScrollPtr->troughGC = new;
407
    if (unixScrollPtr->copyGC == None) {
408
        gcValues.graphics_exposures = False;
409
        unixScrollPtr->copyGC = Tk_GetGC(scrollPtr->tkwin, GCGraphicsExposures,
410
            &gcValues);
411
    }
412
}
413
 
414
/*
415
 *--------------------------------------------------------------
416
 *
417
 * TkpScrollbarPosition --
418
 *
419
 *      Determine the scrollbar element corresponding to a
420
 *      given position.
421
 *
422
 * Results:
423
 *      One of TOP_ARROW, TOP_GAP, etc., indicating which element
424
 *      of the scrollbar covers the position given by (x, y).  If
425
 *      (x,y) is outside the scrollbar entirely, then OUTSIDE is
426
 *      returned.
427
 *
428
 * Side effects:
429
 *      None.
430
 *
431
 *--------------------------------------------------------------
432
 */
433
 
434
int
435
TkpScrollbarPosition(scrollPtr, x, y)
436
    register TkScrollbar *scrollPtr;    /* Scrollbar widget record. */
437
    int x, y;                           /* Coordinates within scrollPtr's
438
                                         * window. */
439
{
440
    int length, width, tmp;
441
 
442
    if (scrollPtr->vertical) {
443
        length = Tk_Height(scrollPtr->tkwin);
444
        width = Tk_Width(scrollPtr->tkwin);
445
    } else {
446
        tmp = x;
447
        x = y;
448
        y = tmp;
449
        length = Tk_Width(scrollPtr->tkwin);
450
        width = Tk_Height(scrollPtr->tkwin);
451
    }
452
 
453
    if ((x < scrollPtr->inset) || (x >= (width - scrollPtr->inset))
454
            || (y < scrollPtr->inset) || (y >= (length - scrollPtr->inset))) {
455
        return OUTSIDE;
456
    }
457
 
458
    /*
459
     * All of the calculations in this procedure mirror those in
460
     * TkpDisplayScrollbar.  Be sure to keep the two consistent.
461
     */
462
 
463
    if (y < (scrollPtr->inset + scrollPtr->arrowLength)) {
464
        return TOP_ARROW;
465
    }
466
    if (y < scrollPtr->sliderFirst) {
467
        return TOP_GAP;
468
    }
469
    if (y < scrollPtr->sliderLast) {
470
        return SLIDER;
471
    }
472
    if (y >= (length - (scrollPtr->arrowLength + scrollPtr->inset))) {
473
        return BOTTOM_ARROW;
474
    }
475
    return BOTTOM_GAP;
476
}

powered by: WebSVN 2.1.0

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