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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tk/] [unix/] [tkUnixButton.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
 * tkUnixButton.c --
3
 *
4
 *      This file implements the Unix specific portion of the button
5
 *      widgets.
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: tkUnixButton.c,v 1.1.1.1 2002-01-16 10:26:01 markom Exp $
13
 */
14
 
15
#include "tkButton.h"
16
 
17
/*
18
 * Declaration of Unix specific button structure.
19
 */
20
 
21
typedef struct UnixButton {
22
    TkButton info;              /* Generic button info. */
23
} UnixButton;
24
 
25
/*
26
 * The class procedure table for the button widgets.
27
 */
28
 
29
TkClassProcs tkpButtonProcs = {
30
    NULL,                       /* createProc. */
31
    TkButtonWorldChanged,       /* geometryProc. */
32
    NULL                        /* modalProc. */
33
};
34
 
35
/*
36
 *----------------------------------------------------------------------
37
 *
38
 * TkpCreateButton --
39
 *
40
 *      Allocate a new TkButton structure.
41
 *
42
 * Results:
43
 *      Returns a newly allocated TkButton structure.
44
 *
45
 * Side effects:
46
 *      Registers an event handler for the widget.
47
 *
48
 *----------------------------------------------------------------------
49
 */
50
 
51
TkButton *
52
TkpCreateButton(tkwin)
53
    Tk_Window tkwin;
54
{
55
    UnixButton *butPtr = (UnixButton *)ckalloc(sizeof(UnixButton));
56
    return (TkButton *) butPtr;
57
}
58
 
59
/*
60
 *----------------------------------------------------------------------
61
 *
62
 * TkpDisplayButton --
63
 *
64
 *      This procedure is invoked to display a button widget.  It is
65
 *      normally invoked as an idle handler.
66
 *
67
 * Results:
68
 *      None.
69
 *
70
 * Side effects:
71
 *      Commands are output to X to display the button in its
72
 *      current mode.  The REDRAW_PENDING flag is cleared.
73
 *
74
 *----------------------------------------------------------------------
75
 */
76
 
77
void
78
TkpDisplayButton(clientData)
79
    ClientData clientData;      /* Information about widget. */
80
{
81
    register TkButton *butPtr = (TkButton *) clientData;
82
    GC gc;
83
    Tk_3DBorder border;
84
    Pixmap pixmap;
85
    int x = 0;                   /* Initialization only needed to stop
86
                                 * compiler warning. */
87
    int y, relief;
88
    register Tk_Window tkwin = butPtr->tkwin;
89
    int width, height;
90
    int offset;                 /* 0 means this is a label widget.  1 means
91
                                 * it is a flavor of button, so we offset
92
                                 * the text to make the button appear to
93
                                 * move up and down as the relief changes. */
94
 
95
    butPtr->flags &= ~REDRAW_PENDING;
96
    if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
97
        return;
98
    }
99
 
100
    border = butPtr->normalBorder;
101
    if ((butPtr->state == tkDisabledUid) && (butPtr->disabledFg != NULL)) {
102
        gc = butPtr->disabledGC;
103
    } else if ((butPtr->state == tkActiveUid)
104
            && !Tk_StrictMotif(butPtr->tkwin)) {
105
        gc = butPtr->activeTextGC;
106
        border = butPtr->activeBorder;
107
    } else {
108
        gc = butPtr->normalTextGC;
109
    }
110
    if ((butPtr->flags & SELECTED) && (butPtr->state != tkActiveUid)
111
            && (butPtr->selectBorder != NULL) && !butPtr->indicatorOn) {
112
        border = butPtr->selectBorder;
113
    }
114
 
115
    /*
116
     * Override the relief specified for the button if this is a
117
     * checkbutton or radiobutton and there's no indicator.
118
     */
119
 
120
    relief = butPtr->relief;
121
    if ((butPtr->type >= TYPE_CHECK_BUTTON) && !butPtr->indicatorOn) {
122
        relief = (butPtr->flags & SELECTED) ? TK_RELIEF_SUNKEN
123
                : TK_RELIEF_RAISED;
124
    }
125
 
126
    offset = (butPtr->type == TYPE_BUTTON) && !Tk_StrictMotif(butPtr->tkwin);
127
 
128
    /*
129
     * In order to avoid screen flashes, this procedure redraws
130
     * the button in a pixmap, then copies the pixmap to the
131
     * screen in a single operation.  This means that there's no
132
     * point in time where the on-sreen image has been cleared.
133
     */
134
 
135
    pixmap = Tk_GetPixmap(butPtr->display, Tk_WindowId(tkwin),
136
            Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));
137
    Tk_Fill3DRectangle(tkwin, pixmap, border, 0, 0, Tk_Width(tkwin),
138
            Tk_Height(tkwin), 0, TK_RELIEF_FLAT);
139
 
140
    /*
141
     * Display image or bitmap or text for button.
142
     */
143
 
144
    if (butPtr->image != None) {
145
        Tk_SizeOfImage(butPtr->image, &width, &height);
146
 
147
        imageOrBitmap:
148
        TkComputeAnchor(butPtr->anchor, tkwin, 0, 0,
149
                butPtr->indicatorSpace + width, height, &x, &y);
150
        x += butPtr->indicatorSpace;
151
 
152
        x += offset;
153
        y += offset;
154
        if (relief == TK_RELIEF_RAISED) {
155
            x -= offset;
156
            y -= offset;
157
        } else if (relief == TK_RELIEF_SUNKEN) {
158
            x += offset;
159
            y += offset;
160
        }
161
        if (butPtr->image != NULL) {
162
            if ((butPtr->selectImage != NULL) && (butPtr->flags & SELECTED)) {
163
                Tk_RedrawImage(butPtr->selectImage, 0, 0, width, height, pixmap,
164
                        x, y);
165
            } else {
166
                Tk_RedrawImage(butPtr->image, 0, 0, width, height, pixmap,
167
                        x, y);
168
            }
169
        } else {
170
            XSetClipOrigin(butPtr->display, gc, x, y);
171
            XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, gc, 0, 0,
172
                    (unsigned int) width, (unsigned int) height, x, y, 1);
173
            XSetClipOrigin(butPtr->display, gc, 0, 0);
174
        }
175
        y += height/2;
176
    } else if (butPtr->bitmap != None) {
177
        Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height);
178
        goto imageOrBitmap;
179
    } else {
180
        TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY,
181
                butPtr->indicatorSpace + butPtr->textWidth, butPtr->textHeight,
182
                &x, &y);
183
 
184
        x += butPtr->indicatorSpace;
185
 
186
        x += offset;
187
        y += offset;
188
        if (relief == TK_RELIEF_RAISED) {
189
            x -= offset;
190
            y -= offset;
191
        } else if (relief == TK_RELIEF_SUNKEN) {
192
            x += offset;
193
            y += offset;
194
        }
195
        Tk_DrawTextLayout(butPtr->display, pixmap, gc, butPtr->textLayout,
196
                x, y, 0, -1);
197
        Tk_UnderlineTextLayout(butPtr->display, pixmap, gc,
198
                butPtr->textLayout, x, y, butPtr->underline);
199
        y += butPtr->textHeight/2;
200
    }
201
 
202
    /*
203
     * Draw the indicator for check buttons and radio buttons.  At this
204
     * point x and y refer to the top-left corner of the text or image
205
     * or bitmap.
206
     */
207
 
208
    if ((butPtr->type == TYPE_CHECK_BUTTON) && butPtr->indicatorOn) {
209
        int dim;
210
 
211
        dim = butPtr->indicatorDiameter;
212
        x -= butPtr->indicatorSpace;
213
        y -= dim/2;
214
        if (dim > 2*butPtr->borderWidth) {
215
            Tk_Draw3DRectangle(tkwin, pixmap, border, x, y, dim, dim,
216
                    butPtr->borderWidth,
217
                    (butPtr->flags & SELECTED) ? TK_RELIEF_SUNKEN :
218
                    TK_RELIEF_RAISED);
219
            x += butPtr->borderWidth;
220
            y += butPtr->borderWidth;
221
            dim -= 2*butPtr->borderWidth;
222
            if (butPtr->flags & SELECTED) {
223
                GC gc;
224
 
225
                gc = Tk_3DBorderGC(tkwin,(butPtr->selectBorder != NULL)
226
                        ? butPtr->selectBorder : butPtr->normalBorder,
227
                        TK_3D_FLAT_GC);
228
                XFillRectangle(butPtr->display, pixmap, gc, x, y,
229
                        (unsigned int) dim, (unsigned int) dim);
230
            } else {
231
                Tk_Fill3DRectangle(tkwin, pixmap, butPtr->normalBorder, x, y,
232
                        dim, dim, butPtr->borderWidth, TK_RELIEF_FLAT);
233
            }
234
        }
235
    } else if ((butPtr->type == TYPE_RADIO_BUTTON) && butPtr->indicatorOn) {
236
        XPoint points[4];
237
        int radius;
238
 
239
        radius = butPtr->indicatorDiameter/2;
240
        points[0].x = x - butPtr->indicatorSpace;
241
        points[0].y = y;
242
        points[1].x = points[0].x + radius;
243
        points[1].y = points[0].y + radius;
244
        points[2].x = points[1].x + radius;
245
        points[2].y = points[0].y;
246
        points[3].x = points[1].x;
247
        points[3].y = points[0].y - radius;
248
        if (butPtr->flags & SELECTED) {
249
            GC gc;
250
 
251
            gc = Tk_3DBorderGC(tkwin, (butPtr->selectBorder != NULL)
252
                    ? butPtr->selectBorder : butPtr->normalBorder,
253
                    TK_3D_FLAT_GC);
254
            XFillPolygon(butPtr->display, pixmap, gc, points, 4, Convex,
255
                    CoordModeOrigin);
256
        } else {
257
            Tk_Fill3DPolygon(tkwin, pixmap, butPtr->normalBorder, points,
258
                    4, butPtr->borderWidth, TK_RELIEF_FLAT);
259
        }
260
        Tk_Draw3DPolygon(tkwin, pixmap, border, points, 4, butPtr->borderWidth,
261
                (butPtr->flags & SELECTED) ? TK_RELIEF_SUNKEN :
262
                TK_RELIEF_RAISED);
263
    }
264
 
265
    /*
266
     * If the button is disabled with a stipple rather than a special
267
     * foreground color, generate the stippled effect.  If the widget
268
     * is selected and we use a different background color when selected,
269
     * must temporarily modify the GC.
270
     */
271
 
272
    if ((butPtr->state == tkDisabledUid)
273
            && ((butPtr->disabledFg == NULL) || (butPtr->image != NULL))) {
274
        if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn
275
                && (butPtr->selectBorder != NULL)) {
276
            XSetForeground(butPtr->display, butPtr->disabledGC,
277
                    Tk_3DBorderColor(butPtr->selectBorder)->pixel);
278
        }
279
        XFillRectangle(butPtr->display, pixmap, butPtr->disabledGC,
280
                butPtr->inset, butPtr->inset,
281
                (unsigned) (Tk_Width(tkwin) - 2*butPtr->inset),
282
                (unsigned) (Tk_Height(tkwin) - 2*butPtr->inset));
283
        if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn
284
                && (butPtr->selectBorder != NULL)) {
285
            XSetForeground(butPtr->display, butPtr->disabledGC,
286
                    Tk_3DBorderColor(butPtr->normalBorder)->pixel);
287
        }
288
    }
289
 
290
    /*
291
     * Draw the border and traversal highlight last.  This way, if the
292
     * button's contents overflow they'll be covered up by the border.
293
     * This code is complicated by the possible combinations of focus
294
     * highlight and default rings.  We draw the focus and highlight rings
295
     * using the highlight border and highlight foreground color.
296
     */
297
 
298
    if (relief != TK_RELIEF_FLAT) {
299
        int inset = butPtr->highlightWidth;
300
        if (butPtr->defaultState == tkActiveUid) {
301
            /*
302
             * Draw the default ring with 2 pixels of space between the
303
             * default ring and the button and the default ring and the
304
             * focus ring.  Note that we need to explicitly draw the space
305
             * in the highlightBorder color to ensure that we overwrite any
306
             * overflow text and/or a different button background color.
307
             */
308
 
309
            Tk_Draw3DRectangle(tkwin, pixmap, butPtr->highlightBorder, inset,
310
                    inset, Tk_Width(tkwin) - 2*inset,
311
                    Tk_Height(tkwin) - 2*inset, 2, TK_RELIEF_FLAT);
312
            inset += 2;
313
            Tk_Draw3DRectangle(tkwin, pixmap, butPtr->highlightBorder, inset,
314
                    inset, Tk_Width(tkwin) - 2*inset,
315
                    Tk_Height(tkwin) - 2*inset, 1, TK_RELIEF_SUNKEN);
316
            inset++;
317
            Tk_Draw3DRectangle(tkwin, pixmap, butPtr->highlightBorder, inset,
318
                    inset, Tk_Width(tkwin) - 2*inset,
319
                    Tk_Height(tkwin) - 2*inset, 2, TK_RELIEF_FLAT);
320
 
321
            inset += 2;
322
        } else if (butPtr->defaultState == tkNormalUid) {
323
            /*
324
             * Leave room for the default ring and write over any text or
325
             * background color.
326
             */
327
 
328
            Tk_Draw3DRectangle(tkwin, pixmap, butPtr->highlightBorder, 0,
329
                    0, Tk_Width(tkwin),
330
                    Tk_Height(tkwin), 5, TK_RELIEF_FLAT);
331
            inset += 5;
332
        }
333
 
334
        /*
335
         * Draw the button border.
336
         */
337
 
338
        Tk_Draw3DRectangle(tkwin, pixmap, border, inset, inset,
339
                Tk_Width(tkwin) - 2*inset, Tk_Height(tkwin) - 2*inset,
340
                butPtr->borderWidth, relief);
341
    }
342
    if (butPtr->highlightWidth != 0) {
343
        GC gc;
344
 
345
        if (butPtr->flags & GOT_FOCUS) {
346
            gc = Tk_GCForColor(butPtr->highlightColorPtr, pixmap);
347
        } else {
348
            gc = Tk_GCForColor(Tk_3DBorderColor(butPtr->highlightBorder),
349
                    pixmap);
350
        }
351
 
352
        /*
353
         * Make sure the focus ring shrink-wraps the actual button, not the
354
         * padding space left for a default ring.
355
         */
356
 
357
        if (butPtr->defaultState == tkNormalUid) {
358
            TkDrawInsetFocusHighlight(tkwin, gc, butPtr->highlightWidth,
359
                    pixmap, 5);
360
        } else {
361
            Tk_DrawFocusHighlight(tkwin, gc, butPtr->highlightWidth, pixmap);
362
        }
363
    }
364
 
365
    /*
366
     * Copy the information from the off-screen pixmap onto the screen,
367
     * then delete the pixmap.
368
     */
369
 
370
    XCopyArea(butPtr->display, pixmap, Tk_WindowId(tkwin),
371
            butPtr->copyGC, 0, 0, (unsigned) Tk_Width(tkwin),
372
            (unsigned) Tk_Height(tkwin), 0, 0);
373
    Tk_FreePixmap(butPtr->display, pixmap);
374
}
375
 
376
/*
377
 *----------------------------------------------------------------------
378
 *
379
 * TkpComputeButtonGeometry --
380
 *
381
 *      After changes in a button's text or bitmap, this procedure
382
 *      recomputes the button's geometry and passes this information
383
 *      along to the geometry manager for the window.
384
 *
385
 * Results:
386
 *      None.
387
 *
388
 * Side effects:
389
 *      The button's window may change size.
390
 *
391
 *----------------------------------------------------------------------
392
 */
393
 
394
void
395
TkpComputeButtonGeometry(butPtr)
396
    register TkButton *butPtr;  /* Button whose geometry may have changed. */
397
{
398
    int width, height, avgWidth;
399
    Tk_FontMetrics fm;
400
 
401
    if (butPtr->highlightWidth < 0) {
402
        butPtr->highlightWidth = 0;
403
    }
404
    butPtr->inset = butPtr->highlightWidth + butPtr->borderWidth;
405
 
406
    /*
407
     * Leave room for the default ring if needed.
408
     */
409
 
410
    if (butPtr->defaultState != tkDisabledUid) {
411
        butPtr->inset += 5;
412
    }
413
    butPtr->indicatorSpace = 0;
414
    if (butPtr->image != NULL) {
415
        Tk_SizeOfImage(butPtr->image, &width, &height);
416
        imageOrBitmap:
417
        if (butPtr->width > 0) {
418
            width = butPtr->width;
419
        }
420
        if (butPtr->height > 0) {
421
            height = butPtr->height;
422
        }
423
        if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) {
424
            butPtr->indicatorSpace = height;
425
            if (butPtr->type == TYPE_CHECK_BUTTON) {
426
                butPtr->indicatorDiameter = (65*height)/100;
427
            } else {
428
                butPtr->indicatorDiameter = (75*height)/100;
429
            }
430
        }
431
    } else if (butPtr->bitmap != None) {
432
        Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height);
433
        goto imageOrBitmap;
434
    } else {
435
        Tk_FreeTextLayout(butPtr->textLayout);
436
        butPtr->textLayout = Tk_ComputeTextLayout(butPtr->tkfont,
437
                butPtr->text, -1, butPtr->wrapLength, butPtr->justify, 0,
438
                &butPtr->textWidth, &butPtr->textHeight);
439
 
440
        width = butPtr->textWidth;
441
        height = butPtr->textHeight;
442
        avgWidth = Tk_TextWidth(butPtr->tkfont, "0", 1);
443
        Tk_GetFontMetrics(butPtr->tkfont, &fm);
444
 
445
        if (butPtr->width > 0) {
446
            width = butPtr->width * avgWidth;
447
        }
448
        if (butPtr->height > 0) {
449
            height = butPtr->height * fm.linespace;
450
        }
451
        if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) {
452
            butPtr->indicatorDiameter = fm.linespace;
453
            if (butPtr->type == TYPE_CHECK_BUTTON) {
454
                butPtr->indicatorDiameter = (80*butPtr->indicatorDiameter)/100;
455
            }
456
            butPtr->indicatorSpace = butPtr->indicatorDiameter + avgWidth;
457
        }
458
    }
459
 
460
    /*
461
     * When issuing the geometry request, add extra space for the indicator,
462
     * if any, and for the border and padding, plus two extra pixels so the
463
     * display can be offset by 1 pixel in either direction for the raised
464
     * or lowered effect.
465
     */
466
 
467
    if ((butPtr->image == NULL) && (butPtr->bitmap == None)) {
468
        width += 2*butPtr->padX;
469
        height += 2*butPtr->padY;
470
    }
471
    if ((butPtr->type == TYPE_BUTTON) && !Tk_StrictMotif(butPtr->tkwin)) {
472
        width += 2;
473
        height += 2;
474
    }
475
    Tk_GeometryRequest(butPtr->tkwin, (int) (width + butPtr->indicatorSpace
476
            + 2*butPtr->inset), (int) (height + 2*butPtr->inset));
477
    Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset);
478
}

powered by: WebSVN 2.1.0

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