home *** CD-ROM | disk | FTP | other *** search
- //==================================================================
- // window with virtual output-area and scrollbars
- // (C) 1992-1994 StarDivision GmbH, Hamburg, Germany
- //------------------------------------------------------------------
- #include <stdlib.h>
- #include <stdio.h>
-
- #define _SVT_SCRWIN_CXX
- #include "scrwin.hxx"
-
- //===================================================================
-
- void ScrollableWindow::Initialize( ScrollableWindowFlags nFlags )
- {
- aCornerWin.ChangeBackgroundBrush( Brush( Color(COL_SCROLLBAR) ) );
-
- bHandleDragging = (BOOL) ( nFlags & SCRWIN_THUMBDRAGGING );
- bVCenter = (nFlags & SCRWIN_VCENTER) == SCRWIN_VCENTER;
- bHCenter = (nFlags & SCRWIN_HCENTER) == SCRWIN_HCENTER;
- bScrolling = FALSE;
-
- // set the handlers for the scrollbars
- aVScroll.ChangeScrollHdl( LINK(this, ScrollableWindow, ScrollHdl) );
- aHScroll.ChangeScrollHdl( LINK(this, ScrollableWindow, ScrollHdl) );
- aVScroll.ChangeEndScrollHdl( LINK(this, ScrollableWindow, EndScrollHdl) );
- aHScroll.ChangeEndScrollHdl( LINK(this, ScrollableWindow, EndScrollHdl) );
-
- // get the default width
- nScrPixW = aVScroll.GetSizePixel().Width();
- nColumnPixW = nScrPixW;
- nScrPixH = aHScroll.GetSizePixel().Height();
- nLinePixH = nScrPixH;
- }
-
- //-------------------------------------------------------------------
-
- ScrollableWindow::ScrollableWindow( Window* pParent, WinBits nBits,
- ScrollableWindowFlags nFlags ):
- Window( pParent, WinBits(nBits|WB_CLIPCHILDREN) ),
- aVScroll( this, WinBits(WB_VSCROLL | WB_DRAG) ),
- aHScroll( this, WinBits(WB_HSCROLL | WB_DRAG) ),
- aCornerWin( this )
- { Initialize( nFlags ); }
-
- //-------------------------------------------------------------------
-
- ScrollableWindow::ScrollableWindow( Window* pParent, const ResId& rId,
- ScrollableWindowFlags nFlags ):
- Window( pParent, rId ),
- aVScroll( this, WinBits(WB_VSCROLL | WB_DRAG) ),
- aHScroll( this, WinBits(WB_HSCROLL | WB_DRAG) ),
- aCornerWin( this )
- { Initialize( nFlags ); }
-
- //-------------------------------------------------------------------
-
- Size ScrollableWindow::GetOutputSizePixel() const
- {
- Size aSz( Window::GetOutputSizePixel() );
- if ( aHScroll.IsVisible() )
- aSz.Height() -= nScrPixH;
- if ( aVScroll.IsVisible() )
- aSz.Width() -= nScrPixW;
- return aSz;
- }
-
- //-------------------------------------------------------------------
-
- Size ScrollableWindow::GetOutputSize() const
- {
- Size aSz( Window::GetOutputSizePixel() );
- if ( aHScroll.IsVisible() )
- aSz.Height() -= nScrPixH;
- if ( aVScroll.IsVisible() )
- aSz.Width() -= nScrPixW;
- return PixelToLogic( aSz );
- }
-
- //-------------------------------------------------------------------
-
- void ScrollableWindow::EndScrollHdl( ScrollBar* pScroll )
- {
- // notify the start of scrolling, if not already scrolling
- if ( !bScrolling )
- StartScroll(), bScrolling = TRUE;
-
- // get the delta in logic coordinates
- Size aDelta( PixelToLogic(
- Size( aHScroll.GetDelta(), aVScroll.GetDelta() ) ) );
-
- // scroll the window, if this is not already done
- if ( !bHandleDragging )
- if ( pScroll == &aHScroll )
- Scroll( aDelta.Width(), 0 );
- else
- Scroll( 0, aDelta.Height() );
-
- // notify the end of scrolling
- bScrolling = FALSE;
- EndScroll( aDelta.Width(), aDelta.Height() );
- }
-
- //-------------------------------------------------------------------
-
- void ScrollableWindow::ScrollHdl( ScrollBar* pScroll )
- {
- // notify the start of scrolling, if not already scrolling
- if ( !bScrolling )
- StartScroll(), bScrolling = TRUE;
-
- if ( bHandleDragging )
- {
- // get the delta in logic coordinates
- Size aDelta( PixelToLogic(
- Size( aHScroll.GetDelta(), aVScroll.GetDelta() ) ) );
- if ( pScroll == &aHScroll )
- Scroll( aDelta.Width(), 0 );
- else
- Scroll( 0, aDelta.Height() );
- }
- }
-
- //-------------------------------------------------------------------
-
- void ScrollableWindow::Resize()
- {
- // get the new output-size in pixel
- Size aOutPixSz = Window::GetOutputSizePixel();
-
- // determine the size of the output-area and if we need scrollbars
- BOOL bVVisible = FALSE; // by default no vertical-ScrollBar
- BOOL bHVisible = FALSE; // by default no horizontal-ScrollBar
- BOOL bChanged; // determines if a visiblility was changed
- do
- {
- bChanged = FALSE;
-
- // does we need a vertical ScrollBar
- if ( aOutPixSz.Width() < aTotPixSz.Width() && !bHVisible )
- { bHVisible = TRUE;
- aOutPixSz.Height() -= nScrPixH;
- bChanged = TRUE;
- }
-
- // does we need a horizontal ScrollBar
- if ( aOutPixSz.Height() < aTotPixSz.Height() && !bVVisible )
- { bVVisible = TRUE;
- aOutPixSz.Width() -= nScrPixW;
- bChanged = TRUE;
- }
-
- } while ( bChanged ); // until no visibility has changed
-
- // store the old offset and map-mode
- MapMode aMap( GetMapMode() );
- Point aOldPixOffset( aPixOffset );
-
- // justify (right/bottom borders should never exceed the virtual window)
- Size aPixDelta;
- if ( aPixOffset.X() < 0 &&
- aPixOffset.X() + aTotPixSz.Width() < aOutPixSz.Width() )
- aPixDelta.Width() =
- aOutPixSz.Width() - ( aPixOffset.X() + aTotPixSz.Width() );
- if ( aPixOffset.Y() < 0 &&
- aPixOffset.Y() + aTotPixSz.Height() < aOutPixSz.Height() )
- aPixDelta.Height() =
- aOutPixSz.Height() - ( aPixOffset.Y() + aTotPixSz.Height() );
- if ( aPixDelta.Width() || aPixDelta.Height() )
- {
- aPixOffset.X() += aPixDelta.Width();
- aPixOffset.Y() += aPixDelta.Height();
- }
-
- // for axis without scrollbar restore the origin
- if ( !bVVisible || !bHVisible )
- {
- aPixOffset = Point(
- bHVisible
- ? aPixOffset.X()
- : ( bHCenter
- ? (aOutPixSz.Width()-aTotPixSz.Width()) / 2
- : 0 ),
- bVVisible
- ? aPixOffset.Y()
- : ( bVCenter
- ? (aOutPixSz.Height()-aTotPixSz.Height()) / 2
- : 0 ) );
- }
- if ( bHVisible && !aHScroll.IsVisible() )
- aPixOffset.X() = 0;
- if ( bVVisible && !aVScroll.IsVisible() )
- aPixOffset.Y() = 0;
-
- // select the shifted map-mode
- if ( aPixOffset != aOldPixOffset )
- {
- Window::ChangeMapMode( MapMode(MAP_PIXEL) );
- Window::Scroll(
- aPixOffset.X() - aOldPixOffset.X(),
- aPixOffset.Y() - aOldPixOffset.Y() );
- ChangeMapMode( aMap );
- }
-
- // show or hide scrollbars
- if ( bVVisible ) aVScroll.Show(); else aVScroll.Hide(), ToTop();
- if ( bHVisible ) aHScroll.Show(); else aHScroll.Hide(), ToTop();
-
- // disable painting in the corner between the scrollbars
- if ( bVVisible && bHVisible )
- {
- aCornerWin.SetPosSizePixel(
- *((Point*) &aOutPixSz), Size(nScrPixW, nScrPixH) );
- aCornerWin.Show();
- }
- else
- aCornerWin.Hide();
-
- // resize scrollbars and set their ranges
- if ( bHVisible )
- {
- aHScroll.SetPosSizePixel(
- Point( 0, aOutPixSz.Height() ),
- Size( aOutPixSz.Width(), nScrPixH ) );
- aHScroll.ChangeRange( Range(0, aTotPixSz.Width()) );
- aHScroll.ChangePageSize( aOutPixSz.Width() );
- aHScroll.ChangeVisibleSize( aOutPixSz.Width() );
- aHScroll.ChangeLineSize( nColumnPixW );
- aHScroll.ChangeThumbPos( -aPixOffset.X() );
- }
- if ( bVVisible )
- {
- aVScroll.SetPosSizePixel(
- Point( aOutPixSz.Width(), 0 ),
- Size( nScrPixW, aOutPixSz.Height() ) );
- aVScroll.ChangeRange( Range(0, aTotPixSz.Height()) );
- aVScroll.ChangePageSize( aOutPixSz.Height() );
- aVScroll.ChangeVisibleSize( aOutPixSz.Height() );
- aVScroll.ChangeLineSize( nLinePixH );
- aVScroll.ChangeThumbPos( -aPixOffset.Y() );
- }
- }
-
- //-------------------------------------------------------------------
-
- void ScrollableWindow::StartScroll()
- {
- }
-
- //-------------------------------------------------------------------
-
- void ScrollableWindow::EndScroll( short nDeltaX, short nDeltaY )
- {
- }
-
- //-------------------------------------------------------------------
-
- MapMode ScrollableWindow::ChangeMapMode( const MapMode& rNewMapMode )
- {
- MapMode aMap( rNewMapMode );
- aMap.ChangeOrigin( aMap.GetOrigin() + PixelToLogic(aPixOffset, aMap) );
- return Window::ChangeMapMode( aMap );
- }
-
- //-------------------------------------------------------------------
-
- MapMode ScrollableWindow::GetMapMode() const
- {
- MapMode aMap( Window::GetMapMode() );
- aMap.ChangeOrigin( aMap.GetOrigin() - PixelToLogic(aPixOffset) );
- return aMap;
- }
-
- //-------------------------------------------------------------------
-
- void ScrollableWindow::SetTotalSize( const Size& rNewSize )
- {
- aTotPixSz = LogicToPixel(rNewSize);
- ScrollableWindow::Resize();
- }
-
- //-------------------------------------------------------------------
-
- void ScrollableWindow::SetVisibleSize( const Size& rNewSize )
- {
- // get the rectangle, we wish to view
- Rectangle aWish( Point(0, 0), LogicToPixel(rNewSize) );
-
- // get maximum rectangle for us from our parent-window (subst our border!)
- Rectangle aMax( Point(0, 0), GetParent()->GetOutputSizePixel() );
- aMax.Left() -= ( Window::GetSizePixel().Width() -
- Window::GetOutputSizePixel().Width() );
- aMax.Bottom() -= (Window::GetSizePixel().Height() -
- Window::GetOutputSizePixel().Height());
-
- Size aWill( aWish.GetIntersection(aMax).GetSize() );
- BOOL bHScroll = FALSE;
- if ( aWill.Width() < aWish.GetSize().Width() )
- { bHScroll = TRUE;
- aWill.Height() =
- min( aWill.Height()+nScrPixH, aMax.GetSize().Height() );
- }
- if ( aWill.Height() < aWish.GetSize().Height() )
- aWill.Width() =
- min( aWill.Width()+nScrPixW, aMax.GetSize().Width() );
- if ( !bHScroll && (aWill.Width() < aWish.GetSize().Width()) )
- aWill.Height() =
- min( aWill.Height()+nScrPixH, aMax.GetSize().Height() );
- Window::ChangeOutputSizePixel( aWill );
- }
-
- //-------------------------------------------------------------------
-
- BOOL ScrollableWindow::MakeVisible( const Rectangle& rTarget, BOOL bSloppy )
- {
- Rectangle aTarget;
- Rectangle aTotRect( Point(0, 0), PixelToLogic( aTotPixSz ) );
-
- if ( bSloppy )
- {
- aTarget = rTarget;
-
- // at maximum to right border
- if ( aTarget.Right() > aTotRect.Right() )
- {
- short nDelta = aTarget.Right() - aTotRect.Right();
- aTarget.Left() -= nDelta;
- aTarget.Right() -= nDelta;
-
- // too wide?
- if ( aTarget.Left() < aTotRect.Left() )
- aTarget.Left() = aTotRect.Left();
- }
-
- // at maximum to bottom border
- if ( aTarget.Bottom() > aTotRect.Bottom() )
- {
- short nDelta = aTarget.Bottom() - aTotRect.Bottom();
- aTarget.Top() -= nDelta;
- aTarget.Bottom() -= nDelta;
-
- // too high?
- if ( aTarget.Top() < aTotRect.Top() )
- aTarget.Top() = aTotRect.Top();
- }
-
- // at maximum to left border
- if ( aTarget.Left() < aTotRect.Left() )
- {
- short nDelta = aTarget.Left() - aTotRect.Left();
- aTarget.Right() -= nDelta;
- aTarget.Left() -= nDelta;
-
- // too wide?
- if ( aTarget.Right() > aTotRect.Right() )
- aTarget.Right() = aTotRect.Right();
- }
-
- // at maximum to top border
- if ( aTarget.Top() < aTotRect.Top() )
- {
- short nDelta = aTarget.Top() - aTotRect.Top();
- aTarget.Bottom() -= nDelta;
- aTarget.Top() -= nDelta;
-
- // too high?
- if ( aTarget.Bottom() > aTotRect.Bottom() )
- aTarget.Bottom() = aTotRect.Bottom();
- }
- }
- else
- aTarget = rTarget.GetIntersection( aTotRect );
-
- // is the area already visible?
- Rectangle aVisArea( GetVisibleArea() );
- if ( aVisArea.IsInside(rTarget) )
- return TRUE;
-
- // is there somewhat to scroll?
- if ( aVisArea.TopLeft() != aTarget.TopLeft() )
- {
- Rectangle aBox( aTarget.GetUnion(aVisArea) );
- short nDeltaX = ( aBox.Right() - aVisArea.Right() ) +
- ( aBox.Left() - aVisArea.Left() );
- short nDeltaY = ( aBox.Top() - aVisArea.Top() ) +
- ( aBox.Bottom() - aVisArea.Bottom() );
- Scroll( nDeltaX, nDeltaY );
- }
-
- // determine if the target is completely visible
- return aVisArea.GetWidth() >= aTarget.GetWidth() &&
- aVisArea.GetHeight() >= aTarget.GetHeight();
- }
-
- //-------------------------------------------------------------------
-
- Rectangle ScrollableWindow::GetVisibleArea() const
- {
- Point aTopLeft( PixelToLogic( Point() ) );
- Size aSz( GetOutputSize() );
- return Rectangle( aTopLeft, aSz );
- }
-
- //-------------------------------------------------------------------
-
- void ScrollableWindow::SetLineSize( USHORT nHorz, USHORT nVert )
- {
- Size aPixSz( LogicToPixel( Size(nHorz, nVert) ) );
- nColumnPixW = aPixSz.Width();
- nLinePixH = aPixSz.Height();
- aVScroll.ChangeLineSize( nLinePixH );
- aHScroll.ChangeLineSize( nColumnPixW );
- }
-
- //-------------------------------------------------------------------
-
- void ScrollableWindow::Scroll( short nDeltaX, short nDeltaY )
- {
- if ( !bScrolling )
- StartScroll();
-
- // get the delta in pixel
- Size aDeltaPix( LogicToPixel( Size(nDeltaX, nDeltaY) ) );
- Size aOutPixSz( GetOutputSizePixel() );
- MapMode aMap( GetMapMode() );
- Point aNewPixOffset( aPixOffset );
-
- // scrolling horizontally?
- if ( nDeltaX != 0 )
- {
- aNewPixOffset.X() -= aDeltaPix.Width();
- if ( ( aOutPixSz.Width() - aNewPixOffset.X() ) > aTotPixSz.Width() )
- aNewPixOffset.X() = - ( aTotPixSz.Width() - aOutPixSz.Width() );
- else if ( aNewPixOffset.X() > 0 )
- aNewPixOffset.X() = 0;
- }
-
- // scrolling vertically?
- if ( nDeltaY != 0 )
- {
- aNewPixOffset.Y() -= aDeltaPix.Height();
- if ( ( aOutPixSz.Height() - aNewPixOffset.Y() ) > aTotPixSz.Height() )
- aNewPixOffset.Y() = - ( aTotPixSz.Height() - aOutPixSz.Height() );
- else if ( aNewPixOffset.Y() > 0 )
- aNewPixOffset.Y() = 0;
- }
-
- // recompute the logical scroll units
- aDeltaPix.Width() = aPixOffset.X() - aNewPixOffset.X();
- aDeltaPix.Height() = aPixOffset.Y() - aNewPixOffset.Y();
- Size aDelta( PixelToLogic(aDeltaPix) );
- nDeltaX = aDelta.Width();
- nDeltaY = aDelta.Height();
- aPixOffset = aNewPixOffset;
-
- // scrolling?
- if ( nDeltaX != 0 || nDeltaY != 0 )
- {
- Update();
-
- // does the new area overlap the old one?
- if ( abs( aDeltaPix.Height() ) < aOutPixSz.Height() ||
- abs( aDeltaPix.Width() ) < aOutPixSz.Width() )
- {
- // scroll the overlapping area
- ChangeMapMode(aMap);
-
- // never scroll the scrollbars itself!
- Window::Scroll(-nDeltaX, -nDeltaY,
- PixelToLogic( Rectangle( Point(0, 0), aOutPixSz ) ) );
- }
- else
- // repaint all
- ChangeMapMode(aMap), Invalidate();
-
- Update();
- }
-
- if ( !bScrolling )
- {
- EndScroll( nDeltaX, nDeltaY );
- if ( nDeltaX )
- aHScroll.ChangeThumbPos( -aPixOffset.X() );
- if ( nDeltaY )
- aVScroll.ChangeThumbPos( -aPixOffset.Y() );
- }
- }
-
- //-------------------------------------------------------------------
-
- void ScrollableWindow::ScrollLines( short nLinesX, short nLinesY )
- {
- Size aDelta( PixelToLogic( Size( nColumnPixW, nLinePixH ) ) );
- Scroll( aDelta.Width()*nLinesX, aDelta.Height()*nLinesY );
- }
-
- //-------------------------------------------------------------------
-
- void ScrollableWindow::ScrollPages( short nPagesX, USHORT nOverlapX,
- short nPagesY, USHORT nOverlapY )
- {
- Size aOutSz( GetVisibleArea().GetSize() );
- Scroll( nPagesX * aOutSz.Width() + (nPagesX>0 ? 1 : -1) * nOverlapX,
- nPagesY * aOutSz.Height() + (nPagesY>0 ? 1 : -1) * nOverlapY );
- }
-
- //==================================================================
-