home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / VSCPPv8.zip / VACPP / IBMCPP / samples / IOC / 2D-DRAW / 2D-DRAW.CPP < prev    next >
Text File  |  1995-05-01  |  33KB  |  879 lines

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