tkMacOSXScale.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:12k
源码类别:

通讯编程

开发平台:

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