diff options
Diffstat (limited to 'unix/tkUnixButton.c')
-rw-r--r-- | unix/tkUnixButton.c | 693 |
1 files changed, 473 insertions, 220 deletions
diff --git a/unix/tkUnixButton.c b/unix/tkUnixButton.c index d14f30d..373f2e3 100644 --- a/unix/tkUnixButton.c +++ b/unix/tkUnixButton.c @@ -1,16 +1,27 @@ -/* +/* * tkUnixButton.c -- * - * This file implements the Unix specific portion of the button - * widgets. + * This file implements the Unix specific portion of the button widgets. * * Copyright (c) 1996-1997 by Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ +#include "tkInt.h" #include "tkButton.h" +#include "tk3d.h" + +/* + * Shared with menu widget. + */ + +MODULE_SCOPE void TkpDrawCheckIndicator(Tk_Window tkwin, + Display *display, Drawable d, int x, int y, + Tk_3DBorder bgBorder, XColor *indicatorColor, + XColor *selectColor, XColor *disColor, int on, + int disabled, int mode); /* * Declaration of Unix specific button structure. @@ -21,13 +32,279 @@ typedef struct UnixButton { } UnixButton; /* - * The class procedure table for the button widgets. + * The class function table for the button widgets. */ Tk_ClassProcs tkpButtonProcs = { sizeof(Tk_ClassProcs), /* size */ TkButtonWorldChanged, /* worldChangedProc */ }; + +/* + * The button image. + * The header info here is ignored, it's the image that's important. The + * colors will be applied as follows: + * A = Background + * B = Background + * C = 3D light + * D = selectColor + * E = 3D dark + * F = Background + * G = Indicator Color + * H = disabled Indicator Color + */ + +/* XPM */ +static char *button_images[] = { + /* width height ncolors chars_per_pixel */ + "52 26 7 1", + /* colors */ + "A c #808000000000", + "B c #000080800000", + "C c #808080800000", + "D c #000000008080", + "E c #808000008080", + "F c #000080808080", + "G c #000000000000", + "H c #000080800000", + /* pixels */ + "AAAAAAAAAAAABAAAAAAAAAAAABAAAAAAAAAAAABAAAAAAAAAAAAB", + "AEEEEEEEEEECBAEEEEEEEEEECBAEEEEEEEEEECBAEEEEEEEEEECB", + "AEDDDDDDDDDCBAEDDDDDDDDDCBAEFFFFFFFFFCBAEFFFFFFFFFCB", + "AEDDDDDDDDDCBAEDDDDDDDGDCBAEFFFFFFFFFCBAEFFFFFFFHFCB", + "AEDDDDDDDDDCBAEDDDDDDGGDCBAEFFFFFFFFFCBAEFFFFFFHHFCB", + "AEDDDDDDDDDCBAEDGDDDGGGDCBAEFFFFFFFFFCBAEFHFFFHHHFCB", + "AEDDDDDDDDDCBAEDGGDGGGDDCBAEFFFFFFFFFCBAEFHHFHHHFFCB", + "AEDDDDDDDDDCBAEDGGGGGDDDCBAEFFFFFFFFFCBAEFHHHHHFFFCB", + "AEDDDDDDDDDCBAEDDGGGDDDDCBAEFFFFFFFFFCBAEFFHHHFFFFCB", + "AEDDDDDDDDDCBAEDDDGDDDDDCBAEFFFFFFFFFCBAEFFFHFFFFFCB", + "AEDDDDDDDDDCBAEDDDDDDDDDCBAEFFFFFFFFFCBAEFFFFFFFFFCB", + "ACCCCCCCCCCCBACCCCCCCCCCCBACCCCCCCCCCCBACCCCCCCCCCCB", + "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB", + "FFFFAAAAFFFFFFFFFAAAAFFFFFFFFFAAAAFFFFFFFFFAAAAFFFFF", + "FFAAEEEEAAFFFFFAAEEEEAAFFFFFAAEEEEAAFFFFFAAEEEEAAFFF", + "FAEEDDDDEEBFFFAEEDDDDEEBFFFAEEFFFFEEBFFFAEEFFFFEEBFF", + "FAEDDDDDDCBFFFAEDDDDDDCBFFFAEFFFFFFCBFFFAEFFFFFFCBFF", + "AEDDDDDDDDCBFAEDDDGGDDDCBFAEFFFFFFFFCBFAEFFFHHFFFCBF", + "AEDDDDDDDDCBFAEDDGGGGDDCBFAEFFFFFFFFCBFAEFFHHHHFFCBF", + "AEDDDDDDDDCBFAEDDGGGGDDCBFAEFFFFFFFFCBFAEFFHHHHFFCBF", + "AEDDDDDDDDCBFAEDDDGGDDDCBFAEFFFFFFFFCBFAEFFFHHFFFCBF", + "FAEDDDDDDCBFFFAEDDDDDDCBFFFAEFFFFFFCBFFFAEFFFFFFCBFF", + "FACCDDDDCCBFFFACCDDDDCCBFFFACCFFFFCCBFFFACCFFFFCCBFF", + "FFBBCCCCBBFFFFFBBCCCCBBFFFFFBBCCCCBBFFFFFBBCCCCBBFFF", + "FFFFBBBBFFFFFFFFFBBBBFFFFFFFFFBBBBFFFFFFFFFBBBBFFFFF", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", +}; + +/* + * Sizes and offsets into above XPM file. + */ + +#define CHECK_BUTTON_DIM 13 +#define CHECK_MENU_DIM 9 +#define CHECK_START 9 +#define CHECK_ON_OFFSET 13 +#define CHECK_OFF_OFFSET 0 +#define CHECK_DISON_OFFSET 39 +#define CHECK_DISOFF_OFFSET 26 +#define RADIO_BUTTON_DIM 12 +#define RADIO_MENU_DIM 6 +#define RADIO_WIDTH 13 +#define RADIO_START 22 +#define RADIO_ON_OFFSET 13 +#define RADIO_OFF_OFFSET 0 +#define RADIO_DISON_OFFSET 39 +#define RADIO_DISOFF_OFFSET 26 + +/* + * Indicator Draw Modes + */ + +#define CHECK_BUTTON 0 +#define CHECK_MENU 1 +#define RADIO_BUTTON 2 +#define RADIO_MENU 3 + +/* + *---------------------------------------------------------------------- + * + * TkpDrawCheckIndicator - + * + * Draws the checkbox image in the drawable at the (x,y) location, value, + * and state given. This routine is use by the button and menu widgets + * + * Results: + * None. + * + * Side effects: + * An image is drawn in the drawable at the location given. + * + *---------------------------------------------------------------------- + */ + +void +TkpDrawCheckIndicator( + Tk_Window tkwin, /* handle for resource alloc */ + Display *display, + Drawable d, /* what to draw on */ + int x, int y, /* where to draw */ + Tk_3DBorder bgBorder, /* colors of the border */ + XColor *indicatorColor, /* color of the indicator */ + XColor *selectColor, /* color when selected */ + XColor *disableColor, /* color when disabled */ + int on, /* are we on? */ + int disabled, /* are we disabled? */ + int mode) /* kind of indicator to draw */ +{ + int ix, iy; + int dim; + int imgsel, imgstart; + TkBorder *bg_brdr = (TkBorder*)bgBorder; + XGCValues gcValues; + GC copyGC; + unsigned long imgColors[8]; + XImage *img; + Pixmap pixmap; + int depth; + + /* + * Sanity check. + */ + + if (tkwin == NULL || display == None || d == None || bgBorder == NULL + || indicatorColor == NULL) { + return; + } + + if (disableColor == NULL) { + disableColor = bg_brdr->bgColorPtr; + } + + if (selectColor == NULL) { + selectColor = bg_brdr->bgColorPtr; + } + + depth = Tk_Depth(tkwin); + + /* + * Compute starting point and dimensions of image inside button_images to + * be used. + */ + + switch (mode) { + default: + case CHECK_BUTTON: + imgsel = on == 2 ? CHECK_DISON_OFFSET : + on == 1 ? CHECK_ON_OFFSET : CHECK_OFF_OFFSET; + imgsel += disabled && on != 2 ? CHECK_DISOFF_OFFSET : 0; + imgstart = CHECK_START; + dim = CHECK_BUTTON_DIM; + break; + + case CHECK_MENU: + imgsel = on == 2 ? CHECK_DISOFF_OFFSET : + on == 1 ? CHECK_ON_OFFSET : CHECK_OFF_OFFSET; + imgsel += disabled && on != 2 ? CHECK_DISOFF_OFFSET : 0; + imgstart = CHECK_START + 2; + imgsel += 2; + dim = CHECK_MENU_DIM; + break; + + case RADIO_BUTTON: + imgsel = on == 2 ? RADIO_DISON_OFFSET : + on==1 ? RADIO_ON_OFFSET : RADIO_OFF_OFFSET; + imgsel += disabled && on != 2 ? RADIO_DISOFF_OFFSET : 0; + imgstart = RADIO_START; + dim = RADIO_BUTTON_DIM; + break; + + case RADIO_MENU: + imgsel = on == 2 ? RADIO_DISOFF_OFFSET : + on==1 ? RADIO_ON_OFFSET : RADIO_OFF_OFFSET; + imgsel += disabled && on != 2 ? RADIO_DISOFF_OFFSET : 0; + imgstart = RADIO_START + 3; + imgsel += 3; + dim = RADIO_MENU_DIM; + break; + } + + /* + * Allocate the drawing areas to use. Note that we use double-buffering + * here because not all code paths leading to this function do so. + */ + + pixmap = Tk_GetPixmap(display, d, dim, dim, depth); + if (pixmap == None) { + return; + } + + x -= dim/2; + y -= dim/2; + + img = XGetImage(display, pixmap, 0, 0, + (unsigned int)dim, (unsigned int)dim, AllPlanes, ZPixmap); + if (img == NULL) { + return; + } + + /* + * Set up the color mapping table. + */ + + TkpGetShadows(bg_brdr, tkwin); + + imgColors[0 /*A*/] = + Tk_GetColorByValue(tkwin, bg_brdr->bgColorPtr)->pixel; + imgColors[1 /*B*/] = + Tk_GetColorByValue(tkwin, bg_brdr->bgColorPtr)->pixel; + imgColors[2 /*C*/] = (bg_brdr->lightColorPtr != NULL) ? + Tk_GetColorByValue(tkwin, bg_brdr->lightColorPtr)->pixel : + WhitePixelOfScreen(bg_brdr->screen); + imgColors[3 /*D*/] = + Tk_GetColorByValue(tkwin, selectColor)->pixel; + imgColors[4 /*E*/] = (bg_brdr->darkColorPtr != NULL) ? + Tk_GetColorByValue(tkwin, bg_brdr->darkColorPtr)->pixel : + BlackPixelOfScreen(bg_brdr->screen); + imgColors[5 /*F*/] = + Tk_GetColorByValue(tkwin, bg_brdr->bgColorPtr)->pixel; + imgColors[6 /*G*/] = + Tk_GetColorByValue(tkwin, indicatorColor)->pixel; + imgColors[7 /*H*/] = + Tk_GetColorByValue(tkwin, disableColor)->pixel; + + /* + * Create the image, painting it into an XImage one pixel at a time. + */ + + for (iy=0 ; iy<dim ; iy++) { + for (ix=0 ; ix<dim ; ix++) { + XPutPixel(img, ix, iy, + imgColors[button_images[imgstart+iy][imgsel+ix] - 'A'] ); + } + } + + /* + * Copy onto our target drawable surface. + */ + + memset(&gcValues, 0, sizeof(gcValues)); + gcValues.background = bg_brdr->bgColorPtr->pixel; + gcValues.graphics_exposures = False; + copyGC = Tk_GetGC(tkwin, 0, &gcValues); + + XPutImage(display, pixmap, copyGC, img, 0, 0, 0, 0, + (unsigned int)dim, (unsigned int)dim); + XCopyArea(display, pixmap, d, copyGC, 0, 0, + (unsigned int)dim, (unsigned int)dim, x, y); + + /* + * Tidy up. + */ + + Tk_FreeGC(display, copyGC); + XDestroyImage(img); + Tk_FreePixmap(display, pixmap); +} /* *---------------------------------------------------------------------- @@ -46,10 +323,10 @@ Tk_ClassProcs tkpButtonProcs = { */ TkButton * -TkpCreateButton(tkwin) - Tk_Window tkwin; +TkpCreateButton( + Tk_Window tkwin) { - UnixButton *butPtr = (UnixButton *)ckalloc(sizeof(UnixButton)); + UnixButton *butPtr = (UnixButton *) ckalloc(sizeof(UnixButton)); return (TkButton *) butPtr; } @@ -58,29 +335,29 @@ TkpCreateButton(tkwin) * * TkpDisplayButton -- * - * This procedure is invoked to display a button widget. It is - * normally invoked as an idle handler. + * This function is invoked to display a button widget. It is normally + * invoked as an idle handler. * * Results: * None. * * Side effects: - * Commands are output to X to display the button in its - * current mode. The REDRAW_PENDING flag is cleared. + * Commands are output to X to display the button in its current mode. + * The REDRAW_PENDING flag is cleared. * *---------------------------------------------------------------------- */ void -TkpDisplayButton(clientData) - ClientData clientData; /* Information about widget. */ +TkpDisplayButton( + ClientData clientData) /* Information about widget. */ { register TkButton *butPtr = (TkButton *) clientData; GC gc; Tk_3DBorder border; Pixmap pixmap; - int x = 0; /* Initialization only needed to stop - * compiler warning. */ + int x = 0; /* Initialization only needed to stop compiler + * warning. */ int y, relief; Tk_Window tkwin = butPtr->tkwin; int width, height, fullWidth, fullHeight; @@ -88,12 +365,12 @@ TkpDisplayButton(clientData) int haveImage = 0, haveText = 0; int offset; /* 1 means this is a button widget, so we * offset the text to make the button appear - * to move up and down as the relief changes. - */ + * to move up and down as the relief + * changes. */ int imageWidth, imageHeight; - int imageXOffset = 0, imageYOffset = 0; /* image information that will - * be used to restrict disabled - * pixmap as well */ + int imageXOffset = 0, imageYOffset = 0; + /* image information that will be used to + * restrict disabled pixmap as well */ butPtr->flags &= ~REDRAW_PENDING; if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) { @@ -110,15 +387,14 @@ TkpDisplayButton(clientData) } else { gc = butPtr->normalTextGC; } - if ((butPtr->flags & SELECTED) && (butPtr->state != STATE_ACTIVE) - && (butPtr->selectBorder != NULL) && !butPtr->indicatorOn) { + if ((butPtr->flags & SELECTED) && (butPtr->selectBorder != NULL) + && !butPtr->indicatorOn) { border = butPtr->selectBorder; } /* - * Override the relief specified for the button if this is a - * checkbutton or radiobutton and there's no indicator. The new - * relief is as follows: + * Override the relief specified for the button if this is a checkbutton + * or radiobutton and there's no indicator. The new relief is as follows: * If the button is select --> "sunken" * If relief==overrelief --> relief * Otherwise --> overrelief @@ -132,15 +408,15 @@ TkpDisplayButton(clientData) * on no sunken * on yes sunken * - * This is accomplished by configuring the checkbutton or radiobutton - * like this: + * This is accomplished by configuring the checkbutton or radiobutton like + * this: * * -indicatoron 0 -overrelief raised -offrelief flat * * Bindings (see library/button.tcl) will copy the -overrelief into - * -relief on mouseover. Hence, we can tell if we are in mouse-over by - * comparing relief against overRelief. This is an aweful kludge, but - * it gives use the desired behavior while keeping the code backwards + * -relief on mouseover. Hence, we can tell if we are in mouse-over by + * comparing relief against overRelief. This is an aweful kludge, but it + * gives use the desired behavior while keeping the code backwards * compatible. */ @@ -156,10 +432,10 @@ TkpDisplayButton(clientData) offset = (butPtr->type == TYPE_BUTTON) && !Tk_StrictMotif(butPtr->tkwin); /* - * In order to avoid screen flashes, this procedure redraws - * the button in a pixmap, then copies the pixmap to the - * screen in a single operation. This means that there's no - * point in time where the on-sreen image has been cleared. + * In order to avoid screen flashes, this function redraws the button in a + * pixmap, then copies the pixmap to the screen in a single operation. + * This means that there's no point in time where the on-screen image has + * been cleared. */ pixmap = Tk_GetPixmap(butPtr->display, Tk_WindowId(tkwin), @@ -178,11 +454,11 @@ TkpDisplayButton(clientData) Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height); haveImage = 1; } - imageWidth = width; + imageWidth = width; imageHeight = height; haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0); - + if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) { textXOffset = 0; textYOffset = 0; @@ -190,49 +466,56 @@ TkpDisplayButton(clientData) fullHeight = 0; switch ((enum compound) butPtr->compound) { - case COMPOUND_TOP: - case COMPOUND_BOTTOM: { - /* Image is above or below text */ - if (butPtr->compound == COMPOUND_TOP) { - textYOffset = height + butPtr->padY; - } else { - imageYOffset = butPtr->textHeight + butPtr->padY; - } - fullHeight = height + butPtr->textHeight + butPtr->padY; - fullWidth = (width > butPtr->textWidth ? width : - butPtr->textWidth); - textXOffset = (fullWidth - butPtr->textWidth)/2; - imageXOffset = (fullWidth - width)/2; - break; - } - case COMPOUND_LEFT: - case COMPOUND_RIGHT: { - /* Image is left or right of text */ - if (butPtr->compound == COMPOUND_LEFT) { - textXOffset = width + butPtr->padX; - } else { - imageXOffset = butPtr->textWidth + butPtr->padX; - } - fullWidth = butPtr->textWidth + butPtr->padX + width; - fullHeight = (height > butPtr->textHeight ? height : - butPtr->textHeight); - textYOffset = (fullHeight - butPtr->textHeight)/2; - imageYOffset = (fullHeight - height)/2; - break; + case COMPOUND_TOP: + case COMPOUND_BOTTOM: + /* + * Image is above or below text. + */ + + if (butPtr->compound == COMPOUND_TOP) { + textYOffset = height + butPtr->padY; + } else { + imageYOffset = butPtr->textHeight + butPtr->padY; } - case COMPOUND_CENTER: { - /* Image and text are superimposed */ - fullWidth = (width > butPtr->textWidth ? width : - butPtr->textWidth); - fullHeight = (height > butPtr->textHeight ? height : - butPtr->textHeight); - textXOffset = (fullWidth - butPtr->textWidth)/2; - imageXOffset = (fullWidth - width)/2; - textYOffset = (fullHeight - butPtr->textHeight)/2; - imageYOffset = (fullHeight - height)/2; - break; + fullHeight = height + butPtr->textHeight + butPtr->padY; + fullWidth = (width > butPtr->textWidth ? width : + butPtr->textWidth); + textXOffset = (fullWidth - butPtr->textWidth)/2; + imageXOffset = (fullWidth - width)/2; + break; + case COMPOUND_LEFT: + case COMPOUND_RIGHT: + /* + * Image is left or right of text. + */ + + if (butPtr->compound == COMPOUND_LEFT) { + textXOffset = width + butPtr->padX; + } else { + imageXOffset = butPtr->textWidth + butPtr->padX; } - case COMPOUND_NONE: {break;} + fullWidth = butPtr->textWidth + butPtr->padX + width; + fullHeight = (height > butPtr->textHeight ? height : + butPtr->textHeight); + textYOffset = (fullHeight - butPtr->textHeight)/2; + imageYOffset = (fullHeight - height)/2; + break; + case COMPOUND_CENTER: + /* + * Image and text are superimposed. + */ + + fullWidth = (width > butPtr->textWidth ? width : + butPtr->textWidth); + fullHeight = (height > butPtr->textHeight ? height : + butPtr->textHeight); + textXOffset = (fullWidth - butPtr->textWidth)/2; + imageXOffset = (fullWidth - width)/2; + textYOffset = (fullHeight - butPtr->textHeight)/2; + imageYOffset = (fullHeight - height)/2; + break; + case COMPOUND_NONE: + break; } TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY, @@ -255,8 +538,8 @@ TkpDisplayButton(clientData) if (butPtr->image != NULL) { /* - * Do boundary clipping, so that Tk_RedrawImage is passed - * valid coordinates. [Bug 979239] + * Do boundary clipping, so that Tk_RedrawImage is passed valid + * coordinates. [Bug 979239] */ if (imageXOffset < 0) { @@ -281,6 +564,9 @@ TkpDisplayButton(clientData) if ((butPtr->selectImage != NULL) && (butPtr->flags & SELECTED)) { Tk_RedrawImage(butPtr->selectImage, 0, 0, width, height, pixmap, imageXOffset, imageYOffset); + } else if ((butPtr->tristateImage != NULL) && (butPtr->flags & TRISTATED)) { + Tk_RedrawImage(butPtr->tristateImage, 0, 0, + width, height, pixmap, imageXOffset, imageYOffset); } else { Tk_RedrawImage(butPtr->image, 0, 0, width, height, pixmap, imageXOffset, imageYOffset); @@ -304,7 +590,7 @@ TkpDisplayButton(clientData) TkComputeAnchor(butPtr->anchor, tkwin, 0, 0, butPtr->indicatorSpace + width, height, &x, &y); x += butPtr->indicatorSpace; - + x += offset; y += offset; if (relief == TK_RELIEF_RAISED) { @@ -345,6 +631,10 @@ TkpDisplayButton(clientData) (butPtr->flags & SELECTED)) { Tk_RedrawImage(butPtr->selectImage, 0, 0, width, height, pixmap, imageXOffset, imageYOffset); + } else if ((butPtr->tristateImage != NULL) && + (butPtr->flags & TRISTATED)) { + Tk_RedrawImage(butPtr->tristateImage, 0, 0, width, + height, pixmap, imageXOffset, imageYOffset); } else { Tk_RedrawImage(butPtr->image, 0, 0, width, height, pixmap, imageXOffset, imageYOffset); @@ -360,9 +650,9 @@ TkpDisplayButton(clientData) TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY, butPtr->indicatorSpace + butPtr->textWidth, butPtr->textHeight, &x, &y); - + x += butPtr->indicatorSpace; - + x += offset; y += offset; if (relief == TK_RELIEF_RAISED) { @@ -379,104 +669,51 @@ TkpDisplayButton(clientData) y += butPtr->textHeight/2; } } - + /* - * Draw the indicator for check buttons and radio buttons. At this - * point x and y refer to the top-left corner of the text or image - * or bitmap. + * Draw the indicator for check buttons and radio buttons. At this point, + * x and y refer to the top-left corner of the text or image or bitmap. */ if ((butPtr->type == TYPE_CHECK_BUTTON) && butPtr->indicatorOn) { - int dim; - - dim = butPtr->indicatorDiameter; - x -= butPtr->indicatorSpace; - y -= dim/2; - if (dim > 2*butPtr->borderWidth) { - Tk_Draw3DRectangle(tkwin, pixmap, border, x, y, dim, dim, - butPtr->borderWidth, - (butPtr->flags & SELECTED) ? TK_RELIEF_SUNKEN : - TK_RELIEF_RAISED); - x += butPtr->borderWidth; - y += butPtr->borderWidth; - dim -= 2*butPtr->borderWidth; - if (butPtr->flags & SELECTED) { - GC gc; - if (butPtr->state != STATE_DISABLED) { - if (butPtr->selectBorder != NULL) { - gc = Tk_3DBorderGC(tkwin, butPtr->selectBorder, - TK_3D_FLAT_GC); - } else { - gc = Tk_3DBorderGC(tkwin, butPtr->normalBorder, - TK_3D_FLAT_GC); - } - } else { - if (butPtr->disabledFg != NULL) { - gc = butPtr->disabledGC; - } else { - gc = butPtr->normalTextGC; - XSetForeground(butPtr->display, butPtr->disabledGC, - Tk_3DBorderColor(butPtr->normalBorder)->pixel); - } - } + if (butPtr->indicatorDiameter > 2*butPtr->borderWidth) { + TkBorder *selBorder = (TkBorder *) butPtr->selectBorder; + XColor *selColor = NULL; - XFillRectangle(butPtr->display, pixmap, gc, x, y, - (unsigned int) dim, (unsigned int) dim); - } else { - Tk_Fill3DRectangle(tkwin, pixmap, butPtr->normalBorder, x, y, - dim, dim, butPtr->borderWidth, TK_RELIEF_FLAT); + if (selBorder != NULL) { + selColor = selBorder->bgColorPtr; } + x -= butPtr->indicatorSpace/2; + y = Tk_Height(tkwin)/2; + TkpDrawCheckIndicator(tkwin, butPtr->display, pixmap, x, y, + border, butPtr->normalFg, selColor, butPtr->disabledFg, + ((butPtr->flags & SELECTED) ? 1 : + (butPtr->flags & TRISTATED) ? 2 : 0), + (butPtr->state == STATE_DISABLED), CHECK_BUTTON); } } else if ((butPtr->type == TYPE_RADIO_BUTTON) && butPtr->indicatorOn) { - XPoint points[4]; - int radius; - - radius = butPtr->indicatorDiameter/2; - points[0].x = x - butPtr->indicatorSpace; - points[0].y = y; - points[1].x = points[0].x + radius; - points[1].y = points[0].y + radius; - points[2].x = points[1].x + radius; - points[2].y = points[0].y; - points[3].x = points[1].x; - points[3].y = points[0].y - radius; - if (butPtr->flags & SELECTED) { - GC gc; + if (butPtr->indicatorDiameter > 2*butPtr->borderWidth) { + TkBorder *selBorder = (TkBorder *) butPtr->selectBorder; + XColor *selColor = NULL; - if (butPtr->state != STATE_DISABLED) { - if (butPtr->selectBorder != NULL) { - gc = Tk_3DBorderGC(tkwin, butPtr->selectBorder, - TK_3D_FLAT_GC); - } else { - gc = Tk_3DBorderGC(tkwin, butPtr->normalBorder, - TK_3D_FLAT_GC); - } - } else { - if (butPtr->disabledFg != NULL) { - gc = butPtr->disabledGC; - } else { - gc = butPtr->normalTextGC; - XSetForeground(butPtr->display, butPtr->disabledGC, - Tk_3DBorderColor(butPtr->normalBorder)->pixel); - } + if (selBorder != NULL) { + selColor = selBorder->bgColorPtr; } - - XFillPolygon(butPtr->display, pixmap, gc, points, 4, Convex, - CoordModeOrigin); - } else { - Tk_Fill3DPolygon(tkwin, pixmap, butPtr->normalBorder, points, - 4, butPtr->borderWidth, TK_RELIEF_FLAT); + x -= butPtr->indicatorSpace/2; + y = Tk_Height(tkwin)/2; + TkpDrawCheckIndicator(tkwin, butPtr->display, pixmap, x, y, + border, butPtr->normalFg, selColor, butPtr->disabledFg, + ((butPtr->flags & SELECTED) ? 1 : + (butPtr->flags & TRISTATED) ? 2 : 0), + (butPtr->state == STATE_DISABLED), RADIO_BUTTON); } - Tk_Draw3DPolygon(tkwin, pixmap, border, points, 4, butPtr->borderWidth, - (butPtr->flags & SELECTED) ? TK_RELIEF_SUNKEN : - TK_RELIEF_RAISED); } /* * If the button is disabled with a stipple rather than a special - * foreground color, generate the stippled effect. If the widget - * is selected and we use a different background color when selected, - * must temporarily modify the GC so the stippling is the right color. + * foreground color, generate the stippled effect. If the widget is + * selected and we use a different background color when selected, must + * temporarily modify the GC so the stippling is the right color. */ if ((butPtr->state == STATE_DISABLED) @@ -486,10 +723,12 @@ TkpDisplayButton(clientData) XSetForeground(butPtr->display, butPtr->stippleGC, Tk_3DBorderColor(butPtr->selectBorder)->pixel); } + /* - * Stipple the whole button if no disabledFg was specified, - * otherwise restrict stippling only to displayed image + * Stipple the whole button if no disabledFg was specified, otherwise + * restrict stippling only to displayed image */ + if (butPtr->disabledFg == NULL) { XFillRectangle(butPtr->display, pixmap, butPtr->stippleGC, 0, 0, (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin)); @@ -506,11 +745,11 @@ TkpDisplayButton(clientData) } /* - * Draw the border and traversal highlight last. This way, if the - * button's contents overflow they'll be covered up by the border. - * This code is complicated by the possible combinations of focus - * highlight and default rings. We draw the focus and highlight rings - * using the highlight border and highlight foreground color. + * Draw the border and traversal highlight last. This way, if the button's + * contents overflow they'll be covered up by the border. This code is + * complicated by the possible combinations of focus highlight and default + * rings. We draw the focus and highlight rings using the highlight border + * and highlight foreground color. */ if (relief != TK_RELIEF_FLAT) { @@ -519,10 +758,10 @@ TkpDisplayButton(clientData) if (butPtr->defaultState == DEFAULT_ACTIVE) { /* * Draw the default ring with 2 pixels of space between the - * default ring and the button and the default ring and the - * focus ring. Note that we need to explicitly draw the space - * in the highlightBorder color to ensure that we overwrite any - * overflow text and/or a different button background color. + * default ring and the button and the default ring and the focus + * ring. Note that we need to explicitly draw the space in the + * highlightBorder color to ensure that we overwrite any overflow + * text and/or a different button background color. */ Tk_Draw3DRectangle(tkwin, pixmap, butPtr->highlightBorder, inset, @@ -581,8 +820,8 @@ TkpDisplayButton(clientData) } /* - * Copy the information from the off-screen pixmap onto the screen, - * then delete the pixmap. + * Copy the information from the off-screen pixmap onto the screen, then + * delete the pixmap. */ XCopyArea(butPtr->display, pixmap, Tk_WindowId(tkwin), @@ -596,9 +835,9 @@ TkpDisplayButton(clientData) * * TkpComputeButtonGeometry -- * - * After changes in a button's text or bitmap, this procedure - * recomputes the button's geometry and passes this information - * along to the geometry manager for the window. + * After changes in a button's text or bitmap, this function recomputes + * the button's geometry and passes this information along to the + * geometry manager for the window. * * Results: * None. @@ -610,8 +849,8 @@ TkpDisplayButton(clientData) */ void -TkpComputeButtonGeometry(butPtr) - register TkButton *butPtr; /* Button whose geometry may have changed. */ +TkpComputeButtonGeometry( + register TkButton *butPtr) /* Button whose geometry may have changed. */ { int width, height, avgWidth, txtWidth, txtHeight; int haveImage = 0, haveText = 0; @@ -633,7 +872,7 @@ TkpComputeButtonGeometry(butPtr) txtWidth = 0; txtHeight = 0; avgWidth = 0; - + if (butPtr->image != NULL) { Tk_SizeOfImage(butPtr->image, &width, &height); haveImage = 1; @@ -641,51 +880,58 @@ TkpComputeButtonGeometry(butPtr) Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height); haveImage = 1; } - + if (haveImage == 0 || butPtr->compound != COMPOUND_NONE) { Tk_FreeTextLayout(butPtr->textLayout); - + butPtr->textLayout = Tk_ComputeTextLayout(butPtr->tkfont, Tcl_GetString(butPtr->textPtr), -1, butPtr->wrapLength, butPtr->justify, 0, &butPtr->textWidth, &butPtr->textHeight); - + txtWidth = butPtr->textWidth; txtHeight = butPtr->textHeight; avgWidth = Tk_TextWidth(butPtr->tkfont, "0", 1); Tk_GetFontMetrics(butPtr->tkfont, &fm); haveText = (txtWidth != 0 && txtHeight != 0); } - + /* - * If the button is compound (ie, it shows both an image and text), - * the new geometry is a combination of the image and text geometry. - * We only honor the compound bit if the button has both text and an - * image, because otherwise it is not really a compound button. + * If the button is compound (i.e., it shows both an image and text), the + * new geometry is a combination of the image and text geometry. We only + * honor the compound bit if the button has both text and an image, + * because otherwise it is not really a compound button. */ if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) { switch ((enum compound) butPtr->compound) { - case COMPOUND_TOP: - case COMPOUND_BOTTOM: { - /* Image is above or below text */ - height += txtHeight + butPtr->padY; - width = (width > txtWidth ? width : txtWidth); - break; - } - case COMPOUND_LEFT: - case COMPOUND_RIGHT: { - /* Image is left or right of text */ - width += txtWidth + butPtr->padX; - height = (height > txtHeight ? height : txtHeight); - break; - } - case COMPOUND_CENTER: { - /* Image and text are superimposed */ - width = (width > txtWidth ? width : txtWidth); - height = (height > txtHeight ? height : txtHeight); - break; - } - case COMPOUND_NONE: {break;} + case COMPOUND_TOP: + case COMPOUND_BOTTOM: + /* + * Image is above or below text. + */ + + height += txtHeight + butPtr->padY; + width = (width > txtWidth ? width : txtWidth); + break; + case COMPOUND_LEFT: + case COMPOUND_RIGHT: + /* + * Image is left or right of text. + */ + + width += txtWidth + butPtr->padX; + height = (height > txtHeight ? height : txtHeight); + break; + case COMPOUND_CENTER: + /* + * Image and text are superimposed. + */ + + width = (width > txtWidth ? width : txtWidth); + height = (height > txtHeight ? height : txtHeight); + break; + case COMPOUND_NONE: + break; } if (butPtr->width > 0) { width = butPtr->width; @@ -705,7 +951,6 @@ TkpComputeButtonGeometry(butPtr) width += 2*butPtr->padX; height += 2*butPtr->padY; - } else { if (haveImage) { if (butPtr->width > 0) { @@ -714,7 +959,7 @@ TkpComputeButtonGeometry(butPtr) if (butPtr->height > 0) { height = butPtr->height; } - + if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) { butPtr->indicatorSpace = height; if (butPtr->type == TYPE_CHECK_BUTTON) { @@ -726,7 +971,7 @@ TkpComputeButtonGeometry(butPtr) } else { width = txtWidth; height = txtHeight; - + if (butPtr->width > 0) { width = butPtr->width * avgWidth; } @@ -747,8 +992,8 @@ TkpComputeButtonGeometry(butPtr) /* * When issuing the geometry request, add extra space for the indicator, * if any, and for the border and padding, plus two extra pixels so the - * display can be offset by 1 pixel in either direction for the raised - * or lowered effect. + * display can be offset by 1 pixel in either direction for the raised or + * lowered effect. */ if ((butPtr->image == NULL) && (butPtr->bitmap == None)) { @@ -763,3 +1008,11 @@ TkpComputeButtonGeometry(butPtr) + 2*butPtr->inset), (int) (height + 2*butPtr->inset)); Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset); } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ |