home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1998 / MacHack 1998.toast / Papers / C++ Exceptions / µShell / Source / SillyBalls.c < prev    next >
Encoding:
Text File  |  1998-06-21  |  8.1 KB  |  357 lines  |  [TEXT/CWIE]

  1. /*------------------------------------------------------------------------------
  2. #
  3. #    Macintosh Developer Technical Support
  4. #
  5. #    Simple Color QuickDraw Sample Application
  6. #
  7. #    SillyBalls
  8. #
  9. #    SillyBalls.c    -    C Source
  10. #
  11. #    Copyright © 1988 Apple Computer, Inc.
  12. #    All rights reserved.
  13. #
  14. #    Versions:    1.0                    8/88
  15. #
  16. #    Components:    SillyBalls.c        August 1, 1988
  17. #                SillyBalls.make        August 1, 1988
  18. #
  19. #    This is a very simple sample program that demonstrates how to use Color 
  20. #    QuickDraw.  It is about two pages of code, and does nothing more than open
  21. #    a color window and draw randomly colored ovals in the window.
  22. #    
  23. #    The purpose is to show how to get some initial results with Color QuickDraw.
  24. #    It is a complete program and is very short to be as clear as possible.
  25. #    
  26. #    It does not have an Event Loop.  It is not fully functional in the sense that
  27. #    it does not do all the things you would expect a well behaved Macintosh 
  28. #    program to do, like size the window naturally, have an event loop, use menus, 
  29. #    etc.
  30. #
  31. #    See Sample and TESample for the general structure and MultiFinder techniques that
  32. #    we recommend that you use when building a new application.
  33. #
  34. ------------------------------------------------------------------------------*/
  35.  
  36.     
  37. //    Version 1.0:    6/2/88
  38. //                    7/20/88     DJB    Converted to C
  39. //    
  40. //    purpose        To demonstrate a simple color App using Color QuickDraw.
  41. //                        It draws colored balls in a color window, then uses colored
  42. //                        text inverted in the ball.  The ball location and color is Random.
  43. //                        
  44. //                        This program was written by Bo3b Johnson, 1/88.
  45. //                        
  46. //                        The inverted Bob text was a Skippy Blair special concept,
  47. //                        kept for obvious aesthetic reasons.
  48. #include "SillyBalls.h"
  49. #include "Exceptions.h"
  50. #include "Main.h"
  51.  
  52. //MW -cut out some other program descriptions.-
  53.  
  54. //MW ** Metrowerks note **
  55. //   All changed code by Metrowerks is commented by "//MW".
  56. //   There is one type of modification to the original source:
  57. //   • Added argument type and return type to function definitions.
  58. //       In order to pass with extended error checking on.
  59. //    
  60. //   8/31/93 JA
  61.  
  62.  
  63. #include <Types.h>
  64. #include <Memory.h>
  65. #include <Quickdraw.h>
  66. #include <Fonts.h>
  67. #include <Events.h>
  68. #include <Menus.h>
  69. #include <Windows.h>
  70. #include <TextEdit.h>
  71. #include <Dialogs.h>
  72. #include <OSUtils.h>
  73. #include <ToolUtils.h>
  74. #include <SegLoad.h>
  75. #include <Sound.h>
  76. #include <AERegistry.h>
  77.  
  78. #include "WindowManager.h"
  79. #include "Toolbox.h"
  80.  
  81. /* Constants */
  82. #define BallWidth        20
  83. #define BallHeight        20
  84. #define BobSize            8        /* Size of text in each ball */
  85.  
  86. /* Globals */
  87. Rect    windRect;
  88.  
  89. ApplicationHeap        gApplicationHeap;
  90. WindowManager        gWindowManager;
  91. Toolbox                gToolbox;
  92. TSillyLoop            xEventLoop;
  93. EventLoop&            gEventLoop(xEventLoop);
  94.  
  95. /* Prototypes */
  96. void Initialize(void);
  97. void NewBall(void);
  98.  
  99. // 
  100. //    Main body of program SillyBalls
  101. //
  102.  
  103. //MW specified argument and return type.
  104.  
  105. /*
  106. void EventLoop(void)
  107. {
  108.     do {
  109.         NewBall();
  110.     } while (!Button());
  111. }
  112. */
  113.  
  114. // 
  115. //    Initialize everything for the program, make sure we can run
  116. //
  117.  
  118.     static pascal OSErr HandleNew(
  119.         const AppleEvent*    theAppleEvent,
  120.         AppleEvent*            reply,
  121.         UInt32                handlerRefcon)
  122.     {
  123.         theAppleEvent; reply; handlerRefcon;
  124.         
  125.         return noErr;
  126.     }
  127.  
  128.     static pascal OSErr HandleQuit(
  129.         const AppleEvent*    theAppleEvent,
  130.         AppleEvent*            reply,
  131.         UInt32                handlerRefcon)
  132.     {
  133.         theAppleEvent; reply; handlerRefcon;
  134.         
  135.         return noErr;
  136.     }
  137.  
  138. //MW specified argument and return type.
  139. void Initialize(void)
  140. {
  141. #if 0
  142.     OSErr        error;
  143.     SysEnvRec    theWorld;
  144.         
  145.     //
  146.     //    Test the computer to be sure we can do color.  
  147.     //    If not we would crash, which would be bad.  
  148.     //    If we can’t run, just beep and exit.
  149.     //
  150.  
  151.     error = SysEnvirons(1, &theWorld);
  152.     if (theWorld.hasColorQD == false) {
  153.         SysBeep(50);
  154.         return; //ExitToShell();                    /* If no color QD, we must leave. */
  155.     }
  156.     
  157.     /* Initialize all the needed managers. */
  158.     InitGraf(&qd.thePort);
  159.     InitFonts();
  160.     InitWindows();
  161.     InitMenus();
  162.     TEInit();
  163.     InitDialogs(nil);
  164.     InitCursor();
  165. #endif
  166.  
  167.     TModule::UseModule(gWindowManager);
  168.     TModule::UseModule(gToolbox);
  169.     TModule::UseModule(gEventLoop);
  170.  
  171.     //
  172.     //    To make the Random sequences truly random, we need to make the seed start
  173.     //    at a different number.  An easy way to do this is to put the current time
  174.     //    and date into the seed.  Since it is always incrementing the starting seed
  175.     //    will always be different.  Don’t for each call of Random, or the sequence
  176.     //    will no longer be random.  Only needed once, here in the init.
  177.     //
  178.     GetDateTime((unsigned long*) &qd.randSeed);
  179.     
  180.     Handle mbar = GetNewMBar(128);
  181.     
  182.     if (mbar != nil)
  183.     {
  184.         SetMenuBar(mbar);
  185.         DrawMenuBar();
  186.     }
  187.  
  188.     EventLoop::InstallAEHandler(kCoreEventClass, kAEQuitApplication, HandleQuit);
  189.  
  190.     EventLoop::InstallAEHandler(kCoreEventClass, kAEOpenApplication, HandleNew);
  191.     EventLoop::InstallAEHandler(kAECoreSuite, kAECreateElement, HandleNew);
  192. }
  193.  
  194. void Finalize(void)
  195. {
  196. }
  197.  
  198.  
  199. TSillyBallWindow::TSillyBallWindow()
  200. :    fWindow(nil),
  201.     fThreadID(kNoThreadID)
  202. {
  203.     //
  204.     //    Make a new window for drawing in, and it must be a color window.  
  205.     //    The window is full screen size, made smaller to make it more visible.
  206.     //
  207.     windRect = qd.screenBits.bounds;
  208.     InsetRect(&windRect, 50, 50);
  209.     fWindow = NewCWindow(nil, &windRect, "\pBob Land", true, zoomDocProc, 
  210.                         (WindowPtr) -1, false, 0);
  211.         
  212.     SetPort(fWindow);                        /* set window to current graf port */
  213.     TextSize(BobSize);                        /* smaller font for drawing. */
  214.  
  215.     FailOSErr(NewThread(kCooperativeThread, SillyBallThread, this, 0, kCreateIfNeeded, nil, &fThreadID));
  216. }
  217.  
  218. TSillyBallWindow::~TSillyBallWindow()
  219. {
  220.     ThreadID thread = fThreadID;
  221.     
  222.     if (thread != kNoThreadID)
  223.     {
  224.         void*    result;
  225.     
  226.         LogIfErr(DisposeThread(thread, &result, true));
  227.  
  228.         fThreadID = kNoThreadID;
  229.     }
  230.  
  231.     WindowPtr wp = fWindow;
  232.  
  233.     if (wp != nil)
  234.     {
  235.         GrafPtr port;
  236.         
  237.         GetPort(&port);
  238.     
  239.         if (port == wp)                // if we're disposing of the current port
  240.         {                            // switch to the WM port
  241.             GetWMgrPort(&port);
  242.             SetPort(port);
  243.         }
  244.         
  245.         DisposeWindow(wp);
  246.     
  247.         fWindow = nil;
  248.     }
  249. }
  250.  
  251. // 
  252. //    NewBall: make another ball in the window at a random location and color.
  253. //
  254.  
  255. //MW -specified argument and return type.-
  256. void TSillyBallWindow::NewBall(void)
  257. {
  258.     RGBColor    ballColor;
  259.     Rect        ballRect;
  260.     long int    newLeft,
  261.                 newTop;
  262.     GrafPtr        oldPort;
  263.     
  264.     GetPort(&oldPort);
  265.     SetPort(fWindow);
  266.     
  267.     // 
  268.     //    Make a random new color for the ball.
  269.     //
  270.     ballColor.red   = Random();
  271.     ballColor.green = Random();
  272.     ballColor.blue  = Random();
  273.     
  274.     // 
  275.     //    Set that color as the new color to use in drawing.
  276.     //
  277.     RGBForeColor (&ballColor);
  278.  
  279.     //    
  280.     //    Make a Random new location for the ball, that is normalized to the window size.  
  281.     //    This makes the Integer from Random into a number that is 0..windRect.bottom
  282.     //    and 0..windRect.right.  They are normalized so that we don't spend most of our
  283.     //    time drawing in places outside of the window.
  284.     //
  285.     newTop = Random();    newLeft = Random();
  286.     newTop = ((newTop+32767) * windRect.bottom)/65536;
  287.     newLeft = ((newLeft+32767) * windRect.right)/65536;
  288.     SetRect(&ballRect, newLeft, newTop, newLeft+BallWidth, newTop+BallHeight);
  289.     
  290.     //
  291.     //    Move pen to the new location, and paint the colored ball.
  292.     //
  293.     MoveTo(newLeft, newTop);
  294.     PaintOval (&ballRect);
  295.     
  296.     //
  297.     //    Move the pen to the middle of the new ball position, for the text
  298.     //
  299.     MoveTo(ballRect.left + BallWidth/2 - BobSize, 
  300.         ballRect.top + BallHeight/2 + BobSize/2 -1);
  301.     
  302.     //    
  303.     //    Invert the color and draw the text there.  This won’t look quite right in 1 bit
  304.     //    mode, since the foreground and background colors will be the same.
  305.     //    Color QuickDraw special cases this to not invert the color, to avoid
  306.     //    invisible drawing.
  307.     //
  308.     InvertColor(&ballColor); 
  309.     RGBForeColor(&ballColor);
  310.     DrawString("\pBob");
  311.     
  312.     SetPort(oldPort);
  313. }
  314.  
  315. pascal voidPtr TSillyBallWindow::SillyBallThread(void *threadParam)
  316. {
  317.     TSillyBallWindow* win = (TSillyBallWindow*) threadParam;
  318.     
  319.     while(1)
  320.     {
  321.         win->NewBall();
  322.         YieldToAnyThread();
  323.     }
  324. }
  325.  
  326.  
  327. TSillyLoop::~TSillyLoop()
  328. {
  329. }
  330.  
  331. bool TSillyLoop::HandleMenuSelection(long what)
  332. {
  333.     int menu = HiWord(what);
  334.     int item = LoWord(what);
  335.     
  336.     switch (menu)
  337.     {
  338.     case 129:
  339.         switch (item)
  340.         {
  341.         case 1:
  342.             TSillyBallWindow* win = new TSillyBallWindow();
  343.             break;
  344.  
  345.         case 3:
  346.             Quit();
  347.             break;
  348.         }
  349.     }
  350.  
  351.     return Inherited::HandleMenuSelection(what);
  352. }
  353.  
  354.  
  355.  
  356.  
  357.