/* * tkMacOSXMenubutton.c -- * * This file implements the Macintosh specific portion of the * menubutton widget. * * Copyright (c) 1996 by Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: tkMacOSXMenubutton.c,v 1.2.2.4 2005/11/27 02:36:46 das Exp $ */ #include #include "tkMenu.h" #include "tkMenubutton.h" #include "tkMacOSXInt.h" #include "tkMacOSXDebug.h" #define kShadowOffset (3) /* amount to offset shadow from frame */ #define kTriangleWidth (11) /* width of the triangle */ #define kTriangleHeight (6) /* height of the triangle */ #define kTriangleMargin (5) /* margin around triangle */ #define TK_POPUP_OFFSET 32 /* size of popup marker */ int TkMacOSXGetNewMenuID _ANSI_ARGS_((Tcl_Interp *interp, TkMenu *menuInstPtr, int cascade, short *menuIDPtr)); void TkMacOSXFreeMenuID _ANSI_ARGS_((short menuID)); typedef struct { SInt16 initialValue; SInt16 minValue; SInt16 maxValue; SInt16 procID; int isBevel; } MenuButtonControlParams; typedef struct { int len; Str255 title; ControlFontStyleRec style; } ControlTitleParams; /* * Declaration of Mac specific button structure. */ typedef struct MacMenuButton { TkMenuButton info; /* Generic button info. */ WindowRef windowRef; ControlRef userPane; ControlRef control; MenuRef menuRef; RGBColor userPaneBackground; MenuButtonControlParams params; ControlTitleParams titleParams; ControlButtonContentInfo bevelButtonContent; OpenCPicParams picParams; int flags; } MacMenuButton; /* * Forward declarations for procedures defined later in this file: */ static OSErr SetUserPaneDrawProc(ControlRef control, ControlUserPaneDrawProcPtr upp); static OSErr SetUserPaneSetUpSpecialBackgroundProc(ControlRef control, ControlUserPaneBackgroundProcPtr upp); static void UserPaneDraw(ControlRef control, ControlPartCode cpc); static void UserPaneBackgroundProc(ControlHandle, ControlBackgroundPtr info); static int MenuButtonInitControl ( MacMenuButton *mbPtr, Rect *paneRect, Rect *cntrRect ); static int UpdateControlColors _ANSI_ARGS_((MacMenuButton *mbPtr )); static void ComputeMenuButtonControlParams _ANSI_ARGS_((TkMenuButton * mbPtr, MenuButtonControlParams * paramsPtr)); static void ComputeControlTitleParams _ANSI_ARGS_((TkMenuButton * mbPtr, ControlTitleParams * paramsPtr)); static void CompareControlTitleParams( ControlTitleParams * p1Ptr, ControlTitleParams * p2Ptr, int * titleChanged, int * styleChanged ); extern int TkFontGetFirstTextLayout(Tk_TextLayout layout, Tk_Font * font, char * dst); extern void TkMacOSXInitControlFontStyle(Tk_Font tkfont,ControlFontStylePtr fsPtr); /* * The structure below defines menubutton class behavior by means of * procedures that can be invoked from generic window code. */ Tk_ClassProcs tkpMenubuttonClass = { sizeof(Tk_ClassProcs), /* size */ TkMenuButtonWorldChanged, /* worldChangedProc */ }; /* *---------------------------------------------------------------------- * * TkpCreateMenuButton -- * * Allocate a new TkMenuButton structure. * * Results: * Returns a newly allocated TkMenuButton structure. * * Side effects: * Registers an event handler for the widget. * *---------------------------------------------------------------------- */ TkMenuButton * TkpCreateMenuButton( Tk_Window tkwin) { MacMenuButton *mbPtr = (MacMenuButton *) ckalloc(sizeof(MacMenuButton)); mbPtr->userPaneBackground.red = 0; mbPtr->userPaneBackground.green = 0; mbPtr->userPaneBackground.blue = ~0; mbPtr->flags = 0; mbPtr->userPane = NULL; mbPtr->control = NULL; mbPtr->picParams.version = -2; mbPtr->picParams.hRes = 0x00480000; mbPtr->picParams.vRes = 0x00480000; mbPtr->picParams.srcRect.top = 0; mbPtr->picParams.srcRect.left = 0; mbPtr->picParams.reserved1 = 0; mbPtr->picParams.reserved2 = 0; mbPtr->bevelButtonContent.contentType = kControlContentPictHandle; mbPtr->menuRef = NULL; bzero(&mbPtr->params, sizeof(mbPtr->params)); bzero(&mbPtr->titleParams,sizeof(mbPtr->titleParams)); return (TkMenuButton *) mbPtr; } /* *---------------------------------------------------------------------- * * TkpDisplayMenuButton -- * * This procedure is invoked to display a menubutton widget. * * Results: * None. * * Side effects: * Commands are output to X to display the menubutton in its * current mode. * *---------------------------------------------------------------------- */ void TkpDisplayMenuButton( ClientData clientData) /* Information about widget. */ { TkMenuButton *butPtr = (TkMenuButton *) clientData; Tk_Window tkwin = butPtr->tkwin; TkWindow * winPtr; Pixmap pixmap; MacMenuButton * mbPtr = (MacMenuButton *) butPtr; GWorldPtr dstPort; CGrafPtr saveWorld; GDHandle saveDevice; int hasImageOrBitmap = 0; int width, height; int err; ControlButtonGraphicAlignment theAlignment; Rect paneRect, cntrRect; butPtr->flags &= ~REDRAW_PENDING; if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) { return; } pixmap = ( Pixmap )Tk_WindowId(tkwin); GetGWorld(&saveWorld, &saveDevice); dstPort = TkMacOSXGetDrawablePort(Tk_WindowId(tkwin)); SetGWorld(dstPort, NULL); TkMacOSXSetUpClippingRgn(Tk_WindowId(tkwin)); winPtr = (TkWindow *)butPtr->tkwin; paneRect.left = winPtr->privatePtr->xOff; paneRect.top = winPtr->privatePtr->yOff; paneRect.right = paneRect.left+Tk_Width(butPtr->tkwin)-1; paneRect.bottom = paneRect.top+Tk_Height(butPtr->tkwin)-1; cntrRect = paneRect; cntrRect.left += butPtr->inset; cntrRect.top += butPtr->inset; cntrRect.right -= butPtr->inset; cntrRect.bottom -= butPtr->inset; if (mbPtr->userPane) { MenuButtonControlParams params; bzero(¶ms, sizeof(params)); ComputeMenuButtonControlParams(butPtr, ¶ms ); if (bcmp(¶ms,&mbPtr->params,sizeof(params))) { if (mbPtr->userPane) { DisposeControl(mbPtr->userPane); mbPtr->userPane = NULL; mbPtr->control = NULL; } } } if (!mbPtr->userPane) { if (MenuButtonInitControl(mbPtr,&paneRect,&cntrRect ) ) { #ifdef TK_MAC_DEBUG fprintf(stderr,"Init Control failed\n" ); #endif return; } } SetControlBounds(mbPtr->userPane,&paneRect); SetControlBounds(mbPtr->control,&cntrRect); /* * We need to cache the title and its style */ if (!(mbPtr->flags&2)) { ControlTitleParams titleParams; int titleChanged; int styleChanged; ComputeControlTitleParams(butPtr,&titleParams); CompareControlTitleParams(&titleParams,&mbPtr->titleParams, &titleChanged,&styleChanged); if (titleChanged) { CFStringRef cf; cf = CFStringCreateWithCString(NULL, (char*) titleParams.title, kCFStringEncodingUTF8); if (hasImageOrBitmap) { SetControlTitleWithCFString(mbPtr->control, cf); } else { SetMenuItemTextWithCFString(mbPtr->menuRef, 1, cf); } CFRelease(cf); bcopy(titleParams.title,mbPtr->titleParams.title,titleParams.len+1); mbPtr->titleParams.len = titleParams.len; } if ((titleChanged||styleChanged) && titleParams .len) { if (hasImageOrBitmap) { err = SetControlFontStyle(mbPtr->control,&titleParams.style); if (err !=noErr) { #ifdef TK_MAC_DEBUG fprintf(stderr,"SetControlFontStyle failed %d\n", err); #endif return; } } bcopy(&titleParams.style,&mbPtr->titleParams.style,sizeof(titleParams.style)); } } if (butPtr->image != None) { Tk_SizeOfImage(butPtr->image, &width, &height); hasImageOrBitmap = 1; } else if (butPtr->bitmap != None) { Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height); hasImageOrBitmap = 1; } if (hasImageOrBitmap) { mbPtr->picParams.srcRect.right = width; mbPtr->picParams.srcRect.bottom = height; /* Set the flag to circumvent clipping and bounds problems with OS 10.0.4 */ tkPictureIsOpen = 1; if (!(mbPtr->bevelButtonContent.u.picture = OpenCPicture(&mbPtr->picParams)) ) { #ifdef TK_MAC_DEBUG fprintf(stderr,"OpenCPicture failed\n"); #endif } /* * TO DO - There is one case where XCopyPlane calls CopyDeepMask, * which does not get recorded in the picture. So the bitmap code * will fail in that case. */ if (butPtr->image != NULL) { Tk_RedrawImage(butPtr->image, 0, 0, width, height, pixmap, 0, 0); } else { XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, NULL, 0, 0, (unsigned int) width, (unsigned int) height, 0, 0, 1); } ClosePicture(); tkPictureIsOpen = 0; err = SetControlData(mbPtr->control, kControlButtonPart, kControlBevelButtonContentTag, sizeof(ControlButtonContentInfo), (char *) &mbPtr->bevelButtonContent); if (err != noErr) { #ifdef TK_MAC_DEBUG fprintf(stderr,"SetControlData BevelButtonContent failed, %d\n", err ); #endif } switch (butPtr->anchor) { case TK_ANCHOR_N: theAlignment = kControlBevelButtonAlignTop; break; case TK_ANCHOR_NE: theAlignment = kControlBevelButtonAlignTopRight; break; case TK_ANCHOR_E: theAlignment = kControlBevelButtonAlignRight; break; case TK_ANCHOR_SE: theAlignment = kControlBevelButtonAlignBottomRight; break; case TK_ANCHOR_S: theAlignment = kControlBevelButtonAlignBottom; break; case TK_ANCHOR_SW: theAlignment = kControlBevelButtonAlignBottomLeft; break; case TK_ANCHOR_W: theAlignment = kControlBevelButtonAlignLeft; break; case TK_ANCHOR_NW: theAlignment = kControlBevelButtonAlignTopLeft; break; case TK_ANCHOR_CENTER: theAlignment = kControlBevelButtonAlignCenter; break; } err = SetControlData(mbPtr->control, kControlButtonPart, kControlBevelButtonGraphicAlignTag, sizeof(ControlButtonGraphicAlignment), (char *) &theAlignment); if (err != noErr ) { #ifdef TK_MAC_DEBUG fprintf(stderr,"SetControlData BevelButtonGraphicAlign failed, %d\n", err ); #endif } } if (butPtr->flags & GOT_FOCUS) { HiliteControl(mbPtr->control,kControlButtonPart); } else { HiliteControl(mbPtr->control,kControlNoPart); } UpdateControlColors(mbPtr); if (mbPtr->flags&2) { ShowControl(mbPtr->control); ShowControl(mbPtr->userPane); mbPtr->flags ^= 2; } else { Draw1Control(mbPtr->userPane); SetControlVisibility(mbPtr->control, true, true); } if (hasImageOrBitmap) { KillPicture(mbPtr->bevelButtonContent.u.picture); } SetGWorld(saveWorld, saveDevice); } /* *---------------------------------------------------------------------- * * TkpDestroyMenuButton -- * * Free data structures associated with the menubutton control. * * Results: * None. * * Side effects: * Restores the default control state. * *---------------------------------------------------------------------- */ void TkpDestroyMenuButton( TkMenuButton *mbPtr) { MacMenuButton * macMbPtr = (MacMenuButton *)mbPtr; if (macMbPtr->userPane) { DisposeControl(macMbPtr->userPane); macMbPtr->userPane = NULL; } if (macMbPtr->menuRef) { short menuID; menuID = GetMenuID(macMbPtr->menuRef); TkMacOSXFreeMenuID(menuID); DisposeMenu(macMbPtr->menuRef); macMbPtr->menuRef = NULL; } } /* *---------------------------------------------------------------------- * * TkpComputeMenuButtonGeometry -- * * After changes in a menu button's text or bitmap, this procedure * recomputes the menu button's geometry and passes this information * along to the geometry manager for the window. * * Results: * None. * * Side effects: * The menu button's window may change size. * *---------------------------------------------------------------------- */ void TkpComputeMenuButtonGeometry(mbPtr) register TkMenuButton *mbPtr; /* Widget record for menu button. */ { int width, height, mm, pixels; int hasImageOrBitmap = 0; mbPtr->inset = mbPtr->highlightWidth + mbPtr->borderWidth; if (mbPtr->image != None) { Tk_SizeOfImage(mbPtr->image, &width, &height); if (mbPtr->width > 0) { width = mbPtr->width; } if (mbPtr->height > 0) { height = mbPtr->height; } hasImageOrBitmap = 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; } hasImageOrBitmap = 1; } else { hasImageOrBitmap = 0; 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; Tk_GetFontMetrics(mbPtr->tkfont, &fm); height = mbPtr->height * fm.linespace; } 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 = kTriangleHeight; mbPtr->indicatorWidth = kTriangleWidth + kTriangleMargin; width += mbPtr->indicatorWidth; } else { mbPtr->indicatorHeight = 0; mbPtr->indicatorWidth = 0; } if (!hasImageOrBitmap) { width += TK_POPUP_OFFSET; } Tk_GeometryRequest(mbPtr->tkwin, (int) (width + 2*mbPtr->inset), (int) (height + 2*mbPtr->inset)); Tk_SetInternalBorder(mbPtr->tkwin, mbPtr->inset); } /* *---------------------------------------------------------------------- * * ComputeMenuButtonControlParams -- * * This procedure computes the various parameters used * when creating a Carbon control (NewControl) * These are determined by the various tk menu button parameters * * Results: * None. * * Side effects: * Sets the control initialisation parameters * *---------------------------------------------------------------------- */ static void ComputeMenuButtonControlParams(TkMenuButton * mbPtr, MenuButtonControlParams * paramsPtr ) { int fakeMenuID = 256; /* * Determine ProcID based on button type and dimensions * * We need to set minValue to some non-zero value, * Otherwise, the markers do not show up */ paramsPtr->minValue = kControlBehaviorMultiValueMenu; paramsPtr->maxValue = 0; if (mbPtr->image || mbPtr->bitmap) { paramsPtr->isBevel = 1; if (mbPtr->borderWidth <= 2) { paramsPtr->procID = kControlBevelButtonSmallBevelProc; } else if (mbPtr->borderWidth == 3) { paramsPtr->procID = kControlBevelButtonNormalBevelProc; } else { paramsPtr->procID = kControlBevelButtonLargeBevelProc; } if (mbPtr->indicatorOn) { paramsPtr->initialValue = fakeMenuID; } else { paramsPtr->initialValue = 0; } } else { paramsPtr->isBevel = 0; paramsPtr->procID = kControlPopupButtonProc + kControlPopupVariableWidthVariant; paramsPtr->minValue = -12345; paramsPtr->maxValue = -1; paramsPtr->initialValue = 0; } } /* *---------------------------------------------------------------------- * * returns 0 if same, 1 otherwise *---------------------------------------------------------------------- */ static void CompareControlTitleParams( ControlTitleParams * p1Ptr, ControlTitleParams * p2Ptr, int * titleChanged, int * styleChanged ) { if (p1Ptr->len != p2Ptr->len) { *titleChanged = 1; } else { if (bcmp(p1Ptr->title,p2Ptr->title,p1Ptr->len)) { *titleChanged = 1; } else { *titleChanged = 0; } } if (p1Ptr->len && p2Ptr->len) { *styleChanged = bcmp(&p1Ptr->style, &p2Ptr->style, sizeof(p2Ptr->style)); } else { *styleChanged = p1Ptr->len||p2Ptr->len; } } static void ComputeControlTitleParams(TkMenuButton * butPtr, ControlTitleParams * paramsPtr ) { Tk_Font font; paramsPtr->len =TkFontGetFirstTextLayout(butPtr->textLayout,&font, (char*) paramsPtr->title); paramsPtr->title [paramsPtr->len] = 0; if (paramsPtr->len) { TkMacOSXInitControlFontStyle(font,¶msPtr->style); } } /* *---------------------------------------------------------------------- * * MenuButtonInitControl -- * * This procedure initialises a Carbon control * * Results: * 0 on success, 1 on failure. * * Side effects: * A background pane control and the control itself is created * The contol is embedded in the background control * The background control is embedded in the root control * of the containing window * The creation parameters for the control are also computed * *---------------------------------------------------------------------- */ int MenuButtonInitControl ( MacMenuButton *mbPtr, /* Mac button. */ Rect *paneRect, Rect *cntrRect ) { OSStatus err; TkMenuButton * butPtr = ( TkMenuButton * )mbPtr; ControlRef rootControl; SInt16 procID; Boolean initiallyVisible; SInt16 initialValue; SInt16 minValue; SInt16 maxValue; SInt32 controlReference; short menuID; rootControl = TkMacOSXGetRootControl(Tk_WindowId(butPtr->tkwin)); mbPtr->windowRef = GetWindowFromPort(TkMacOSXGetDrawablePort(Tk_WindowId(butPtr->tkwin))); /* * Set up the user pane */ initiallyVisible = false; initialValue = kControlSupportsEmbedding| kControlHasSpecialBackground; minValue = 0; maxValue = 1; procID = kControlUserPaneProc; controlReference = (SInt32)mbPtr; mbPtr->userPane = NewControl(mbPtr->windowRef, paneRect, "\p", initiallyVisible, initialValue, minValue, maxValue, procID, controlReference ); if (!mbPtr->userPane) { #ifdef TK_MAC_DEBUG fprintf(stderr,"Failed to create user pane control\n"); #endif return 1; } err = EmbedControl(mbPtr->userPane,rootControl); if (err != noErr) { #ifdef TK_MAC_DEBUG fprintf(stderr,"Failed to embed user pane control %d\n", (int) err); #endif return 1; } SetUserPaneSetUpSpecialBackgroundProc(mbPtr->userPane, UserPaneBackgroundProc); SetUserPaneDrawProc(mbPtr->userPane,UserPaneDraw); initiallyVisible = false; ComputeMenuButtonControlParams(butPtr,&mbPtr->params); /* Do this only if we are using bevel buttons */ ComputeControlTitleParams(butPtr,&mbPtr->titleParams); mbPtr->control = NewControl(mbPtr->windowRef, cntrRect, "\p", //mbPtr->titleParams.title, initiallyVisible, mbPtr->params.initialValue, mbPtr->params.minValue, mbPtr->params.maxValue, mbPtr->params.procID, controlReference ); if (!mbPtr->control) { #ifdef TK_MAC_DEBUG fprintf(stderr,"failed to create control of type %d : line %d\n",mbPtr->params.procID, __LINE__); #endif return 1; } err = EmbedControl(mbPtr->control,mbPtr->userPane); if (err != noErr ) { #ifdef TK_MAC_DEBUG fprintf(stderr,"failed to embed control of type %d,%d\n",procID, (int) err); #endif return 1; } if (mbPtr->params.isBevel) { CFStringRef cf; cf = CFStringCreateWithCString(NULL, (char*) mbPtr->titleParams.title, kCFStringEncodingUTF8); SetControlTitleWithCFString(mbPtr->control, cf); CFRelease(cf); if (mbPtr->titleParams.len) { err = SetControlFontStyle(mbPtr->control,&mbPtr->titleParams.style); if (err !=noErr) { #ifdef TK_MAC_DEBUG fprintf(stderr,"SetControlFontStyle failed %d\n", (int) err); #endif return 1; } } } else { CFStringRef cfStr; err = TkMacOSXGetNewMenuID(mbPtr->info.interp, (TkMenu *)mbPtr, 0, &menuID); if (err != TCL_OK) { return 1; } err = CreateNewMenu(menuID, kMenuAttrDoNotUseUserCommandKeys, &(mbPtr->menuRef)); if (err != noErr) { #ifdef TK_MAC_DEBUG fprintf(stderr,"CreateNewMenu failed, %d.\n", (int) err); #endif return 1; } cfStr = CFStringCreateWithCString(NULL, Tk_PathName(mbPtr->info.tkwin), kCFStringEncodingUTF8); if (!cfStr) { #ifdef TK_MAC_DEBUG fprintf(stderr,"CFStringCreateWithCString failed.\n"); #endif return 1; } err = SetMenuTitleWithCFString(mbPtr->menuRef, cfStr); CFRelease(cfStr); if (err != noErr) { #ifdef TK_MAC_DEBUG fprintf(stderr,"SetMenuTitleWithCFString failed, %d.\n", (int) err); #endif return 1; } cfStr = CFStringCreateWithCString(NULL, (char*) mbPtr->titleParams.title, kCFStringEncodingUTF8); AppendMenuItemText(mbPtr->menuRef, "\px"); if (cfStr) { SetMenuItemTextWithCFString(mbPtr->menuRef, 1, cfStr); CFRelease(cfStr); } err = SetControlData(mbPtr->control, kControlNoPart, kControlPopupButtonMenuRefTag, sizeof(mbPtr->menuRef), &mbPtr->menuRef); SetControlMinimum(mbPtr->control, 1); SetControlMaximum(mbPtr->control, 1); SetControlValue(mbPtr->control, 1); } mbPtr->flags |= 2; return 0; } /* *-------------------------------------------------------------- * * SetUserPane * * Utility function to add a UserPaneDrawProc * to a userPane control. From MoreControls code * from Apple DTS. * * Results: * MacOS system error. * * Side effects: * The user pane gets a new UserPaneDrawProc. * *-------------------------------------------------------------- */ OSErr SetUserPaneDrawProc ( ControlRef control, ControlUserPaneDrawProcPtr upp) { ControlUserPaneDrawUPP myControlUserPaneDrawUPP; myControlUserPaneDrawUPP = NewControlUserPaneDrawUPP(upp); return SetControlData (control, kControlNoPart, kControlUserPaneDrawProcTag, sizeof(myControlUserPaneDrawUPP), (Ptr) &myControlUserPaneDrawUPP); } /* *-------------------------------------------------------------- * * SetUserPaneSetUpSpecialBackgroundProc -- * * Utility function to add a UserPaneBackgroundProc * to a userPane control * * Results: * MacOS system error. * * Side effects: * The user pane gets a new UserPaneBackgroundProc. * *-------------------------------------------------------------- */ OSErr SetUserPaneSetUpSpecialBackgroundProc( ControlRef control, ControlUserPaneBackgroundProcPtr upp) { ControlUserPaneBackgroundUPP myControlUserPaneBackgroundUPP; myControlUserPaneBackgroundUPP = NewControlUserPaneBackgroundUPP(upp); return SetControlData (control, kControlNoPart, kControlUserPaneBackgroundProcTag, sizeof(myControlUserPaneBackgroundUPP), (Ptr) &myControlUserPaneBackgroundUPP); } /* *-------------------------------------------------------------- * * UserPaneDraw -- * * This function draws the background of the user pane that will * lie under checkboxes and radiobuttons. * * Results: * None. * * Side effects: * The user pane gets updated to the current color. * *-------------------------------------------------------------- */ void UserPaneDraw( ControlRef control, ControlPartCode cpc) { Rect contrlRect; MacMenuButton * mbPtr; mbPtr = ( MacMenuButton *)GetControlReference(control); GetControlBounds(control,&contrlRect); RGBBackColor (&mbPtr->userPaneBackground); EraseRect (&contrlRect); } /* *-------------------------------------------------------------- * * UserPaneBackgroundProc -- * * This function sets up the background of the user pane that will * lie under checkboxes and radiobuttons. * * Results: * None. * * Side effects: * The user pane background gets set to the current color. * *-------------------------------------------------------------- */ void UserPaneBackgroundProc( ControlHandle control, ControlBackgroundPtr info) { MacMenuButton * mbPtr; mbPtr = (MacMenuButton *)GetControlReference(control); if (info->colorDevice) { RGBBackColor (&mbPtr->userPaneBackground); } } /* *-------------------------------------------------------------- * * UpdateControlColors -- * * This function will review the colors used to display * a Macintosh button. If any non-standard colors are * used we create a custom palette for the button, populate * with the colors for the button and install the palette. * * Under Appearance, we just set the pointer that will be * used by the UserPaneDrawProc. * * Results: * None. * * Side effects: * The Macintosh control may get a custom palette installed. * *-------------------------------------------------------------- */ static int UpdateControlColors(MacMenuButton * mbPtr) { XColor *xcolor; TkMenuButton * butPtr = ( TkMenuButton * )mbPtr; /* * Under Appearance we cannot change the background of the * button itself. However, the color we are setting is the color * of the containing userPane. This will be the color that peeks * around the rounded corners of the button. * We make this the highlightbackground rather than the background, * because if you color the background of a frame containing a * button, you usually also color the highlightbackground as well, * or you will get a thin grey ring around the button. */ xcolor = Tk_3DBorderColor(butPtr->normalBorder); TkSetMacColor(xcolor->pixel, &mbPtr->userPaneBackground); return false; }