LCOV - code coverage report
Current view: top level - libreoffice/svx/source/stbctrls - zoomsliderctrl.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 1 186 0.5 %
Date: 2012-12-27 Functions: 1 13 7.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <svx/zoomsliderctrl.hxx>
      21             : #include <vcl/status.hxx>
      22             : #include <vcl/menu.hxx>
      23             : #include <vcl/image.hxx>
      24             : #include <vcl/svapp.hxx>
      25             : #include <svx/zoomslideritem.hxx>
      26             : #include <svx/dialmgr.hxx>
      27             : #include <svx/dialogs.hrc>
      28             : 
      29             : #include <basegfx/tools/zoomtools.hxx>
      30             : 
      31             : #include <set>
      32             : 
      33             : // -----------------------------------------------------------------------
      34             : 
      35          18 : SFX_IMPL_STATUSBAR_CONTROL( SvxZoomSliderControl, SvxZoomSliderItem );
      36             : 
      37             : // -----------------------------------------------------------------------
      38             : 
      39           0 : struct SvxZoomSliderControl::SvxZoomSliderControl_Impl
      40             : {
      41             :     sal_uInt16                   mnCurrentZoom;
      42             :     sal_uInt16                   mnMinZoom;
      43             :     sal_uInt16                   mnMaxZoom;
      44             :     sal_uInt16                   mnSliderCenter;
      45             :     std::vector< long >      maSnappingPointOffsets;
      46             :     std::vector< sal_uInt16 >    maSnappingPointZooms;
      47             :     Image                    maSliderButton;
      48             :     Image                    maIncreaseButton;
      49             :     Image                    maDecreaseButton;
      50             :     bool                     mbValuesSet;
      51             :     bool                     mbOmitPaint;
      52             : 
      53           0 :     SvxZoomSliderControl_Impl() :
      54             :         mnCurrentZoom( 0 ),
      55             :         mnMinZoom( 0 ),
      56             :         mnMaxZoom( 0 ),
      57             :         mnSliderCenter( 0 ),
      58             :         maSnappingPointOffsets(),
      59             :         maSnappingPointZooms(),
      60             :         maSliderButton(),
      61             :         maIncreaseButton(),
      62             :         maDecreaseButton(),
      63             :         mbValuesSet( false ),
      64           0 :         mbOmitPaint( false ) {}
      65             : };
      66             : 
      67             : // -----------------------------------------------------------------------
      68             : 
      69             : const long nButtonWidth   = 10;
      70             : const long nButtonHeight  = 10;
      71             : const long nIncDecWidth   = 10;
      72             : const long nIncDecHeight  = 10;
      73             : const long nSliderHeight  = 2;
      74             : const long nSnappingHeight = 4;
      75             : const long nSliderXOffset = 20;
      76             : const long nSnappingEpsilon = 5; // snapping epsilon in pixels
      77             : const long nSnappingPointsMinDist = nSnappingEpsilon; // minimum distance of two adjacent snapping points
      78             : 
      79             : // -----------------------------------------------------------------------
      80             : 
      81             : // nOffset referes to the origin of the control:
      82             : // + ----------- -
      83           0 : sal_uInt16 SvxZoomSliderControl::Offset2Zoom( long nOffset ) const
      84             : {
      85           0 :     const long nControlWidth = getControlRect().GetWidth();
      86           0 :     sal_uInt16 nRet = 0;
      87             : 
      88           0 :     if ( nOffset < nSliderXOffset )
      89           0 :         return mpImpl->mnMinZoom;
      90             : 
      91           0 :     if ( nOffset > nControlWidth - nSliderXOffset )
      92           0 :         return mpImpl->mnMaxZoom;
      93             : 
      94             :     // check for snapping points:
      95           0 :     sal_uInt16 nCount = 0;
      96           0 :     std::vector< long >::iterator aSnappingPointIter;
      97           0 :     for ( aSnappingPointIter = mpImpl->maSnappingPointOffsets.begin();
      98           0 :           aSnappingPointIter != mpImpl->maSnappingPointOffsets.end();
      99             :           ++aSnappingPointIter )
     100             :     {
     101           0 :         const long nCurrent = *aSnappingPointIter;
     102           0 :         if ( Abs(nCurrent - nOffset) < nSnappingEpsilon )
     103             :         {
     104           0 :             nOffset = nCurrent;
     105           0 :             nRet = mpImpl->maSnappingPointZooms[ nCount ];
     106           0 :             break;
     107             :         }
     108           0 :         ++nCount;
     109             :     }
     110             : 
     111           0 :     if ( 0 == nRet )
     112             :     {
     113           0 :         if ( nOffset < nControlWidth / 2 )
     114             :         {
     115             :             // first half of slider
     116           0 :             const long nFirstHalfRange = mpImpl->mnSliderCenter - mpImpl->mnMinZoom;
     117           0 :             const long nHalfSliderWidth = nControlWidth/2 - nSliderXOffset;
     118           0 :             const long nZoomPerSliderPixel = (1000 * nFirstHalfRange) / nHalfSliderWidth;
     119           0 :             const long nOffsetToSliderLeft = nOffset - nSliderXOffset;
     120           0 :             nRet = mpImpl->mnMinZoom + sal_uInt16( nOffsetToSliderLeft * nZoomPerSliderPixel / 1000 );
     121             :         }
     122             :         else
     123             :         {
     124             :             // second half of slider
     125           0 :             const long nSecondHalfRange = mpImpl->mnMaxZoom - mpImpl->mnSliderCenter;
     126           0 :             const long nHalfSliderWidth = nControlWidth/2 - nSliderXOffset;
     127           0 :             const long nZoomPerSliderPixel = 1000 * nSecondHalfRange / nHalfSliderWidth;
     128           0 :             const long nOffsetToSliderCenter = nOffset - nControlWidth/2;
     129           0 :             nRet = mpImpl->mnSliderCenter + sal_uInt16( nOffsetToSliderCenter * nZoomPerSliderPixel / 1000 );
     130             :         }
     131             :     }
     132             : 
     133           0 :     if ( nRet < mpImpl->mnMinZoom )
     134           0 :         nRet = mpImpl->mnMinZoom;
     135           0 :     else if ( nRet > mpImpl->mnMaxZoom )
     136           0 :         nRet = mpImpl->mnMaxZoom;
     137             : 
     138           0 :     return nRet;
     139             : }
     140             : 
     141             : // returns the offset to the left control border
     142           0 : long SvxZoomSliderControl::Zoom2Offset( sal_uInt16 nCurrentZoom ) const
     143             : {
     144           0 :     const long nControlWidth = getControlRect().GetWidth();
     145           0 :     long nRet = nSliderXOffset;
     146             : 
     147           0 :     const long nHalfSliderWidth = nControlWidth/2 - nSliderXOffset;
     148             : 
     149           0 :     if ( nCurrentZoom <= mpImpl->mnSliderCenter )
     150             :     {
     151           0 :         nCurrentZoom = nCurrentZoom - mpImpl->mnMinZoom;
     152           0 :         const long nFirstHalfRange = mpImpl->mnSliderCenter - mpImpl->mnMinZoom;
     153           0 :         const long nSliderPixelPerZoomPercent = 1000 * nHalfSliderWidth  / nFirstHalfRange;
     154           0 :         const long nOffset = (nSliderPixelPerZoomPercent * nCurrentZoom) / 1000;
     155           0 :         nRet += nOffset;
     156             :     }
     157             :     else
     158             :     {
     159           0 :         nCurrentZoom = nCurrentZoom - mpImpl->mnSliderCenter;
     160           0 :         const long nSecondHalfRange = mpImpl->mnMaxZoom - mpImpl->mnSliderCenter;
     161           0 :         const long nSliderPixelPerZoomPercent = 1000 * nHalfSliderWidth  / nSecondHalfRange;
     162           0 :         const long nOffset = (nSliderPixelPerZoomPercent * nCurrentZoom) / 1000;
     163           0 :         nRet += nHalfSliderWidth + nOffset;
     164             :     }
     165             : 
     166           0 :     return nRet;
     167             : }
     168             : 
     169             : // -----------------------------------------------------------------------
     170             : 
     171           0 : SvxZoomSliderControl::SvxZoomSliderControl( sal_uInt16 _nSlotId,  sal_uInt16 _nId, StatusBar& _rStb ) :
     172             :     SfxStatusBarControl( _nSlotId, _nId, _rStb ),
     173           0 :     mpImpl( new SvxZoomSliderControl_Impl )
     174             : {
     175           0 :     mpImpl->maSliderButton   = Image( SVX_RES( RID_SVXBMP_SLIDERBUTTON   ) );
     176           0 :     mpImpl->maIncreaseButton = Image( SVX_RES( RID_SVXBMP_SLIDERINCREASE ) );
     177           0 :     mpImpl->maDecreaseButton = Image( SVX_RES( RID_SVXBMP_SLIDERDECREASE ) );
     178           0 : }
     179             : 
     180             : // -----------------------------------------------------------------------
     181             : 
     182           0 : SvxZoomSliderControl::~SvxZoomSliderControl()
     183             : {
     184           0 :     delete mpImpl;
     185           0 : }
     186             : 
     187             : // -----------------------------------------------------------------------
     188             : 
     189           0 : void SvxZoomSliderControl::StateChanged( sal_uInt16 /*nSID*/, SfxItemState eState, const SfxPoolItem* pState )
     190             : {
     191           0 :     if ( (SFX_ITEM_AVAILABLE != eState) || pState->ISA( SfxVoidItem ) )
     192             :     {
     193           0 :         GetStatusBar().SetItemText( GetId(), String() );
     194           0 :         mpImpl->mbValuesSet   = false;
     195             :     }
     196             :     else
     197             :     {
     198             :         OSL_ENSURE( pState->ISA( SvxZoomSliderItem ), "invalid item type: should be a SvxZoomSliderItem" );
     199           0 :         mpImpl->mnCurrentZoom = static_cast<const SvxZoomSliderItem*>( pState )->GetValue();
     200           0 :         mpImpl->mnMinZoom     = static_cast<const SvxZoomSliderItem*>( pState )->GetMinZoom();
     201           0 :         mpImpl->mnMaxZoom     = static_cast<const SvxZoomSliderItem*>( pState )->GetMaxZoom();
     202           0 :         mpImpl->mnSliderCenter= 100;
     203           0 :         mpImpl->mbValuesSet   = true;
     204             : 
     205           0 :         if ( mpImpl->mnSliderCenter == mpImpl->mnMaxZoom )
     206           0 :             mpImpl->mnSliderCenter = mpImpl->mnMinZoom + (sal_uInt16)((mpImpl->mnMaxZoom - mpImpl->mnMinZoom) * 0.5);
     207             : 
     208             : 
     209             :         DBG_ASSERT( mpImpl->mnMinZoom <= mpImpl->mnCurrentZoom &&
     210             :                     mpImpl->mnMinZoom <  mpImpl->mnSliderCenter &&
     211             :                     mpImpl->mnMaxZoom >= mpImpl->mnCurrentZoom &&
     212             :                     mpImpl->mnMaxZoom > mpImpl->mnSliderCenter,
     213             :                     "Looks like the zoom slider item is corrupted" );
     214             : 
     215           0 :         const com::sun::star::uno::Sequence < sal_Int32 > rSnappingPoints = static_cast<const SvxZoomSliderItem*>( pState )->GetSnappingPoints();
     216           0 :         mpImpl->maSnappingPointOffsets.clear();
     217           0 :         mpImpl->maSnappingPointZooms.clear();
     218             : 
     219             :         // get all snapping points:
     220           0 :         std::set< sal_uInt16 > aTmpSnappingPoints;
     221           0 :         for ( sal_uInt16 j = 0; j < rSnappingPoints.getLength(); ++j )
     222             :         {
     223           0 :             const sal_Int32 nSnappingPoint = rSnappingPoints[j];
     224           0 :             aTmpSnappingPoints.insert( (sal_uInt16)nSnappingPoint );
     225             :         }
     226             : 
     227             :         // remove snapping points that are to close to each other:
     228           0 :         std::set< sal_uInt16 >::iterator aSnappingPointIter;
     229           0 :         long nLastOffset = 0;
     230             : 
     231           0 :         for ( aSnappingPointIter = aTmpSnappingPoints.begin(); aSnappingPointIter != aTmpSnappingPoints.end(); ++aSnappingPointIter )
     232             :         {
     233           0 :             const sal_uInt16 nCurrent = *aSnappingPointIter;
     234           0 :             const long nCurrentOffset = Zoom2Offset( nCurrent );
     235             : 
     236           0 :             if ( nCurrentOffset - nLastOffset >= nSnappingPointsMinDist )
     237             :             {
     238           0 :                 mpImpl->maSnappingPointOffsets.push_back( nCurrentOffset );
     239           0 :                 mpImpl->maSnappingPointZooms.push_back( nCurrent );
     240           0 :                 nLastOffset = nCurrentOffset;
     241             :             }
     242           0 :         }
     243             :     }
     244             : 
     245           0 :     if ( !mpImpl->mbOmitPaint && GetStatusBar().AreItemsVisible() )
     246           0 :         GetStatusBar().SetItemData( GetId(), 0 );    // force repaint
     247           0 : }
     248             : 
     249             : // -----------------------------------------------------------------------
     250             : 
     251           0 : void SvxZoomSliderControl::Paint( const UserDrawEvent& rUsrEvt )
     252             : {
     253           0 :     if ( !mpImpl->mbValuesSet || mpImpl->mbOmitPaint )
     254           0 :         return;
     255             : 
     256           0 :     const Rectangle     aControlRect = getControlRect();
     257           0 :     OutputDevice*       pDev =  rUsrEvt.GetDevice();
     258           0 :     Rectangle           aRect = rUsrEvt.GetRect();
     259           0 :     Rectangle           aSlider = aRect;
     260             : 
     261           0 :     aSlider.Top()   += (aControlRect.GetHeight() - nSliderHeight)/2;
     262           0 :     aSlider.Bottom() = aSlider.Top() + nSliderHeight - 1;
     263           0 :     aSlider.Left()  += nSliderXOffset;
     264           0 :     aSlider.Right() -= nSliderXOffset;
     265             : 
     266           0 :     Color               aOldLineColor = pDev->GetLineColor();
     267           0 :     Color               aOldFillColor = pDev->GetFillColor();
     268             : 
     269           0 :     const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
     270           0 :     pDev->SetLineColor( rStyleSettings.GetShadowColor() );
     271           0 :     pDev->SetFillColor( rStyleSettings.GetShadowColor() );
     272             : 
     273             :     // draw snapping points:
     274           0 :     std::vector< long >::iterator aSnappingPointIter;
     275           0 :     for ( aSnappingPointIter = mpImpl->maSnappingPointOffsets.begin();
     276           0 :           aSnappingPointIter != mpImpl->maSnappingPointOffsets.end();
     277             :           ++aSnappingPointIter )
     278             :     {
     279           0 :         long nSnapPosX = aRect.Left() + *aSnappingPointIter;
     280             : 
     281           0 :         pDev->DrawRect( Rectangle( nSnapPosX - 1, aSlider.Top() - nSnappingHeight,
     282           0 :                     nSnapPosX, aSlider.Bottom() + nSnappingHeight ) );
     283             :     }
     284             : 
     285             :     // draw slider
     286           0 :     pDev->DrawRect( aSlider );
     287             : 
     288             :     // draw slider button
     289           0 :     Point aImagePoint = aRect.TopLeft();
     290           0 :     aImagePoint.X() += Zoom2Offset( mpImpl->mnCurrentZoom );
     291           0 :     aImagePoint.X() -= nButtonWidth/2;
     292           0 :     aImagePoint.Y() += (aControlRect.GetHeight() - nButtonHeight)/2;
     293           0 :     pDev->DrawImage( aImagePoint, mpImpl->maSliderButton );
     294             : 
     295             :     // draw decrease button
     296           0 :     aImagePoint = aRect.TopLeft();
     297           0 :     aImagePoint.X() += (nSliderXOffset - nIncDecWidth)/2;
     298           0 :     aImagePoint.Y() += (aControlRect.GetHeight() - nIncDecHeight)/2;
     299           0 :     pDev->DrawImage( aImagePoint, mpImpl->maDecreaseButton );
     300             : 
     301             :     // draw increase button
     302           0 :     aImagePoint.X() = aRect.TopLeft().X() + aControlRect.GetWidth() - nIncDecWidth - (nSliderXOffset - nIncDecWidth)/2;
     303           0 :     pDev->DrawImage( aImagePoint, mpImpl->maIncreaseButton );
     304             : 
     305           0 :     pDev->SetLineColor( aOldLineColor );
     306           0 :     pDev->SetFillColor( aOldFillColor );
     307             : }
     308             : 
     309             : // -----------------------------------------------------------------------
     310             : 
     311           0 : sal_Bool SvxZoomSliderControl::MouseButtonDown( const MouseEvent & rEvt )
     312             : {
     313           0 :     if ( !mpImpl->mbValuesSet )
     314           0 :         return sal_True;
     315             : 
     316           0 :     const Rectangle aControlRect = getControlRect();
     317           0 :     const Point aPoint = rEvt.GetPosPixel();
     318           0 :     const sal_Int32 nXDiff = aPoint.X() - aControlRect.Left();
     319             : 
     320           0 :     const long nButtonLeftOffset = (nSliderXOffset - nIncDecWidth)/2;
     321           0 :     const long nButtonRightOffset = (nSliderXOffset + nIncDecWidth)/2;
     322             : 
     323           0 :     const long nOldZoom = mpImpl->mnCurrentZoom;
     324             : 
     325             :     // click to - button
     326           0 :     if ( nXDiff >= nButtonLeftOffset && nXDiff <= nButtonRightOffset )
     327           0 :         mpImpl->mnCurrentZoom = basegfx::zoomtools::zoomOut( static_cast<int>(mpImpl->mnCurrentZoom) );
     328             :     // click to + button
     329           0 :     else if ( nXDiff >= aControlRect.GetWidth() - nSliderXOffset + nButtonLeftOffset &&
     330           0 :               nXDiff <= aControlRect.GetWidth() - nSliderXOffset + nButtonRightOffset )
     331           0 :         mpImpl->mnCurrentZoom = basegfx::zoomtools::zoomIn( static_cast<int>(mpImpl->mnCurrentZoom) );
     332             :     // click to slider
     333           0 :     else if( nXDiff >= nSliderXOffset && nXDiff <= aControlRect.GetWidth() - nSliderXOffset )
     334           0 :         mpImpl->mnCurrentZoom = Offset2Zoom( nXDiff );
     335             : 
     336           0 :     if ( mpImpl->mnCurrentZoom < mpImpl->mnMinZoom )
     337           0 :         mpImpl->mnCurrentZoom = mpImpl->mnMinZoom;
     338           0 :     else if ( mpImpl->mnCurrentZoom > mpImpl->mnMaxZoom )
     339           0 :         mpImpl->mnCurrentZoom = mpImpl->mnMaxZoom;
     340             : 
     341           0 :     if ( nOldZoom == mpImpl->mnCurrentZoom )
     342           0 :         return sal_True;
     343             : 
     344           0 :     if ( GetStatusBar().AreItemsVisible() )
     345           0 :         GetStatusBar().SetItemData( GetId(), 0 );    // force repaint
     346             : 
     347           0 :     mpImpl->mbOmitPaint = true; // optimization: paint before executing command,
     348             :                                 // then omit painting which is triggered by the execute function
     349             : 
     350           0 :     SvxZoomSliderItem aZoomSliderItem( mpImpl->mnCurrentZoom );
     351             : 
     352           0 :     ::com::sun::star::uno::Any a;
     353           0 :     aZoomSliderItem.QueryValue( a );
     354             : 
     355           0 :     ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aArgs( 1 );
     356           0 :     aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ZoomSlider" ));
     357           0 :     aArgs[0].Value = a;
     358             : 
     359           0 :     execute( aArgs );
     360             : 
     361           0 :     mpImpl->mbOmitPaint = false;
     362             : 
     363           0 :     return sal_True;
     364             : }
     365             : 
     366             : // -----------------------------------------------------------------------
     367             : 
     368           0 : sal_Bool SvxZoomSliderControl::MouseMove( const MouseEvent & rEvt )
     369             : {
     370           0 :     if ( !mpImpl->mbValuesSet )
     371           0 :         return sal_True;
     372             : 
     373           0 :     const short nButtons = rEvt.GetButtons();
     374             : 
     375             :     // check mouse move with button pressed
     376           0 :     if ( 1 == nButtons )
     377             :     {
     378           0 :         const Rectangle aControlRect = getControlRect();
     379           0 :         const Point aPoint = rEvt.GetPosPixel();
     380           0 :         const sal_Int32 nXDiff = aPoint.X() - aControlRect.Left();
     381             : 
     382           0 :         if ( nXDiff >= nSliderXOffset && nXDiff <= aControlRect.GetWidth() - nSliderXOffset )
     383             :         {
     384           0 :             mpImpl->mnCurrentZoom = Offset2Zoom( nXDiff );
     385             : 
     386           0 :             if ( GetStatusBar().AreItemsVisible() )
     387           0 :                 GetStatusBar().SetItemData( GetId(), 0 );    // force repaint
     388             : 
     389           0 :             mpImpl->mbOmitPaint = true; // optimization: paint before executing command,
     390             :                                         // then omit painting which is triggered by the execute function
     391             : 
     392             :             // commit state change
     393           0 :             SvxZoomSliderItem aZoomSliderItem( mpImpl->mnCurrentZoom );
     394             : 
     395           0 :             ::com::sun::star::uno::Any a;
     396           0 :             aZoomSliderItem.QueryValue( a );
     397             : 
     398           0 :             ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aArgs( 1 );
     399           0 :             aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ZoomSlider" ));
     400           0 :             aArgs[0].Value = a;
     401             : 
     402           0 :             execute( aArgs );
     403             : 
     404           0 :             mpImpl->mbOmitPaint = false;
     405             :         }
     406             :     }
     407             : 
     408           0 :     return sal_True;
     409             : }
     410             : 
     411             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10