home *** CD-ROM | disk | FTP | other *** search
/ Power GUI Programming with VisualAge C++ / powergui.iso / trialva / ibmcppw / samples / ioc / 2ddraw / 2ddraw.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-22  |  34.0 KB  |  910 lines

  1. /******************************************************************************
  2. * .FILE:         2d-draw.cpp                                                  *
  3. *                                                                             *
  4. * .DESCRIPTION:  2D Graphics Drawing Program :         Class Implementation   *
  5. *                                                                             *
  6. * .CLASSES:      MainWindow                                                   *
  7. *                DrawingArea                                                  *
  8. *                                                                             *
  9. * .COPYRIGHT:                                                                 *
  10. *    Licensed Material - Program-Property of IBM                              *
  11. *    (C) Copyright IBM Corp. 1992, 1996 - All Rights Reserved                 *
  12. *                                                                             *
  13. * .DISCLAIMER:                                                                *
  14. *   The following [enclosed] code is sample code created by IBM               *
  15. *   Corporation.  This sample code is not part of any standard IBM product    *
  16. *   and is provided to you solely for the purpose of assisting you in the     *
  17. *   development of your applications.  The code is provided 'AS IS',          *
  18. *   without warranty of any kind.  IBM shall not be liable for any damages    *
  19. *   arising out of your use of the sample code, even if they have been        *
  20. *   advised of the possibility of such damages.                               *
  21. *                                                                             *
  22. * .NOTE: WE RECOMMEND USING A FIXED SPACE FONT TO LOOK AT THE SOURCE          *
  23. *                                                                             *
  24. ******************************************************************************/
  25. #ifndef _IBASE_                         //Make sure ibase.hpp is included
  26.   #include <ibase.hpp>                  //  since that is where IC_<environ>
  27. #endif                                  //  is defined.
  28. #include <igline.hpp>
  29. #include <igpyline.hpp>
  30. #include <igelipse.hpp>
  31. #include <igarc.hpp>
  32. #include <igpie.hpp>
  33. #include <igstring.hpp>
  34. #include <igbitmap.hpp>
  35. #include <icolor.hpp>
  36. #include <iglist.hpp>
  37. #include <math.h>
  38. #include "2ddraw.hpp"
  39.  
  40. //*************************************************************************
  41. // main  - Application entry point                                        *
  42. //*************************************************************************
  43. int main()
  44. {
  45.   IToolBarButton::setDefaultStyle( IToolBarButton::defaultStyle() |
  46.                                    IToolBarButton::autoLatch      |
  47.                                    IToolBarButton::useIdForText   |
  48.                                    IWindow::visible );
  49.   IToolBar::setDefaultStyle(IToolBar::classDefaultStyle |
  50.                             IToolBar::buttonBitmapAndTextVisible);
  51.  
  52.   MainWindow  mainWindow(WND_MAIN);     //Create our main window on the desktop
  53.  
  54.   IApplication::current().run();        //Get the current application and
  55.                                         // run it
  56.   return 0;
  57. } /* end main */
  58.  
  59.  
  60. /*------------------------------------------------------------------------------
  61. | MainWindow::MainWindow                                                       |
  62. |                                                                              |
  63. |                                                                              |
  64. ------------------------------------------------------------------------------*/
  65. MainWindow::MainWindow(unsigned long windowId)
  66.   : IFrameWindow (                      //Call IFrameWindow constructor
  67.     IFrameWindow::defaultStyle()        //  Use default plus
  68.     | IFrameWindow::animated            //  Set to show with "animation"
  69.     | IFrameWindow::menuBar             //  Frame has a menu bar
  70.     | IFrameWindow::minimizedIcon,      //  Frame has an icon
  71.     windowId),                          //  Main Window ID
  72.     drawingArea( WND_DRAW, this, this ),
  73.     toolBar( WND_TOOLBAR,this, IToolBar::aboveClient),
  74.     menuBar( this, IMenuBar::wrapper ),
  75.     infoArea( this, WND_TEXT ),
  76.     flyText( 1054, &menuBar ),
  77.  
  78.     // Set the initial delay for fly over help to 1 1/2 seconds and
  79.     // set the regular delay to 1/3 seconds.
  80.     flyOver( &flyText, &infoArea, 1500, 333 ),
  81.     lastPenColorId( ID_COL_BLK ),
  82.     lastFillColorId( ID_FLCOL_BLK ),
  83.     lastPenPatternId( ID_PENPATTERN_SOLID ),
  84.     lastFillPatternId( ID_FILLPATTERN_SOLID ),
  85.     lastPenTypeId( ID_PENTYPE_SOLID ),
  86.     lastPenWidthId( ID_PENWIDTH_1 ),
  87.     lastDrawOperationId( ID_FILLANDFRAME ),
  88.     normalButton(PALLET_NORM, &toolBar, &toolBar),
  89.     lineButton(PALLET_LINE, &toolBar, &toolBar),
  90.     drawButton(PALLET_DRAW, &toolBar, &toolBar),
  91.     rectangleButton(PALLET_RECTANGLE, &toolBar, &toolBar),
  92.     ellipseButton(PALLET_ELLIPSE, &toolBar, &toolBar),
  93.     polylineButton(PALLET_POLYLINE, &toolBar, &toolBar),
  94.     polygonButton(PALLET_POLYGON, &toolBar, &toolBar),
  95.     arcButton(PALLET_ARC, &toolBar, &toolBar),
  96.     pieButton(PALLET_PIE, &toolBar, &toolBar),
  97.     chordButton(PALLET_CHORD, &toolBar, &toolBar),
  98.     textButton(PALLET_TEXT, &toolBar, &toolBar),
  99.     bitmapButton(PALLET_BITMAP, &toolBar, &toolBar)
  100. {
  101.   ICommandHandler::handleEventsFor(this);
  102.   IMenuDrawItemHandler::handleEventsFor(this);
  103.  
  104.   // Allow the information area to wrap to a second line.
  105.   infoArea.setLineCount( 2 );
  106.  
  107.   setExtensionSize(&infoArea, (unsigned long)(2*IFont(&infoArea).maxCharHeight()));
  108.  
  109.   menuBar.checkItem( lastPenColorId      )
  110.          .checkItem( lastFillColorId     )
  111.          .checkItem( lastPenPatternId    )
  112.          .checkItem( lastFillPatternId   )
  113.          .checkItem( lastPenTypeId       )
  114.          .checkItem( lastPenWidthId      )
  115.          .checkItem( lastDrawOperationId );
  116.  
  117.   toolBar.addAsLast( &normalButton    )
  118.          .addAsLast( &lineButton      )
  119.          .addAsLast( &drawButton      )
  120.          .addAsLast( &rectangleButton )
  121.          .addAsLast( &ellipseButton   )
  122.          .addAsLast( &polylineButton  )
  123.          .addAsLast( &polygonButton   )
  124.          .addAsLast( &arcButton       )
  125.          .addAsLast( &pieButton       )
  126.          .addAsLast( &chordButton     )
  127.          .addAsLast( &textButton      )
  128.          .addAsLast( &bitmapButton    );
  129.   normalButton.latch();
  130.  
  131.   // Set the fly over help for the client window to the
  132.   // help information for the pointer (normal) button.
  133.  
  134.   flyOver.setHelpText( drawingArea.handle(),
  135.                        IResourceId(0),
  136.                        IResourceId(PALLET_NORM + LONG_OFFSET ));
  137.  
  138.   flyOver.handleEventsFor( this );
  139.   flyOver.handleEventsFor( &drawingArea );
  140.   flyOver.setLongStringTableOffset( LONG_OFFSET );
  141.  
  142.   setClient( &drawingArea );
  143.   setFocus();
  144.   show();
  145. }
  146.  
  147. /*------------------------------------------------------------------------------
  148. | MainWindow::MainWindow                                                       |
  149. |                                                                              |
  150. |                                                                              |
  151. ------------------------------------------------------------------------------*/
  152. MainWindow::~MainWindow()
  153. {
  154. }
  155.  
  156. /*------------------------------------------------------------------------------
  157. | angleFromPoints                                                              |
  158. |                                                                              |
  159. | Given two points determine the angle between the horizontal line through     |
  160. | the first point and the line from the first point to the second point.       |
  161. ------------------------------------------------------------------------------*/
  162. double angleFromPoints( const IPoint& center, const IPoint& drop )
  163. {
  164.   IPoint temp;
  165.   double angle;
  166.  
  167.   temp  = drop - center;
  168.   angle = atan2((double)temp.y(), (double)temp.x());
  169.   angle *= 57.295779;
  170.  
  171.   if ( angle < 0.0 )
  172.     angle += 360.0;
  173.  
  174. #ifdef IC_PM
  175.   return angle;
  176. #else
  177.   return -angle;
  178. #endif
  179. }
  180.  
  181. /*------------------------------------------------------------------------------
  182. | DrawingArea::DrawingArea                                                     |
  183. |                                                                              |
  184. |                                                                              |
  185. ------------------------------------------------------------------------------*/
  186. DrawingArea::DrawingArea( unsigned long windowId, IWindow* parent,
  187.                           IWindow* owner, const IRectangle& initial )
  188.   : IDrawingCanvas( windowId, parent, owner, initial,
  189.                     IDrawingCanvas::defaultStyle() | IWindow::clipSiblings ),
  190.     currentfont(),
  191.     currentBundle(),
  192.     animateBundle(),
  193.     currentBitmap(),
  194.     dState( notDrawing ),
  195.     currentObj( pointer ),
  196.     iGraphic(0),
  197.     moveGraphic(0),
  198.     moveRect(IRectangle()),
  199.     startingPt(), previousPt(), tempPt(),
  200.     pointCount(0)
  201. {
  202.   currentBundle.setPenColor(IGraphicContext::defaultPenColor())
  203.                .setFillColor(IGraphicContext::defaultFillColor())
  204.                .setMixMode(IGraphicContext::defaultMixMode())
  205.                .setDrawOperation( IGraphicBundle::fillAndFrame );
  206.  
  207.   animateBundle.setMixMode( IGraphicBundle::bitExclusiveOr )
  208.                .setPenColor( IColor::white )
  209.                .setFillColor( IColor::white )
  210.                .setDrawOperation( IGraphicBundle::frame );
  211.  
  212.   setGraphicList( new IGList() );
  213.  
  214.   // Load the pointers.
  215.  
  216.   IResourceLibrary reslib;
  217.   ptrLine      = reslib.loadPointer( PALLET_LINE );
  218.   ptrDraw      = reslib.loadPointer( PALLET_DRAW );
  219.   ptrRectangle = reslib.loadPointer( PALLET_RECTANGLE );
  220.   ptrEllipse   = reslib.loadPointer( PALLET_ELLIPSE );
  221.   ptrPolyline  = reslib.loadPointer( PALLET_POLYLINE );
  222.   ptrPolygon   = reslib.loadPointer( PALLET_POLYGON );
  223.   ptrArc       = reslib.loadPointer( PALLET_ARC );
  224.   ptrPie       = reslib.loadPointer( PALLET_PIE );
  225.   ptrChord     = reslib.loadPointer( PALLET_CHORD );
  226.   ptrText      = reslib.loadPointer( PALLET_TEXT );
  227.   ptrBitmap    = reslib.loadPointer( PALLET_BITMAP );
  228.  
  229.   ((IMouseHandler*)this)->handleEventsFor(this);
  230. }
  231.  
  232. /*------------------------------------------------------------------------------
  233. | DrawingArea::DrawingArea                                                     |
  234. |                                                                              |
  235. |                                                                              |
  236. ------------------------------------------------------------------------------*/
  237. DrawingArea::~DrawingArea( )
  238. {
  239.   // Delete all the graphic objects in the drawing canvas.
  240.   IGList::Cursor graphicsCursor( *graphicList() );
  241.   for ( graphicsCursor.setToFirst();
  242.         graphicsCursor.isValid();
  243.         graphicsCursor.setToNext() )
  244.   {
  245.     IGraphic* graphic(&(graphicList()->graphicAt(graphicsCursor)));
  246.     delete graphic;
  247.   } /* endfor */
  248.   delete graphicList();
  249. }
  250.  
  251. /*------------------------------------------------------------------------------
  252. | DrawingArea::mouseClicked                                                    |
  253. |                                                                              |
  254. | Translate the mouse clicked events.                                          |
  255. ------------------------------------------------------------------------------*/
  256. IBase::Boolean DrawingArea::mouseClicked( IMouseClickEvent& event )
  257. {
  258.   Boolean bRc = false;
  259.   if ( event.mouseButton() == IMouseClickEvent::button1 &&
  260.        event.mouseAction() == IMouseClickEvent::down )
  261.   {
  262.     button1Down(event.mousePosition());
  263.     bRc = false;
  264.   }
  265.   else if ( event.mouseButton() == IMouseClickEvent::button1 &&
  266.             event.mouseAction() == IMouseClickEvent::up )
  267.   {
  268.     button1Up(event.mousePosition());
  269.     bRc = true;
  270.   }
  271.   else if ( event.mouseButton() == IMouseClickEvent::button1 &&
  272.             event.mouseAction() == IMouseClickEvent::doubleClick )
  273.   {
  274.     button1DoubleClick(event.mousePosition());
  275.     bRc = true;
  276.   }
  277.   else if ( event.mouseButton() == IMouseClickEvent::button2 &&
  278.             event.mouseAction() == IMouseClickEvent::down )
  279.   {
  280.     button2Down(event.mousePosition());
  281.   }
  282.   else if ( event.mouseButton() == IMouseClickEvent::button2 &&
  283.             event.mouseAction() == IMouseClickEvent::up )
  284.   {
  285.     button2Up(event.mousePosition());
  286.   }
  287.  
  288.   return bRc;
  289. }
  290.  
  291.  
  292. /*------------------------------------------------------------------------------
  293. | DrawingArea::changeMousePointer                                              |
  294. |                                                                              |
  295. | Change the cursor to reflect the object being drawn.                         |
  296. ------------------------------------------------------------------------------*/
  297. IBase::Boolean DrawingArea::mousePointerChange( IMousePointerEvent& event )
  298. {
  299.   Boolean fReturn(true);
  300.  
  301.   switch (drawObject())
  302.   {
  303.     case PALLET_NORM:
  304.       return fReturn = false;
  305.     break;
  306.     case PALLET_LINE:
  307.       event.setMousePointer( ptrLine );
  308.     break;
  309.     case PALLET_DRAW:
  310.       event.setMousePointer( ptrDraw );
  311.     break;
  312.     case PALLET_RECTANGLE:
  313.       event.setMousePointer( ptrRectangle );
  314.     break;
  315.     case PALLET_ELLIPSE:
  316.       event.setMousePointer( ptrEllipse );
  317.     break;
  318.     case PALLET_POLYLINE:
  319.       event.setMousePointer( ptrPolyline );
  320.     break;
  321.     case PALLET_POLYGON:
  322.       event.setMousePointer( ptrPolygon );
  323.     break;
  324.     case PALLET_ARC:
  325.       event.setMousePointer( ptrArc );
  326.     break;
  327.     case PALLET_PIE:
  328.       event.setMousePointer( ptrPie );
  329.     break;
  330.     case PALLET_CHORD:
  331.       event.setMousePointer( ptrChord );
  332.     break;
  333.     case PALLET_TEXT:
  334.       event.setMousePointer( ptrText );
  335.     break;
  336.     case PALLET_BITMAP:
  337.       event.setMousePointer( ptrBitmap );
  338.     break;
  339.     default:
  340.       fReturn = false;
  341.     break;
  342.   } // end switch
  343.  
  344.   return fReturn;
  345. }
  346.  
  347. /*------------------------------------------------------------------------------
  348. | DrawingArea::button1Down                                                     |
  349. |                                                                              |
  350. | Handle button 1 down messages.  This event indicates a new graphic object is |
  351. | to be created of additional data points to add to an existing graphic object.|
  352. ------------------------------------------------------------------------------*/
  353. DrawingArea& DrawingArea::button1Down( const IPoint& point )
  354. {
  355.   IGraphicContext gc(this->handle());
  356.   gc.setGraphicBundle(animateBundle);
  357.  
  358.   switch (currentObj)
  359.   {
  360.     case pointer:
  361.     {
  362.       // Change all objects to the current pen and fill color.
  363.       IGList::Cursor cursor( *graphicList(), gc, point );
  364.       for (cursor.setToFirst(); cursor.isValid(); cursor.setToNext())
  365.       {
  366.         IGraphic& graphic(graphicList()->graphicAt( cursor ));
  367.         this->refresh( graphic.boundingRect( gc ));//    .expandBy(1) );
  368.         graphic.setGraphicBundle( currentBundle );
  369.         graphic.drawOn( gc );
  370.       } /* endfor */
  371.     }
  372.     break;
  373.     case line:
  374.       startingPt = point;
  375.       previousPt = point;
  376.       iGraphic = new IGLine( startingPt, previousPt );
  377.       setDrawState();
  378.     break;
  379.     case freeHand:
  380.       iGraphic = new IGPolygon(IPointArray());
  381.       ((IGPolygon*)iGraphic)->addPoint( point );
  382.       setDrawState();
  383.     break;
  384.     case rectangle:
  385.       startingPt = point;
  386.       previousPt = point;
  387.       iGraphic = new IGRectangle(IRectangle(startingPt, previousPt));
  388.       setDrawState();
  389.     break;
  390.     case ellipse:
  391.       startingPt = point;
  392.       previousPt = point;
  393.       iGraphic = new IGEllipse( startingPt, 0L );
  394.       setDrawState();
  395.     break;
  396.     case polyline:
  397.     case polygon:
  398.       if (drawState() == notDrawing)
  399.       {
  400.         startingPt = point;
  401.         previousPt = point;
  402.         if (currentObj == polyline)
  403.           iGraphic = new IGPolyline(IPointArray());
  404.         else
  405.           iGraphic = new IGPolygon(IPointArray());
  406.  
  407.         ((IGPolyline*)iGraphic)->addPoint( startingPt );
  408.         ((IGPolyline*)iGraphic)->addPoint( previousPt );
  409.         setDrawState();
  410.       }
  411.       else
  412.       {
  413.         ((IGPolyline*)iGraphic)->IGPolyline::drawOn( gc );
  414.         ((IGPolyline*)iGraphic)->addPoint( point );
  415.         ((IGPolyline*)iGraphic)->IGPolyline::drawOn( gc );
  416.       }
  417.     break;
  418.     case arc:
  419.       pointCount++;
  420.       if (drawState() == notDrawing)
  421.       {
  422.         iGraphic = new IG3PointArc( point, IPoint(0,0), IPoint(0,0) );
  423.         startingPt = point;
  424.         previousPt = point;
  425.       }
  426.       else if ( pointCount == 2 )
  427.       {
  428.         previousPt = point;
  429.         IGLine tempLine( ((IG3PointArc*)iGraphic)->startingPoint(), point );
  430.         tempLine.drawOn( gc );
  431.       }
  432.       else if ( pointCount == 3 )
  433.       {
  434.         IGLine tempLine( ((IG3PointArc*)iGraphic)->startingPoint(), previousPt );
  435.         tempLine.drawOn( gc );
  436.         previousPt = point;
  437.         ((IG3PointArc*)iGraphic)->setEndingPoint( point );
  438.         iGraphic->drawOn( gc );
  439.       }
  440.       setDrawState();
  441.     break;
  442.     case pie:
  443.     case chord:
  444.       pointCount++;
  445.       if (drawState() == notDrawing)
  446.       {
  447.         if (currentObj == pie)
  448.           iGraphic = new IGPie( IRectangle(), 0, 0);
  449.         else
  450.           iGraphic = new IGChord( IRectangle(), 0, 0);
  451.  
  452.         ((IGPie*)iGraphic)->setEnclosingRect(
  453.                              ((IGPie*)iGraphic)->enclosingRect().centerAt( point ));
  454.         startingPt = point;
  455.         previousPt = point;
  456.       }
  457.       else if ( pointCount == 2 )
  458.       {
  459.         previousPt = point;
  460.         IGLine tempLine( ((IGPie*)iGraphic)->enclosingRect().center(), point );
  461.         tempLine.drawOn( gc );
  462.       }
  463.       else if ( pointCount == 3 )
  464.       {
  465.         IGLine tempLine( ((IGPie*)iGraphic)->enclosingRect().center(), previousPt );
  466.         tempLine.drawOn( gc );
  467.         previousPt = point;
  468.         double sweep(angleFromPoints( ((IGPie*)iGraphic)->enclosingRect().center(), point ));
  469.         if ( sweep < ((IGPie*)iGraphic)->startAngle() )
  470.           ((IGPie*)iGraphic)->setSweepAngle( 360.0 -
  471.                                 ( ((IGPie*)iGraphic)->startAngle() - sweep ));
  472.         else
  473.           ((IGPie*)iGraphic)->setSweepAngle( sweep -
  474.                                             ((IGPie*)iGraphic)->startAngle());
  475.         iGraphic->drawOn( gc );
  476.       }
  477.       setDrawState();
  478.     break;
  479.     case text:
  480.       setDrawState();
  481.     break;
  482.     case bitmap:
  483.       setDrawState();
  484.     break;
  485.   } /* endswitch */
  486.   return *this;
  487. }
  488.  
  489. /*------------------------------------------------------------------------------
  490. | DrawingArea::button2Down                                                     |
  491. |                                                                              |
  492. | Determine the object under the mouse and start moving.                       |
  493. ------------------------------------------------------------------------------*/
  494. DrawingArea& DrawingArea::button2Down( const IPoint& point )
  495. {
  496.   if (drawState() == notDrawing)
  497.   {
  498.     IGraphicContext gc(this->handle());
  499.     gc.setGraphicBundle(animateBundle);
  500.  
  501.     moveGraphic = graphicList()->topGraphicUnderPoint( point, gc );
  502.     if ( moveGraphic )
  503.     {
  504.       moveRect.setEnclosingRect(moveGraphic->boundingRect( gc ));
  505.       previousPt = point;
  506.       startingPt = point;
  507.       capturePointer();
  508.     }
  509.   }
  510.   return *this;
  511. }
  512.  
  513. /*------------------------------------------------------------------------------
  514. | DrawingArea::mouseMoved                                                      |
  515. |                                                                              |
  516. | Handle button 1 down mouse move events.  This allows data points to be       |
  517. | moved while the object is drawn with a rubber band effect.                   |
  518. ------------------------------------------------------------------------------*/
  519. IBase::Boolean DrawingArea::mouseMoved( IMouseEvent& event )
  520. {
  521.   IGraphicContext gc(this->handle());
  522.   gc.setGraphicBundle(animateBundle);
  523.  
  524.   IPoint point(event.mousePosition());
  525.   if ( hasPointerCaptured() )
  526.   {
  527.     IRectangle windowRect(this->rect());
  528.     windowRect.moveTo(IPoint(0,0));
  529.     if (!windowRect.contains(point))
  530.     {
  531.       if ((short)point.x() < (short)windowRect.left())
  532.         point.setX(windowRect.left());
  533.       else if ((short)point.x() > (short)windowRect.right())
  534.         point.setX(windowRect.right());
  535.       else if ((short)point.y() < (short)windowRect.bottom())
  536.         point.setY(windowRect.bottom());
  537.       else if ((short)point.y() > (short)windowRect.top())
  538.         point.setY(windowRect.top());
  539.  
  540.       IPoint mapPt( IWindow::mapPoint( point,
  541.                                        this->handle(),
  542.                                        IWindow::desktopWindow()->handle()));
  543.  
  544.       IWindow::movePointerTo( mapPt );
  545.     }
  546.   }
  547.  
  548.   // If we're not moving an object
  549.   if (!moveGraphic)
  550.   {
  551.     if ( drawState() == drawing )
  552.     {
  553.       switch (currentObj)
  554.       {
  555.         case pointer:
  556.         break;
  557.         case line:
  558.           ((IGLine*)iGraphic)->drawOn( gc );
  559.           ((IGLine*)iGraphic)->setEndingPoint( point );
  560.           ((IGLine*)iGraphic)->drawOn( gc );
  561.         break;
  562.         case freeHand:
  563.           ((IGPolygon*)iGraphic)->addPoint( point );
  564.           ((IGPolyline*)iGraphic)->IGPolyline::drawOn( gc );
  565.         break;
  566.         case rectangle:
  567.         {
  568.           IRectangle rc(((IGRectangle*)iGraphic)->enclosingRect());
  569.           iGraphic->drawOn( gc );
  570.           rc.sizeTo( rc.size() + point - previousPt );
  571.           ((IGRectangle*)iGraphic)->setEnclosingRect( rc );
  572.           iGraphic->drawOn( gc );
  573.           previousPt = point;
  574.         }
  575.         break;
  576.         case ellipse:
  577.         {
  578.           iGraphic->drawOn( gc );
  579.           IPoint centerPt(((IGEllipse*)iGraphic)->enclosingRect().center());
  580.  
  581.           ((IGEllipse*)iGraphic)->setEnclosingRect(
  582.             ((IGEllipse*)iGraphic)->enclosingRect().sizeTo( IPair(
  583.                                                   abs(2*(point.x() - centerPt.x())),
  584.                                                   abs(2*(point.y() - centerPt.y()))))
  585.                                                .centerAt( centerPt ));
  586.           iGraphic->drawOn( gc );
  587.         }
  588.         break;
  589.         case polyline:
  590.         case polygon:
  591.           ((IGPolyline*)iGraphic)->IGPolyline::drawOn( gc );
  592.           ((IGPolyline*)iGraphic)->setPoint(
  593.                            ((IGPolyline*)iGraphic)->numberOfPoints()-1, point );
  594.           ((IGPolyline*)iGraphic)->IGPolyline::drawOn( gc );
  595.         break;
  596.         case arc:
  597.           if (drawState() != waitingForInput)
  598.           {
  599.             if ( pointCount == 2 )
  600.             {
  601.               IGLine tempLine( ((IG3PointArc*)iGraphic)->startingPoint(), previousPt );
  602.               tempLine.drawOn( gc );
  603.               tempLine.setEndingPoint( point );
  604.               tempLine.drawOn( gc );
  605.               previousPt = point;
  606.             } else if ( pointCount == 3 ) {
  607.               iGraphic->drawOn( gc );
  608.               ((IG3PointArc*)iGraphic)->setEndingPoint( point );
  609.               iGraphic->drawOn( gc );
  610.             }
  611.           } /* endif */
  612.         break;
  613.         case pie:
  614.         case chord:
  615.           if (drawState() != waitingForInput)
  616.           {
  617.             if ( pointCount == 2 )
  618.             {
  619.               IGLine tempLine( ((IGPie*)iGraphic)->enclosingRect().center(), previousPt );
  620.               tempLine.drawOn( gc );
  621.               tempLine.setEndingPoint( point );
  622.               tempLine.drawOn( gc );
  623.               previousPt = point;
  624.             } else if ( pointCount == 3 ) {
  625.               iGraphic->drawOn( gc );
  626.               double sweep(angleFromPoints( ((IGPie*)iGraphic)->enclosingRect().center(), point ));
  627.               if ( sweep < ((IGPie*)iGraphic)->startAngle() )
  628.                 ((IGPie*)iGraphic)->setSweepAngle( 360.0 -
  629.                                     ( ((IGPie*)iGraphic)->startAngle() - sweep ));
  630.               else
  631.                 ((IGPie*)iGraphic)->setSweepAngle( sweep -
  632.                                                 ((IGPie*)iGraphic)->startAngle());
  633.               iGraphic->drawOn( gc );
  634.             }
  635.           } /* endif */
  636.         break;
  637.       } /* endswitch */
  638.     }
  639.   }
  640.   else
  641.   {
  642.     moveRect.drawOn( gc );
  643.     moveRect.translateBy( point - previousPt );
  644.     moveRect.drawOn( gc );
  645.     previousPt = point;
  646.   }
  647.   return false;
  648. }
  649.  
  650. /*------------------------------------------------------------------------------
  651. | DrawingArea::button1Up                                                       |
  652. |                                                                              |
  653. | Handle button 1 up events.  This indicates a data points final location.     |
  654. ------------------------------------------------------------------------------*/
  655. DrawingArea& DrawingArea::button1Up( const IPoint& point )
  656. {
  657.   IGraphicContext gc(this->handle());
  658.   gc.setGraphicBundle(animateBundle);
  659.  
  660.   if ( drawState() == drawing )
  661.   {
  662.     switch (currentObj)
  663.     {
  664.       case pointer:
  665.       break;
  666.       case line:
  667.         ((IGLine*)iGraphic)->setEndingPoint( point );
  668.         iGraphic->setGraphicBundle( currentBundle );
  669.         iGraphic->drawOn( gc );
  670.         setDrawState( notDrawing );
  671.         graphicList()->addAsLast( *iGraphic );
  672.       break;
  673.       case freeHand:
  674.         ((IGPolygon*)iGraphic)->addPoint( point );
  675.         iGraphic->setGraphicBundle( currentBundle );
  676.         iGraphic->drawOn( gc );
  677.         setDrawState( notDrawing );
  678.         graphicList()->addAsLast( *iGraphic );
  679.       break;
  680.       case rectangle:
  681.       {
  682.         IRectangle rc(((IGRectangle*)iGraphic)->enclosingRect());
  683.         rc.sizeTo( rc.size() + point - previousPt );
  684.         ((IGRectangle*)iGraphic)->setEnclosingRect( rc );
  685.         iGraphic->setGraphicBundle( currentBundle );
  686.         iGraphic->drawOn( gc );
  687.         setDrawState( notDrawing );
  688.         graphicList()->addAsLast( *iGraphic );
  689.       }
  690.       break;
  691.       case ellipse:
  692.       {
  693.         IPoint centerPt(((IGEllipse*)iGraphic)->enclosingRect().center());
  694.  
  695.         ((IGEllipse*)iGraphic)->setEnclosingRect(
  696.           ((IGEllipse*)iGraphic)->enclosingRect().sizeTo( IPair(
  697.                                                 abs(2*(point.x() - centerPt.x())),
  698.                                                 abs(2*(point.y() - centerPt.y()))))
  699.                                              .centerAt( centerPt ));
  700.  
  701.         iGraphic->setGraphicBundle( currentBundle );
  702.         iGraphic->drawOn( gc );
  703.         setDrawState( notDrawing );
  704.         graphicList()->addAsLast( *iGraphic );
  705.       }
  706.       break;
  707.       case polyline:
  708.       case polygon:
  709.         previousPt = point;
  710.         ((IGPolyline*)iGraphic)->setPoint(
  711.                          ((IGPolyline*)iGraphic)->numberOfPoints()-1, point );
  712.         setDrawState( waitingForInput );
  713.       break;
  714.       case arc:
  715.       if ( pointCount == 2 )
  716.       {
  717.         ((IG3PointArc*)iGraphic)->setIntermediatePoint( point );
  718.         gc.setMixMode( IGraphicBundle::bitExclusiveOr ).setPenColor( IColor::white );
  719.         IGLine tempLine( ((IG3PointArc*)iGraphic)->startingPoint(), previousPt );
  720.         tempLine.drawOn( gc );
  721.         tempLine.setEndingPoint( point );
  722.         tempLine.drawOn( gc );
  723.         setDrawState( waitingForInput );
  724.       }
  725.       else if ( pointCount == 3 )
  726.       {
  727.         gc.setMixMode( IGraphicBundle::bitExclusiveOr ).setPenColor( IColor::white );
  728.         iGraphic->drawOn( gc );
  729.         ((IG3PointArc*)iGraphic)->setEndingPoint( point );
  730.         iGraphic->setGraphicBundle( currentBundle );
  731.         iGraphic->drawOn( gc );
  732.         setDrawState( notDrawing );
  733.         graphicList()->addAsLast( *iGraphic );
  734.         pointCount = 0;
  735.       }
  736.       break;
  737.       case pie:
  738.       case chord:
  739.       if ( pointCount == 2 )
  740.       {
  741.         gc.setMixMode( IGraphicBundle::bitExclusiveOr ).setPenColor( IColor::white );
  742.         setDrawState( waitingForInput );
  743.         IPoint centerPt(((IGPie*)iGraphic)->enclosingRect().center());
  744.  
  745.         ((IGPie*)iGraphic)->setStartAngle( angleFromPoints( centerPt, point ));
  746.  
  747.         unsigned a(abs(centerPt.x()) - abs(point.x()));
  748.         unsigned b(abs(centerPt.y()) - abs(point.y()));
  749.  
  750.         unsigned long radius((unsigned long)sqrt(a*a + b*b));
  751.  
  752.         ((IGPie*)iGraphic)->setEnclosingRect(
  753.            ((IGPie*)iGraphic)->enclosingRect().expandBy(radius));
  754.       }
  755.       else if ( pointCount == 3 )
  756.       {
  757.         gc.setMixMode( IGraphicBundle::bitExclusiveOr ).setPenColor( IColor::white );
  758.         iGraphic->drawOn( gc );
  759.  
  760.         double sweep(angleFromPoints(
  761.                               ((IGPie*)iGraphic)->enclosingRect().center(), point ));
  762.  
  763.         if ( sweep < ((IGPie*)iGraphic)->startAngle() )
  764.           ((IGPie*)iGraphic)->setSweepAngle( 360.0 -
  765.                                 ( ((IGPie*)iGraphic)->startAngle() - sweep ));
  766.         else
  767.           ((IGPie*)iGraphic)->setSweepAngle( sweep -
  768.                                             ((IGPie*)iGraphic)->startAngle());
  769.  
  770.         iGraphic->setGraphicBundle( currentBundle );
  771.         iGraphic->drawOn( gc );
  772.         setDrawState( notDrawing );
  773.         graphicList()->addAsLast( *iGraphic );
  774.         pointCount = 0;
  775.       }
  776.       break;
  777.       case text:
  778.       {
  779.         IGString* text = new IGString( currentFont().name(), point, currentFont());
  780.         text->setGraphicBundle( currentBundle );
  781.         text->drawOn( gc );
  782.         setDrawState( notDrawing );
  783.         graphicList()->addAsLast( *text );
  784.       }
  785.       break;
  786.       case bitmap:
  787.       {
  788.         IGBitmap *bmp;
  789.         if (bitmapFileName().length() > 0)
  790.         {
  791.           bmp = new IGBitmap(bitmapFileName());
  792.         }
  793.         else
  794.           bmp = new IGBitmap(BMP_EAGLE);
  795.         bmp->moveTo( point );
  796.         bmp->drawOn( gc );
  797.         setDrawState( notDrawing );
  798.         graphicList()->addAsLast( *bmp );
  799.       }
  800.       break;
  801.     } /* endswitch */
  802.   } /* endif */
  803.   return *this;
  804. }
  805.  
  806. /*------------------------------------------------------------------------------
  807. | DrawingArea::button2Up                                                       |
  808. |                                                                              |
  809. ------------------------------------------------------------------------------*/
  810. DrawingArea& DrawingArea::button2Up( const IPoint& point )
  811. {
  812.   IGraphicContext gc(this->handle());
  813.   gc.setGraphicBundle(animateBundle);
  814.  
  815.   if (moveGraphic)
  816.   {
  817.     moveRect.translateBy( point - previousPt );
  818.     moveRect.drawOn( gc );
  819.     moveRect.resetTransformMatrix();
  820.     this->refresh( moveRect.boundingRect(gc).expandBy(1) );
  821.     moveGraphic->translateBy( point - startingPt );
  822.     moveGraphic->drawOn( gc );
  823.     moveGraphic = 0;
  824.     capturePointer(false);
  825.   }
  826.   return *this;
  827. }
  828.  
  829. /*------------------------------------------------------------------------------
  830. | DrawingArea::button1DoubleClick                                              |
  831. |                                                                              |
  832. | Handle button 1 up double click events.  In the case of polyline and polygon |
  833. | a double click indicates the user has finished adding data points to the     |
  834. | object.                                                                      |
  835. ------------------------------------------------------------------------------*/
  836. DrawingArea& DrawingArea::button1DoubleClick( const IPoint& point )
  837. {
  838.   IGraphicContext gc(this->handle());
  839.   gc.setGraphicBundle(animateBundle);
  840.  
  841.   if (drawState() == waitingForInput )
  842.   {
  843.     switch (currentObj)
  844.     {
  845.       case polyline:
  846.       {
  847.         iGraphic->drawOn( gc );
  848.         unsigned lastPt = ((IGPolyline*)iGraphic)->numberOfPoints()-1;
  849.         ((IGPolyline*)iGraphic)->removePoint( lastPt );
  850.         iGraphic->setGraphicBundle( currentBundle );
  851.         iGraphic->drawOn( gc );
  852.         setDrawState( notDrawing );
  853.         graphicList()->addAsLast( *iGraphic );
  854.       }
  855.       break;
  856.       case polygon:
  857.       {
  858.         ((IGPolyline*)iGraphic)->IGPolyline::drawOn( gc );
  859.         unsigned lastPt = ((IGPolygon*)iGraphic)->numberOfPoints()-1;
  860.         ((IGPolygon*)iGraphic)->removePoint( lastPt );
  861.         iGraphic->setGraphicBundle( currentBundle );
  862.         iGraphic->drawOn( gc );
  863.         setDrawState( notDrawing );
  864.         graphicList()->addAsLast( *iGraphic );
  865.       }
  866.       break;
  867.     }
  868.   }
  869.   return *this;
  870. }
  871.  
  872. /*------------------------------------------------------------------------------
  873. | DrawingArea::setDrawState                                                    |
  874. |                                                                              |
  875. |                                                                              |
  876. ------------------------------------------------------------------------------*/
  877. DrawingArea& DrawingArea::setDrawState( const DrawState newState )
  878. {
  879.   dState = newState;
  880.   if (dState == drawing)
  881.   {
  882.     if (!hasPointerCaptured())
  883.       capturePointer();
  884.   }
  885.   else if (dState == notDrawing)
  886.     capturePointer(false);
  887.   return *this;
  888. }
  889.  
  890. /*------------------------------------------------------------------------------
  891. | DrawingArea::setFont                                                         |
  892. |                                                                              |
  893. |                                                                              |
  894. ------------------------------------------------------------------------------*/
  895. DrawingArea& DrawingArea::setCurrentFont( const IFont& font )
  896. {
  897.   currentfont = font;
  898.   return *this;
  899. }
  900.  
  901. /*------------------------------------------------------------------------------
  902. | DrawingArea::font                                                            |
  903. |                                                                              |
  904. |                                                                              |
  905. ------------------------------------------------------------------------------*/
  906. IFont DrawingArea::currentFont( ) const
  907. {
  908.   return currentfont;
  909. }
  910.