OSDN Git Service

Please enter the commit message for your changes. Lines starting
[eos/base.git] / util / src / TclTk / tk8.6.12 / macosx / tkMacOSXScale.c
1 /*
2  * tkMacOSXScale.c --
3  *
4  *      This file implements the Macintosh specific portion of the
5  *      scale widget.
6  *
7  * Copyright (c) 1996 by Sun Microsystems, Inc.
8  * Copyright (c) 1998-2000 by Scriptics Corporation.
9  * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net>
10  * Copyright 2008-2009, Apple Inc.
11  *
12  * See the file "license.terms" for information on usage and redistribution
13  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14  */
15
16 #include "tkMacOSXPrivate.h"
17 #include "tkScale.h"
18
19 #ifdef MAC_OSX_TK_TODO
20 /*
21 #ifdef TK_MAC_DEBUG
22 #define TK_MAC_DEBUG_SCALE
23 #endif
24 */
25
26 /*
27  * Defines used in this file.
28  */
29
30 #define slider          1110
31 #define inSlider        1
32 #define inInc           2
33 #define inDecr          3
34
35 /*
36  * Declaration of Macintosh specific scale structure.
37  */
38
39 typedef struct MacScale {
40     TkScale info;               /* Generic scale info. */
41     int flags;                  /* Flags. */
42     ControlRef scaleHandle;     /* Handle to the Scale control struct. */
43 } MacScale;
44
45 /*
46  * Globals uses locally in this file.
47  */
48 static ControlActionUPP scaleActionProc = NULL; /* Pointer to func. */
49
50 /*
51  * Forward declarations for procedures defined later in this file:
52  */
53
54 static void             MacScaleEventProc(ClientData clientData,
55                             XEvent *eventPtr);
56 static pascal void      ScaleActionProc(ControlRef theControl,
57                             ControlPartCode partCode);
58 \f
59 /*
60  *----------------------------------------------------------------------
61  *
62  * TkpCreateScale --
63  *
64  *      Allocate a new TkScale structure.
65  *
66  * Results:
67  *      Returns a newly allocated TkScale structure.
68  *
69  * Side effects:
70  *      None.
71  *
72  *----------------------------------------------------------------------
73  */
74
75 TkScale *
76 TkpCreateScale(
77     Tk_Window tkwin)
78 {
79     MacScale *macScalePtr = (MacScale *)ckalloc(sizeof(MacScale));
80
81     macScalePtr->scaleHandle = NULL;
82     if (scaleActionProc == NULL) {
83         scaleActionProc = NewControlActionUPP(ScaleActionProc);
84     }
85
86     Tk_CreateEventHandler(tkwin, ButtonPressMask,
87             MacScaleEventProc, macScalePtr);
88
89     return (TkScale *) macScalePtr;
90 }
91 \f
92 /*
93  *----------------------------------------------------------------------
94  *
95  * TkpDestroyScale --
96  *
97  *      Free Macintosh specific resources.
98  *
99  * Results:
100  *      None
101  *
102  * Side effects:
103  *      The slider control is destroyed.
104  *
105  *----------------------------------------------------------------------
106  */
107
108 void
109 TkpDestroyScale(
110     TkScale *scalePtr)
111 {
112     MacScale *macScalePtr = (MacScale *) scalePtr;
113
114     /*
115      * Free Macintosh control.
116      */
117
118     if (macScalePtr->scaleHandle != NULL) {
119         DisposeControl(macScalePtr->scaleHandle);
120     }
121 }
122 \f
123 /*
124  *----------------------------------------------------------------------
125  *
126  * TkpDisplayScale --
127  *
128  *      This procedure is invoked as an idle handler to redisplay the contents
129  *      of a scale widget.
130  *
131  * Results:
132  *      None.
133  *
134  * Side effects:
135  *      The scale gets redisplayed.
136  *
137  *----------------------------------------------------------------------
138  */
139
140 void
141 TkpDisplayScale(
142     ClientData clientData)      /* Widget record for scale. */
143 {
144     TkScale *scalePtr = clientData;
145     Tk_Window tkwin = scalePtr->tkwin;
146     Tcl_Interp *interp = scalePtr->interp;
147     int result;
148     char string[TCL_DOUBLE_SPACE];
149     MacScale *macScalePtr = clientData;
150     Rect r;
151     WindowRef windowRef;
152     MacDrawable *macDraw;
153     SInt32 initialValue, minValue, maxValue;
154     UInt16 numTicks;
155     Tcl_DString buf;
156
157 #ifdef TK_MAC_DEBUG_SCALE
158     TkMacOSXDbgMsg("TkpDisplayScale");
159 #endif
160     scalePtr->flags &= ~REDRAW_PENDING;
161     if ((scalePtr->tkwin == NULL) || !Tk_IsMapped(scalePtr->tkwin)) {
162         goto done;
163     }
164
165     /*
166      * Invoke the scale's command if needed.
167      */
168
169     Tcl_Preserve(scalePtr);
170     if ((scalePtr->flags & INVOKE_COMMAND) && (scalePtr->command != NULL)) {
171         Tcl_Preserve(interp);
172         if (snprintf(string, TCL_DOUBLE_SPACE, scalePtr->format,
173                 scalePtr->value) < 0) {
174             string[TCL_DOUBLE_SPACE - 1] = '\0';
175         }
176         Tcl_DStringInit(&buf);
177         Tcl_DStringAppend(&buf, scalePtr->command, -1);
178         Tcl_DStringAppend(&buf, " ", -1);
179         Tcl_DStringAppend(&buf, string, -1);
180         result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, TCL_EVAL_GLOBAL);
181         Tcl_DStringFree(&buf);
182         if (result != TCL_OK) {
183             Tcl_AddErrorInfo(interp, "\n    (command executed by scale)");
184             Tcl_BackgroundException(interp, result);
185         }
186         Tcl_Release(interp);
187     }
188     scalePtr->flags &= ~INVOKE_COMMAND;
189     if (scalePtr->flags & SCALE_DELETED) {
190         Tcl_Release(scalePtr);
191         return;
192     }
193     Tcl_Release(scalePtr);
194
195     /*
196      * Now handle the part of redisplay that is the same for horizontal and
197      * vertical scales: border and traversal highlight.
198      */
199
200     if (scalePtr->highlightWidth != 0) {
201         GC gc = Tk_GCForColor(scalePtr->highlightColorPtr, Tk_WindowId(tkwin));
202
203         Tk_DrawFocusHighlight(tkwin, gc, scalePtr->highlightWidth,
204                 Tk_WindowId(tkwin));
205     }
206     Tk_Draw3DRectangle(tkwin, Tk_WindowId(tkwin), scalePtr->bgBorder,
207             scalePtr->highlightWidth, scalePtr->highlightWidth,
208             Tk_Width(tkwin) - 2*scalePtr->highlightWidth,
209             Tk_Height(tkwin) - 2*scalePtr->highlightWidth,
210             scalePtr->borderWidth, scalePtr->relief);
211
212     /*
213      * Set up port for drawing Macintosh control.
214      */
215
216     macDraw = (MacDrawable *)Tk_WindowId(tkwin);
217     windowRef = TkMacOSXGetNSWindowForDrawable(Tk_WindowId(tkwin));
218
219     /*
220      * Create Macintosh control.
221      */
222
223 #define MAC_OSX_SCROLL_WIDTH 10
224
225     if (scalePtr->orient == ORIENT_HORIZONTAL) {
226         int offset = (Tk_Height(tkwin) - MAC_OSX_SCROLL_WIDTH) / 2;
227
228         if (offset < 0) {
229             offset = 0;
230         }
231
232         r.left = macDraw->xOff + scalePtr->inset;
233         r.top = macDraw->yOff + offset;
234         r.right = macDraw->xOff+Tk_Width(tkwin) - scalePtr->inset;
235         r.bottom = macDraw->yOff + offset + MAC_OSX_SCROLL_WIDTH/2;
236     } else {
237         int offset = (Tk_Width(tkwin) - MAC_OSX_SCROLL_WIDTH) / 2;
238
239         if (offset < 0) {
240             offset = 0;
241         }
242
243         r.left = macDraw->xOff + offset;
244         r.top = macDraw->yOff + scalePtr->inset;
245         r.right = macDraw->xOff + offset + MAC_OSX_SCROLL_WIDTH/2;
246         r.bottom = macDraw->yOff + Tk_Height(tkwin) - scalePtr->inset;
247     }
248
249     if (macScalePtr->scaleHandle == NULL) {
250 #ifdef TK_MAC_DEBUG_SCALE
251         TkMacOSXDbgMsg("Initialising scale");
252 #endif
253         initialValue = scalePtr->value;
254         if (scalePtr->orient == ORIENT_HORIZONTAL) {
255             minValue = scalePtr->fromValue;
256             maxValue = scalePtr->toValue;
257         } else {
258             minValue = scalePtr->fromValue;
259             maxValue = scalePtr->toValue;
260         }
261
262         if (scalePtr->tickInterval == 0) {
263             numTicks = 0;
264         } else {
265             numTicks = (maxValue - minValue)/scalePtr->tickInterval;
266         }
267
268         CreateSliderControl(windowRef, &r, initialValue, minValue, maxValue,
269                 kControlSliderPointsDownOrRight, numTicks, 1, scaleActionProc,
270                 &macScalePtr->scaleHandle);
271         SetControlReference(macScalePtr->scaleHandle, (UInt32) scalePtr);
272
273         if (IsWindowActive(windowRef)) {
274             macScalePtr->flags |= ACTIVE;
275         }
276     } else {
277         SetControlBounds(macScalePtr->scaleHandle, &r);
278         SetControl32BitValue(macScalePtr->scaleHandle, scalePtr->value);
279         SetControl32BitMinimum(macScalePtr->scaleHandle, scalePtr->fromValue);
280         SetControl32BitMaximum(macScalePtr->scaleHandle, scalePtr->toValue);
281     }
282
283     /*
284      * Finally draw the control.
285      */
286
287     SetControlVisibility(macScalePtr->scaleHandle, true, true);
288     HiliteControl(macScalePtr->scaleHandle, 0);
289     Draw1Control(macScalePtr->scaleHandle);
290 done:
291     scalePtr->flags &= ~REDRAW_ALL;
292 }
293 \f
294 /*
295  *----------------------------------------------------------------------
296  *
297  * TkpScaleElement --
298  *
299  *      Determine which part of a scale widget lies under a given point.
300  *
301  * Results:
302  *      The return value is either TROUGH1, SLIDER, TROUGH2, or OTHER,
303  *      depending on which of the scale's active elements (if any) is under the
304  *      point at (x,y).
305  *
306  * Side effects:
307  *      None.
308  *
309  *----------------------------------------------------------------------
310  */
311
312 int
313 TkpScaleElement(
314     TkScale *scalePtr,          /* Widget record for scale. */
315     int x, int y)               /* Coordinates within scalePtr's window. */
316 {
317     MacScale *macScalePtr = (MacScale *) scalePtr;
318     ControlPartCode part;
319     Point where;
320     Rect bounds;
321
322 #ifdef TK_MAC_DEBUG_SCALE
323     TkMacOSXDbgMsg("TkpScaleElement");
324 #endif
325
326     /*
327      * All of the calculations in this procedure mirror those in
328      * DisplayScrollbar. Be sure to keep the two consistent.
329      */
330
331     TkMacOSXWinBounds((TkWindow *) scalePtr->tkwin, &bounds);
332     where.h = x + bounds.left;
333     where.v = y + bounds.top;
334     part = TestControl(macScalePtr->scaleHandle, where);
335
336 #ifdef TK_MAC_DEBUG_SCALE
337     fprintf (stderr,"ScalePart %d, pos ( %d %d )\n", part, where.h, where.v );
338 #endif
339
340     switch (part) {
341     case inSlider:
342         return SLIDER;
343     case inInc:
344         if (scalePtr->orient == ORIENT_VERTICAL) {
345             return TROUGH1;
346         } else {
347             return TROUGH2;
348         }
349     case inDecr:
350         if (scalePtr->orient == ORIENT_VERTICAL) {
351             return TROUGH2;
352         } else {
353             return TROUGH1;
354         }
355     default:
356         return OTHER;
357     }
358 }
359 \f
360 /*
361  *--------------------------------------------------------------
362  *
363  * MacScaleEventProc --
364  *
365  *      This procedure is invoked by the Tk dispatcher for ButtonPress events
366  *      on scales.
367  *
368  * Results:
369  *      None.
370  *
371  * Side effects:
372  *      When the window gets deleted, internal structures get cleaned up. When
373  *      it gets exposed, it is redisplayed.
374  *
375  *--------------------------------------------------------------
376  */
377
378 static void
379 MacScaleEventProc(
380     ClientData clientData,      /* Information about window. */
381     XEvent *eventPtr)           /* Information about event. */
382 {
383     MacScale *macScalePtr = (MacScale *) clientData;
384     Point where;
385     Rect bounds;
386     int part;
387
388 #ifdef TK_MAC_DEBUG_SCALE
389     fprintf(stderr,"MacScaleEventProc\n" );
390 #endif
391
392     TkMacOSXWinBounds((TkWindow *) macScalePtr->info.tkwin, &bounds);
393     where.h = eventPtr->xbutton.x + bounds.left;
394     where.v = eventPtr->xbutton.y + bounds.top;
395 #ifdef TK_MAC_DEBUG_SCALE
396     TkMacOSXDbgMsg("calling TestControl");
397 #endif
398     part = TestControl(macScalePtr->scaleHandle, where);
399     if (part == 0) {
400         return;
401     }
402
403     TkMacOSXTrackingLoop(1);
404     part = HandleControlClick(macScalePtr->scaleHandle, where,
405             TkMacOSXModifierState(), scaleActionProc);
406     TkMacOSXTrackingLoop(0);
407
408     /*
409      * Update the value for the widget.
410      */
411
412     macScalePtr->info.value = GetControlValue(macScalePtr->scaleHandle);
413     /* TkScaleSetValue(&macScalePtr->info, macScalePtr->info.value, 1, 0); */
414
415     /*
416      * The HandleControlClick call will "eat" the ButtonUp event. We now
417      * generate a ButtonUp event so Tk will unset implicit grabs etc.
418      */
419
420     TkGenerateButtonEventForXPointer(Tk_WindowId(macScalePtr->info.tkwin));
421 }
422 \f
423 /*
424  *--------------------------------------------------------------
425  *
426  * ScaleActionProc --
427  *
428  *      Callback procedure used by the Macintosh toolbox call
429  *      HandleControlClick. This call will update the display while the
430  *      scrollbar is being manipulated by the user.
431  *
432  * Results:
433  *      None.
434  *
435  * Side effects:
436  *      May change the display.
437  *
438  *--------------------------------------------------------------
439  */
440
441 static pascal void
442 ScaleActionProc(
443     ControlRef theControl,      /* Handle to scrollbat control */
444     ControlPartCode partCode)   /* Part of scrollbar that was "hit" */
445 {
446     int value;
447     TkScale *scalePtr = (TkScale *) GetControlReference(theControl);
448
449 #ifdef TK_MAC_DEBUG_SCALE
450     TkMacOSXDbgMsg("ScaleActionProc");
451 #endif
452     value = GetControlValue(theControl);
453     TkScaleSetValue(scalePtr, value, 1, 1);
454     Tcl_Preserve(scalePtr);
455     TkMacOSXRunTclEventLoop();
456     Tcl_Release(scalePtr);
457 }
458 #endif
459 \f
460 /*
461  * Local Variables:
462  * mode: objc
463  * c-basic-offset: 4
464  * fill-column: 79
465  * coding: utf-8
466  * End:
467  */