void 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 y, relief; Tk_Window tkwin = butPtr->tkwin; int width, height, fullWidth, fullHeight; int textXOffset, textYOffset; 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. */ int imageWidth, imageHeight; 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)) { return; } border = butPtr->normalBorder; if ((butPtr->state == STATE_DISABLED) && (butPtr->disabledFg != NULL)) { gc = butPtr->disabledGC; } else if ((butPtr->state == STATE_ACTIVE) && !Tk_StrictMotif(butPtr->tkwin)) { gc = butPtr->activeTextGC; border = butPtr->activeBorder; } else { gc = butPtr->normalTextGC; } if ((butPtr->flags & SELECTED) && (butPtr->state != STATE_ACTIVE) && (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: * If the button is select --> "sunken" * If relief==overrelief --> relief * Otherwise --> overrelief * * The effect we are trying to achieve is as follows: * * value mouse-over? --> relief * ------- ------------ -------- * off no flat * off yes raised * on no sunken * on yes sunken * * 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 * compatible. */ relief = butPtr->relief; if ((butPtr->type >= TYPE_CHECK_BUTTON) && !butPtr->indicatorOn) { if (butPtr->flags & SELECTED) { relief = TK_RELIEF_SUNKEN; } else if (butPtr->overRelief != relief) { relief = butPtr->offRelief; } } offset = (butPtr->type == TYPE_BUTTON) && !Tk_StrictMotif(butPtr->tkwin); /* * 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), Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin)); Tk_Fill3DRectangle(tkwin, pixmap, border, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT); /* * Display image or bitmap or text for button. */ if (butPtr->image != NULL) { Tk_SizeOfImage(butPtr->image, &width, &height); haveImage = 1; } else if (butPtr->bitmap != None) { Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height); haveImage = 1; } imageWidth = width; imageHeight = height; haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0); if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) { textXOffset = 0; textYOffset = 0; fullWidth = 0; 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_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, butPtr->indicatorSpace + fullWidth, fullHeight, &x, &y); x += butPtr->indicatorSpace; x += offset; y += offset; if (relief == TK_RELIEF_RAISED) { x -= offset; y -= offset; } else if (relief == TK_RELIEF_SUNKEN) { x += offset; y += offset; } imageXOffset += x; imageYOffset += y; if (butPtr->image != NULL) { /* * Do boundary clipping, so that Tk_RedrawImage is passed valid * coordinates. [Bug 979239] */ if (imageXOffset < 0) { imageXOffset = 0; } if (imageYOffset < 0) { imageYOffset = 0; } if (width > Tk_Width(tkwin)) { width = Tk_Width(tkwin); } if (height > Tk_Height(tkwin)) { height = Tk_Height(tkwin); } if ((width + imageXOffset) > Tk_Width(tkwin)) { imageXOffset = Tk_Width(tkwin) - width; } if ((height + imageYOffset) > Tk_Height(tkwin)) { imageYOffset = Tk_Height(tkwin) - height; } 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); } } else { XSetClipOrigin(butPtr->display, gc, imageXOffset, imageYOffset); XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, gc, 0, 0, (unsigned int) width, (unsigned int) height, imageXOffset, imageYOffset, 1); XSetClipOrigin(butPtr->display, gc, 0, 0); } Tk_DrawTextLayout(butPtr->display, pixmap, gc, butPtr->textLayout, x + textXOffset, y + textYOffset, 0, -1); Tk_UnderlineTextLayout(butPtr->display, pixmap, gc, butPtr->textLayout, x + textXOffset, y + textYOffset, butPtr->underline); y += fullHeight/2; } else { if (haveImage) { TkComputeAnchor(butPtr->anchor, tkwin, 0, 0, butPtr->indicatorSpace + width, height, &x, &y); x += butPtr->indicatorSpace; x += offset; y += offset; if (relief == TK_RELIEF_RAISED) { x -= offset; y -= offset; } else if (relief == TK_RELIEF_SUNKEN) { x += offset; y += offset; } imageXOffset += x; imageYOffset += y; if (butPtr->image != NULL) { /* * Do boundary clipping, so that Tk_RedrawImage is passed * valid coordinates. [Bug 979239] */ if (imageXOffset < 0) { imageXOffset = 0; } if (imageYOffset < 0) { imageYOffset = 0; } if (width > Tk_Width(tkwin)) { width = Tk_Width(tkwin); } if (height > Tk_Height(tkwin)) { height = Tk_Height(tkwin); } if ((width + imageXOffset) > Tk_Width(tkwin)) { imageXOffset = Tk_Width(tkwin) - width; } if ((height + imageYOffset) > Tk_Height(tkwin)) { imageYOffset = Tk_Height(tkwin) - height; } 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); } } else { XSetClipOrigin(butPtr->display, gc, x, y); XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, gc, 0, 0, (unsigned int) width, (unsigned int) height, x, y, 1); XSetClipOrigin(butPtr->display, gc, 0, 0); } y += height/2; } else { 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) { x -= offset; y -= offset; } else if (relief == TK_RELIEF_SUNKEN) { x += offset; y += offset; } Tk_DrawTextLayout(butPtr->display, pixmap, gc, butPtr->textLayout, x, y, 0, -1); Tk_UnderlineTextLayout(butPtr->display, pixmap, gc, butPtr->textLayout, x, y, butPtr->underline); 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. */ if ((butPtr->type == TYPE_CHECK_BUTTON) && butPtr->indicatorOn) { if (butPtr->indicatorDiameter > 2*butPtr->borderWidth) { TkBorder *selBorder = (TkBorder *) butPtr->selectBorder; XColor *selColor = NULL; 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) { if (butPtr->indicatorDiameter > 2*butPtr->borderWidth) { TkBorder *selBorder = (TkBorder *) butPtr->selectBorder; XColor *selColor = NULL; 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), RADIO_BUTTON); } } /* * 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. */ if ((butPtr->state == STATE_DISABLED) && ((butPtr->disabledFg == NULL) || (butPtr->image != NULL))) { if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn && (butPtr->selectBorder != NULL)) { 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 */ if (butPtr->disabledFg == NULL) { XFillRectangle(butPtr->display, pixmap, butPtr->stippleGC, 0, 0, (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin)); } else { XFillRectangle(butPtr->display, pixmap, butPtr->stippleGC, imageXOffset, imageYOffset, (unsigned) imageWidth, (unsigned) imageHeight); } if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn && (butPtr->selectBorder != NULL)) { XSetForeground(butPtr->display, butPtr->stippleGC, Tk_3DBorderColor(butPtr->normalBorder)->pixel); } } /* * 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) { int inset = butPtr->highlightWidth; 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. */ Tk_Draw3DRectangle(tkwin, pixmap, butPtr->highlightBorder, inset, inset, Tk_Width(tkwin) - 2*inset, Tk_Height(tkwin) - 2*inset, 2, TK_RELIEF_FLAT); inset += 2; Tk_Draw3DRectangle(tkwin, pixmap, butPtr->highlightBorder, inset, inset, Tk_Width(tkwin) - 2*inset, Tk_Height(tkwin) - 2*inset, 1, TK_RELIEF_SUNKEN); inset++; Tk_Draw3DRectangle(tkwin, pixmap, butPtr->highlightBorder, inset, inset, Tk_Width(tkwin) - 2*inset, Tk_Height(tkwin) - 2*inset, 2, TK_RELIEF_FLAT); inset += 2; } else if (butPtr->defaultState == DEFAULT_NORMAL) { /* * Leave room for the default ring and write over any text or * background color. */ Tk_Draw3DRectangle(tkwin, pixmap, butPtr->highlightBorder, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 5, TK_RELIEF_FLAT); inset += 5; } /* * Draw the button border. */ Tk_Draw3DRectangle(tkwin, pixmap, border, inset, inset, Tk_Width(tkwin) - 2*inset, Tk_Height(tkwin) - 2*inset, butPtr->borderWidth, relief); } if (butPtr->highlightWidth > 0) { GC gc; if (butPtr->flags & GOT_FOCUS) { gc = Tk_GCForColor(butPtr->highlightColorPtr, pixmap); } else { gc = Tk_GCForColor(Tk_3DBorderColor(butPtr->highlightBorder), pixmap); } /* * Make sure the focus ring shrink-wraps the actual button, not the * padding space left for a default ring. */ if (butPtr->defaultState == DEFAULT_NORMAL) { TkDrawInsetFocusHighlight(tkwin, gc, butPtr->highlightWidth, pixmap, 5); } else { Tk_DrawFocusHighlight(tkwin, gc, butPtr->highlightWidth, pixmap); } } /* * Copy the information from the off-screen pixmap onto the screen, then * delete the pixmap. */ XCopyArea(butPtr->display, pixmap, Tk_WindowId(tkwin), butPtr->copyGC, 0, 0, (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin), 0, 0); Tk_FreePixmap(butPtr->display, pixmap); }
/* * TextDraw -- * Draw a text element. * Called by TextElementDraw() and LabelElementDraw(). */ static void TextDraw(TextElement *text, Tk_Window tkwin, Drawable d, Ttk_Box b) { XColor *color = Tk_GetColorFromObj(tkwin, text->foregroundObj); int underline = -1; XGCValues gcValues; GC gc1, gc2; Tk_Anchor anchor = TK_ANCHOR_CENTER; TkRegion clipRegion = NULL; gcValues.font = Tk_FontId(text->tkfont); gcValues.foreground = color->pixel; gc1 = Tk_GetGC(tkwin, GCFont | GCForeground, &gcValues); gcValues.foreground = WhitePixelOfScreen(Tk_Screen(tkwin)); gc2 = Tk_GetGC(tkwin, GCFont | GCForeground, &gcValues); /* * Place text according to -anchor: */ Tk_GetAnchorFromObj(NULL, text->anchorObj, &anchor); b = Ttk_AnchorBox(b, text->width, text->height, anchor); /* * Clip text if it's too wide: */ if (b.width < text->width) { XRectangle rect; clipRegion = TkCreateRegion(); rect.x = b.x; rect.y = b.y; rect.width = b.width + (text->embossed ? 1 : 0); rect.height = b.height + (text->embossed ? 1 : 0); TkUnionRectWithRegion(&rect, clipRegion, clipRegion); TkSetRegion(Tk_Display(tkwin), gc1, clipRegion); TkSetRegion(Tk_Display(tkwin), gc2, clipRegion); #ifdef HAVE_XFT TkUnixSetXftClipRegion(clipRegion); #endif } if (text->embossed) { Tk_DrawTextLayout(Tk_Display(tkwin), d, gc2, text->textLayout, b.x+1, b.y+1, 0/*firstChar*/, -1/*lastChar*/); } Tk_DrawTextLayout(Tk_Display(tkwin), d, gc1, text->textLayout, b.x, b.y, 0/*firstChar*/, -1/*lastChar*/); Tcl_GetIntFromObj(NULL, text->underlineObj, &underline); if (underline >= 0) { if (text->embossed) { Tk_UnderlineTextLayout(Tk_Display(tkwin), d, gc2, text->textLayout, b.x+1, b.y+1, underline); } Tk_UnderlineTextLayout(Tk_Display(tkwin), d, gc1, text->textLayout, b.x, b.y, underline); } if (clipRegion != NULL) { #ifdef HAVE_XFT TkUnixSetXftClipRegion(None); #endif XSetClipMask(Tk_Display(tkwin), gc1, None); XSetClipMask(Tk_Display(tkwin), gc2, None); TkDestroyRegion(clipRegion); } Tk_FreeGC(Tk_Display(tkwin), gc1); Tk_FreeGC(Tk_Display(tkwin), gc2); }
void TkpDisplayMenuButton( ClientData clientData) /* Information about widget. */ { register TkMenuButton *mbPtr = (TkMenuButton *) clientData; GC gc; Tk_3DBorder border; Pixmap pixmap; int x = 0; /* Initialization needed only to stop compiler * warning. */ int y = 0; register Tk_Window tkwin = mbPtr->tkwin; int fullWidth, fullHeight; int textXOffset, textYOffset; int imageWidth, imageHeight; int imageXOffset, imageYOffset; int width = 0, height = 0; /* Image information that will be used to * restrict disabled pixmap as well */ int haveImage = 0, haveText = 0; mbPtr->flags &= ~REDRAW_PENDING; if ((mbPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) { return; } if ((mbPtr->state == STATE_DISABLED) && (mbPtr->disabledFg != NULL)) { gc = mbPtr->disabledGC; border = mbPtr->normalBorder; } else if ((mbPtr->state == STATE_ACTIVE) && !Tk_StrictMotif(mbPtr->tkwin)) { gc = mbPtr->activeTextGC; border = mbPtr->activeBorder; } else { gc = mbPtr->normalTextGC; border = mbPtr->normalBorder; } if (mbPtr->image != None) { Tk_SizeOfImage(mbPtr->image, &width, &height); haveImage = 1; } else if (mbPtr->bitmap != None) { Tk_SizeOfBitmap(mbPtr->display, mbPtr->bitmap, &width, &height); haveImage = 1; } imageWidth = width; imageHeight = height; haveText = (mbPtr->textWidth != 0 && mbPtr->textHeight != 0); /* * In order to avoid screen flashes, this function redraws the menu 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. */ pixmap = Tk_GetPixmap(mbPtr->display, Tk_WindowId(tkwin), Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin)); Tk_Fill3DRectangle(tkwin, pixmap, border, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT); imageXOffset = 0; imageYOffset = 0; textXOffset = 0; textYOffset = 0; fullWidth = 0; fullHeight = 0; if (mbPtr->compound != COMPOUND_NONE && haveImage && haveText) { switch ((enum compound) mbPtr->compound) { case COMPOUND_TOP: case COMPOUND_BOTTOM: /* * Image is above or below text. */ if (mbPtr->compound == COMPOUND_TOP) { textYOffset = height + mbPtr->padY; } else { imageYOffset = mbPtr->textHeight + mbPtr->padY; } fullHeight = height + mbPtr->textHeight + mbPtr->padY; fullWidth = (width > mbPtr->textWidth ? width : mbPtr->textWidth); textXOffset = (fullWidth - mbPtr->textWidth)/2; imageXOffset = (fullWidth - width)/2; break; case COMPOUND_LEFT: case COMPOUND_RIGHT: /* * Image is left or right of text. */ if (mbPtr->compound == COMPOUND_LEFT) { textXOffset = width + mbPtr->padX; } else { imageXOffset = mbPtr->textWidth + mbPtr->padX; } fullWidth = mbPtr->textWidth + mbPtr->padX + width; fullHeight = (height > mbPtr->textHeight ? height : mbPtr->textHeight); textYOffset = (fullHeight - mbPtr->textHeight)/2; imageYOffset = (fullHeight - height)/2; break; case COMPOUND_CENTER: /* * Image and text are superimposed. */ fullWidth = (width > mbPtr->textWidth ? width : mbPtr->textWidth); fullHeight = (height > mbPtr->textHeight ? height : mbPtr->textHeight); textXOffset = (fullWidth - mbPtr->textWidth)/2; imageXOffset = (fullWidth - width)/2; textYOffset = (fullHeight - mbPtr->textHeight)/2; imageYOffset = (fullHeight - height)/2; break; case COMPOUND_NONE: break; } TkComputeAnchor(mbPtr->anchor, tkwin, 0, 0, mbPtr->indicatorWidth + fullWidth, fullHeight, &x, &y); imageXOffset += x; imageYOffset += y; if (mbPtr->image != NULL) { Tk_RedrawImage(mbPtr->image, 0, 0, width, height, pixmap, imageXOffset, imageYOffset); } else if (mbPtr->bitmap != None) { XSetClipOrigin(mbPtr->display, gc, imageXOffset, imageYOffset); XCopyPlane(mbPtr->display, mbPtr->bitmap, pixmap, gc, 0, 0, (unsigned) width, (unsigned) height, imageXOffset, imageYOffset, 1); XSetClipOrigin(mbPtr->display, gc, 0, 0); } Tk_DrawTextLayout(mbPtr->display, pixmap, gc, mbPtr->textLayout, x + textXOffset, y + textYOffset, 0, -1); Tk_UnderlineTextLayout(mbPtr->display, pixmap, gc, mbPtr->textLayout, x + textXOffset, y + textYOffset, mbPtr->underline); } else if (haveImage) { TkComputeAnchor(mbPtr->anchor, tkwin, 0, 0, width + mbPtr->indicatorWidth, height, &x, &y); imageXOffset += x; imageYOffset += y; if (mbPtr->image != NULL) { Tk_RedrawImage(mbPtr->image, 0, 0, width, height, pixmap, imageXOffset, imageYOffset); } else if (mbPtr->bitmap != None) { XSetClipOrigin(mbPtr->display, gc, x, y); XCopyPlane(mbPtr->display, mbPtr->bitmap, pixmap, gc, 0, 0, (unsigned) width, (unsigned) height, x, y, 1); XSetClipOrigin(mbPtr->display, gc, 0, 0); } } else { TkComputeAnchor(mbPtr->anchor, tkwin, mbPtr->padX, mbPtr->padY, mbPtr->textWidth + mbPtr->indicatorWidth, mbPtr->textHeight, &x, &y); Tk_DrawTextLayout(mbPtr->display, pixmap, gc, mbPtr->textLayout, x + textXOffset, y + textYOffset, 0, -1); Tk_UnderlineTextLayout(mbPtr->display, pixmap, gc, mbPtr->textLayout, x + textXOffset, y + textYOffset, mbPtr->underline); } /* * If the menu button is disabled with a stipple rather than a special * foreground color, generate the stippled effect. */ if ((mbPtr->state == STATE_DISABLED) && ((mbPtr->disabledFg == NULL) || (mbPtr->image != NULL))) { /* * Stipple the whole button if no disabledFg was specified, otherwise * restrict stippling only to displayed image */ if (mbPtr->disabledFg == NULL) { XFillRectangle(mbPtr->display, pixmap, mbPtr->stippleGC, mbPtr->inset, mbPtr->inset, (unsigned) (Tk_Width(tkwin) - 2*mbPtr->inset), (unsigned) (Tk_Height(tkwin) - 2*mbPtr->inset)); } else { XFillRectangle(mbPtr->display, pixmap, mbPtr->stippleGC, imageXOffset, imageYOffset, (unsigned) imageWidth, (unsigned) imageHeight); } } /* * Draw the cascade indicator for the menu button on the right side of the * window, if desired. */ if (mbPtr->indicatorOn) { int borderWidth; borderWidth = (mbPtr->indicatorHeight+1)/3; if (borderWidth < 1) { borderWidth = 1; } /*y += mbPtr->textHeight / 2;*/ Tk_Fill3DRectangle(tkwin, pixmap, border, Tk_Width(tkwin) - mbPtr->inset - mbPtr->indicatorWidth + mbPtr->indicatorHeight, ((int) (Tk_Height(tkwin) - mbPtr->indicatorHeight))/2, mbPtr->indicatorWidth - 2*mbPtr->indicatorHeight, mbPtr->indicatorHeight, borderWidth, TK_RELIEF_RAISED); } /* * Draw the border and traversal highlight last. This way, if the menu * button's contents overflow onto the border they'll be covered up by the * border. */ if (mbPtr->relief != TK_RELIEF_FLAT) { Tk_Draw3DRectangle(tkwin, pixmap, border, mbPtr->highlightWidth, mbPtr->highlightWidth, Tk_Width(tkwin) - 2*mbPtr->highlightWidth, Tk_Height(tkwin) - 2*mbPtr->highlightWidth, mbPtr->borderWidth, mbPtr->relief); } if (mbPtr->highlightWidth != 0) { GC gc; if (mbPtr->flags & GOT_FOCUS) { gc = Tk_GCForColor(mbPtr->highlightColorPtr, pixmap); } else { gc = Tk_GCForColor(mbPtr->highlightBgColorPtr, pixmap); } Tk_DrawFocusHighlight(tkwin, gc, mbPtr->highlightWidth, pixmap); } /* * Copy the information from the off-screen pixmap onto the screen, then * delete the pixmap. */ XCopyArea(mbPtr->display, pixmap, Tk_WindowId(tkwin), mbPtr->normalTextGC, 0, 0, (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin), 0, 0); Tk_FreePixmap(mbPtr->display, pixmap); }
void TkpDisplayMenuButton( ClientData clientData) /* Information about widget. */ { TkMenuButton *mbPtr = (TkMenuButton *) clientData; GC gc; Tk_3DBorder border; int x = 0; /* Initialization needed only to stop * compiler warning. */ int y; Tk_Window tkwin = mbPtr->tkwin; int width, height, fullWidth, fullHeight; int imageXOffset, imageYOffset, textXOffset, textYOffset; int haveImage = 0, haveText = 0; MacMenuButton * macMBPtr = (MacMenuButton *) mbPtr; GWorldPtr destPort; CGrafPtr saveWorld; GDHandle saveDevice; MacDrawable *macDraw; mbPtr->flags &= ~REDRAW_PENDING; if ((mbPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) { return; } GetGWorld(&saveWorld, &saveDevice); destPort = TkMacGetDrawablePort(Tk_WindowId(tkwin)); SetGWorld(destPort, NULL); macDraw = (MacDrawable *) Tk_WindowId(tkwin); if ((mbPtr->state == STATE_DISABLED) && (mbPtr->disabledFg != NULL)) { gc = mbPtr->disabledGC; } else if ((mbPtr->state == STATE_ACTIVE) && !Tk_StrictMotif(mbPtr->tkwin)) { gc = mbPtr->activeTextGC; } else { gc = mbPtr->normalTextGC; } border = mbPtr->normalBorder; if (mbPtr->image != None) { Tk_SizeOfImage(mbPtr->image, &width, &height); haveImage = 1; } else if (mbPtr->bitmap != None) { Tk_SizeOfBitmap(mbPtr->display, mbPtr->bitmap, &width, &height); haveImage = 1; } haveText = (mbPtr->textWidth != 0 && mbPtr->textHeight != 0); /* * In order to avoid screen flashes, this procedure redraws * the menu 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. */ Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), border, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT); imageXOffset = 0; imageYOffset = 0; textXOffset = 0; textYOffset = 0; fullWidth = 0; fullHeight = 0; if (mbPtr->compound != COMPOUND_NONE && haveImage && haveText) { switch ((enum compound) mbPtr->compound) { case COMPOUND_TOP: case COMPOUND_BOTTOM: { /* Image is above or below text */ if (mbPtr->compound == COMPOUND_TOP) { textYOffset = height + mbPtr->padY; } else { imageYOffset = mbPtr->textHeight + mbPtr->padY; } fullHeight = height + mbPtr->textHeight + mbPtr->padY; fullWidth = (width > mbPtr->textWidth ? width : mbPtr->textWidth); textXOffset = (fullWidth - mbPtr->textWidth)/2; imageXOffset = (fullWidth - width)/2; break; } case COMPOUND_LEFT: case COMPOUND_RIGHT: { /* Image is left or right of text */ if (mbPtr->compound == COMPOUND_LEFT) { textXOffset = width + mbPtr->padX; } else { imageXOffset = mbPtr->textWidth + mbPtr->padX; } fullWidth = mbPtr->textWidth + mbPtr->padX + width; fullHeight = (height > mbPtr->textHeight ? height : mbPtr->textHeight); textYOffset = (fullHeight - mbPtr->textHeight)/2; imageYOffset = (fullHeight - height)/2; break; } case COMPOUND_CENTER: { /* Image and text are superimposed */ fullWidth = (width > mbPtr->textWidth ? width : mbPtr->textWidth); fullHeight = (height > mbPtr->textHeight ? height : mbPtr->textHeight); textXOffset = (fullWidth - mbPtr->textWidth)/2; imageXOffset = (fullWidth - width)/2; textYOffset = (fullHeight - mbPtr->textHeight)/2; imageYOffset = (fullHeight - height)/2; break; } case COMPOUND_NONE: {break;} } TkComputeAnchor(mbPtr->anchor, tkwin, 0, 0, mbPtr->indicatorWidth + fullWidth, fullHeight, &x, &y); if (mbPtr->image != NULL) { Tk_RedrawImage(mbPtr->image, 0, 0, width, height, Tk_WindowId(tkwin), x + imageXOffset, y + imageYOffset); } if (mbPtr->bitmap != None) { XCopyPlane(mbPtr->display, mbPtr->bitmap, Tk_WindowId(tkwin), gc, 0, 0, (unsigned) width, (unsigned) height, x + imageXOffset, y + imageYOffset, 1); } if (haveText) { Tk_DrawTextLayout(mbPtr->display, Tk_WindowId(tkwin), gc, mbPtr->textLayout, x + textXOffset, y + textYOffset , 0, -1); Tk_UnderlineTextLayout(mbPtr->display, Tk_WindowId(tkwin), gc, mbPtr->textLayout, x + textXOffset, y + textYOffset , mbPtr->underline); } } else { if (mbPtr->image != NULL) { TkComputeAnchor(mbPtr->anchor, tkwin, 0, 0, width + mbPtr->indicatorWidth, height, &x, &y); Tk_RedrawImage(mbPtr->image, 0, 0, width, height, Tk_WindowId(tkwin), x + imageXOffset, y + imageYOffset); } else if (mbPtr->bitmap != None) { TkComputeAnchor(mbPtr->anchor, tkwin, 0, 0, width + mbPtr->indicatorWidth, height, &x, &y); XCopyPlane(mbPtr->display, mbPtr->bitmap, Tk_WindowId(tkwin), gc, 0, 0, (unsigned) width, (unsigned) height, x + imageXOffset, y + imageYOffset, 1); } else { TkComputeAnchor(mbPtr->anchor, tkwin, mbPtr->padX, mbPtr->padY, mbPtr->textWidth + mbPtr->indicatorWidth, mbPtr->textHeight, &x, &y); Tk_DrawTextLayout(mbPtr->display, Tk_WindowId(tkwin), gc, mbPtr->textLayout, x + textXOffset, y + textYOffset, 0, -1); Tk_UnderlineTextLayout(mbPtr->display, Tk_WindowId(tkwin), gc, mbPtr->textLayout, x + textXOffset, y + textYOffset , mbPtr->underline); } } #if 0 /* this is the original code */ /* * Display image or bitmap or text for button. */ if (mbPtr->image != None) { Tk_SizeOfImage(mbPtr->image, &width, &height); imageOrBitmap: TkComputeAnchor(mbPtr->anchor, tkwin, 0, 0, width + mbPtr->indicatorWidth, height, &x, &y); if (mbPtr->image != NULL) { Tk_RedrawImage(mbPtr->image, 0, 0, width, height, Tk_WindowId(tkwin), x, y); } else { XCopyPlane(mbPtr->display, mbPtr->bitmap, Tk_WindowId(tkwin), gc, 0, 0, (unsigned) width, (unsigned) height, x, y, 1); } } else if (mbPtr->bitmap != None) { Tk_SizeOfBitmap(mbPtr->display, mbPtr->bitmap, &width, &height); goto imageOrBitmap; } else { TkComputeAnchor(mbPtr->anchor, tkwin, mbPtr->padX, mbPtr->padY, mbPtr->textWidth + mbPtr->indicatorWidth, mbPtr->textHeight, &x, &y); Tk_DrawTextLayout(mbPtr->display, Tk_WindowId(tkwin), gc, mbPtr->textLayout, x, y, 0, -1); } #endif /* * If the menu button is disabled with a stipple rather than a special * foreground color, generate the stippled effect. */ if ((mbPtr->state == STATE_DISABLED) && ((mbPtr->disabledFg != NULL) || (mbPtr->image != NULL))) { XFillRectangle(mbPtr->display, Tk_WindowId(tkwin), mbPtr->disabledGC, mbPtr->inset, mbPtr->inset, (unsigned) (Tk_Width(tkwin) - 2*mbPtr->inset), (unsigned) (Tk_Height(tkwin) - 2*mbPtr->inset)); } /* * Draw the cascade indicator for the menu button on the * right side of the window, if desired. */ if (mbPtr->indicatorOn) { int w, h, i; Rect r; r.left = macDraw->xOff + Tk_Width(tkwin) - mbPtr->inset - mbPtr->indicatorWidth; r.top = macDraw->yOff + Tk_Height(tkwin)/2 - mbPtr->indicatorHeight/2; r.right = macDraw->xOff + Tk_Width(tkwin) - mbPtr->inset - kTriangleMargin; r.bottom = macDraw->yOff + Tk_Height(tkwin)/2 + mbPtr->indicatorHeight/2; h = mbPtr->indicatorHeight; w = mbPtr->indicatorWidth - 1 - kTriangleMargin; for (i = 0; i < h; i++) { MoveTo(r.left + i, r.top + i); LineTo(r.left + i + w, r.top + i); w -= 2; } } /* * Draw the border and traversal highlight last. This way, if the * menu button's contents overflow onto the border they'll be covered * up by the border. */ TkMacSetUpClippingRgn(Tk_WindowId(tkwin)); if (mbPtr->borderWidth > 0) { Rect r; r.left = macDraw->xOff + mbPtr->highlightWidth + mbPtr->borderWidth; r.top = macDraw->yOff + mbPtr->highlightWidth + mbPtr->borderWidth; r.right = macDraw->xOff + Tk_Width(tkwin) - mbPtr->highlightWidth - mbPtr->borderWidth; r.bottom = macDraw->yOff + Tk_Height(tkwin) - mbPtr->highlightWidth - mbPtr->borderWidth; FrameRect(&r); PenSize(mbPtr->borderWidth - 1, mbPtr->borderWidth - 1); MoveTo(r.right, r.top + kShadowOffset); LineTo(r.right, r.bottom); LineTo(r.left + kShadowOffset, r.bottom); } if (mbPtr->highlightWidth != 0) { GC fgGC, bgGC; bgGC = Tk_GCForColor(mbPtr->highlightBgColorPtr, Tk_WindowId(tkwin)); if (mbPtr->flags & GOT_FOCUS) { fgGC = Tk_GCForColor(mbPtr->highlightColorPtr, Tk_WindowId(tkwin)); TkpDrawHighlightBorder(tkwin, fgGC, bgGC, mbPtr->highlightWidth, Tk_WindowId(tkwin)); } else { TkpDrawHighlightBorder(tkwin, bgGC, bgGC, mbPtr->highlightWidth, Tk_WindowId(tkwin)); } } SetGWorld(saveWorld, saveDevice); }
/* *---------------------------------------------------------------------- * * DrawButtonImageAndText -- * * Draws the image and text associated with a button or label. * * Results: * None. * * Side effects: * The image and text are drawn. * *---------------------------------------------------------------------- */ static void DrawButtonImageAndText( TkButton* butPtr) { MacButton *mbPtr = (MacButton*)butPtr; Tk_Window tkwin = butPtr->tkwin; Pixmap pixmap; int haveImage = 0; int haveText = 0; int imageWidth = 0; int imageHeight = 0; int imageXOffset = 0; int imageYOffset = 0; int textXOffset = 0; int textYOffset = 0; int width = 0; int height = 0; int fullWidth = 0; int fullHeight = 0; int pressed = 0; if (tkwin == NULL || !Tk_IsMapped(tkwin)) { return; } DrawParams* dpPtr = &mbPtr->drawParams; pixmap = (Pixmap)Tk_WindowId(tkwin); if (butPtr->image != None) { Tk_SizeOfImage(butPtr->image, &width, &height); haveImage = 1; } else if (butPtr->bitmap != None) { Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height); haveImage = 1; } imageWidth = width; imageHeight = height; if (mbPtr->drawinfo.state == kThemeStatePressed) { /* Offset bitmaps by a bit when the button is pressed. */ pressed = 1; } haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0); if (haveImage && haveText) { /* Image and Text */ int x; int y; textXOffset = 0; textYOffset = 0; fullWidth = 0; 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_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; } default: break; } TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX + butPtr->borderWidth, butPtr->padY + butPtr->borderWidth, fullWidth + butPtr->indicatorSpace, fullHeight, &x, &y); x += butPtr->indicatorSpace; if (dpPtr->relief == TK_RELIEF_SUNKEN) { x += dpPtr->offset; y += dpPtr->offset; } else if (dpPtr->relief == TK_RELIEF_RAISED) { x -= dpPtr->offset; y -= dpPtr->offset; } if (pressed) { x += dpPtr->offset; y += dpPtr->offset; } imageXOffset += x; imageYOffset += y; textYOffset -= 1; if (butPtr->image != NULL) { 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); } } else { XSetClipOrigin(butPtr->display, dpPtr->gc, imageXOffset, imageYOffset); XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, dpPtr->gc, 0, 0, (unsigned int) width, (unsigned int) height, imageXOffset, imageYOffset, 1); XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0); } Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc, butPtr->textLayout, x + textXOffset, y + textYOffset, 0, -1); Tk_UnderlineTextLayout(butPtr->display, pixmap, dpPtr->gc, butPtr->textLayout, x + textXOffset, y + textYOffset, butPtr->underline); } else if (haveImage) { /* Image only */ int x = 0; int y; TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX + butPtr->borderWidth, butPtr->padY + butPtr->borderWidth, width + butPtr->indicatorSpace, height, &x, &y); x += butPtr->indicatorSpace; if (pressed) { x += dpPtr->offset; y += dpPtr->offset; } imageXOffset += x; imageYOffset += y; if (butPtr->image != NULL) { 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); } } else { XSetClipOrigin(butPtr->display, dpPtr->gc, x, y); XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, dpPtr->gc, 0, 0, (unsigned int) width, (unsigned int) height, imageXOffset, imageYOffset, 1); XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0); } } else { /* Text only */ int x, y; TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY, butPtr->textWidth + butPtr->indicatorSpace, butPtr->textHeight, &x, &y); x += butPtr->indicatorSpace; Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc, butPtr->textLayout, x, y, 0, -1); } /* * 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. */ if (mbPtr->useTkText) { if ((butPtr->state == STATE_DISABLED) && ((butPtr->disabledFg == NULL) || (butPtr->image != NULL))) { if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn && (butPtr->selectBorder != NULL)) { 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 */ if (butPtr->disabledFg == NULL) { XFillRectangle(butPtr->display, pixmap, butPtr->stippleGC, 0, 0, (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin)); } else { XFillRectangle(butPtr->display, pixmap, butPtr->stippleGC, imageXOffset, imageYOffset, (unsigned) imageWidth, (unsigned) imageHeight); } if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn && (butPtr->selectBorder != NULL) ) { XSetForeground(butPtr->display, butPtr->stippleGC, Tk_3DBorderColor(butPtr->normalBorder)->pixel); } } /* * Draw the border and traversal highlight last. This way, if the * button's contents overflow they'll be covered up by the border. */ if (dpPtr->relief != TK_RELIEF_FLAT) { int inset = butPtr->highlightWidth; Tk_Draw3DRectangle(tkwin, pixmap, dpPtr->border, inset, inset, Tk_Width(tkwin) - 2*inset, Tk_Height(tkwin) - 2*inset, butPtr->borderWidth, dpPtr->relief); } } }
void TkpDisplayButton( ClientData clientData) /* Information about widget. */ { MacButton *macButtonPtr = (MacButton *) clientData; TkButton *butPtr = (TkButton *) clientData; Tk_Window tkwin = butPtr->tkwin; CGrafPtr destPort, savePort; Boolean portChanged; Pixmap pixmap; int width, height, fullWidth, fullHeight, textXOffset, textYOffset; int borderWidth, wasUsingControl; int haveImage = 0, haveText = 0, imageWidth = 0, imageHeight = 0; int imageXOffset = 0, imageYOffset = 0; /* image information that will * be used to restrict disabled * pixmap as well */ DrawParams drawParams, *dpPtr = &drawParams; butPtr->flags &= ~REDRAW_PENDING; if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) { return; } pixmap = (Pixmap) Tk_WindowId(tkwin); wasUsingControl = macButtonPtr->usingControl; if (TkMacOSXComputeDrawParams(butPtr, &drawParams) ) { macButtonPtr->usingControl = 1; if (butPtr->type == TYPE_BUTTON) { macButtonPtr->useTkText = 0; } else { macButtonPtr->useTkText = 1; } } else { macButtonPtr->usingControl = 0; macButtonPtr->useTkText = 1; } /* * See the comment in UpdateControlColors as to why we use the * highlightbackground for the border of Macintosh buttons. */ if (macButtonPtr->useTkText) { if (butPtr->type == TYPE_BUTTON) { Tk_Fill3DRectangle(tkwin, pixmap, butPtr->highlightBorder, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT); } else { Tk_Fill3DRectangle(tkwin, pixmap, butPtr->normalBorder, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT); } } /* * Set up clipping region. Make sure the we are using the port * for this button, or we will set the wrong window's clip. */ destPort = TkMacOSXGetDrawablePort(pixmap); portChanged = QDSwapPort(destPort, &savePort); TkMacOSXSetUpClippingRgn(pixmap); /* * Draw the native portion of the buttons. Start by creating the control * if it doesn't already exist. Then configure the Macintosh control from * the Tk info. Finally, we call Draw1Control to draw to the screen. */ if (macButtonPtr->usingControl) { borderWidth = 0; TkMacOSXDrawControl(macButtonPtr, destPort, dpPtr->gc, pixmap); } else if (wasUsingControl && macButtonPtr->userPane) { DisposeControl(macButtonPtr->userPane); macButtonPtr->userPane = NULL; macButtonPtr->control = NULL; macButtonPtr->flags = 0; } if ((dpPtr->drawType == DRAW_CUSTOM) || (dpPtr->drawType == DRAW_LABEL)) { borderWidth = butPtr->borderWidth; } /* * Display image or bitmap or text for button. This has * already been done under Appearance with the Bevel * button types. */ if (dpPtr->drawType == DRAW_BEVEL) { goto applyStipple; } if (butPtr->image != None) { Tk_SizeOfImage(butPtr->image, &width, &height); haveImage = 1; } else if (butPtr->bitmap != None) { Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height); haveImage = 1; } imageWidth = width; imageHeight = height; haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0); if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) { int x, y; textXOffset = 0; textYOffset = 0; fullWidth = 0; 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_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, butPtr->indicatorSpace + fullWidth, fullHeight, &x, &y); x += butPtr->indicatorSpace; x += dpPtr->offset; y += dpPtr->offset; if (dpPtr->relief == TK_RELIEF_RAISED) { x -= dpPtr->offset; y -= dpPtr->offset; } else if (dpPtr->relief == TK_RELIEF_SUNKEN) { x += dpPtr->offset; y += dpPtr->offset; } imageXOffset += x; imageYOffset += y; if (butPtr->image != NULL) { if ((butPtr->selectImage != NULL) && (butPtr->flags & SELECTED)) { Tk_RedrawImage(butPtr->selectImage, 0, 0, width, height, pixmap, imageXOffset, imageYOffset); #if 0 } else if ((butPtr->tristateImage != NULL) && (butPtr->flags & TRISTATED)) { Tk_RedrawImage(butPtr->tristateImage, 0, 0, width, height, pixmap, imageXOffset, imageYOffset); #endif } else { Tk_RedrawImage(butPtr->image, 0, 0, width, height, pixmap, imageXOffset, imageYOffset); } } else { XSetClipOrigin(butPtr->display, dpPtr->gc, imageXOffset, imageYOffset); XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, dpPtr->gc, 0, 0, width, height, imageXOffset, imageYOffset, 1); XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0); } if (macButtonPtr->useTkText) { Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc, butPtr->textLayout, x + textXOffset, y + textYOffset, 0, -1); Tk_UnderlineTextLayout(butPtr->display, pixmap, dpPtr->gc, butPtr->textLayout, x + textXOffset, y + textYOffset, butPtr->underline); } y += fullHeight/2; } else if (haveImage) { int x = 0, y; TkComputeAnchor(butPtr->anchor, tkwin, 0, 0, butPtr->indicatorSpace + width, height, &x, &y); x += butPtr->indicatorSpace; x += dpPtr->offset; y += dpPtr->offset; if (dpPtr->relief == TK_RELIEF_RAISED) { x -= dpPtr->offset; y -= dpPtr->offset; } else if (dpPtr->relief == TK_RELIEF_SUNKEN) { x += dpPtr->offset; y += dpPtr->offset; } imageXOffset += x; imageYOffset += y; if (butPtr->image != NULL) { if ((butPtr->selectImage != NULL) && (butPtr->flags & SELECTED)) { Tk_RedrawImage(butPtr->selectImage, 0, 0, width, height, pixmap, imageXOffset, imageYOffset); #if 0 } else if ((butPtr->tristateImage != NULL) && (butPtr->flags & TRISTATED)) { Tk_RedrawImage(butPtr->tristateImage, 0, 0, width, height, pixmap, imageXOffset, imageYOffset); #endif } else { Tk_RedrawImage(butPtr->image, 0, 0, width, height, pixmap, imageXOffset, imageYOffset); } } else { XSetClipOrigin(butPtr->display, dpPtr->gc, x, y); XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, dpPtr->gc, 0, 0, width, height, x, y, 1); XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0); } y += height/2; } else if (macButtonPtr->useTkText) { int x = 0, y; TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY, butPtr->indicatorSpace + butPtr->textWidth, butPtr->textHeight, &x, &y); x += butPtr->indicatorSpace; Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc, butPtr->textLayout, x, y, 0, -1); } /* * 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. */ applyStipple: if (macButtonPtr->useTkText) { if ((butPtr->state == STATE_DISABLED) && ((butPtr->disabledFg == NULL) || (butPtr->image != NULL))) { if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn && (butPtr->selectBorder != NULL)) { 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 */ if (butPtr->disabledFg == NULL) { XFillRectangle(butPtr->display, pixmap, butPtr->stippleGC, 0, 0, (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin)); } else { XFillRectangle(butPtr->display, pixmap, butPtr->stippleGC, imageXOffset, imageYOffset, (unsigned) imageWidth, (unsigned) imageHeight); } if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn && (butPtr->selectBorder != NULL)) { XSetForeground(butPtr->display, butPtr->stippleGC, Tk_3DBorderColor(butPtr->normalBorder)->pixel); } } /* * Draw the border and traversal highlight last. This way, if the * button's contents overflow they'll be covered up by the border. */ if (dpPtr->relief != TK_RELIEF_FLAT) { int inset = butPtr->highlightWidth; Tk_Draw3DRectangle(tkwin, pixmap, dpPtr->border, inset, inset, Tk_Width(tkwin) - 2*inset, Tk_Height(tkwin) - 2*inset, butPtr->borderWidth, dpPtr->relief); } } if (portChanged) { QDSwapPort(savePort, NULL); } }