📄 tkunixmenu.c
字号:
int height; /* Height of menu entry */{ /* * Draw check-button indicator. */ if ((mePtr->type == CHECK_BUTTON_ENTRY) && mePtr->indicatorOn) { int dim, top, left; dim = (int) mePtr->platformEntryData; left = x + menuPtr->activeBorderWidth + (mePtr->indicatorSpace - dim)/2; if (menuPtr->menuType == MENUBAR) { left += 5; } top = y + (height - dim)/2; Tk_Fill3DRectangle(menuPtr->tkwin, d, menuPtr->border, left, top, dim, dim, DECORATION_BORDER_WIDTH, TK_RELIEF_SUNKEN); left += DECORATION_BORDER_WIDTH; top += DECORATION_BORDER_WIDTH; dim -= 2*DECORATION_BORDER_WIDTH; if ((dim > 0) && (mePtr->entryFlags & ENTRY_SELECTED)) { XFillRectangle(menuPtr->display, d, indicatorGC, left, top, (unsigned int) dim, (unsigned int) dim); } } /* * Draw radio-button indicator. */ if ((mePtr->type == RADIO_BUTTON_ENTRY) && mePtr->indicatorOn) { XPoint points[4]; int radius; radius = ((int) mePtr->platformEntryData)/2; points[0].x = x + (mePtr->indicatorSpace - (int) mePtr->platformEntryData)/2; points[0].y = y + (height)/2; points[1].x = points[0].x + radius; points[1].y = points[0].y + radius; points[2].x = points[1].x + radius; points[2].y = points[0].y; points[3].x = points[1].x; points[3].y = points[0].y - radius; if (mePtr->entryFlags & ENTRY_SELECTED) { XFillPolygon(menuPtr->display, d, indicatorGC, points, 4, Convex, CoordModeOrigin); } else { Tk_Fill3DPolygon(menuPtr->tkwin, d, menuPtr->border, points, 4, DECORATION_BORDER_WIDTH, TK_RELIEF_FLAT); } Tk_Draw3DPolygon(menuPtr->tkwin, d, menuPtr->border, points, 4, DECORATION_BORDER_WIDTH, TK_RELIEF_SUNKEN); }}/* *---------------------------------------------------------------------- * * DrawMenuSeparator -- * * This procedure draws a separator menu item. * * Results: * None. * * Side effects: * Commands are output to X to display the menu in its * current mode. * *---------------------------------------------------------------------- */static voidDrawMenuSeparator(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y, width, height) TkMenu *menuPtr; /* The menu we are drawing */ TkMenuEntry *mePtr; /* The entry we are drawing */ Drawable d; /* The drawable we are using */ GC gc; /* The gc to draw into */ Tk_Font tkfont; /* The font to draw with */ CONST Tk_FontMetrics *fmPtr; /* The font metrics from the font */ int x; int y; int width; int height;{ XPoint points[2]; int margin; if (menuPtr->menuType == MENUBAR) { return; } margin = (fmPtr->ascent + fmPtr->descent)/2; points[0].x = x; points[0].y = y + height/2; points[1].x = width - 1; points[1].y = points[0].y; Tk_Draw3DPolygon(menuPtr->tkwin, d, menuPtr->border, points, 2, 1, TK_RELIEF_RAISED);}/* *---------------------------------------------------------------------- * * DrawMenuEntryLabel -- * * This procedure draws the label part of a menu. * * Results: * None. * * Side effects: * Commands are output to X to display the menu in its * current mode. * *---------------------------------------------------------------------- */static voidDrawMenuEntryLabel( menuPtr, /* The menu we are drawing */ mePtr, /* The entry we are drawing */ d, /* What we are drawing into */ gc, /* The gc we are drawing into */ tkfont, /* The precalculated font */ fmPtr, /* The precalculated font metrics */ x, /* left edge */ y, /* right edge */ width, /* width of entry */ height) /* height of entry */ TkMenu *menuPtr; TkMenuEntry *mePtr; Drawable d; GC gc; Tk_Font tkfont; CONST Tk_FontMetrics *fmPtr; int x, y, width, height;{ int baseline; int indicatorSpace = mePtr->indicatorSpace; int leftEdge = x + indicatorSpace + menuPtr->activeBorderWidth; int imageHeight, imageWidth; if (menuPtr->menuType == MENUBAR) { leftEdge += 5; } /* * Draw label or bitmap or image for entry. */ baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2; if (mePtr->image != NULL) { Tk_SizeOfImage(mePtr->image, &imageWidth, &imageHeight); if ((mePtr->selectImage != NULL) && (mePtr->entryFlags & ENTRY_SELECTED)) { Tk_RedrawImage(mePtr->selectImage, 0, 0, imageWidth, imageHeight, d, leftEdge, (int) (y + (mePtr->height - imageHeight)/2)); } else { Tk_RedrawImage(mePtr->image, 0, 0, imageWidth, imageHeight, d, leftEdge, (int) (y + (mePtr->height - imageHeight)/2)); } } else if (mePtr->bitmap != None) { int width, height; Tk_SizeOfBitmap(menuPtr->display, mePtr->bitmap, &width, &height); XCopyPlane(menuPtr->display, mePtr->bitmap, d, gc, 0, 0, (unsigned) width, (unsigned) height, leftEdge, (int) (y + (mePtr->height - height)/2), 1); } else { if (mePtr->labelLength > 0) { Tk_DrawChars(menuPtr->display, d, gc, tkfont, mePtr->label, mePtr->labelLength, leftEdge, baseline); DrawMenuUnderline(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y, width, height); } } if (mePtr->state == tkDisabledUid) { if (menuPtr->disabledFg == NULL) { XFillRectangle(menuPtr->display, d, menuPtr->disabledGC, x, y, (unsigned) width, (unsigned) height); } else if ((mePtr->image != NULL) && (menuPtr->disabledImageGC != None)) { XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC, leftEdge, (int) (y + (mePtr->height - imageHeight)/2), (unsigned) imageWidth, (unsigned) imageHeight); } }}/* *---------------------------------------------------------------------- * * DrawMenuUnderline -- * * On appropriate platforms, draw the underline character for the * menu. * * Results: * None. * * Side effects: * Commands are output to X to display the menu in its * current mode. * *---------------------------------------------------------------------- */static voidDrawMenuUnderline(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, y, width, height) TkMenu *menuPtr; /* The menu to draw into */ TkMenuEntry *mePtr; /* The entry we are drawing */ Drawable d; /* What we are drawing into */ GC gc; /* The gc to draw into */ Tk_Font tkfont; /* The precalculated font */ CONST Tk_FontMetrics *fmPtr; /* The precalculated font metrics */ int x; int y; int width; int height;{ int indicatorSpace = mePtr->indicatorSpace; if (mePtr->underline >= 0) { int leftEdge = x + indicatorSpace + menuPtr->activeBorderWidth; if (menuPtr->menuType == MENUBAR) { leftEdge += 5; } Tk_UnderlineChars(menuPtr->display, d, gc, tkfont, mePtr->label, leftEdge, y + (height + fmPtr->ascent - fmPtr->descent) / 2, mePtr->underline, mePtr->underline + 1); } }/* *---------------------------------------------------------------------- * * TkpPostMenu -- * * Posts a menu on the screen * * Results: * None. * * Side effects: * The menu is posted and handled. * *---------------------------------------------------------------------- */intTkpPostMenu(interp, menuPtr, x, y) Tcl_Interp *interp; TkMenu *menuPtr; int x; int y;{ return TkPostTearoffMenu(interp, menuPtr, x, y);}/* *---------------------------------------------------------------------- * * GetMenuSeparatorGeometry -- * * Gets the width and height of the indicator area of a menu. * * Results: * widthPtr and heightPtr are set. * * Side effects: * None. * *---------------------------------------------------------------------- */static voidGetMenuSeparatorGeometry(menuPtr, mePtr, tkfont, fmPtr, widthPtr, heightPtr) TkMenu *menuPtr; /* The menu we are measuring */ TkMenuEntry *mePtr; /* The entry we are measuring */ Tk_Font tkfont; /* The precalculated font */ CONST Tk_FontMetrics *fmPtr; /* The precalcualted font metrics */ int *widthPtr; /* The resulting width */ int *heightPtr; /* The resulting height */{ *widthPtr = 0; *heightPtr = fmPtr->linespace;}/* *---------------------------------------------------------------------- * * GetTearoffEntryGeometry -- * * Gets the width and height of the indicator area of a menu. * * Results: * widthPtr and heightPtr are set. * * Side effects: * None. * *---------------------------------------------------------------------- */static voidGetTearoffEntryGeometry(menuPtr, mePtr, tkfont, fmPtr, widthPtr, heightPtr) TkMenu *menuPtr; /* The menu we are drawing */ TkMenuEntry *mePtr; /* The entry we are measuring */ Tk_Font tkfont; /* The precalculated font */ CONST Tk_FontMetrics *fmPtr; /* The precalculated font metrics */ int *widthPtr; /* The resulting width */ int *heightPtr; /* The resulting height */{ if (menuPtr->menuType != MASTER_MENU) { *heightPtr = 0; *widthPtr = 0; } else { *heightPtr = fmPtr->linespace; *widthPtr = Tk_TextWidth(tkfont, "W", -1); }}/* *-------------------------------------------------------------- * * TkpComputeMenubarGeometry -- * * This procedure is invoked to recompute the size and * layout of a menu that is a menubar clone. * * Results: * None. * * Side effects: * Fields of menu entries are changed to reflect their * current positions, and the size of the menu window * itself may be changed. * *-------------------------------------------------------------- */voidTkpComputeMenubarGeometry(menuPtr) TkMenu *menuPtr; /* Structure describing menu. */{ Tk_Font tkfont; Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr; int width, height; int i, j; int x, y, currentRowHeight, currentRowWidth, maxWidth; int maxWindowWidth; int lastRowBreak; int helpMenuIndex = -1; TkMenuEntry *mePtr; int lastEntry; if (menuPtr->tkwin == NULL) { return; } maxWidth = 0; if (menuPtr->numEntries == 0) { height = 0; } else { maxWindowWidth = Tk_Width(menuPtr->tkwin); if (maxWindowWidth == 1) { maxWindowWidth = 0x7ffffff; } currentRowHeight = 0; x = y = menuPtr->borderWidth; lastRowBreak = 0; currentRowWidth = 0; /* * On the Mac especially, getting font metrics can be quite slow, * so we want to do it intelligently. We are going to precalculate * them and pass them down to all of the measureing and drawing * routines. We will measure the font metrics of the menu once, * and if an entry has a font set, we will measure it as we come * to it, and then we decide which set to give the geometry routines. */ Tk_GetFontMetrics(menuPtr->tkfont, &menuMetrics); for (i = 0; i < menuPtr->numEntries; i++) { mePtr = menuPtr->entries[i]; mePtr->entryFlags &= ~ENTRY_LAST_COLUMN; tkfont = mePtr->tkfont; if (tkfont == NULL) { tkfont = menuPtr->tkfont; fmPtr = &menuMetrics; } else { Tk_GetFontMetrics(tkfont, &entryMetrics); fmPtr = &entryMetrics; } /* * For every entry, we need to check to see whether or not we * wrap. If we do wrap, then we have to adjust all of the previous * entries' height and y position, because when we see them * the first time, we don't know how big its neighbor might * be. */ if ((mePtr->type == SEPARATOR_ENTRY) || (mePtr->type == TEAROFF_ENTRY)) { mePtr->height = mePtr->width = 0; } else { GetMenuLabelGeometry(mePtr, tkfont, fmPtr, &width, &height); mePtr->height = height + 2 * menuPtr->activeBorderWidth + 10; mePtr->width = width; GetMenuIndicatorGeometry(menuPtr, mePtr, tkfont, fmPtr, &width, &height); mePtr->indicatorSpace = width; if (width > 0) { mePtr->width += width; } mePtr->width += 2 * menuPtr->activeBorderWidth + 10; } if (mePtr->entryFlags & ENTRY_HELP_MENU) { helpMenuIndex = i; } else if (x + mePtr->width + menuPtr->borderWidth > maxWindowWidth) { if (i == lastRowBreak) { mePtr->y = y; mePtr->x = x; lastRowBreak++; y += mePtr->height; currentRowHeight = 0; } else { x = menuPtr->borderWidth; for (j = lastRowBreak; j < i; j++) { menuPtr->entries[j]->y = y + currentRowHeight - menuPtr->entries[j]->height; menuPtr->entries[j]->x = x; x += menuPtr->entries[j]->width; } lastRowBreak = i; y += currentRowHeight; currentRowHeight = mePtr->height; } if (x > maxWidth) { maxWidth = x; } x = menuPtr->borderWidth; } else { x += mePtr->width; if (mePtr->height > currentRowHeight) { currentRowHeight = mePtr->height; } } } lastEntry = menuPtr->numEntries - 1; if (helpMenuIndex == lastEntry) { lastEntry--; } if ((lastEntry >= 0) && (x + menuPtr->entries[lastEntry]->width + menuPtr->borderWidth > maxWidth)) { maxWidth = x + menuPtr->entries[lastEntry]->width + menuPtr->borderWidth; } x = menuPtr->borderWidth; for (j = lastRowBreak; j < menuPtr->numEntries; j++) { if (j == helpMenuIndex) { continue; } menuPtr->entries[j]->y = y + currentRowHeight - menuPtr->entries[j]->height; menuPtr->entries[j]->x = x; x += menuPtr->entries[j]->width; } if (helpMenuIndex != -1) { mePtr = menuPtr->entries[helpMenuIndex]; if (x + mePtr->width + menuPtr->borderWidth > maxWindowWidth) { y += currentRowHeight; currentRowHeight = mePtr->height; x = menuPtr->borderWidth; } else if (mePtr->height > currentRowHeight) { currentRowHeight = mePtr->height; } mePtr->x = maxWindowWidth - menuPtr->borderWidth - mePtr->width; mePtr->y = y + currentRowHeight - mePtr->height; } height = y + currentRowHeight + menuPtr->borderWidth; } width = Tk_Width(menuPtr->tkwin); /* * The X server doesn't like zero dimensions, so round up to at least * 1 (a zero-sized menu should never really occur, anyway). */ if (width <= 0) { width = 1; } if (height <= 0) { height = 1; } menuPtr->totalWidth = maxWidth; menuPtr->totalHeight = height;}/* *---------------------------------------------------------------------- * * DrawTearoffEntry -- * * This procedure draws the background part of a menu. * * Results: * None. * * Side effects:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -