home *** CD-ROM | disk | FTP | other *** search
/ Power GUI Programming with VisualAge C++ / powergui.iso / powergui / canvas / vportlog / vportlog.cpp < prev    next >
Text File  |  1996-10-29  |  11KB  |  354 lines

  1. //*********************************************************
  2. // Canvas - IViewPort with Logically-sized View Window
  3. //
  4. // Copyright (C) 1994, Law, Leong, Love, Olson, Tsuji.
  5. // Copyright (c) 1997 John Wiley & Sons, Inc. 
  6. // All Rights Reserved.
  7. //*********************************************************
  8. #include <iapp.hpp>
  9. #include <icconst.h>
  10. #include <icolor.hpp>
  11. #include <icoordsy.hpp>
  12. #include <ifont.hpp>
  13. #include <iframe.hpp>
  14. #include <igbundle.hpp>
  15. #include <igline.hpp>
  16. #include <iglist.hpp>
  17. #include <igrect.hpp>
  18. #include <igstring.hpp>
  19. #include <ipoint.hpp>
  20. #include <iscroll.hpp>
  21. #include <istring.hpp>
  22.  
  23. #include "vportlog.hpp"
  24.  
  25. // #define ORIGIN_UPPER_LEFT  1    // Comment out to use lower left.
  26.  
  27. #define NUMBER_COLORS  8
  28. static IColor::Color colorEnums[ NUMBER_COLORS ] =
  29.   { IColor::blue, IColor::darkGreen, IColor::red,
  30.     IColor::darkCyan, IColor::pink, IColor::darkRed,
  31.     IColor::brown, IColor::black };
  32.  
  33. //=================== LogicalSizeViewPort =====================
  34.  
  35. LogicalSizeViewPort::LogicalSizeViewPort
  36.                        ( unsigned long windowId,
  37.                           IWindow* parentAndOwner,
  38.                           unsigned long scale,
  39.                           Boolean  specialScrolling )
  40.   : IViewPort( windowId, parentAndOwner,
  41.                parentAndOwner, IRectangle(),
  42.                IViewPort::classDefaultStyle
  43.                  | IViewPort::noViewWindowFill ),
  44.     clViewWindow( windowId, this, this ),
  45.     clGraphicList( new IGList() ),
  46.     clCustomScrolling( false )
  47. {
  48.   // Physically size the view window to the size of the
  49.   // screen, and leave it positioned at (0, 0).
  50.   ISize
  51.     desktopSize = IWindow::desktopWindow()->size();
  52.   clViewWindow
  53.    .setBackgroundColor( IColor::black )
  54.    .sizeTo( desktopSize );
  55.  
  56.   // Logically size the view window using the scaling factor.
  57.   ISize
  58.     logicalSize( 0x4000 * scale, 0x8000 * scale );
  59.   if ( scale == 0 )
  60.   {                     // <32K logical sizes.
  61.      logicalSize = ISize( 0x4000, 0x7FFF );
  62.   }
  63.   this->setViewWindowSize( logicalSize );
  64.  
  65.   // Increase the "line" scroll amounts by four times.
  66.   IScrollBar
  67.    *horz = this->horizontalScrollBar(),
  68.    *vert = this->verticalScrollBar();
  69.   (*horz)
  70.    .setMinScrollIncrement( horz->minScrollIncrement() * 4 );
  71.   (*vert)
  72.    .setMinScrollIncrement( vert->minScrollIncrement() * 4 );
  73.  
  74.   // Also change the page scroll amounts?
  75.   if ( specialScrolling )
  76.   {           // Set a flag to be used in setupScrollBars.
  77.      clCustomScrolling = true;
  78.   }
  79. } // LogicalSizeViewPort ctor
  80.  
  81. LogicalSizeViewPort::~LogicalSizeViewPort ( )
  82. {
  83.   this->cleanUpGraphicList();
  84.   delete clGraphicList;
  85. }
  86.  
  87. LogicalSizeViewPort& LogicalSizeViewPort::setupScrollBars ( )
  88. {
  89.   this->IViewPort::setupScrollBars();
  90.  
  91.   // Modify the page scrolling amounts if necessary.  We do this
  92.   // here because IViewPort::setupScrollBars resets the page
  93.   // scroll amounts to their default values in logical size
  94.   // units when the logical view window size exceeds 32K.
  95.   // Otherwise, the scroll bars would do page scrolling using
  96.   // scaled values instead of logical values.
  97.   if ( clCustomScrolling )
  98.   {
  99.      IScrollBar
  100.       *horz = this->horizontalScrollBar(),
  101.       *vert = this->verticalScrollBar();
  102.      (*horz)
  103.       .setPageScrollIncrement
  104.            ( horz->pageScrollIncrement() / 2 );
  105.      (*vert)
  106.       .setPageScrollIncrement
  107.            ( vert->pageScrollIncrement() / 2 );
  108.   }
  109.  
  110.   return *this;
  111. }
  112.  
  113. LogicalSizeViewPort& LogicalSizeViewPort::positionViewWindow
  114.                             ( const IWindowHandle& viewWindow,
  115.                               const IRectangle& viewRectangle )
  116. {
  117.   // Do not call IViewPort::positionViewWindow, which scrolls
  118.   // the window.
  119.  
  120.   // Prepare the view window so it appears to scroll when it
  121.   // paints; then force it to paint.
  122.   this->buildGraphicList();
  123.   clViewWindow
  124.    .refresh();
  125.  
  126.   return *this;
  127. }
  128.  
  129. LogicalSizeViewPort& LogicalSizeViewPort::buildGraphicList ( )
  130. {
  131.   this->cleanUpGraphicList();   // Empty previous contents.
  132.  
  133.   // Initialize drawing variables.
  134.   unsigned long
  135.     blockWidth  = 0x0100,           // 256
  136.     verticalLabelSpacing = 0x0080,  // 128
  137.     fontHeight = IFont( this ).maxCharHeight();
  138.   IGraphicBundle
  139.     colorBlockBundle,
  140.     dividerBundle,
  141.     offsetTextBundle;
  142.   colorBlockBundle
  143.    .setBackgroundMixMode( IGraphicBundle::backOverPaint )
  144.    .setDrawOperation( IGraphicBundle::fill );
  145.   dividerBundle
  146.    .setPenColor( IColor::yellow )
  147.    .setPenWidth( 1 );
  148.   offsetTextBundle
  149.    .setPenColor( IColor::yellow );
  150.  
  151.   // Figure out where we are so we can do width-dependent
  152.   // painting of colors and horizontal offsets.  Because the
  153.   // drawing canvas is only being logically scrolled, its size
  154.   // and position do not change.  However, the view port tells
  155.   // us where it considers the drawing canvas to be.  The
  156.   // portion that it considers visible is what we store in
  157.   // logicalVisibleRect.  What is actually visible is in
  158.   // trueVisibleRect.
  159.   IRectangle
  160.     logicalVisibleRect = this->viewWindowDrawRectangle(),
  161.     trueVisibleRect = logicalVisibleRect.movedTo( IPoint() );
  162.   long
  163.     x = logicalVisibleRect.minX();
  164.   unsigned long
  165.     xIndex = x / blockWidth;   // Which block of color?
  166.  
  167.   // Create the background blocks of color, their dividers, and
  168.   // their their labels from left to right.
  169.   while ( x < logicalVisibleRect.maxX() )
  170.   {
  171.     // Create a block of color that fills the entire height.
  172.     IColor
  173.       bgColor( colorEnums[ xIndex % NUMBER_COLORS ] );
  174.     unsigned long
  175.       x2 = (xIndex + 1) * blockWidth - 1;
  176.     Boolean
  177.       rightEdge = true;
  178.     if ( x2 > logicalVisibleRect.maxX() )
  179.     {         // Right edge of block is clipped.
  180.        x2 = logicalVisibleRect.maxX();
  181.        rightEdge = false;
  182.     }
  183.     IRectangle
  184.       colorRect( IPoint( x - logicalVisibleRect.minX(),
  185.                          trueVisibleRect.minY() ),
  186.                  IPoint( x2 - logicalVisibleRect.minX(),
  187.                          trueVisibleRect.maxY() ) );
  188.     IGRectangle
  189.      *colorBlock = new IGRectangle( colorRect );
  190.     colorBlockBundle
  191.      .setFillColor( bgColor );
  192.     ( *colorBlock )
  193.      .setGraphicBundle( colorBlockBundle );
  194.     ( *clGraphicList )
  195.      .addAsLast( *colorBlock );
  196.  
  197.     // Create a divider between this and the next block of color.
  198.     if ( rightEdge )
  199.     {                // Right edge is visible.
  200.        IGLine
  201.         *divider =
  202.            new IGLine( IPoint( x2 - logicalVisibleRect.minX(),
  203.                                trueVisibleRect.minY() ),
  204.                        IPoint( x2 - logicalVisibleRect.minX(),
  205.                                trueVisibleRect.maxY() ) );
  206.        ( *divider )
  207.         .setGraphicBundle( dividerBundle );
  208.        ( *clGraphicList )
  209.         .addAsLast( *divider );
  210.     }
  211.  
  212.     // Create a label at the left edge of the color block for
  213.     // the logical horizontal offset.
  214.     if ( ! ( x % blockWidth ) )
  215.     {         // The left edge of the color block is showing.
  216.        IGString
  217.         *offset =
  218.            new IGString( IString( xIndex * blockWidth ),
  219. #ifdef ORIGIN_UPPER_LEFT
  220.                          IPoint( x - logicalVisibleRect.minX(),
  221.                                  trueVisibleRect.maxY() -
  222.                                    fontHeight ) );
  223. #else
  224.                          IPoint( x - logicalVisibleRect.minX(), 0 ) );
  225. #endif
  226.        ( *offset )
  227.         .setGraphicBundle( offsetTextBundle );
  228.        ( *clGraphicList )
  229.         .addAsLast( *offset );
  230.     }
  231.  
  232.     x = x2 + 1;
  233.     xIndex++;
  234.   }
  235.  
  236.   // Figure out where we are so we can do height-dependent
  237.   // painting of the vertical offsets.
  238.   long
  239. #ifdef ORIGIN_UPPER_LEFT
  240.     y = logicalVisibleRect.minY(),
  241. #else
  242.     y = this->viewWindowSize().height() - logicalVisibleRect.maxY(),
  243. #endif
  244.     yOffsetBase = y,
  245.     logicalVisibleBottom = y + logicalVisibleRect.height(),
  246.     yIndex = y / verticalLabelSpacing;
  247.  
  248.   // Create labels for identifying vertical offsets from top to
  249.   // bottom.
  250.   while ( y < logicalVisibleBottom )
  251.   {
  252.     unsigned long
  253.       y2 = (yIndex + 1) * verticalLabelSpacing;
  254.     if ( y2 - fontHeight < logicalVisibleBottom )
  255.     {              // This vertical offset is visible.
  256.        IGString
  257.         *offset =
  258.            new IGString( IString( y2 ),
  259.                          IPoint( 10,
  260. #ifdef ORIGIN_UPPER_LEFT
  261.                                  y2 - yOffsetBase - fontHeight ) );
  262. #else
  263.                                  trueVisibleRect.minY() +
  264.                                    trueVisibleRect.height() -
  265.                                    ( y2 - yOffsetBase ) ) );
  266. #endif
  267.        offsetTextBundle
  268.         .setPenColor( IColor::white );
  269.        ( *offset )
  270.         .setGraphicBundle( offsetTextBundle );
  271.        ( *clGraphicList )
  272.         .addAsLast( *offset );
  273.     }
  274.  
  275.     y = y2 + 1;
  276.     yIndex++;
  277.   }
  278.  
  279.   clViewWindow
  280.    .setGraphicList( clGraphicList );
  281.  
  282.   return *this;
  283. } // LogicalSizeViewPort::buildGraphicList
  284.  
  285. LogicalSizeViewPort& LogicalSizeViewPort::cleanUpGraphicList ( )
  286. {
  287.   // Clean out the contents of the graphic list.
  288.   unsigned long
  289.     count = clGraphicList->numberOfGraphics();
  290.   while ( count-- )
  291.   {
  292.     IGraphic
  293.      *graphic = clGraphicList->firstGraphic();
  294.     clGraphicList->removeFirst();
  295.     delete graphic;
  296.   }
  297.   return *this;
  298. }
  299.  
  300. //========================== Main =============================
  301.  
  302. void main( int argc, char *argv[] )
  303. {
  304. #ifdef ORIGIN_UPPER_LEFT
  305.   ICoordinateSystem::setApplicationOrientation
  306.                         ( ICoordinateSystem::originUpperLeft );
  307. #else
  308.   ICoordinateSystem::setApplicationOrientation
  309.                         ( ICoordinateSystem::originLowerLeft );
  310. #endif
  311.  
  312.   // This .exe take two optional command line arguments.
  313.   // The first is a "scale" value, which specifies the multiples
  314.   // of 0x4000 for width and 0x8000 for height that the view
  315.   // port should logically size its view window.  A value of
  316.   // zero means to use (0x4000, 0x7FFF), so that IViewPort does
  317.   // not need to use special processing to emulate scrolling
  318.   // beyond the limits of the scroll bar.  The default is to use
  319.   // 0x4000 x 0x8000.
  320.   // A second argument means that the default scroll amounts
  321.   // should not be used.
  322.   long
  323.     scale = 1;
  324.   Boolean
  325.     specialScrolling = false;
  326.  
  327.   if ( argc > 1 )
  328.   {                     // First argument is scale.
  329.      scale = IString( argv[1] ).asInt();
  330.      if ( scale < 0 )
  331.      {                  // Valid values are 0 or greater.
  332.         scale = 1;      // 1 is default.
  333.      }
  334.      if ( argc > 2 )
  335.      {                  // Second command line argument.
  336.         specialScrolling = true;
  337.      }
  338.   }
  339.  
  340.   // Create the frame window and its client view port.
  341.   IFrameWindow
  342.     frame( "View Port with Logically-Sized View Window" );
  343.   LogicalSizeViewPort
  344.     vport( IC_FRAME_CLIENT_ID, &frame,
  345.            scale, specialScrolling );
  346.  
  347.   // Show it all now.
  348.   frame
  349.    .setFocus()
  350.    .show();
  351.  
  352.   IApplication::current().run();
  353. }
  354.