home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Code Resources / ColourBlock CDEF 1.1.1 / ColourBlock.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-05  |  13.8 KB  |  638 lines  |  [TEXT/CWIE]

  1. /*    NAME:
  2.         ColourBlock.c
  3.  
  4.     WRITTEN BY:
  5.         Dair Grant
  6.         dair@kagi.com
  7.                 
  8.     DESCRIPTION:
  9.         A CDEF for getting a colour value from the user.
  10.  
  11.     ___________________________________________________________________________
  12.  
  13.     VERSION HISTORY:
  14.         1.1.1: updated for CW7 on 951215
  15.  
  16.         1.1: (May 1995, dg)
  17.             •    Ported to Metrowerks - for 68K, PPC, and Fat versions.
  18.  
  19.             •    Changed flag passed to DeviceLoop from allDevices to 0. Stopped
  20.                 bug whereby pen was messed up if CDEF drew first on a BW display
  21.                 and then on a colour one.
  22.  
  23.  
  24.         1.0: (Jan 1994, dg)
  25.             •    First public release.
  26.  
  27.     ___________________________________________________________________________
  28. */
  29. //=============================================================================
  30. //        Include files                                                                     
  31. //-----------------------------------------------------------------------------
  32. #include <QuickDraw.h>
  33. #include "A4Stuff.h"
  34. #include "SetupA4.h"
  35. #include "ColourBlock.h"
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50.  
  51. //=============================================================================
  52. //        Private defines                                                             
  53. //-----------------------------------------------------------------------------
  54. #define kBlockWidth            21                                // Width of colour block
  55. #define kBlockHeight        12                                // Height of colour block
  56. #define kTitleOffset        4                                // Offset of title
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72. //=============================================================================
  73. //        Private function prototypes                                                                     
  74. //-----------------------------------------------------------------------------
  75. pascal long main(short theVarCode, ControlHandle theCntl, short theMsg, long theParam);
  76.  
  77. void        InitialiseMyControl(void);
  78. void        DisposeMyControl(void);
  79. long        TestMyControl(void);
  80. void        DrawMyControl(void);
  81. pascal void    DeviceLoopRoutine(short theDepth, short theFlags, GDHandle theDevice,
  82.                               Handle theHnd);
  83. RgnHandle    CalculateMyRegion(void);
  84. long        TrackMyControl(void);
  85.  
  86.  
  87.  
  88.  
  89.  
  90.  
  91.  
  92.  
  93.  
  94.  
  95.  
  96.  
  97.  
  98.  
  99.  
  100. //=============================================================================
  101. //        Global variables                                                                 
  102. //-----------------------------------------------------------------------------
  103. Boolean            gHasBeenCalled=false;                // Has the CDEF been called before?
  104. RGBColor        gFrameColour;                        // Colour of the control frame
  105. RGBColor        gTextColour;                        // Colour of the control text
  106. RGBColor        gBodyColour;                        // Fill colour for the control
  107. Rect            gTheColourRect;                        // Rectangle for the colour block
  108. Point            gTheTitlePt;                        // Point to draw the title on
  109.     
  110. short            gTheVarCode;                        // The varCode paramater
  111. ControlHandle    gTheCntl;                            // The theCntl paramater
  112. short            gTheMsg;                            // The theMsg paramater
  113. long            gTheParam;                            // The theParam paramater
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123.  
  124.  
  125.  
  126.  
  127.  
  128.  
  129. //=============================================================================
  130. //        main : Entry point for the WDEF definition.
  131. //-----------------------------------------------------------------------------
  132. //        Note :    Basically we case out on theMsg and let other routines do the
  133. //                work.
  134. //-----------------------------------------------------------------------------
  135. pascal long main(short theVarCode, ControlHandle theCntl, short theMsg, long theParam)
  136. {    long        retVal = 0L;
  137.     long        oldA4;
  138.  
  139.  
  140.  
  141.     // Set up A4 if we need to so we can access our globals
  142. #ifndef powerc
  143.     oldA4 = SetCurrentA4();
  144.     RememberA4();
  145. #endif
  146.  
  147.     
  148.  
  149.     // Store the paramaters in globals for speed
  150.     gTheVarCode        = theVarCode;
  151.     gTheCntl        = theCntl;
  152.     gTheMsg            = theMsg;
  153.     gTheParam        = theParam;
  154.     
  155.     
  156.     // Case out on what we're meant to be doing
  157.     switch (theMsg) {
  158.         case initCntl:                    // Initialise our private data for this control
  159.             InitialiseMyControl();
  160.             break;
  161.         
  162.  
  163.         case dispCntl:                    // Dispose of our private data for this control
  164.             DisposeMyControl();
  165.             break;
  166.  
  167.  
  168.         case testCntl:                    // Test mouse to see if in control
  169.             retVal = TestMyControl();
  170.             break;
  171.         
  172.         
  173.         case drawCntl:                    // Draw the correct part of this control
  174.             DrawMyControl();
  175.             break;
  176.         
  177.         
  178.         case calcCRgns:                    // Calculate the draw region of this control
  179.         case calcCntlRgn:
  180.         case calcThumbRgn:
  181.             retVal = (long) CalculateMyRegion();
  182.             break;
  183.         
  184.         
  185.         case autoTrack:                    // Ignored messages
  186.         case posCntl:    
  187.         case thumbCntl:
  188.         case dragCntl:
  189.             break;
  190.         
  191.  
  192.         default:                        // Anything else
  193.             break;
  194.     }
  195.     
  196.  
  197.  
  198.  
  199.     // Restore A4 for our caller (if we need to) and return the result
  200. #ifndef powerc
  201.     SetA4(oldA4);
  202. #endif
  203.     return(retVal);
  204. }
  205.  
  206.  
  207.  
  208.  
  209.  
  210.  
  211.  
  212.  
  213.  
  214.  
  215.  
  216.  
  217.  
  218.  
  219.  
  220. //=============================================================================
  221. //        InitialiseMyControl : Create a new instance of the control.
  222. //-----------------------------------------------------------------------------
  223. //        Note :    Allocate some private data and initialise a few variables,
  224. //                including auxillary colour.
  225. //-----------------------------------------------------------------------------
  226. void InitialiseMyControl(void)
  227. {    CDEFStructHnd    theCDEFDataHnd;
  228.     CDEFStructPtr    theCDEFDataPtr;
  229.     AuxCtlHandle    theAuxHnd;
  230.     CCTabHandle        theTableHnd;
  231.     
  232.     
  233.     
  234.     
  235.     
  236.     // If this is the first control this CDEF has created,
  237.     // we initialise some shared variables.
  238.     if (!gHasBeenCalled)
  239.         {
  240.         // We assume we have colour QuickDraw, and try and get the System colours
  241.         GetAuxCtl(gTheCntl, &theAuxHnd);
  242.         if (theAuxHnd)
  243.             {
  244.             // Lock the handle and dereference.
  245.             HLock((Handle) theAuxHnd);
  246.             theTableHnd = (*theAuxHnd)->acCTable;
  247.             
  248.             
  249.             // Copy the right colours
  250.             gFrameColour    = (*theTableHnd)->ctTable[cFrameColor].rgb; 
  251.             gTextColour        = (*theTableHnd)->ctTable[cTextColor].rgb;
  252.             gBodyColour        = (*theTableHnd)->ctTable[cBodyColor].rgb;
  253.             
  254.             
  255.             // Unlock the handle
  256.             HUnlock((Handle) theAuxHnd);
  257.             }
  258.         
  259.         
  260.         // If we couldn't get the colour table, we use some hardwired defaults
  261.         else
  262.             {
  263.             PackRGB(gFrameColour,    0x0000, 0x0000, 0x0000);
  264.             PackRGB(gTextColour,    0x0000, 0x0000, 0x0000);
  265.             PackRGB(gBodyColour,    0xFFFF, 0xFFFF, 0xFFFF);
  266.             }
  267.         
  268.         
  269.         // None of the above code needs to be done again
  270.         gHasBeenCalled = true;
  271.         }
  272.  
  273.  
  274.  
  275.     // Create some space for the control's data and initialise it.
  276.     theCDEFDataHnd = (CDEFStructHnd) NewHandle(sizeof(CDEFStruct));
  277.     if (theCDEFDataHnd)
  278.         {
  279.         // Start off white
  280.         PackRGB((*theCDEFDataHnd)->blockColour, 0xFFFF, 0xFFFF, 0xFFFF);
  281.         }
  282.  
  283.  
  284.     // Copy the handle into the control
  285.     (*gTheCntl)->contrlData = (Handle) theCDEFDataHnd;
  286. }
  287.  
  288.  
  289.  
  290.  
  291.  
  292.  
  293.  
  294.  
  295.  
  296.  
  297.  
  298.  
  299.  
  300.  
  301.  
  302. //=============================================================================
  303. //        DisposeMyControl : Dispose of an instance of the control.
  304. //-----------------------------------------------------------------------------
  305. void DisposeMyControl(void)
  306. {
  307.  
  308.  
  309.     // If the control has a private data structure, dispose of it
  310.     if ((*gTheCntl)->contrlData)
  311.         DisposeHandle((*gTheCntl)->contrlData);
  312. }
  313.  
  314.  
  315.  
  316.  
  317.  
  318.  
  319.  
  320.  
  321.  
  322.  
  323.  
  324.  
  325.  
  326.  
  327.  
  328. //=============================================================================
  329. //        TestMyControl : Return the part code for a point.
  330. //-----------------------------------------------------------------------------
  331. //        Note :    This routine is used when a mousedown has occurred or a track
  332. //                is underway. We have to decide if a point is within our
  333. //                boundaries.
  334. //-----------------------------------------------------------------------------
  335. long TestMyControl(void)
  336. {    Point            testPoint;
  337.     long            retVal=0;
  338.     
  339.     
  340.     
  341.     // We only test if we're enabled
  342.     if ((*gTheCntl)->contrlHilite < 255)
  343.         {
  344.         // Convert the two coordinates to a point
  345.         testPoint.h = LoWord(gTheParam);
  346.         testPoint.v = HiWord(gTheParam);
  347.  
  348.     
  349.         // Return inCheckBox if it's in our control at all
  350.         if (PtInRect(testPoint, &(*gTheCntl)->contrlRect))
  351.             retVal = inCheckBox;
  352.         }
  353.  
  354.     
  355.     // Return the result
  356.     return(retVal);
  357. }
  358.  
  359.  
  360.  
  361.  
  362.  
  363.  
  364.  
  365.  
  366.  
  367.  
  368.  
  369.  
  370.  
  371.  
  372.  
  373. //=============================================================================
  374. //        DrawMyControl : Draw a part of a control.
  375. //-----------------------------------------------------------------------------
  376. //        Note :    We use DeviceLoop to call the actual drawing routine.
  377. //-----------------------------------------------------------------------------
  378. void DrawMyControl(void)
  379. {    short            center;
  380.     RGBColor        saveForeColour;
  381.     FontInfo        theFontInfo;
  382.  
  383.  
  384.  
  385.  
  386.     // Quick (and lazy) test to see if we've to do anything
  387.     if (!(*gTheCntl)->contrlVis)
  388.         return;
  389.         
  390.         
  391.     // Zap the high word of gTheParam
  392.     gTheParam = LoWord(gTheParam);
  393.     
  394.     
  395.     // The colour block is put on the left side of the control rectangle...
  396.     gTheColourRect            = (*gTheCntl)->contrlRect;
  397.     gTheColourRect.right    = gTheColourRect.left + kBlockWidth;
  398.     
  399.     // And centered vertically inside it...
  400.     center        = gTheColourRect.top + ((gTheColourRect.bottom - gTheColourRect.top) >> 1);
  401.     gTheColourRect.top        = center - (kBlockHeight >> 1);
  402.     gTheColourRect.bottom    = gTheColourRect.top + kBlockHeight;
  403.     
  404.  
  405.  
  406.     // The title is placed next to the colour block...
  407.     gTheTitlePt.h = gTheColourRect.right + kTitleOffset;
  408.  
  409.     // And centered vertically for the font size...    we have the center of
  410.     // the colour block, and we want to center the title on that.
  411.     GetFontInfo(&theFontInfo);
  412.     gTheTitlePt.v    = center + (theFontInfo.ascent >> 1) - 1;
  413.     
  414.  
  415.  
  416.     // Save the foreground colour
  417.     GetForeColor(&saveForeColour);
  418.  
  419.  
  420.     // Call the DeviceLoopRoutine with DeviceLoop to do the actual drawing.
  421.     DeviceLoop((*gTheCntl)->contrlOwner->visRgn,
  422.                (DeviceLoopDrawingProcPtr) DeviceLoopRoutine, 0, 0);
  423.  
  424.  
  425.     // Restore the foreground colour
  426.     RGBForeColor(&saveForeColour);
  427. }
  428.  
  429.  
  430.  
  431.  
  432.  
  433.  
  434.  
  435.  
  436.  
  437.  
  438.  
  439.  
  440.  
  441.  
  442.  
  443. //=============================================================================
  444. //        DeviceLoopRoutine : Called by DeviceLoop to do the drawing.
  445. //-----------------------------------------------------------------------------
  446. //        Note :    If we're disabled, we draw ourselves in a real gray if the
  447. //                device is deep enough, and a dithered gray otherwise.
  448. //-----------------------------------------------------------------------------
  449. pascal void DeviceLoopRoutine(short theDepth, short theFlags, GDHandle theDevice,
  450.                               Handle theHnd)
  451. {    RGBColor        blockColour, titleColour;
  452.     Rect            theColourRect;
  453.     CDEFStructHnd    theCDEFDataHnd;
  454.     Boolean            ditherText=false;
  455.     long            oldA4;
  456.  
  457.  
  458.  
  459.     // Get access to our globals again
  460. #ifndef powerc
  461.     oldA4 = SetUpA4();
  462. #endif
  463.  
  464.  
  465.     // Draw what we're to draw
  466.     switch (gTheParam) {
  467.         case inCheckBox:                    // Draw/remove a selection from the block
  468.             // Set the draw colour
  469.             if ((*gTheCntl)->contrlHilite)
  470.                 RGBForeColor(&gFrameColour);
  471.             else
  472.                 RGBForeColor(&gBodyColour);
  473.  
  474.  
  475.             // Draw the selection rectangle
  476.             theColourRect = gTheColourRect;
  477.             InsetRect(&theColourRect, 1, 1);
  478.             FrameRect(&theColourRect);
  479.             break;
  480.         
  481.         
  482.         case 255:                            // Change in dimming
  483.         case 0:                                // Draw the entire control
  484.             // Draw the frame
  485.             theColourRect = gTheColourRect;
  486.             RGBForeColor(&gFrameColour);
  487.             FrameRect(&theColourRect);
  488.  
  489.  
  490.             // Draw the selection rectangle
  491.             RGBForeColor(&gBodyColour);
  492.             InsetRect(&theColourRect, 1, 1);
  493.             FrameRect(&theColourRect);
  494.  
  495.  
  496.             // The interior of the colour block and the title are
  497.             // coloured white and grey if the control is disabled.
  498.             // If we're on a mono display, we will dither the
  499.             // text if it's disabled.
  500.             if ((*gTheCntl)->contrlHilite == 255)
  501.                 {
  502.                 blockColour = gBodyColour;
  503.                 PackRGB(titleColour, 0x8000, 0x8000, 0x8000);
  504.                 
  505.                 if (theDepth == 1)
  506.                     ditherText = true;
  507.                 }
  508.             
  509.             
  510.             // Otherwise we use the normal colours.
  511.             else
  512.                 {
  513.                 theCDEFDataHnd    = (CDEFStructHnd) ((*gTheCntl)->contrlData);
  514.                 blockColour        = (*theCDEFDataHnd)->blockColour;
  515.                 titleColour        = gFrameColour;
  516.                 }
  517.                 
  518.             
  519.             // Draw the interior of the colour block
  520.             RGBForeColor(&blockColour);
  521.             InsetRect(&theColourRect, 1, 1);
  522.             PaintRect(&theColourRect);
  523.                         
  524.             
  525.             // Draw the title - switching to dithered text if in mono
  526.             RGBForeColor(&titleColour);
  527.             MoveTo(gTheTitlePt.h, gTheTitlePt.v);
  528.             if (ditherText)
  529.                 TextMode(grayishTextOr);
  530.             DrawString((*gTheCntl)->contrlTitle);
  531.             if (ditherText)
  532.                 TextMode(srcOr);
  533.             break;
  534.     }
  535.  
  536.  
  537.     // Restore A4 for our caller (if we need to)
  538. #ifndef powerc
  539.     RestoreA4(oldA4);
  540. #endif
  541. }
  542.  
  543.  
  544.  
  545.  
  546.  
  547.  
  548.  
  549.  
  550.  
  551.  
  552.  
  553.  
  554.  
  555.  
  556.  
  557. //=============================================================================
  558. //        CalculateMyRegion : Calculate the control's area region.
  559. //-----------------------------------------------------------------------------
  560. //        Note :    If we're running under 24-bit addressing, gTheMsg will be
  561. //                calcCRgns. Depending on the high bit of gTheParam we're
  562. //                then to calculate either the indicator region (bit is set)
  563. //                or the entire control (bit is not set).
  564. //
  565. //                Under 32-bit mode we can get sent either calcCntlRgn or
  566. //                calcThumbRgn messages.
  567. //
  568. //                We check first for the calcCRgns message, and fudge things
  569. //                so it turns into either a calcCntlRgn or a calcThumbRgn
  570. //                message.
  571. //-----------------------------------------------------------------------------
  572. RgnHandle CalculateMyRegion(void)
  573. {    RgnHandle    theRegion;
  574.     Rect        theRect;
  575.     short        theMsg;
  576.  
  577.  
  578.  
  579.  
  580.     // Cast the param to a RegionHandle
  581.     theRegion = (RgnHandle) gTheParam;
  582.     
  583.     
  584.     // If we're running under 24 bit addressing, find out which message we're
  585.     // meant to be doing.
  586.     if (gTheMsg == calcCRgns)
  587.         {
  588.         // If the high bit is set we're to calculate the indicator
  589.         if (0x80000000L & (long) theRegion)
  590.             theMsg = calcThumbRgn;
  591.             
  592.             
  593.         // Otherwise we're to calculate the entire control
  594.         else
  595.             theMsg = calcCntlRgn;
  596.             
  597.             
  598.         // Mask off the high bit from the region handle
  599.         theRegion = (RgnHandle) (0x7FFFFFFFL & (long) theRegion); 
  600.         }
  601.     else
  602.         theMsg = gTheMsg;
  603.     
  604.     
  605.  
  606.     // theMsg is either calcThumbRgn or calcCntl region, irrespective
  607.     // of 24 or 32 bit addressing. We handle it accordingly
  608.     theRect = (*gTheCntl)->contrlRect;
  609.     if (theMsg == calcThumbRgn)
  610.         {
  611.         // Calculate the indicator region
  612.         theRect = (*gTheCntl)->contrlRect;
  613.         theRect.right = theRect.left + kBlockWidth;
  614.         }
  615.     
  616.     // Calculate the entire control region
  617.     else
  618.         {
  619.         theRect = (*gTheCntl)->contrlRect;
  620.         }
  621.     
  622.     
  623.     
  624.     // Set theRegion to the rectangle
  625.     RectRgn(theRegion, &theRect);
  626.     
  627.     
  628.     
  629.     // See 'Control Manager Q&As' Tech note for why we return 1 if
  630.     // we were called under 32 bit mode.
  631.     if (gTheMsg != calcCRgns)
  632.         theRegion = (RgnHandle) 0x1L;
  633.         
  634.     
  635.     // Return the answer
  636.     return(theRegion);
  637. }
  638.