📄 tkmenudraw.c
字号:
/* * tkMenuDraw.c -- * * This module implements the platform-independent drawing and * geometry calculations of menu widgets. * * Copyright (c) 1996-1997 by Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * SCCS: @(#) tkMenuDraw.c 1.46 97/10/28 14:26:00 */#include "tkMenu.h"/* * Forward declarations for procedures defined later in this file: */static void AdjustMenuCoords _ANSI_ARGS_ ((TkMenu *menuPtr, TkMenuEntry *mePtr, int *xPtr, int *yPtr, char *string));static void ComputeMenuGeometry _ANSI_ARGS_(( ClientData clientData));static void DisplayMenu _ANSI_ARGS_((ClientData clientData));/* *---------------------------------------------------------------------- * * TkMenuInitializeDrawingFields -- * * Fills in drawing fields of a new menu. Called when new menu is * created by Tk_MenuCmd. * * Results: * None. * * Side effects: * menuPtr fields are initialized. * *---------------------------------------------------------------------- */voidTkMenuInitializeDrawingFields(menuPtr) TkMenu *menuPtr; /* The menu we are initializing. */{ menuPtr->textGC = None; menuPtr->gray = None; menuPtr->disabledGC = None; menuPtr->activeGC = None; menuPtr->indicatorGC = None; menuPtr->disabledImageGC = None; menuPtr->totalWidth = menuPtr->totalHeight = 0;}/* *---------------------------------------------------------------------- * * TkMenuInitializeEntryDrawingFields -- * * Fills in drawing fields of a new menu entry. Called when an * entry is created. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */voidTkMenuInitializeEntryDrawingFields(mePtr) TkMenuEntry *mePtr; /* The menu we are initializing. */{ mePtr->width = 0; mePtr->height = 0; mePtr->x = 0; mePtr->y = 0; mePtr->indicatorSpace = 0; mePtr->labelWidth = 0; mePtr->textGC = None; mePtr->activeGC = None; mePtr->disabledGC = None; mePtr->indicatorGC = None;}/* *---------------------------------------------------------------------- * * TkMenuFreeDrawOptions -- * * Frees up any structures allocated for the drawing of a menu. * Called when menu is deleted. * * Results: * None. * * Side effects: * Storage is released. * *---------------------------------------------------------------------- */voidTkMenuFreeDrawOptions(menuPtr) TkMenu *menuPtr;{ if (menuPtr->textGC != None) { Tk_FreeGC(menuPtr->display, menuPtr->textGC); } if (menuPtr->disabledImageGC != None) { Tk_FreeGC(menuPtr->display, menuPtr->disabledImageGC); } if (menuPtr->gray != None) { Tk_FreeBitmap(menuPtr->display, menuPtr->gray); } if (menuPtr->disabledGC != None) { Tk_FreeGC(menuPtr->display, menuPtr->disabledGC); } if (menuPtr->activeGC != None) { Tk_FreeGC(menuPtr->display, menuPtr->activeGC); } if (menuPtr->indicatorGC != None) { Tk_FreeGC(menuPtr->display, menuPtr->indicatorGC); }}/* *---------------------------------------------------------------------- * * TkMenuEntryFreeDrawOptions -- * * Frees up drawing structures for a menu entry. Called when * menu entry is freed. * * RESULTS: * None. * * Side effects: * Storage is freed. * *---------------------------------------------------------------------- */voidTkMenuEntryFreeDrawOptions(mePtr) TkMenuEntry *mePtr;{ if (mePtr->textGC != None) { Tk_FreeGC(mePtr->menuPtr->display, mePtr->textGC); } if (mePtr->disabledGC != None) { Tk_FreeGC(mePtr->menuPtr->display, mePtr->disabledGC); } if (mePtr->activeGC != None) { Tk_FreeGC(mePtr->menuPtr->display, mePtr->activeGC); } if (mePtr->indicatorGC != None) { Tk_FreeGC(mePtr->menuPtr->display, mePtr->indicatorGC); }}/* *---------------------------------------------------------------------- * * TkMenuConfigureDrawOptions -- * * Sets the menu's drawing attributes in preparation for drawing * the menu. * * RESULTS: * None. * * Side effects: * Storage is allocated. * *---------------------------------------------------------------------- */voidTkMenuConfigureDrawOptions(menuPtr) TkMenu *menuPtr; /* The menu we are configuring. */{ XGCValues gcValues; GC newGC; unsigned long mask; /* * A few options need special processing, such as setting the * background from a 3-D border, or filling in complicated * defaults that couldn't be specified to Tk_ConfigureWidget. */ Tk_SetBackgroundFromBorder(menuPtr->tkwin, menuPtr->border); gcValues.font = Tk_FontId(menuPtr->tkfont); gcValues.foreground = menuPtr->fg->pixel; gcValues.background = Tk_3DBorderColor(menuPtr->border)->pixel; newGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCBackground|GCFont, &gcValues); if (menuPtr->textGC != None) { Tk_FreeGC(menuPtr->display, menuPtr->textGC); } menuPtr->textGC = newGC; gcValues.font = Tk_FontId(menuPtr->tkfont); gcValues.background = Tk_3DBorderColor(menuPtr->border)->pixel; if (menuPtr->disabledFg != NULL) { gcValues.foreground = menuPtr->disabledFg->pixel; mask = GCForeground|GCBackground|GCFont; } else { gcValues.foreground = gcValues.background; mask = GCForeground; if (menuPtr->gray == None) { menuPtr->gray = Tk_GetBitmap(menuPtr->interp, menuPtr->tkwin, Tk_GetUid("gray50")); } if (menuPtr->gray != None) { gcValues.fill_style = FillStippled; gcValues.stipple = menuPtr->gray; mask = GCForeground|GCFillStyle|GCStipple; } } newGC = Tk_GetGC(menuPtr->tkwin, mask, &gcValues); if (menuPtr->disabledGC != None) { Tk_FreeGC(menuPtr->display, menuPtr->disabledGC); } menuPtr->disabledGC = newGC; gcValues.foreground = Tk_3DBorderColor(menuPtr->border)->pixel; if (menuPtr->gray == None) { menuPtr->gray = Tk_GetBitmap(menuPtr->interp, menuPtr->tkwin, Tk_GetUid("gray50")); } if (menuPtr->gray != None) { gcValues.fill_style = FillStippled; gcValues.stipple = menuPtr->gray; newGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCFillStyle|GCStipple, &gcValues); } if (menuPtr->disabledImageGC != None) { Tk_FreeGC(menuPtr->display, menuPtr->disabledImageGC); } menuPtr->disabledImageGC = newGC; gcValues.font = Tk_FontId(menuPtr->tkfont); gcValues.foreground = menuPtr->activeFg->pixel; gcValues.background = Tk_3DBorderColor(menuPtr->activeBorder)->pixel; newGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCBackground|GCFont, &gcValues); if (menuPtr->activeGC != None) { Tk_FreeGC(menuPtr->display, menuPtr->activeGC); } menuPtr->activeGC = newGC; gcValues.foreground = menuPtr->indicatorFg->pixel; gcValues.background = Tk_3DBorderColor(menuPtr->border)->pixel; newGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCBackground|GCFont, &gcValues); if (menuPtr->indicatorGC != None) { Tk_FreeGC(menuPtr->display, menuPtr->indicatorGC); } menuPtr->indicatorGC = newGC;}/* *---------------------------------------------------------------------- * * TkMenuConfigureEntryDrawOptions -- * * Calculates any entry-specific draw options for the given menu * entry. * * Results: * Returns a standard Tcl error. * * Side effects: * Storage may be allocated. * *---------------------------------------------------------------------- */intTkMenuConfigureEntryDrawOptions(mePtr, index) TkMenuEntry *mePtr; int index;{ XGCValues gcValues; GC newGC, newActiveGC, newDisabledGC, newIndicatorGC; unsigned long mask; Tk_Font tkfont; TkMenu *menuPtr = mePtr->menuPtr; tkfont = (mePtr->tkfont == NULL) ? menuPtr->tkfont : mePtr->tkfont; if (mePtr->state == tkActiveUid) { if (index != menuPtr->active) { TkActivateMenuEntry(menuPtr, index); } } else { if (index == menuPtr->active) { TkActivateMenuEntry(menuPtr, -1); } if ((mePtr->state != tkNormalUid) && (mePtr->state != tkDisabledUid)) { Tcl_AppendResult(menuPtr->interp, "bad state value \"", mePtr->state, "\": must be normal, active, or disabled", (char *) NULL); mePtr->state = tkNormalUid; return TCL_ERROR; } } if ((mePtr->tkfont != NULL) || (mePtr->border != NULL) || (mePtr->fg != NULL) || (mePtr->activeBorder != NULL) || (mePtr->activeFg != NULL) || (mePtr->indicatorFg != NULL)) { gcValues.foreground = (mePtr->fg != NULL) ? mePtr->fg->pixel : menuPtr->fg->pixel; gcValues.background = Tk_3DBorderColor( (mePtr->border != NULL) ? mePtr->border : menuPtr->border) ->pixel; gcValues.font = Tk_FontId(tkfont); /* * Note: disable GraphicsExpose events; we know there won't be * obscured areas when copying from an off-screen pixmap to the * screen and this gets rid of unnecessary events. */ gcValues.graphics_exposures = False; newGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCBackground|GCFont|GCGraphicsExposures, &gcValues); if (mePtr->indicatorFg != NULL) { gcValues.foreground = mePtr->indicatorFg->pixel; } else if (menuPtr->indicatorFg != NULL) { gcValues.foreground = menuPtr->indicatorFg->pixel; } newIndicatorGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCBackground|GCGraphicsExposures, &gcValues); if ((menuPtr->disabledFg != NULL) || (mePtr->image != NULL)) { gcValues.foreground = menuPtr->disabledFg->pixel; mask = GCForeground|GCBackground|GCFont|GCGraphicsExposures; } else { gcValues.foreground = gcValues.background; gcValues.fill_style = FillStippled; gcValues.stipple = menuPtr->gray; mask = GCForeground|GCFillStyle|GCStipple; } newDisabledGC = Tk_GetGC(menuPtr->tkwin, mask, &gcValues); gcValues.foreground = (mePtr->activeFg != NULL) ? mePtr->activeFg->pixel : menuPtr->activeFg->pixel; gcValues.background = Tk_3DBorderColor( (mePtr->activeBorder != NULL) ? mePtr->activeBorder : menuPtr->activeBorder)->pixel; newActiveGC = Tk_GetGC(menuPtr->tkwin, GCForeground|GCBackground|GCFont|GCGraphicsExposures, &gcValues); } else { newGC = None; newActiveGC = None; newDisabledGC = None; newIndicatorGC = None; } if (mePtr->textGC != None) { Tk_FreeGC(menuPtr->display, mePtr->textGC); } mePtr->textGC = newGC; if (mePtr->activeGC != None) { Tk_FreeGC(menuPtr->display, mePtr->activeGC); } mePtr->activeGC = newActiveGC; if (mePtr->disabledGC != None) { Tk_FreeGC(menuPtr->display, mePtr->disabledGC); } mePtr->disabledGC = newDisabledGC; if (mePtr->indicatorGC != None) { Tk_FreeGC(menuPtr->display, mePtr->indicatorGC); } mePtr->indicatorGC = newIndicatorGC; return TCL_OK;}/* *---------------------------------------------------------------------- * * TkEventuallyRecomputeMenu -- * * Tells Tcl to redo the geometry because this menu has changed. * * Results: * None. * * Side effects: * Menu geometry is recomputed at idle time, and the menu will be * redisplayed. * *---------------------------------------------------------------------- */voidTkEventuallyRecomputeMenu(menuPtr) TkMenu *menuPtr;{ if (!(menuPtr->menuFlags & RESIZE_PENDING)) { menuPtr->menuFlags |= RESIZE_PENDING; Tcl_DoWhenIdle(ComputeMenuGeometry, (ClientData) menuPtr); }}/* *---------------------------------------------------------------------- * * TkRecomputeMenu -- * * Tells Tcl to redo the geometry because this menu has changed. * Does it now; removes any ComputeMenuGeometries from the idler. * * Results: * None. * * Side effects: * Menu geometry is immediately reconfigured. * *---------------------------------------------------------------------- */voidTkRecomputeMenu(menuPtr) TkMenu *menuPtr;{ if (menuPtr->menuFlags & RESIZE_PENDING) { Tcl_CancelIdleCall(ComputeMenuGeometry, (ClientData) menuPtr); ComputeMenuGeometry((ClientData) menuPtr); }}/* *---------------------------------------------------------------------- * * TkEventuallyRedrawMenu -- * * Arrange for an entry of a menu, or the whole menu, to be * redisplayed at some point in the future. * * Results: * None. * * Side effects: * A when-idle hander is scheduled to do the redisplay, if there * isn't one already scheduled. * *---------------------------------------------------------------------- */voidTkEventuallyRedrawMenu(menuPtr, mePtr) register TkMenu *menuPtr; /* Information about menu to redraw. */ register TkMenuEntry *mePtr; /* Entry to redraw. NULL means redraw * all the entries in the menu. */{ int i; if (menuPtr->tkwin == NULL) { return; } if (mePtr != NULL) { mePtr->entryFlags |= ENTRY_NEEDS_REDISPLAY; } else { for (i = 0; i < menuPtr->numEntries; i++) { menuPtr->entries[i]->entryFlags |= ENTRY_NEEDS_REDISPLAY; } } if (!Tk_IsMapped(menuPtr->tkwin) || (menuPtr->menuFlags & REDRAW_PENDING)) { return; } Tcl_DoWhenIdle(DisplayMenu, (ClientData) menuPtr); menuPtr->menuFlags |= REDRAW_PENDING;}/* *-------------------------------------------------------------- * * ComputeMenuGeometry -- * * This procedure is invoked to recompute the size and * layout of a menu. It is called as a when-idle handler so * that it only gets done once, even if a group of changes is * made to the menu. *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -