📄 tkunixmenu.c
字号:
* Commands are output to X to display the menu in its * current mode. * *---------------------------------------------------------------------- */static voidDrawTearoffEntry(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 drawing into */ GC gc; /* The gc we are drawing with */ Tk_Font tkfont; /* The font we are drawing with */ CONST Tk_FontMetrics *fmPtr; /* The metrics we are drawing with */ int x; int y; int width; int height;{ XPoint points[2]; int margin, segmentWidth, maxX; if (menuPtr->menuType != MASTER_MENU) { return; } margin = (fmPtr->ascent + fmPtr->descent)/2; points[0].x = x; points[0].y = y + height/2; points[1].y = points[0].y; segmentWidth = 6; maxX = width - 1; while (points[0].x < maxX) { points[1].x = points[0].x + segmentWidth; if (points[1].x > maxX) { points[1].x = maxX; } Tk_Draw3DPolygon(menuPtr->tkwin, d, menuPtr->border, points, 2, 1, TK_RELIEF_RAISED); points[0].x += 2*segmentWidth; }}/* *-------------------------------------------------------------- * * TkpInitializeMenuBindings -- * * For every interp, initializes the bindings for Windows * menus. Does nothing on Mac or XWindows. * * Results: * None. * * Side effects: * C-level bindings are setup for the interp which will * handle Alt-key sequences for menus without beeping * or interfering with user-defined Alt-key bindings. * *-------------------------------------------------------------- */voidTkpInitializeMenuBindings(interp, bindingTable) Tcl_Interp *interp; /* The interpreter to set. */ Tk_BindingTable bindingTable; /* The table to add to. */{ /* * Nothing to do. */}/* *---------------------------------------------------------------------- * * SetHelpMenu -- * * Given a menu, check to see whether or not it is a help menu * cascade in a menubar. If it is, the entry that points to * this menu will be marked. * * RESULTS: * None. * * Side effects: * Will set the ENTRY_HELP_MENU flag appropriately. * *---------------------------------------------------------------------- */static voidSetHelpMenu(menuPtr) TkMenu *menuPtr; /* The menu we are checking */{ TkMenuEntry *cascadeEntryPtr; for (cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr; cascadeEntryPtr != NULL; cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) { if ((cascadeEntryPtr->menuPtr->menuType == MENUBAR) && (cascadeEntryPtr->menuPtr->masterMenuPtr->tkwin != NULL) && (menuPtr->masterMenuPtr->tkwin != NULL)) { TkMenu *masterMenuPtr = cascadeEntryPtr->menuPtr->masterMenuPtr; char *helpMenuName = ckalloc(strlen(Tk_PathName( masterMenuPtr->tkwin)) + strlen(".help") + 1); strcpy(helpMenuName, Tk_PathName(masterMenuPtr->tkwin)); strcat(helpMenuName, ".help"); if (strcmp(helpMenuName, Tk_PathName(menuPtr->masterMenuPtr->tkwin)) == 0) { cascadeEntryPtr->entryFlags |= ENTRY_HELP_MENU; } else { cascadeEntryPtr->entryFlags &= ~ENTRY_HELP_MENU; } ckfree(helpMenuName); } }}/* *---------------------------------------------------------------------- * * TkpDrawMenuEntry -- * * Draws the given menu entry at the given coordinates with the * given attributes. * * Results: * None. * * Side effects: * X Server commands are executed to display the menu entry. * *---------------------------------------------------------------------- */voidTkpDrawMenuEntry(mePtr, d, tkfont, menuMetricsPtr, x, y, width, height, strictMotif, drawArrow) TkMenuEntry *mePtr; /* The entry to draw */ Drawable d; /* What to draw into */ Tk_Font tkfont; /* Precalculated font for menu */ CONST Tk_FontMetrics *menuMetricsPtr; /* Precalculated metrics for menu */ int x; /* X-coordinate of topleft of entry */ int y; /* Y-coordinate of topleft of entry */ int width; /* Width of the entry rectangle */ int height; /* Height of the current rectangle */ int strictMotif; /* Boolean flag */ int drawArrow; /* Whether or not to draw the cascade * arrow for cascade items. Only applies * to Windows. */{ GC gc, indicatorGC; TkMenu *menuPtr = mePtr->menuPtr; Tk_3DBorder bgBorder, activeBorder; CONST Tk_FontMetrics *fmPtr; Tk_FontMetrics entryMetrics; int padY = (menuPtr->menuType == MENUBAR) ? 3 : 0; int adjustedY = y + padY; int adjustedHeight = height - 2 * padY; /* * Choose the gc for drawing the foreground part of the entry. */ if ((mePtr->state == tkActiveUid) && !strictMotif) { gc = mePtr->activeGC; if (gc == NULL) { gc = menuPtr->activeGC; } } else { TkMenuEntry *cascadeEntryPtr; int parentDisabled = 0; for (cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr; cascadeEntryPtr != NULL; cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) { if (strcmp(cascadeEntryPtr->name, Tk_PathName(menuPtr->tkwin)) == 0) { if (cascadeEntryPtr->state == tkDisabledUid) { parentDisabled = 1; } break; } } if (((parentDisabled || (mePtr->state == tkDisabledUid))) && (menuPtr->disabledFg != NULL)) { gc = mePtr->disabledGC; if (gc == NULL) { gc = menuPtr->disabledGC; } } else { gc = mePtr->textGC; if (gc == NULL) { gc = menuPtr->textGC; } } } indicatorGC = mePtr->indicatorGC; if (indicatorGC == NULL) { indicatorGC = menuPtr->indicatorGC; } bgBorder = mePtr->border; if (bgBorder == NULL) { bgBorder = menuPtr->border; } if (strictMotif) { activeBorder = bgBorder; } else { activeBorder = mePtr->activeBorder; if (activeBorder == NULL) { activeBorder = menuPtr->activeBorder; } } if (mePtr->tkfont == NULL) { fmPtr = menuMetricsPtr; } else { tkfont = mePtr->tkfont; Tk_GetFontMetrics(tkfont, &entryMetrics); fmPtr = &entryMetrics; } /* * Need to draw the entire background, including padding. On Unix, * for menubars, we have to draw the rest of the entry taking * into account the padding. */ DrawMenuEntryBackground(menuPtr, mePtr, d, activeBorder, bgBorder, x, y, width, height); if (mePtr->type == SEPARATOR_ENTRY) { DrawMenuSeparator(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY, width, adjustedHeight); } else if (mePtr->type == TEAROFF_ENTRY) { DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY, width, adjustedHeight); } else { DrawMenuEntryLabel(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY, width, adjustedHeight); DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr, activeBorder, x, adjustedY, width, adjustedHeight, drawArrow); if (!mePtr->hideMargin) { DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont, fmPtr, x, adjustedY, width, adjustedHeight); } }}/* *---------------------------------------------------------------------- * * GetMenuLabelGeometry -- * * Figures out the size of the label portion of a menu item. * * Results: * widthPtr and heightPtr are filled in with the correct geometry * information. * * Side effects: * None. * *---------------------------------------------------------------------- */static voidGetMenuLabelGeometry(mePtr, tkfont, fmPtr, widthPtr, heightPtr) TkMenuEntry *mePtr; /* The entry we are computing */ Tk_Font tkfont; /* The precalculated font */ CONST Tk_FontMetrics *fmPtr; /* The precalculated metrics */ int *widthPtr; /* The resulting width of the label * portion */ int *heightPtr; /* The resulting height of the label * portion */{ TkMenu *menuPtr = mePtr->menuPtr; if (mePtr->image != NULL) { Tk_SizeOfImage(mePtr->image, widthPtr, heightPtr); } else if (mePtr->bitmap != (Pixmap) NULL) { Tk_SizeOfBitmap(menuPtr->display, mePtr->bitmap, widthPtr, heightPtr); } else { *heightPtr = fmPtr->linespace; if (mePtr->label != NULL) { *widthPtr = Tk_TextWidth(tkfont, mePtr->label, mePtr->labelLength); } else { *widthPtr = 0; } } *heightPtr += 1;}/* *-------------------------------------------------------------- * * TkpComputeStandardMenuGeometry -- * * This procedure is invoked to recompute the size and * layout of a menu that is not 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. * *-------------------------------------------------------------- */voidTkpComputeStandardMenuGeometry( menuPtr) /* Structure describing menu. */ TkMenu *menuPtr;{ Tk_Font tkfont; Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr; int x, y, height, width, indicatorSpace, labelWidth, accelWidth; int windowWidth, windowHeight, accelSpace; int i, j, lastColumnBreak = 0; TkMenuEntry *mePtr; if (menuPtr->tkwin == NULL) { return; } x = y = menuPtr->borderWidth; indicatorSpace = labelWidth = accelWidth = 0; windowHeight = windowWidth = 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 measuring and drawing * routines. We will measure the font metrics of the menu once. * If an entry does not have its own font set, then we give * the geometry/drawing routines the menu's font and metrics. * If an entry has its own font, we will measure that font and * give all of the geometry/drawing the entry's font and metrics. */ Tk_GetFontMetrics(menuPtr->tkfont, &menuMetrics); accelSpace = Tk_TextWidth(menuPtr->tkfont, "M", 1); for (i = 0; i < menuPtr->numEntries; i++) { mePtr = menuPtr->entries[i]; tkfont = mePtr->tkfont; if (tkfont == NULL) { tkfont = menuPtr->tkfont; fmPtr = &menuMetrics; } else { Tk_GetFontMetrics(tkfont, &entryMetrics); fmPtr = &entryMetrics; } if ((i > 0) && mePtr->columnBreak) { if (accelWidth != 0) { labelWidth += accelSpace; } for (j = lastColumnBreak; j < i; j++) { menuPtr->entries[j]->indicatorSpace = indicatorSpace; menuPtr->entries[j]->labelWidth = labelWidth; menuPtr->entries[j]->width = indicatorSpace + labelWidth + accelWidth + 2 * menuPtr->activeBorderWidth; menuPtr->entries[j]->x = x; menuPtr->entries[j]->entryFlags &= ~ENTRY_LAST_COLUMN; } x += indicatorSpace + labelWidth + accelWidth + 2 * menuPtr->activeBorderWidth; windowWidth = x; indicatorSpace = labelWidth = accelWidth = 0; lastColumnBreak = i; y = menuPtr->borderWidth; } if (mePtr->type == SEPARATOR_ENTRY) { GetMenuSeparatorGeometry(menuPtr, mePtr, tkfont, fmPtr, &width, &height); mePtr->height = height; } else if (mePtr->type == TEAROFF_ENTRY) { GetTearoffEntryGeometry(menuPtr, mePtr, tkfont, fmPtr, &width, &height); mePtr->height = height; labelWidth = width; } else { /* * For each entry, compute the height required by that * particular entry, plus three widths: the width of the * label, the width to allow for an indicator to be displayed * to the left of the label (if any), and the width of the * accelerator to be displayed to the right of the label * (if any). These sizes depend, of course, on the type * of the entry. */ GetMenuLabelGeometry(mePtr, tkfont, fmPtr, &width, &height); mePtr->height = height; if (!mePtr->hideMargin) { width += MENU_MARGIN_WIDTH; } if (width > labelWidth) { labelWidth = width; } GetMenuAccelGeometry(menuPtr, mePtr, tkfont, fmPtr, &width, &height); if (height > mePtr->height) { mePtr->height = height; } if (!mePtr->hideMargin) { width += MENU_MARGIN_WIDTH; } if (width > accelWidth) { accelWidth = width; } GetMenuIndicatorGeometry(menuPtr, mePtr, tkfont, fmPtr, &width, &height); if (height > mePtr->height) { mePtr->height = height; } if (!mePtr->hideMargin) { width += MENU_MARGIN_WIDTH; } if (width > indicatorSpace) { indicatorSpace = width; } mePtr->height += 2 * menuPtr->activeBorderWidth + MENU_DIVIDER_HEIGHT; } mePtr->y = y; y += mePtr->height; if (y > windowHeight) { windowHeight = y; } } if (accelWidth != 0) { labelWidth += accelSpace; } for (j = lastColumnBreak; j < menuPtr->numEntries; j++) { menuPtr->entries[j]->indicatorSpace = indicatorSpace; menuPtr->entries[j]->labelWidth = labelWidth; menuPtr->entries[j]->width = indicatorSpace + labelWidth + accelWidth + 2 * menuPtr->activeBorderWidth; menuPtr->entries[j]->x = x; menuPtr->entries[j]->entryFlags |= ENTRY_LAST_COLUMN; } windowWidth = x + indicatorSpace + labelWidth + accelWidth + 2 * menuPtr->activeBorderWidth + 2 * menuPtr->borderWidth; windowHeight += menuPtr->borderWidth; /* * 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 (windowWidth <= 0) { windowWidth = 1; } if (windowHeight <= 0) { windowHeight = 1; } menuPtr->totalWidth = windowWidth; menuPtr->totalHeight = windowHeight;}/* *---------------------------------------------------------------------- * * TkpMenuNotifyToplevelCreate -- * * This routine reconfigures the menu and the clones indicated by * menuName becuase a toplevel has been created and any system * menus need to be created. Not applicable to UNIX. * * Results: * None. * * Side effects: * An idle handler is set up to do the reconfiguration. * *---------------------------------------------------------------------- */voidTkpMenuNotifyToplevelCreate(interp, menuName) Tcl_Interp *interp; /* The interp the menu lives in. */ char *menuName; /* The name of the menu to * reconfigure. */{ /* * Nothing to do. */}/* *---------------------------------------------------------------------- * * TkpMenuInit -- * * Does platform-specific initialization of menus. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */voidTkpMenuInit(){ /* * Nothing to do. */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -