/* * tkMacOSXEntry.c -- * * This file implements the native aqua entry widget. * * Copyright © 2001 Apple Computer, Inc. * Copyright © 2006-2009 Daniel A. Steffen * Copyright © 2008-2009 Apple Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkMacOSXPrivate.h" #include "tkEntry.h" static ThemeButtonKind ComputeIncDecParameters(int height, int *width); #define HIOrientation kHIThemeOrientationNormal /* *-------------------------------------------------------------- * * ComputeIncDecParameters -- * * This procedure figures out which of the kThemeIncDec buttons to use. * It also sets width to the width of the IncDec button. * * Results: * The ThemeButtonKind of the button we should use. * * Side effects: * May draw the entry border into pixmap. * *-------------------------------------------------------------- */ static ThemeButtonKind ComputeIncDecParameters( int height, int *width) { ThemeButtonKind kind; if (height < 11 || height > 28) { *width = 0; kind = (ThemeButtonKind) 0; } else { if (height >= 21) { *width = 13; kind = kThemeIncDecButton; } else if (height >= 18) { *width = 12; kind = kThemeIncDecButtonSmall; } else { *width = 11; kind = kThemeIncDecButtonMini; } } return kind; } /* *-------------------------------------------------------------- * * TkpDrawEntryBorderAndFocus -- * * This procedure redraws the border of an entry window. It overrides the * generic border drawing code if the entry widget parameters are such * that the native widget drawing is a good fit. This version just * returns 1, so platforms that don't do special native drawing don't * have to implement it. * * Results: * 1 if it has drawn the border, 0 if not. * * Side effects: * May draw the entry border into pixmap. * *-------------------------------------------------------------- */ int TkpDrawEntryBorderAndFocus( Entry *entryPtr, Drawable d, int isSpinbox) { CGRect bounds; TkMacOSXDrawingContext dc; GC bgGC; Tk_Window tkwin = entryPtr->tkwin; int oldWidth = 0; MacDrawable *macDraw = (MacDrawable *)d; const HIThemeFrameDrawInfo info = { .version = 0, .kind = kHIThemeFrameTextFieldSquare, .state = (entryPtr->state == STATE_DISABLED ? kThemeStateInactive : kThemeStateActive), .isFocused = (entryPtr->flags & GOT_FOCUS ? 1 : 0), }; /* * I use 6 as the borderwidth. 2 of the 5 go into the actual frame the 3 * are because the Mac OS Entry widgets leave more space around the Text * than Tk does on X11. */ if (entryPtr->borderWidth != MAC_OSX_ENTRY_BORDER || entryPtr->highlightWidth != MAC_OSX_FOCUS_WIDTH || entryPtr->relief != MAC_OSX_ENTRY_RELIEF) { return 0; } /* * For the spinbox, we have to make the entry part smaller by the size of * the buttons. We also leave 2 pixels to the left (as per the HIG) and * space for one pixel to the right, 'cause it makes the buttons look * nicer. */ if (isSpinbox) { int incDecWidth; /* * If native spinbox buttons are going to be drawn, then temporarily * change the width of the widget so that the same code can be used * for drawing the Entry portion of the Spinbox as is used to draw * an ordinary Entry. The width must be restored before returning. */ oldWidth = Tk_Width(tkwin); if (ComputeIncDecParameters(Tk_Height(tkwin) - 2 * MAC_OSX_FOCUS_WIDTH, &incDecWidth) != 0) { Tk_Width(tkwin) -= incDecWidth + 1; } } /* * The focus ring is drawn with an Alpha at the outside part of the ring, * so we have to draw over the edges of the ring before drawing the focus * or the text will peep through. */ bgGC = Tk_GCForColor(entryPtr->highlightBgColorPtr, d); TkDrawInsetFocusHighlight(entryPtr->tkwin, bgGC, MAC_OSX_FOCUS_WIDTH, d, 0); /* * Inset the entry Frame by the maximum width of the focus rect, which is * 3 according to the Carbon docs. */ bounds.origin.x = macDraw->xOff + MAC_OSX_FOCUS_WIDTH; bounds.origin.y = macDraw->yOff + MAC_OSX_FOCUS_WIDTH; bounds.size.width = Tk_Width(tkwin) - 2*MAC_OSX_FOCUS_WIDTH; bounds.size.height = Tk_Height(tkwin) - 2*MAC_OSX_FOCUS_WIDTH; if (!TkMacOSXSetupDrawingContext(d, NULL, &dc)) { /* * No graphics context is available. If the widget is a Spinbox, we * must restore its width before returning 0. (Ticket [273b6a4996].) */ if (isSpinbox) { Tk_Width(tkwin) = oldWidth; } return 0; } ChkErr(HIThemeDrawFrame, &bounds, &info, dc.context, HIOrientation); TkMacOSXRestoreDrawingContext(&dc); if (isSpinbox) { Tk_Width(tkwin) = oldWidth; } return 1; } /* *-------------------------------------------------------------- * * TkpDrawSpinboxButtons -- * * This procedure redraws the buttons of an spinbox widget. It overrides * the generic button drawing code if the spinbox widget parameters are * such that the native widget drawing is a good fit. This version just * returns 0, so platforms that don't do special native drawing don't * have to implement it. * * Results: * 1 if it has drawn the buttons, 0 if not. * * Side effects: * May draw the buttons into pixmap. * *-------------------------------------------------------------- */ int TkpDrawSpinboxButtons( Spinbox *sbPtr, Drawable d) { CGRect bounds; Tk_Window tkwin = sbPtr->entry.tkwin; int height = Tk_Height(tkwin); int buttonHeight = height - 2 * MAC_OSX_FOCUS_WIDTH; int incDecWidth; TkMacOSXDrawingContext dc; XRectangle rects[1]; GC bgGC; MacDrawable *macDraw = (MacDrawable *)d; HIThemeButtonDrawInfo info = { .version = 0, .adornment = kThemeAdornmentNone, }; /* * FIXME: RAISED really makes more sense */ if (sbPtr->buRelief != TK_RELIEF_FLAT) { return 0; } /* * The actual sizes of the IncDec button are 21 for the normal, 18 for the * small and 15 for the mini. But the spinbox still looks okay if the * entry is a little bigger than this, so we give it a little slop. */ info.kind = ComputeIncDecParameters(buttonHeight, &incDecWidth); if (info.kind == (ThemeButtonKind) 0) { return 0; } if (sbPtr->entry.state == STATE_DISABLED) { info.state = kThemeStateInactive; info.value = kThemeButtonOff; } else if (sbPtr->selElement == SEL_BUTTONUP) { info.state = kThemeStatePressedUp; info.value = kThemeButtonOn; } else if (sbPtr->selElement == SEL_BUTTONDOWN) { info.state = kThemeStatePressedDown; info.value = kThemeButtonOn; } else { info.state = kThemeStateActive; info.value = kThemeButtonOff; } bounds.origin.x = macDraw->xOff + Tk_Width(tkwin) - incDecWidth - 1; bounds.origin.y = macDraw->yOff + MAC_OSX_FOCUS_WIDTH; bounds.size.width = incDecWidth; bounds.size.height = Tk_Height(tkwin) - 2*MAC_OSX_FOCUS_WIDTH; /* * We had to make the entry part of the window smaller so that we wouldn't * overdraw the spin buttons with the focus highlight. So now we have to * draw the highlightbackground. */ bgGC = Tk_GCForColor(sbPtr->entry.highlightBgColorPtr, d); rects[0].x = Tk_Width(tkwin) - incDecWidth - 1; rects[0].y = 0; rects[0].width = incDecWidth + 1; rects[0].height = Tk_Height(tkwin); XFillRectangles(Tk_Display(tkwin), d, bgGC, rects, 1); if (!TkMacOSXSetupDrawingContext(d, NULL, &dc)) { return 0; } ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); TkMacOSXRestoreDrawingContext(&dc); return 1; } /* * Local Variables: * mode: objc * c-basic-offset: 4 * fill-column: 79 * coding: utf-8 * End: */