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