home *** CD-ROM | disk | FTP | other *** search
/ PC Direkt 1995 March / PCD_395.iso / starview / pm2csci / german / scrwin.cx_ / SCRWIN.CXX
Encoding:
C/C++ Source or Header  |  1994-06-23  |  16.7 KB  |  507 lines

  1. //==================================================================
  2. // window with virtual output-area and scrollbars
  3. // (C) 1992-1994 StarDivision GmbH, Hamburg, Germany
  4. //------------------------------------------------------------------
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7.  
  8. #define _SVT_SCRWIN_CXX
  9. #include "scrwin.hxx"
  10.  
  11. //===================================================================
  12.  
  13. void ScrollableWindow::Initialize( ScrollableWindowFlags nFlags )
  14. {
  15.     aCornerWin.ChangeBackgroundBrush( Brush( Color(COL_SCROLLBAR) ) );
  16.  
  17.     bHandleDragging = (BOOL) ( nFlags & SCRWIN_THUMBDRAGGING );
  18.     bVCenter = (nFlags & SCRWIN_VCENTER) == SCRWIN_VCENTER;
  19.     bHCenter = (nFlags & SCRWIN_HCENTER) == SCRWIN_HCENTER;
  20.     bScrolling = FALSE;
  21.  
  22.     // set the handlers for the scrollbars
  23.     aVScroll.ChangeScrollHdl( LINK(this, ScrollableWindow, ScrollHdl) );
  24.     aHScroll.ChangeScrollHdl( LINK(this, ScrollableWindow, ScrollHdl) );
  25.     aVScroll.ChangeEndScrollHdl( LINK(this, ScrollableWindow, EndScrollHdl) );
  26.     aHScroll.ChangeEndScrollHdl( LINK(this, ScrollableWindow, EndScrollHdl) );
  27.  
  28.     // get the default width
  29.     nScrPixW = aVScroll.GetSizePixel().Width();
  30.     nColumnPixW = nScrPixW;
  31.     nScrPixH = aHScroll.GetSizePixel().Height();
  32.     nLinePixH = nScrPixH;
  33. }
  34.  
  35. //-------------------------------------------------------------------
  36.  
  37. ScrollableWindow::ScrollableWindow( Window* pParent, WinBits nBits,
  38.                                     ScrollableWindowFlags nFlags ):
  39.     Window( pParent, WinBits(nBits|WB_CLIPCHILDREN) ),
  40.     aVScroll( this, WinBits(WB_VSCROLL | WB_DRAG) ),
  41.     aHScroll( this, WinBits(WB_HSCROLL | WB_DRAG) ),
  42.     aCornerWin( this )
  43. { Initialize( nFlags ); }
  44.  
  45. //-------------------------------------------------------------------
  46.  
  47. ScrollableWindow::ScrollableWindow( Window* pParent, const ResId& rId,
  48.                                     ScrollableWindowFlags nFlags ):
  49.     Window( pParent, rId ),
  50.     aVScroll( this, WinBits(WB_VSCROLL | WB_DRAG) ),
  51.     aHScroll( this, WinBits(WB_HSCROLL | WB_DRAG) ),
  52.     aCornerWin( this )
  53. { Initialize( nFlags ); }
  54.  
  55. //-------------------------------------------------------------------
  56.  
  57. Size ScrollableWindow::GetOutputSizePixel() const
  58. {
  59.     Size aSz( Window::GetOutputSizePixel() );
  60.     if ( aHScroll.IsVisible() )
  61.         aSz.Height() -= nScrPixH;
  62.     if ( aVScroll.IsVisible() )
  63.         aSz.Width() -= nScrPixW;
  64.     return aSz;
  65. }
  66.  
  67. //-------------------------------------------------------------------
  68.  
  69. Size ScrollableWindow::GetOutputSize() const
  70. {
  71.     Size aSz( Window::GetOutputSizePixel() );
  72.     if ( aHScroll.IsVisible() )
  73.         aSz.Height() -= nScrPixH;
  74.     if ( aVScroll.IsVisible() )
  75.         aSz.Width() -= nScrPixW;
  76.     return PixelToLogic( aSz );
  77. }
  78.  
  79. //-------------------------------------------------------------------
  80.  
  81. void ScrollableWindow::EndScrollHdl( ScrollBar* pScroll )
  82. {
  83.     // notify the start of scrolling, if not already scrolling
  84.     if ( !bScrolling )
  85.         StartScroll(), bScrolling = TRUE;
  86.  
  87.     // get the delta in logic coordinates
  88.     Size aDelta( PixelToLogic(
  89.         Size( aHScroll.GetDelta(), aVScroll.GetDelta() ) ) );
  90.  
  91.     // scroll the window, if this is not already done
  92.     if ( !bHandleDragging )
  93.         if ( pScroll == &aHScroll )
  94.             Scroll( aDelta.Width(), 0 );
  95.         else
  96.             Scroll( 0, aDelta.Height() );
  97.  
  98.     // notify the end of scrolling
  99.     bScrolling = FALSE;
  100.     EndScroll( aDelta.Width(), aDelta.Height() );
  101. }
  102.  
  103. //-------------------------------------------------------------------
  104.  
  105. void ScrollableWindow::ScrollHdl( ScrollBar* pScroll )
  106. {
  107.     // notify the start of scrolling, if not already scrolling
  108.     if ( !bScrolling )
  109.         StartScroll(), bScrolling = TRUE;
  110.  
  111.     if ( bHandleDragging )
  112.     {
  113.         // get the delta in logic coordinates
  114.         Size aDelta( PixelToLogic(
  115.             Size( aHScroll.GetDelta(), aVScroll.GetDelta() ) ) );
  116.         if ( pScroll == &aHScroll )
  117.             Scroll( aDelta.Width(), 0 );
  118.         else
  119.             Scroll( 0, aDelta.Height() );
  120.     }
  121. }
  122.  
  123. //-------------------------------------------------------------------
  124.  
  125. void ScrollableWindow::Resize()
  126. {
  127.     // get the new output-size in pixel
  128.     Size aOutPixSz = Window::GetOutputSizePixel();
  129.  
  130.     // determine the size of the output-area and if we need scrollbars
  131.     BOOL bVVisible = FALSE; // by default no vertical-ScrollBar
  132.     BOOL bHVisible = FALSE; // by default no horizontal-ScrollBar
  133.     BOOL bChanged;          // determines if a visiblility was changed
  134.     do
  135.     {
  136.         bChanged = FALSE;
  137.  
  138.         // does we need a vertical ScrollBar
  139.         if ( aOutPixSz.Width() < aTotPixSz.Width() && !bHVisible )
  140.         {   bHVisible = TRUE;
  141.             aOutPixSz.Height() -= nScrPixH;
  142.             bChanged = TRUE;
  143.         }
  144.  
  145.         // does we need a horizontal ScrollBar
  146.         if ( aOutPixSz.Height() < aTotPixSz.Height() && !bVVisible )
  147.         {   bVVisible = TRUE;
  148.             aOutPixSz.Width() -= nScrPixW;
  149.             bChanged = TRUE;
  150.         }
  151.  
  152.     } while ( bChanged );   // until no visibility has changed
  153.  
  154.     // store the old offset and map-mode
  155.     MapMode aMap( GetMapMode() );
  156.     Point aOldPixOffset( aPixOffset );
  157.  
  158.     // justify (right/bottom borders should never exceed the virtual window)
  159.     Size aPixDelta;
  160.     if ( aPixOffset.X() < 0 &&
  161.          aPixOffset.X() + aTotPixSz.Width() < aOutPixSz.Width() )
  162.         aPixDelta.Width() =
  163.             aOutPixSz.Width() - ( aPixOffset.X() + aTotPixSz.Width() );
  164.     if ( aPixOffset.Y() < 0 &&
  165.          aPixOffset.Y() + aTotPixSz.Height() < aOutPixSz.Height() )
  166.         aPixDelta.Height() =
  167.             aOutPixSz.Height() - ( aPixOffset.Y() + aTotPixSz.Height() );
  168.     if ( aPixDelta.Width() || aPixDelta.Height() )
  169.     {
  170.         aPixOffset.X() += aPixDelta.Width();
  171.         aPixOffset.Y() += aPixDelta.Height();
  172.     }
  173.  
  174.     // for axis without scrollbar restore the origin
  175.     if ( !bVVisible || !bHVisible )
  176.     {
  177.         aPixOffset = Point(
  178.                      bHVisible
  179.                      ? aPixOffset.X()
  180.                      : ( bHCenter
  181.                             ? (aOutPixSz.Width()-aTotPixSz.Width()) / 2
  182.                             : 0 ),
  183.                      bVVisible
  184.                      ? aPixOffset.Y()
  185.                      : ( bVCenter
  186.                             ? (aOutPixSz.Height()-aTotPixSz.Height()) / 2
  187.                             : 0 ) );
  188.     }
  189.     if ( bHVisible && !aHScroll.IsVisible() )
  190.         aPixOffset.X() = 0;
  191.     if ( bVVisible && !aVScroll.IsVisible() )
  192.         aPixOffset.Y() = 0;
  193.  
  194.     // select the shifted map-mode
  195.     if ( aPixOffset != aOldPixOffset )
  196.     {
  197.         Window::ChangeMapMode( MapMode(MAP_PIXEL) );
  198.         Window::Scroll(
  199.             aPixOffset.X() - aOldPixOffset.X(),
  200.             aPixOffset.Y() - aOldPixOffset.Y() );
  201.         ChangeMapMode( aMap );
  202.     }
  203.  
  204.     // show or hide scrollbars
  205.     if ( bVVisible ) aVScroll.Show(); else aVScroll.Hide(), ToTop();
  206.     if ( bHVisible ) aHScroll.Show(); else aHScroll.Hide(), ToTop();
  207.  
  208.     // disable painting in the corner between the scrollbars
  209.     if ( bVVisible && bHVisible )
  210.     {
  211.         aCornerWin.SetPosSizePixel(
  212.             *((Point*) &aOutPixSz), Size(nScrPixW, nScrPixH) );
  213.         aCornerWin.Show();
  214.     }
  215.     else
  216.         aCornerWin.Hide();
  217.  
  218.     // resize scrollbars and set their ranges
  219.     if ( bHVisible )
  220.     {
  221.         aHScroll.SetPosSizePixel(
  222.             Point( 0, aOutPixSz.Height() ),
  223.             Size( aOutPixSz.Width(), nScrPixH ) );
  224.         aHScroll.ChangeRange( Range(0, aTotPixSz.Width()) );
  225.         aHScroll.ChangePageSize( aOutPixSz.Width() );
  226.         aHScroll.ChangeVisibleSize( aOutPixSz.Width() );
  227.         aHScroll.ChangeLineSize( nColumnPixW );
  228.         aHScroll.ChangeThumbPos( -aPixOffset.X() );
  229.     }
  230.     if ( bVVisible )
  231.     {
  232.         aVScroll.SetPosSizePixel(
  233.             Point( aOutPixSz.Width(), 0 ),
  234.             Size( nScrPixW, aOutPixSz.Height() ) );
  235.         aVScroll.ChangeRange( Range(0, aTotPixSz.Height()) );
  236.         aVScroll.ChangePageSize( aOutPixSz.Height() );
  237.         aVScroll.ChangeVisibleSize( aOutPixSz.Height() );
  238.         aVScroll.ChangeLineSize( nLinePixH );
  239.         aVScroll.ChangeThumbPos( -aPixOffset.Y() );
  240.     }
  241. }
  242.  
  243. //-------------------------------------------------------------------
  244.  
  245. void ScrollableWindow::StartScroll()
  246. {
  247. }
  248.  
  249. //-------------------------------------------------------------------
  250.  
  251. void ScrollableWindow::EndScroll( short nDeltaX, short nDeltaY )
  252. {
  253. }
  254.  
  255. //-------------------------------------------------------------------
  256.  
  257. MapMode ScrollableWindow::ChangeMapMode( const MapMode& rNewMapMode )
  258. {
  259.     MapMode aMap( rNewMapMode );
  260.     aMap.ChangeOrigin( aMap.GetOrigin() + PixelToLogic(aPixOffset, aMap) );
  261.     return Window::ChangeMapMode( aMap );
  262. }
  263.  
  264. //-------------------------------------------------------------------
  265.  
  266. MapMode ScrollableWindow::GetMapMode() const
  267. {
  268.     MapMode aMap( Window::GetMapMode() );
  269.     aMap.ChangeOrigin( aMap.GetOrigin() - PixelToLogic(aPixOffset) );
  270.     return aMap;
  271. }
  272.  
  273. //-------------------------------------------------------------------
  274.  
  275. void ScrollableWindow::SetTotalSize( const Size& rNewSize )
  276. {
  277.     aTotPixSz = LogicToPixel(rNewSize);
  278.     ScrollableWindow::Resize();
  279. }
  280.  
  281. //-------------------------------------------------------------------
  282.  
  283. void ScrollableWindow::SetVisibleSize( const Size& rNewSize )
  284. {
  285.     // get the rectangle, we wish to view
  286.     Rectangle aWish( Point(0, 0), LogicToPixel(rNewSize) );
  287.  
  288.     // get maximum rectangle for us from our parent-window (subst our border!)
  289.     Rectangle aMax( Point(0, 0), GetParent()->GetOutputSizePixel() );
  290.     aMax.Left() -=  ( Window::GetSizePixel().Width() -
  291.                     Window::GetOutputSizePixel().Width() );
  292.     aMax.Bottom() -= (Window::GetSizePixel().Height() -
  293.                      Window::GetOutputSizePixel().Height());
  294.  
  295.     Size aWill( aWish.GetIntersection(aMax).GetSize() );
  296.     BOOL bHScroll = FALSE;
  297.     if ( aWill.Width() < aWish.GetSize().Width() )
  298.     {   bHScroll = TRUE;
  299.         aWill.Height() =
  300.             min( aWill.Height()+nScrPixH, aMax.GetSize().Height() );
  301.     }
  302.     if ( aWill.Height() < aWish.GetSize().Height() )
  303.         aWill.Width() =
  304.             min( aWill.Width()+nScrPixW, aMax.GetSize().Width() );
  305.     if ( !bHScroll && (aWill.Width() < aWish.GetSize().Width()) )
  306.         aWill.Height() =
  307.             min( aWill.Height()+nScrPixH, aMax.GetSize().Height() );
  308.     Window::ChangeOutputSizePixel( aWill );
  309. }
  310.  
  311. //-------------------------------------------------------------------
  312.  
  313. BOOL ScrollableWindow::MakeVisible( const Rectangle& rTarget, BOOL bSloppy )
  314. {
  315.     Rectangle aTarget;
  316.     Rectangle aTotRect( Point(0, 0), PixelToLogic( aTotPixSz ) );
  317.  
  318.     if ( bSloppy )
  319.     {
  320.         aTarget = rTarget;
  321.  
  322.         // at maximum to right border
  323.         if ( aTarget.Right() > aTotRect.Right() )
  324.         {
  325.             short nDelta = aTarget.Right() - aTotRect.Right();
  326.             aTarget.Left() -= nDelta;
  327.             aTarget.Right() -= nDelta;
  328.  
  329.             // too wide?
  330.             if ( aTarget.Left() < aTotRect.Left() )
  331.                 aTarget.Left() = aTotRect.Left();
  332.         }
  333.  
  334.         // at maximum to bottom border
  335.         if ( aTarget.Bottom() > aTotRect.Bottom() )
  336.         {
  337.             short nDelta = aTarget.Bottom() - aTotRect.Bottom();
  338.             aTarget.Top() -= nDelta;
  339.             aTarget.Bottom() -= nDelta;
  340.  
  341.             // too high?
  342.             if ( aTarget.Top() < aTotRect.Top() )
  343.                 aTarget.Top() = aTotRect.Top();
  344.         }
  345.  
  346.         // at maximum to left border
  347.         if ( aTarget.Left() < aTotRect.Left() )
  348.         {
  349.             short nDelta = aTarget.Left() - aTotRect.Left();
  350.             aTarget.Right() -= nDelta;
  351.             aTarget.Left() -= nDelta;
  352.  
  353.             // too wide?
  354.             if ( aTarget.Right() > aTotRect.Right() )
  355.                 aTarget.Right() = aTotRect.Right();
  356.         }
  357.  
  358.         // at maximum to top border
  359.         if ( aTarget.Top() < aTotRect.Top() )
  360.         {
  361.             short nDelta = aTarget.Top() - aTotRect.Top();
  362.             aTarget.Bottom() -= nDelta;
  363.             aTarget.Top() -= nDelta;
  364.  
  365.             // too high?
  366.             if ( aTarget.Bottom() > aTotRect.Bottom() )
  367.                 aTarget.Bottom() = aTotRect.Bottom();
  368.         }
  369.     }
  370.     else
  371.         aTarget = rTarget.GetIntersection( aTotRect );
  372.  
  373.     // is the area already visible?
  374.     Rectangle aVisArea( GetVisibleArea() );
  375.     if ( aVisArea.IsInside(rTarget) )
  376.         return TRUE;
  377.  
  378.     // is there somewhat to scroll?
  379.     if ( aVisArea.TopLeft() != aTarget.TopLeft() )
  380.     {
  381.         Rectangle aBox( aTarget.GetUnion(aVisArea) );
  382.         short nDeltaX = ( aBox.Right() - aVisArea.Right() ) +
  383.                         ( aBox.Left() - aVisArea.Left() );
  384.         short nDeltaY = ( aBox.Top() - aVisArea.Top() ) +
  385.                         ( aBox.Bottom() - aVisArea.Bottom() );
  386.         Scroll( nDeltaX, nDeltaY );
  387.     }
  388.  
  389.     // determine if the target is completely visible
  390.     return aVisArea.GetWidth() >= aTarget.GetWidth() &&
  391.            aVisArea.GetHeight() >= aTarget.GetHeight();
  392. }
  393.  
  394. //-------------------------------------------------------------------
  395.  
  396. Rectangle ScrollableWindow::GetVisibleArea() const
  397. {
  398.     Point aTopLeft( PixelToLogic( Point() ) );
  399.     Size aSz( GetOutputSize() );
  400.     return Rectangle( aTopLeft, aSz );
  401. }
  402.  
  403. //-------------------------------------------------------------------
  404.  
  405. void ScrollableWindow::SetLineSize( USHORT nHorz, USHORT nVert )
  406. {
  407.     Size aPixSz( LogicToPixel( Size(nHorz, nVert) ) );
  408.     nColumnPixW = aPixSz.Width();
  409.     nLinePixH = aPixSz.Height();
  410.     aVScroll.ChangeLineSize( nLinePixH );
  411.     aHScroll.ChangeLineSize( nColumnPixW );
  412. }
  413.  
  414. //-------------------------------------------------------------------
  415.  
  416. void ScrollableWindow::Scroll( short nDeltaX, short nDeltaY )
  417. {
  418.     if ( !bScrolling )
  419.         StartScroll();
  420.  
  421.     // get the delta in pixel
  422.     Size aDeltaPix( LogicToPixel( Size(nDeltaX, nDeltaY) ) );
  423.     Size aOutPixSz( GetOutputSizePixel() );
  424.     MapMode aMap( GetMapMode() );
  425.     Point aNewPixOffset( aPixOffset );
  426.  
  427.     // scrolling horizontally?
  428.     if ( nDeltaX != 0 )
  429.     {
  430.         aNewPixOffset.X() -= aDeltaPix.Width();
  431.         if ( ( aOutPixSz.Width() - aNewPixOffset.X() ) > aTotPixSz.Width() )
  432.             aNewPixOffset.X() = - ( aTotPixSz.Width() - aOutPixSz.Width() );
  433.         else if ( aNewPixOffset.X() > 0 )
  434.             aNewPixOffset.X() = 0;
  435.     }
  436.  
  437.     // scrolling vertically?
  438.     if ( nDeltaY != 0 )
  439.     {
  440.         aNewPixOffset.Y() -= aDeltaPix.Height();
  441.         if ( ( aOutPixSz.Height() - aNewPixOffset.Y() ) > aTotPixSz.Height() )
  442.             aNewPixOffset.Y() = - ( aTotPixSz.Height() - aOutPixSz.Height() );
  443.         else if ( aNewPixOffset.Y() > 0 )
  444.             aNewPixOffset.Y() = 0;
  445.     }
  446.  
  447.     // recompute the logical scroll units
  448.     aDeltaPix.Width() = aPixOffset.X() - aNewPixOffset.X();
  449.     aDeltaPix.Height() = aPixOffset.Y() - aNewPixOffset.Y();
  450.     Size aDelta( PixelToLogic(aDeltaPix) );
  451.     nDeltaX = aDelta.Width();
  452.     nDeltaY = aDelta.Height();
  453.     aPixOffset = aNewPixOffset;
  454.  
  455.     // scrolling?
  456.     if ( nDeltaX != 0 || nDeltaY != 0 )
  457.     {
  458.         Update();
  459.  
  460.         // does the new area overlap the old one?
  461.         if ( abs( aDeltaPix.Height() ) < aOutPixSz.Height() ||
  462.              abs( aDeltaPix.Width() ) < aOutPixSz.Width() )
  463.         {
  464.             // scroll the overlapping area
  465.             ChangeMapMode(aMap);
  466.  
  467.             // never scroll the scrollbars itself!
  468.             Window::Scroll(-nDeltaX, -nDeltaY,
  469.                 PixelToLogic( Rectangle( Point(0, 0), aOutPixSz ) ) );
  470.         }
  471.         else
  472.             // repaint all
  473.             ChangeMapMode(aMap), Invalidate();
  474.  
  475.         Update();
  476.     }
  477.  
  478.     if ( !bScrolling )
  479.     {
  480.         EndScroll( nDeltaX, nDeltaY );
  481.         if ( nDeltaX )
  482.             aHScroll.ChangeThumbPos( -aPixOffset.X() );
  483.         if ( nDeltaY )
  484.             aVScroll.ChangeThumbPos( -aPixOffset.Y() );
  485.     }
  486. }
  487.  
  488. //-------------------------------------------------------------------
  489.  
  490. void ScrollableWindow::ScrollLines( short nLinesX, short nLinesY )
  491. {
  492.     Size aDelta( PixelToLogic( Size( nColumnPixW, nLinePixH ) ) );
  493.     Scroll( aDelta.Width()*nLinesX, aDelta.Height()*nLinesY );
  494. }
  495.  
  496. //-------------------------------------------------------------------
  497.  
  498. void ScrollableWindow::ScrollPages( short nPagesX, USHORT nOverlapX,
  499.                                 short nPagesY, USHORT nOverlapY )
  500. {
  501.     Size aOutSz( GetVisibleArea().GetSize() );
  502.     Scroll( nPagesX * aOutSz.Width() + (nPagesX>0 ? 1 : -1) * nOverlapX,
  503.             nPagesY * aOutSz.Height() + (nPagesY>0 ? 1 : -1) * nOverlapY );
  504. }
  505.  
  506. //==================================================================
  507.