summaryrefslogtreecommitdiffstats
path: root/unix/tkUnixMenubu.c
diff options
context:
space:
mode:
authortmh <tmh>2001-05-21 14:07:32 (GMT)
committertmh <tmh>2001-05-21 14:07:32 (GMT)
commit29e6415ec425f744f1595e852af0c922a09258bb (patch)
tree20838e3aece8170aafef73f9007c1064480550df /unix/tkUnixMenubu.c
parent234f863650b0b7804c98c2994e07e9ef354b0e92 (diff)
downloadtk-29e6415ec425f744f1595e852af0c922a09258bb.zip
tk-29e6415ec425f744f1595e852af0c922a09258bb.tar.gz
tk-29e6415ec425f744f1595e852af0c922a09258bb.tar.bz2
implement TIP11, -compound option for menubutton widget
Diffstat (limited to 'unix/tkUnixMenubu.c')
-rw-r--r--unix/tkUnixMenubu.c261
1 files changed, 201 insertions, 60 deletions
diff --git a/unix/tkUnixMenubu.c b/unix/tkUnixMenubu.c
index 8e46f46..186bd75 100644
--- a/unix/tkUnixMenubu.c
+++ b/unix/tkUnixMenubu.c
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkUnixMenubu.c,v 1.5 2000/11/22 01:49:38 ericm Exp $
+ * RCS: @(#) $Id: tkUnixMenubu.c,v 1.6 2001/05/21 14:07:33 tmh Exp $
*/
#include "tkMenubutton.h"
@@ -74,9 +74,11 @@ TkpDisplayMenuButton(clientData)
Pixmap pixmap;
int x = 0; /* Initialization needed only to stop
* compiler warning. */
- int y;
+ int y = 0;
register Tk_Window tkwin = mbPtr->tkwin;
- int width, height;
+ int width, height, fullWidth, fullHeight;
+ int imageXOffset, imageYOffset, textXOffset, textYOffset;
+ int haveImage = 0, haveText = 0;
mbPtr->flags &= ~REDRAW_PENDING;
if ((mbPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
@@ -95,6 +97,15 @@ TkpDisplayMenuButton(clientData)
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
@@ -107,34 +118,105 @@ TkpDisplayMenuButton(clientData)
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.
- */
+ imageXOffset = 0;
+ imageYOffset = 0;
+ textXOffset = 0;
+ textYOffset = 0;
+ fullWidth = 0;
+ fullHeight = 0;
- if (mbPtr->image != None) {
- Tk_SizeOfImage(mbPtr->image, &width, &height);
+ if (mbPtr->compound != COMPOUND_NONE && haveImage && haveText) {
- 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, pixmap,
- x, y);
- } else {
- XCopyPlane(mbPtr->display, mbPtr->bitmap, pixmap,
- 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;
+ 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, pixmap,
+ x + imageXOffset, y + imageYOffset);
+ }
+ if (mbPtr->bitmap != None) {
+ XCopyPlane(mbPtr->display, mbPtr->bitmap, pixmap,
+ gc, 0, 0, (unsigned) width, (unsigned) height,
+ x + imageXOffset, y + imageYOffset, 1);
+ }
+ if (haveText) {
+ 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 {
- 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, y,
- 0, -1);
- Tk_UnderlineTextLayout(mbPtr->display, pixmap, gc, mbPtr->textLayout,
- x, y, mbPtr->underline);
+ if (mbPtr->image != NULL) {
+ TkComputeAnchor(mbPtr->anchor, tkwin, 0, 0,
+ width + mbPtr->indicatorWidth, height, &x, &y);
+ Tk_RedrawImage(mbPtr->image, 0, 0, width, height, pixmap,
+ 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, pixmap,
+ 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, pixmap, gc, mbPtr->textLayout,
+ x + textXOffset, y + textYOffset ,
+ 0, -1);
+ Tk_UnderlineTextLayout(mbPtr->display, pixmap, gc,
+ mbPtr->textLayout, x + textXOffset, y + textYOffset ,
+ mbPtr->underline);
+ }
}
/*
@@ -251,54 +333,113 @@ TkpComputeMenuButtonGeometry(mbPtr)
TkMenuButton *mbPtr; /* Widget record for menu button. */
{
int width, height, mm, pixels;
+ int avgWidth, txtWidth, txtHeight;
+ int haveImage = 0, haveText = 0;
+ Tk_FontMetrics fm;
mbPtr->inset = mbPtr->highlightWidth + mbPtr->borderWidth;
+
+ width = 0;
+ height = 0;
+ txtWidth = 0;
+ txtHeight = 0;
+ avgWidth = 0;
+
if (mbPtr->image != None) {
Tk_SizeOfImage(mbPtr->image, &width, &height);
- if (mbPtr->width > 0) {
- width = mbPtr->width;
- }
- if (mbPtr->height > 0) {
- height = mbPtr->height;
- }
+ haveImage = 1;
} else if (mbPtr->bitmap != None) {
Tk_SizeOfBitmap(mbPtr->display, mbPtr->bitmap, &width, &height);
- if (mbPtr->width > 0) {
- width = mbPtr->width;
- }
- if (mbPtr->height > 0) {
- height = mbPtr->height;
- }
- } else {
+ haveImage = 1;
+ }
+
+ if (haveImage == 0 || mbPtr->compound != COMPOUND_NONE) {
Tk_FreeTextLayout(mbPtr->textLayout);
+
mbPtr->textLayout = Tk_ComputeTextLayout(mbPtr->tkfont, mbPtr->text,
-1, mbPtr->wrapLength, mbPtr->justify, 0, &mbPtr->textWidth,
&mbPtr->textHeight);
- width = mbPtr->textWidth;
- height = mbPtr->textHeight;
- if (mbPtr->width > 0) {
- width = mbPtr->width * Tk_TextWidth(mbPtr->tkfont, "0", 1);
- }
- if (mbPtr->height > 0) {
- Tk_FontMetrics fm;
+ txtWidth = mbPtr->textWidth;
+ txtHeight = mbPtr->textHeight;
+ avgWidth = Tk_TextWidth(mbPtr->tkfont, "0", 1);
+ Tk_GetFontMetrics(mbPtr->tkfont, &fm);
+ haveText = (txtWidth != 0 && txtHeight != 0);
+ }
+
+ /*
+ * If the menubutton is compound (ie, it shows both an image and text),
+ * the new geometry is a combination of the image and text geometry.
+ * We only honor the compound bit if the menubutton has both text and
+ * an image, because otherwise it is not really a compound menubutton.
+ */
- Tk_GetFontMetrics(mbPtr->tkfont, &fm);
- height = mbPtr->height * fm.linespace;
+ if (mbPtr->compound != COMPOUND_NONE && haveImage && haveText) {
+ switch ((enum compound) mbPtr->compound) {
+ case COMPOUND_TOP:
+ case COMPOUND_BOTTOM: {
+ /* Image is above or below text */
+ height += txtHeight + mbPtr->padY;
+ width = (width > txtWidth ? width : txtWidth);
+ break;
+ }
+ case COMPOUND_LEFT:
+ case COMPOUND_RIGHT: {
+ /* Image is left or right of text */
+ width += txtWidth + mbPtr->padX;
+ height = (height > txtHeight ? height : txtHeight);
+ break;
+ }
+ case COMPOUND_CENTER: {
+ /* Image and text are superimposed */
+ width = (width > txtWidth ? width : txtWidth);
+ height = (height > txtHeight ? height : txtHeight);
+ break;
+ }
+ case COMPOUND_NONE: {break;}
+ }
+ if (mbPtr->width > 0) {
+ width = mbPtr->width;
+ }
+ if (mbPtr->height > 0) {
+ height = mbPtr->height;
+ }
+ width += 2*mbPtr->padX;
+ height += 2*mbPtr->padY;
+ } else {
+ if (haveImage) {
+ if (mbPtr->width > 0) {
+ width = mbPtr->width;
+ }
+ if (mbPtr->height > 0) {
+ height = mbPtr->height;
+ }
+ } else {
+ width = txtWidth;
+ height = txtHeight;
+ if (mbPtr->width > 0) {
+ width = mbPtr->width * avgWidth;
+ }
+ if (mbPtr->height > 0) {
+ height = mbPtr->height * fm.linespace;
+ }
}
- width += 2*mbPtr->padX;
- height += 2*mbPtr->padY;
+ }
+
+ if (! haveImage) {
+ width += 2*mbPtr->padX;
+ height += 2*mbPtr->padY;
}
if (mbPtr->indicatorOn) {
- mm = WidthMMOfScreen(Tk_Screen(mbPtr->tkwin));
- pixels = WidthOfScreen(Tk_Screen(mbPtr->tkwin));
- mbPtr->indicatorHeight= (INDICATOR_HEIGHT * pixels)/(10*mm);
- mbPtr->indicatorWidth = (INDICATOR_WIDTH * pixels)/(10*mm)
- + 2*mbPtr->indicatorHeight;
- width += mbPtr->indicatorWidth;
+ mm = WidthMMOfScreen(Tk_Screen(mbPtr->tkwin));
+ pixels = WidthOfScreen(Tk_Screen(mbPtr->tkwin));
+ mbPtr->indicatorHeight= (INDICATOR_HEIGHT * pixels)/(10*mm);
+ mbPtr->indicatorWidth = (INDICATOR_WIDTH * pixels)/(10*mm)
+ + 2*mbPtr->indicatorHeight;
+ width += mbPtr->indicatorWidth;
} else {
- mbPtr->indicatorHeight = 0;
- mbPtr->indicatorWidth = 0;
+ mbPtr->indicatorHeight = 0;
+ mbPtr->indicatorWidth = 0;
}
Tk_GeometryRequest(mbPtr->tkwin, (int) (width + 2*mbPtr->inset),