Exemplo n.º 1
0
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);
}
Exemplo n.º 2
0
/*
 * 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);
}
Exemplo n.º 3
0
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);
}
Exemplo n.º 4
0
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);
}
Exemplo n.º 5
0
/*
 *----------------------------------------------------------------------
 *
 * 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);
        }
    }

   }
Exemplo n.º 6
0
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);
    }
}