1/*
2 * tkMacOSXEntry.c --
3 *
4 *	This file implements the native aqua entry widget.
5 *
6 * Copyright 2001, Apple Computer, Inc.
7 * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
8 * Copyright 2008-2009, Apple Inc.
9 *
10 * See the file "license.terms" for information on usage and redistribution
11 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12 *
13 * RCS: @(#) $Id$
14 */
15
16#include "tkMacOSXPrivate.h"
17#include "tkEntry.h"
18
19static ThemeButtonKind	ComputeIncDecParameters(int height, int *width);
20
21#define HIOrientation kHIThemeOrientationNormal
22
23/*
24 *--------------------------------------------------------------
25 *
26 * ComputeIncDecParameters --
27 *
28 *	This procedure figures out which of the kThemeIncDec buttons to use.
29 *	It also sets width to the width of the IncDec button.
30 *
31 * Results:
32 *	The ThemeButtonKind of the button we should use.
33 *
34 * Side effects:
35 *	May draw the entry border into pixmap.
36 *
37 *--------------------------------------------------------------
38 */
39
40static ThemeButtonKind
41ComputeIncDecParameters(
42    int height,
43    int *width)
44{
45    ThemeButtonKind kind;
46
47    if (height < 11 || height > 28) {
48	*width = 0;
49	kind = (ThemeButtonKind) 0;
50    } else {
51	if (height >= 21) {
52	    *width = 13;
53	    kind = kThemeIncDecButton;
54	} else if (height >= 18) {
55	    *width = 12;
56	    kind = kThemeIncDecButtonSmall;
57	} else {
58	    *width = 11;
59	    kind = kThemeIncDecButtonMini;
60	}
61    }
62
63    return kind;
64}
65
66/*
67 *--------------------------------------------------------------
68 *
69 * TkpDrawEntryBorderAndFocus --
70 *
71 *	This procedure redraws the border of an entry window. It overrides the
72 *	generic border drawing code if the entry widget parameters are such
73 *	that the native widget drawing is a good fit. This version just
74 *	returns 1, so platforms that don't do special native drawing don't
75 *	have to implement it.
76 *
77 * Results:
78 *	1 if it has drawn the border, 0 if not.
79 *
80 * Side effects:
81 *	May draw the entry border into pixmap.
82 *
83 *--------------------------------------------------------------
84 */
85
86int
87TkpDrawEntryBorderAndFocus(
88    Entry *entryPtr,
89    Drawable d,
90    int isSpinbox)
91{
92    CGRect bounds;
93    TkMacOSXDrawingContext dc;
94    GC bgGC;
95    Tk_Window tkwin = entryPtr->tkwin;
96    int oldWidth = 0;
97    MacDrawable *macDraw = (MacDrawable *) d;
98    const HIThemeFrameDrawInfo info = {
99	.version = 0,
100	.kind = kHIThemeFrameTextFieldSquare,
101	.state = (entryPtr->state == STATE_DISABLED ? kThemeStateInactive :
102		kThemeStateActive),
103	.isFocused = (entryPtr->flags & GOT_FOCUS ? 1 : 0),
104    };
105
106    /*
107     * I use 6 as the borderwidth. 2 of the 5 go into the actual frame the 3
108     * are because the Mac OS Entry widgets leave more space around the Text
109     * than Tk does on X11.
110     */
111
112    if (entryPtr->borderWidth != MAC_OSX_ENTRY_BORDER
113	    || entryPtr->highlightWidth != MAC_OSX_FOCUS_WIDTH
114	    || entryPtr->relief != MAC_OSX_ENTRY_RELIEF) {
115	return 0;
116    }
117
118    /*
119     * For the spinbox, we have to make the entry part smaller by the size of
120     * the buttons. We also leave 2 pixels to the left (as per the HIG) and
121     * space for one pixel to the right, 'cause it makes the buttons look
122     * nicer.
123     */
124
125    if (isSpinbox) {
126	int incDecWidth;
127
128	oldWidth = Tk_Width(tkwin);
129
130	ComputeIncDecParameters(Tk_Height(tkwin) - 2 * MAC_OSX_FOCUS_WIDTH,
131		&incDecWidth);
132	Tk_Width(tkwin) -= incDecWidth + 1;
133    }
134
135   /*
136    * The focus ring is drawn with an Alpha at the outside part of the ring,
137    * so we have to draw over the edges of the ring before drawing the focus
138    * or the text will peep through.
139    */
140
141    bgGC = Tk_GCForColor(entryPtr->highlightBgColorPtr, d);
142    TkDrawInsetFocusHighlight(entryPtr->tkwin, bgGC, MAC_OSX_FOCUS_WIDTH, d, 0);
143
144    /*
145     * Inset the entry Frame by the maximum width of the focus rect, which is
146     * 3 according to the Carbon docs.
147     */
148
149    bounds.origin.x = macDraw->xOff + MAC_OSX_FOCUS_WIDTH;
150    bounds.origin.y = macDraw->yOff + MAC_OSX_FOCUS_WIDTH;
151    bounds.size.width = Tk_Width(tkwin) - 2*MAC_OSX_FOCUS_WIDTH;
152    bounds.size.height = Tk_Height(tkwin) - 2*MAC_OSX_FOCUS_WIDTH;
153    if (!TkMacOSXSetupDrawingContext(d, NULL, 1, &dc)) {
154	return 0;
155    }
156    ChkErr(HIThemeDrawFrame, &bounds, &info, dc.context, HIOrientation);
157    TkMacOSXRestoreDrawingContext(&dc);
158    if (isSpinbox) {
159	Tk_Width(tkwin) = oldWidth;
160    }
161    return 1;
162}
163
164/*
165 *--------------------------------------------------------------
166 *
167 * TkpDrawSpinboxButtons --
168 *
169 *	This procedure redraws the buttons of an spinbox widget. It overrides
170 *	the generic button drawing code if the spinbox widget parameters are
171 *	such that the native widget drawing is a good fit. This version just
172 *	returns 0, so platforms that don't do special native drawing don't
173 *	have to implement it.
174 *
175 * Results:
176 *	1 if it has drawn the border, 0 if not.
177 *
178 * Side effects:
179 *	May draw the entry border into pixmap.
180 *
181 *--------------------------------------------------------------
182 */
183
184int
185TkpDrawSpinboxButtons(
186    Spinbox *sbPtr,
187    Drawable d)
188{
189    CGRect bounds;
190    Tk_Window tkwin = sbPtr->entry.tkwin;
191    int height = Tk_Height(tkwin);
192    int buttonHeight = height - 2 * MAC_OSX_FOCUS_WIDTH;
193    int incDecWidth;
194    TkMacOSXDrawingContext dc;
195    XRectangle rects[1];
196    GC bgGC;
197    MacDrawable *macDraw = (MacDrawable *) d;
198    HIThemeButtonDrawInfo info = {
199	.version = 0,
200	.adornment = kThemeAdornmentNone,
201    };
202
203    /*
204     * FIXME: RAISED really makes more sense
205     */
206
207    if (sbPtr->buRelief != TK_RELIEF_FLAT) {
208	return 0;
209    }
210
211    /*
212     * The actual sizes of the IncDec button are 21 for the normal, 18 for the
213     * small and 15 for the mini. But the spinbox still looks okay if the
214     * entry is a little bigger than this, so we give it a little slop.
215     */
216
217    info.kind = ComputeIncDecParameters(buttonHeight, &incDecWidth);
218    if (info.kind == (ThemeButtonKind) 0) {
219	return 0;
220    }
221
222    if (sbPtr->entry.state == STATE_DISABLED) {
223	info.state = kThemeStateInactive;
224	info.value = kThemeButtonOff;
225    } else if (sbPtr->selElement == SEL_BUTTONUP) {
226	info.state = kThemeStatePressedUp;
227	info.value = kThemeButtonOn;
228    } else if (sbPtr->selElement == SEL_BUTTONDOWN) {
229	info.state = kThemeStatePressedDown;
230	info.value = kThemeButtonOn;
231    } else {
232	info.state = kThemeStateActive;
233	info.value = kThemeButtonOff;
234    }
235
236    bounds.origin.x = macDraw->xOff + Tk_Width(tkwin) - incDecWidth - 1;
237    bounds.origin.y = macDraw->yOff + MAC_OSX_FOCUS_WIDTH;
238    bounds.size.width = incDecWidth;
239    bounds.size.height = Tk_Height(tkwin) - 2*MAC_OSX_FOCUS_WIDTH;
240
241    /*
242     * We had to make the entry part of the window smaller so that we wouldn't
243     * overdraw the spin buttons with the focus highlight. So now we have to
244     * draw the highlightbackground.
245     */
246
247    bgGC = Tk_GCForColor(sbPtr->entry.highlightBgColorPtr, d);
248    rects[0].x = bounds.origin.x;
249    rects[0].y = 0;
250    rects[0].width = Tk_Width(tkwin);
251    rects[0].height = Tk_Height(tkwin);
252    XFillRectangles(Tk_Display(tkwin), d, bgGC, rects, 1);
253
254    if (!TkMacOSXSetupDrawingContext(d, NULL, 1, &dc)) {
255	return 0;
256    }
257    ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL);
258    TkMacOSXRestoreDrawingContext(&dc);
259    return 1;
260}
261
262/*
263 * Local Variables:
264 * mode: c
265 * c-basic-offset: 4
266 * fill-column: 79
267 * coding: utf-8
268 * End:
269 */
270