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

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * tkMacScale.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.  *
  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: tkMacScale.c,v 1.7 2000/04/19 09:25:54 hobbs Exp $
  14.  */
  15. #include "tkScale.h"
  16. #include "tkInt.h"
  17. #include <Controls.h>
  18. #include "tkMacInt.h"
  19. /*
  20.  * Defines used in this file.
  21.  */
  22. #define slider 1110
  23. #define inSlider 1
  24. #define inInc 2
  25. #define inDecr 3
  26. /*
  27.  * Declaration of Macintosh specific scale structure.
  28.  */
  29. typedef struct MacScale {
  30.     TkScale info; /* Generic scale info. */
  31.     int flags; /* Flags. */
  32.     ControlRef scaleHandle; /* Handle to the Scale control struct. */
  33. } MacScale;
  34. /*
  35.  * Globals uses locally in this file.
  36.  */
  37. static ControlActionUPP scaleActionProc = NULL; /* Pointer to func. */
  38. /*
  39.  * Forward declarations for procedures defined later in this file:
  40.  */
  41. static void MacScaleEventProc _ANSI_ARGS_((ClientData clientData,
  42.     XEvent *eventPtr));
  43. static pascal void ScaleActionProc _ANSI_ARGS_((ControlRef theControl,
  44.     ControlPartCode partCode));
  45. /*
  46.  *----------------------------------------------------------------------
  47.  *
  48.  * TkpCreateScale --
  49.  *
  50.  * Allocate a new TkScale structure.
  51.  *
  52.  * Results:
  53.  * Returns a newly allocated TkScale structure.
  54.  *
  55.  * Side effects:
  56.  * None.
  57.  *
  58.  *----------------------------------------------------------------------
  59.  */
  60. TkScale *
  61. TkpCreateScale(tkwin)
  62.     Tk_Window tkwin;
  63. {
  64.     MacScale *macScalePtr;;
  65.     
  66.     macScalePtr = (MacScale *) ckalloc(sizeof(MacScale));
  67.     macScalePtr->scaleHandle = NULL;
  68.     if (scaleActionProc == NULL) {
  69. scaleActionProc = NewControlActionProc(ScaleActionProc);
  70.     }
  71.     
  72.     Tk_CreateEventHandler(tkwin, ButtonPressMask,
  73.     MacScaleEventProc, (ClientData) macScalePtr);
  74.     
  75.     return (TkScale *) macScalePtr;
  76. }
  77. /*
  78.  *----------------------------------------------------------------------
  79.  *
  80.  * TkpDestroyScale --
  81.  *
  82.  * Free Macintosh specific resources.
  83.  *
  84.  * Results:
  85.  * None
  86.  *
  87.  * Side effects:
  88.  * The slider control is destroyed.
  89.  *
  90.  *----------------------------------------------------------------------
  91.  */
  92. void
  93. TkpDestroyScale(scalePtr)
  94.     TkScale *scalePtr;
  95. {
  96.     MacScale *macScalePtr = (MacScale *) scalePtr;
  97.     
  98.     /*
  99.      * Free Macintosh control.
  100.      */
  101.     if (macScalePtr->scaleHandle != NULL) {
  102.         DisposeControl(macScalePtr->scaleHandle);
  103.     }
  104. }
  105. /*
  106.  *----------------------------------------------------------------------
  107.  *
  108.  * TkpDisplayScale --
  109.  *
  110.  * This procedure is invoked as an idle handler to redisplay
  111.  * the contents of a scale widget.
  112.  *
  113.  * Results:
  114.  * None.
  115.  *
  116.  * Side effects:
  117.  * The scale gets redisplayed.
  118.  *
  119.  *----------------------------------------------------------------------
  120.  */
  121. void
  122. TkpDisplayScale(clientData)
  123.     ClientData clientData; /* Widget record for scale. */
  124. {
  125.     TkScale *scalePtr = (TkScale *) clientData;
  126.     Tk_Window tkwin = scalePtr->tkwin;
  127.     Tcl_Interp *interp = scalePtr->interp;
  128.     int result;
  129.     char string[PRINT_CHARS];
  130.     MacScale *macScalePtr = (MacScale *) clientData;
  131.     Rect r;
  132.     WindowRef windowRef;
  133.     GWorldPtr destPort;        
  134.     CGrafPtr saveWorld;
  135.     GDHandle saveDevice;
  136.     MacDrawable *macDraw;
  137.     scalePtr->flags &= ~REDRAW_PENDING;
  138.     if ((scalePtr->tkwin == NULL) || !Tk_IsMapped(scalePtr->tkwin)) {
  139. goto done;
  140.     }
  141.     /*
  142.      * Invoke the scale's command if needed.
  143.      */
  144.     Tcl_Preserve((ClientData) scalePtr);
  145.     if ((scalePtr->flags & INVOKE_COMMAND) && (scalePtr->command != NULL)) {
  146. Tcl_Preserve((ClientData) interp);
  147. sprintf(string, scalePtr->format, scalePtr->value);
  148. result = Tcl_VarEval(interp, scalePtr->command, " ", string,
  149. (char *) NULL);
  150. if (result != TCL_OK) {
  151.     Tcl_AddErrorInfo(interp, "n    (command executed by scale)");
  152.     Tcl_BackgroundError(interp);
  153. }
  154. Tcl_Release((ClientData) interp);
  155.     }
  156.     scalePtr->flags &= ~INVOKE_COMMAND;
  157.     if (scalePtr->flags & SCALE_DELETED) {
  158. Tcl_Release((ClientData) scalePtr);
  159. return;
  160.     }
  161.     Tcl_Release((ClientData) scalePtr);
  162.     /*
  163.      * Now handle the part of redisplay that is the same for
  164.      * horizontal and vertical scales:  border and traversal
  165.      * highlight.
  166.      */
  167.     if (scalePtr->highlightWidth != 0) {
  168. GC gc;
  169.     
  170. gc = Tk_GCForColor(scalePtr->highlightColorPtr, Tk_WindowId(tkwin));
  171. Tk_DrawFocusHighlight(tkwin, gc, scalePtr->highlightWidth,
  172. Tk_WindowId(tkwin));
  173.     }
  174.     Tk_Draw3DRectangle(tkwin, Tk_WindowId(tkwin), scalePtr->bgBorder,
  175.     scalePtr->highlightWidth, scalePtr->highlightWidth,
  176.     Tk_Width(tkwin) - 2*scalePtr->highlightWidth,
  177.     Tk_Height(tkwin) - 2*scalePtr->highlightWidth,
  178.     scalePtr->borderWidth, scalePtr->relief);
  179.     /*
  180.      * Set up port for drawing Macintosh control.
  181.      */
  182.     macDraw = (MacDrawable *) Tk_WindowId(tkwin);
  183.     destPort = TkMacGetDrawablePort(Tk_WindowId(tkwin));
  184.     GetGWorld(&saveWorld, &saveDevice);
  185.     SetGWorld(destPort, NULL);
  186.     TkMacSetUpClippingRgn(Tk_WindowId(tkwin));
  187.     /*
  188.      * Create Macintosh control.
  189.      */
  190.     if (macScalePtr->scaleHandle == NULL) {
  191.         r.left = r.top = 0;
  192.         r.right = r.bottom = 1;
  193.         /* TODO: initial value. */
  194.         /* 16*slider+4 */
  195. macScalePtr->scaleHandle = NewControl((WindowRef) destPort, 
  196. &r, "p", false, (short) 35, 0, 1000,
  197. 16*slider, (SInt32) macScalePtr);
  198. /*
  199.  * If we are foremost than make us active.
  200.  */
  201. if ((WindowPtr) destPort == FrontWindow()) {
  202.     macScalePtr->flags |= ACTIVE;
  203. }
  204.     }
  205.     windowRef  = (**macScalePtr->scaleHandle).contrlOwner;
  206.     /*
  207.      * We can't use the Macintosh commands SizeControl and MoveControl as these
  208.      * calls will also cause a redraw which in our case will also cause
  209.      * flicker.  To avoid this we adjust the control record directly.  The
  210.      * Draw1Control command appears to just draw where ever the control says to
  211.      * draw so this seems right.
  212.      *
  213.      * NOTE: changing the control record directly may not work when
  214.      * Apple releases the Copland version of the MacOS in late 1996.
  215.      */
  216.     (**macScalePtr->scaleHandle).contrlRect.left   = macDraw->xOff
  217. + scalePtr->inset;
  218.     (**macScalePtr->scaleHandle).contrlRect.top    = macDraw->yOff
  219. + scalePtr->inset;
  220.     (**macScalePtr->scaleHandle).contrlRect.right  = macDraw->xOff
  221. + Tk_Width(tkwin) - scalePtr->inset;
  222.     (**macScalePtr->scaleHandle).contrlRect.bottom = macDraw->yOff
  223. + Tk_Height(tkwin) - scalePtr->inset;
  224.     /*
  225.      * Set the thumb and resolution etc.
  226.      */
  227.     (**macScalePtr->scaleHandle).contrlMin = (SInt16) scalePtr->toValue;
  228.     (**macScalePtr->scaleHandle).contrlMax = (SInt16) scalePtr->fromValue;
  229.     (**macScalePtr->scaleHandle).contrlValue = (SInt16) scalePtr->value;
  230.     /*
  231.      * Finally draw the control.
  232.      */
  233.     (**macScalePtr->scaleHandle).contrlVis = 255;
  234.     (**macScalePtr->scaleHandle).contrlHilite = 0;
  235.     Draw1Control(macScalePtr->scaleHandle);
  236.     SetGWorld(saveWorld, saveDevice);
  237.     done:
  238.     scalePtr->flags &= ~REDRAW_ALL;
  239. }
  240. /*
  241.  *----------------------------------------------------------------------
  242.  *
  243.  * TkpScaleElement --
  244.  *
  245.  * Determine which part of a scale widget lies under a given
  246.  * point.
  247.  *
  248.  * Results:
  249.  * The return value is either TROUGH1, SLIDER, TROUGH2, or
  250.  * OTHER, depending on which of the scale's active elements
  251.  * (if any) is under the point at (x,y).
  252.  *
  253.  * Side effects:
  254.  * None.
  255.  *
  256.  *----------------------------------------------------------------------
  257.  */
  258. int
  259. TkpScaleElement(scalePtr, x, y)
  260.     TkScale *scalePtr; /* Widget record for scale. */
  261.     int x, y; /* Coordinates within scalePtr's window. */
  262. {
  263.     MacScale *macScalePtr = (MacScale *) scalePtr;
  264.     ControlPartCode part;
  265.     Point where;
  266.     Rect bounds;
  267.     CGrafPtr saveWorld;
  268.     GDHandle saveDevice;
  269.     GWorldPtr destPort;        
  270.     destPort = TkMacGetDrawablePort(Tk_WindowId(scalePtr->tkwin));
  271.     GetGWorld(&saveWorld, &saveDevice);
  272.     SetGWorld(destPort, NULL);
  273.     /*
  274.      * All of the calculations in this procedure mirror those in
  275.      * DisplayScrollbar.  Be sure to keep the two consistent.
  276.      */
  277.     TkMacWinBounds((TkWindow *) scalePtr->tkwin, &bounds);
  278.     where.h = x + bounds.left;
  279.     where.v = y + bounds.top;
  280.     part = TestControl(macScalePtr->scaleHandle, where);
  281.     
  282.     SetGWorld(saveWorld, saveDevice);
  283.     
  284.     switch (part) {
  285.      case inSlider:
  286.     return SLIDER;
  287.      case inInc:
  288.     if (scalePtr->orient == ORIENT_VERTICAL) {
  289. return TROUGH1;
  290.     } else {
  291. return TROUGH2;
  292.     }
  293.      case inDecr:
  294.     if (scalePtr->orient == ORIENT_VERTICAL) {
  295. return TROUGH2;
  296.     } else {
  297. return TROUGH1;
  298.     }
  299.      default:
  300.     return OTHER;
  301.     }
  302. }
  303. /*
  304.  *--------------------------------------------------------------
  305.  *
  306.  * MacScaleEventProc --
  307.  *
  308.  * This procedure is invoked by the Tk dispatcher for 
  309.  * ButtonPress events on scales.
  310.  *
  311.  * Results:
  312.  * None.
  313.  *
  314.  * Side effects:
  315.  * When the window gets deleted, internal structures get
  316.  * cleaned up.  When it gets exposed, it is redisplayed.
  317.  *
  318.  *--------------------------------------------------------------
  319.  */
  320. static void
  321. MacScaleEventProc(clientData, eventPtr)
  322.     ClientData clientData; /* Information about window. */
  323.     XEvent *eventPtr; /* Information about event. */
  324. {
  325.     MacScale *macScalePtr = (MacScale *) clientData;
  326.     Point where;
  327.     Rect bounds;
  328.     int part, x, y, dummy;
  329.     unsigned int state;
  330.     CGrafPtr saveWorld;
  331.     GDHandle saveDevice;
  332.     GWorldPtr destPort;
  333.     Window dummyWin;
  334.     /*
  335.      * To call Macintosh control routines we must have the port
  336.      * set to the window containing the control.  We will then test
  337.      * which part of the control was hit and act accordingly.
  338.      */
  339.     destPort = TkMacGetDrawablePort(Tk_WindowId(macScalePtr->info.tkwin));
  340.     GetGWorld(&saveWorld, &saveDevice);
  341.     SetGWorld(destPort, NULL);
  342.     TkMacSetUpClippingRgn(Tk_WindowId(macScalePtr->info.tkwin));
  343.     TkMacWinBounds((TkWindow *) macScalePtr->info.tkwin, &bounds);
  344.     where.h = eventPtr->xbutton.x + bounds.left;
  345.     where.v = eventPtr->xbutton.y + bounds.top;
  346.     part = TestControl(macScalePtr->scaleHandle, where);
  347.     if (part == 0) {
  348. return;
  349.     }
  350.     
  351.     part = TrackControl(macScalePtr->scaleHandle, where, scaleActionProc);
  352.     
  353.     /*
  354.      * Update the value for the widget.
  355.      */
  356.     macScalePtr->info.value = (**macScalePtr->scaleHandle).contrlValue;
  357.     /* TkScaleSetValue(&macScalePtr->info, macScalePtr->info.value, 1, 0); */
  358.     /*
  359.      * The TrackControl call will "eat" the ButtonUp event.  We now
  360.      * generate a ButtonUp event so Tk will unset implicit grabs etc.
  361.      */
  362.     GetMouse(&where);
  363.     XQueryPointer(NULL, None, &dummyWin, &dummyWin, &x,
  364. &y, &dummy, &dummy, &state);
  365.     TkGenerateButtonEvent(x, y, Tk_WindowId(macScalePtr->info.tkwin), state);
  366.     SetGWorld(saveWorld, saveDevice);
  367. }
  368. /*
  369.  *--------------------------------------------------------------
  370.  *
  371.  * ScaleActionProc --
  372.  *
  373.  * Callback procedure used by the Macintosh toolbox call
  374.  * TrackControl.  This call will update the display while
  375.  * the scrollbar is being manipulated by the user.
  376.  *
  377.  * Results:
  378.  * None.
  379.  *
  380.  * Side effects:
  381.  * May change the display.
  382.  *
  383.  *--------------------------------------------------------------
  384.  */
  385. static pascal void
  386. ScaleActionProc(ControlRef theControl, ControlPartCode partCode)
  387.     /* ControlRef theControl; /* Handle to scrollbat control */
  388.     /* ControlPartCode partCode; /* Part of scrollbar that was "hit" */
  389. {
  390.     register int value;
  391.     register TkScale *scalePtr = (TkScale *) GetCRefCon(theControl);
  392.     value = (**theControl).contrlValue;
  393.     TkScaleSetValue(scalePtr, value, 1, 1);
  394.     Tcl_Preserve((ClientData) scalePtr);
  395.     Tcl_DoOneEvent(TCL_IDLE_EVENTS);
  396.     Tcl_Release((ClientData) scalePtr);
  397. }