home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ocl_ani2.zip / application.cpp next >
Text File  |  1997-07-06  |  11KB  |  319 lines

  1. /* Stéphane Charette, stephane@venus.ubishops.ca
  2.  * IBM Open Class Library Animation Sample #2
  3.  * (using Visual Age C++ v3.0 with OS/2 v4.0)
  4.  * 1997July06
  5.  */
  6.  
  7. /* includes */
  8. #include "ocl_ani2.hpp"    // class definitions
  9.  
  10.  
  11. // constructor for the application
  12. Application::Application() :           // construct inherited class...
  13.    IFrameWindow( DLG_RCID ),           // ...IFrameWindow...
  14.    IFrameHandler(),                    // ...IFrameHandler...
  15.    ICommandHandler(),                  // ...ICommandHandler...
  16.    IMouseHandler(),                    // ...IMouseHandler...
  17.    IGList(),                           // ...and IGList
  18.    canvas( CANVAS_RCID, this, this ),
  19.    mouseClickPosition( 0, 0 ),
  20.    mouseMoveInProgress( false ),
  21.    mouseMovePtrHandle( IResourceLibrary().loadPointer( PTR_MOVE_RCID ) )
  22. {
  23.    // set the "animated" frame dialog style
  24.    setStyle( style() | animated.asUnsignedLong() );
  25.  
  26.    // set the icon for the frame window
  27.    setIcon( DLG_RCID );
  28.  
  29.    // set the canvas to be the correct size
  30.    canvas.moveSizeTo( clientRectFor( rect() ) );
  31.  
  32.    // set the canvas background colour
  33.    canvas.setBackgroundColor( IColor( 0, 64, 0 ) );
  34.  
  35.    // associate the graphic list with the canvas
  36.    canvas.setGraphicList( this );
  37.  
  38.    // set the drawing canvas as the client for the frame
  39.    setClient( &canvas );
  40.  
  41.    // set ourselves up to handle events for the canvas
  42.    IMouseHandler::handleEventsFor( &canvas );
  43.    ICommandHandler::handleEventsFor( &canvas );
  44.    IFrameHandler::handleEventsFor( this );
  45.  
  46.    // add window to the CTRL-ESC window list
  47.    addToWindowList();
  48.  
  49.    // show the dialog and set the focus
  50.    show().setFocus();
  51.  
  52.    return;
  53. }
  54.  
  55.  
  56. // destructor for application dialog class
  57. Application::~Application()
  58. {
  59.    // stop handling events
  60.    IMouseHandler::stopHandlingEventsFor( &canvas );
  61.    ICommandHandler::stopHandlingEventsFor( &canvas );
  62.    IFrameHandler::stopHandlingEventsFor( this );
  63.  
  64.    // delete all of the draw items
  65.    while( ! isEmpty() )
  66.    {
  67.       // get the graphic at the current position
  68.       Person *person = (Person*)&(graphicAtPosition( 1 ));
  69.       // remove the graphic
  70.       removeAtPosition( 1 );
  71.       // free up resources
  72.       delete( person );
  73.    }
  74.    return;
  75. }
  76.  
  77.  
  78. Boolean Application::mouseClicked( IMouseClickEvent &event )
  79. {
  80.    // save the mouse position for when we handle the menu
  81.    mouseClickPosition = IPoint( event.mousePosition() );
  82.  
  83.    // is this a popupmenu request?
  84.    if( event.mouseButton() == IMouseClickEvent::button2 )
  85.    {
  86.       // reset necessary states
  87.       resetAttributes();
  88.  
  89.       if( event.mouseAction() == IMouseClickEvent::click )
  90.       {
  91.          // create a popup menu
  92.          IPopUpMenu *pmenu = new IPopUpMenu( this, MNU_RCID );
  93.          pmenu->setAutoDeleteObject( true );
  94.  
  95.          // add common menu items
  96.          pmenu->addText( MNU_CREATE_PERSON,  "Create" );
  97.          pmenu->addSubmenu( MNU_CREATE_PERSON );   // convert it to submenu
  98.          // add submenu items
  99.          pmenu->addText( MNU_CREATE_ORANGE,  "Orange",   MNU_CREATE_PERSON );
  100.          pmenu->addText( MNU_CREATE_BLUE,    "Blue",     MNU_CREATE_PERSON );
  101.          pmenu->addText( MNU_CREATE_GREEN,   "Green",    MNU_CREATE_PERSON );
  102.          pmenu->addText( MNU_CREATE_RED,     "Red",      MNU_CREATE_PERSON );
  103.          pmenu->addText( MNU_CREATE_GRAY,    "Gray",     MNU_CREATE_PERSON );
  104.  
  105.          // where was the button clicked?
  106.          IGraphicContext graphicContext( canvas.handle() );
  107.          IGraphic *graphic = topGraphicUnderPoint( mouseClickPosition,
  108.                                                          graphicContext );
  109.          if( graphic )
  110.          {
  111.             // button 2 was clicked on a graphic in glist
  112.  
  113.             // figure out which object was clicked for when we handle the menu
  114.             for(  mouseClickBitmapOffset = 1;
  115.                   &( graphicAtPosition( mouseClickBitmapOffset ) ) != graphic;
  116.                   mouseClickBitmapOffset ++ );
  117.  
  118.             // get the person
  119.             Person *person = (Person *)&graphicAtPosition(mouseClickBitmapOffset);
  120.  
  121.             // create the menu items specific to the item
  122.             pmenu->addText( MNU_CLONE_PERSON,   "Clone"  );
  123.             pmenu->addText( MNU_DELETE_PERSON,  "Delete" );
  124.             pmenu->addText( MNU_MOVE_PERSON,    "Move"   );
  125.             pmenu->addSubmenu( MNU_MOVE_PERSON );
  126.             pmenu->addText( MNU_MOVE_SET,       "Set",   MNU_MOVE_PERSON );
  127.             pmenu->addText( MNU_MOVE_STOP,      "Stop",  MNU_MOVE_PERSON );
  128.             // if the person is not moving...
  129.             if( ! person->moveTimer )
  130.             {
  131.                // ...disable the "stop" item...
  132.                pmenu->disableItem( MNU_MOVE_STOP );
  133.                // ...set the "set" item as default
  134.                pmenu->setConditionalCascade( MNU_MOVE_PERSON, MNU_MOVE_SET );
  135.             }
  136.             else  // ...else...
  137.             {
  138.                // ...set the "stop" item as default
  139.                pmenu->setConditionalCascade( MNU_MOVE_PERSON, MNU_MOVE_STOP );
  140.             }
  141.          }
  142.          else
  143.          {
  144.             // button 2 was clicked somewhere on the canvas
  145.             mouseClickBitmapOffset = 0;
  146.          }
  147.  
  148.          // show the menu
  149.          pmenu->show( mouseClickPosition );
  150.  
  151.          // return the event as having been handled
  152.          return true;
  153.       }
  154.    }
  155.    else
  156.    {
  157.       // if this is mousebutton1click and we are currenting setting a move...
  158.       if(   (event.mouseButton() == IMouseClickEvent::button1) &&
  159.             (event.mouseAction() == IMouseClickEvent::click)   &&
  160.             (mouseMoveInProgress) )
  161.       {
  162.          // we want the object to move to this location
  163.          mouseMoveInProgress = false;
  164.          // get the object that has to be moved
  165.          Person *person = (Person *)&graphicAtPosition(mouseClickBitmapOffset);
  166.          // is this object already moving?
  167.          if( person->moveTimer )
  168.          {
  169.             // yes it is...kill the timer
  170.             person->moveTimer->stop();
  171.             delete( person->moveTimer );
  172.          }
  173.          // setup the necessary move information
  174.          person->moveX = (double)person->position().x();
  175.          person->moveY = (double)person->position().y();
  176.          person->moveDestination = event.mousePosition();
  177.          // what is the length of the move line?
  178.          person->moveCount = (int)
  179.             sqrt( pow( person->moveDestination.x() - person->moveX, 2 ) +
  180.                   pow( person->moveDestination.y() - person->moveY, 2 ) ) /
  181.                   5.0;
  182.          // detemine what DX and DY will be
  183.          person->moveDX =
  184.             ((double)person->moveDestination.x() - person->moveX ) /
  185.              (double)person->moveCount;
  186.          person->moveDY =
  187.             ((double)person->moveDestination.y() - person->moveY ) /
  188.              (double)person->moveCount;
  189.          // start the timer to move the object
  190.          person->moveTimer = new ITimer(
  191.             new ITimerMemberFn0<Person>(*person, Person::animateMove), 100);
  192.          // return message as having been handled
  193.          return true;
  194.       }
  195.    }
  196.    // continue processing this event
  197.    return false;
  198. }
  199.  
  200.  
  201. Boolean Application::mousePointerChange( IMousePointerEvent &event )
  202. {
  203.    // are we moving an object?
  204.    if( mouseMoveInProgress )
  205.    {
  206.       // move is in progress...use our built-in mouse pointer
  207.       event.setMousePointer( mouseMovePtrHandle );
  208.       // return message as having been handled
  209.       return true;
  210.    }
  211.  
  212.    // return the event as not having been handled
  213.    return false;
  214. }
  215.  
  216.  
  217. // focus lost event overriden from IFrameHandler
  218. Boolean Application::deactivated( IFrameEvent &event )
  219. {
  220.    resetAttributes();
  221.    return false;
  222. }
  223.  
  224.  
  225. // command event overridden from ICommandHandler
  226. Boolean Application::command( ICommandEvent &event )
  227. {
  228.    switch( event.commandId() )
  229.    {
  230.       case MNU_CREATE_ORANGE:
  231.       case MNU_CREATE_BLUE:
  232.       case MNU_CREATE_GREEN:
  233.       case MNU_CREATE_RED:
  234.       case MNU_CREATE_GRAY:
  235.       {
  236.          // create a new person object
  237.          Person *person = new Person( event.commandId(), canvas.handle() );
  238.          // move the bitmap to the position where the mouse was clicked
  239.          person->moveTo( mouseClickPosition );
  240.          // add the person to the glist
  241.          addAsFirst( *(IGBitmap*)person );
  242.          // invalidate rect
  243.          RECTL rectl =
  244.             IRectangle( person->position(), person->size() ).asRECTL();
  245.          WinInvalidateRect( canvas.handle(), &rectl, FALSE );
  246.          // return message as having been handled
  247.          return true;
  248.          break;
  249.       }
  250.       case MNU_DELETE_PERSON:
  251.       {
  252.          // delete the requested item
  253.          // keep track of graphic being deleted
  254.          Person *person=(Person*)&(graphicAtPosition(mouseClickBitmapOffset) );
  255.          // remove the person from the glist
  256.          removeAtPosition( mouseClickBitmapOffset );
  257.          // invalidate rect
  258.          RECTL rectl =
  259.             IRectangle( person->position(), person->size() ).asRECTL();
  260.          WinInvalidateRect( canvas.handle(), &rectl, FALSE );
  261.          // free up resources
  262.          delete( person );
  263.          // return message as having been handled
  264.          return true;
  265.          break;
  266.       }
  267.       case MNU_CLONE_PERSON:
  268.       {
  269.          // create a new person from the bitmap id of the clone parent
  270.          Person *person = new Person(
  271.             ((Person*)&(graphicAtPosition(mouseClickBitmapOffset)))->bitmapId,
  272.             canvas.handle() );
  273.          // move the bitmap to the position where the mouse was clicked
  274.          person->moveTo( mouseClickPosition );
  275.          // add the person to the glist
  276.          addAsFirst( *(IGBitmap*)person );
  277.          // invalidate rect
  278.          RECTL rectl =
  279.             IRectangle(  person->position(), person->size() ).asRECTL();
  280.          WinInvalidateRect( canvas.handle(), &rectl, FALSE );
  281.          // return message as having been handled
  282.          return true;
  283.          break;
  284.       }
  285.       case MNU_MOVE_SET:
  286.       {
  287.          // start tracking for movement
  288.          mouseMoveInProgress = true;
  289.          // return message as having been handled
  290.          return true;
  291.          break;
  292.       }
  293.       case MNU_MOVE_STOP:
  294.       {
  295.          Person *person = (Person *)&graphicAtPosition(mouseClickBitmapOffset);
  296.          // kill the timer
  297.          person->moveTimer->stop();
  298.          delete( person->moveTimer );
  299.          person->moveTimer = '\0';
  300.          // invalidate rect
  301.          RECTL rectl =
  302.             IRectangle(  person->position(), person->size() ).asRECTL();
  303.          WinInvalidateRect( canvas.handle(), &rectl, FALSE );
  304.          return true;
  305.          break;
  306.       }
  307.    }
  308.    // continue processing this event
  309.    return false;
  310. }
  311.  
  312.  
  313. // used to reset local class variables after context switches, etc
  314. void Application::resetAttributes()
  315. {
  316.    mouseMoveInProgress = false;
  317.    return;
  318. }
  319.