Update ooo320-m1
[ooovba.git] / svx / source / stbctrls / zoomsliderctrl.cxx
bloba452521ed2c3b119a32883c0356eeaa521988a7a
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: zoomsliderctrl.cxx,v $
10 * $Revision: 1.3.138.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
34 // include ---------------------------------------------------------------
35 #include <svx/zoomsliderctrl.hxx>
36 #ifndef _STATUS_HXX //autogen
37 #include <vcl/status.hxx>
38 #endif
39 #ifndef _MENU_HXX //autogen
40 #include <vcl/menu.hxx>
41 #endif
42 #include <vcl/image.hxx>
43 #include <svx/zoomslideritem.hxx>
44 #include <svx/dialmgr.hxx>
45 #include <svx/dialogs.hrc>
47 #include <set>
49 // -----------------------------------------------------------------------
51 SFX_IMPL_STATUSBAR_CONTROL( SvxZoomSliderControl, SvxZoomSliderItem );
53 // -----------------------------------------------------------------------
55 struct SvxZoomSliderControl::SvxZoomSliderControl_Impl
57 USHORT mnCurrentZoom;
58 USHORT mnMinZoom;
59 USHORT mnMaxZoom;
60 USHORT mnSliderCenter;
61 std::vector< long > maSnappingPointOffsets;
62 std::vector< USHORT > maSnappingPointZooms;
63 Image maSliderButton;
64 Image maIncreaseButton;
65 Image maDecreaseButton;
66 bool mbValuesSet;
67 bool mbOmitPaint;
69 SvxZoomSliderControl_Impl() :
70 mnCurrentZoom( 0 ),
71 mnMinZoom( 0 ),
72 mnMaxZoom( 0 ),
73 mnSliderCenter( 0 ),
74 maSnappingPointOffsets(),
75 maSnappingPointZooms(),
76 maSliderButton(),
77 maIncreaseButton(),
78 maDecreaseButton(),
79 mbValuesSet( false ),
80 mbOmitPaint( false ) {}
83 // -----------------------------------------------------------------------
85 const long nButtonWidth = 10;
86 const long nButtonHeight = 10;
87 const long nIncDecWidth = 11;
88 const long nIncDecHeight = 11;
89 const long nSliderHeight = 2;
90 const long nSnappingHeight = 4;
91 const long nSliderXOffset = 20;
92 const long nSnappingEpsilon = 5; // snapping epsilon in pixels
93 const long nSnappingPointsMinDist = nSnappingEpsilon; // minimum distance of two adjacent snapping points
95 // -----------------------------------------------------------------------
97 // nOffset referes to the origin of the control:
98 // + ----------- -
99 USHORT SvxZoomSliderControl::Offset2Zoom( long nOffset ) const
101 const long nControlWidth = getControlRect().GetWidth();
102 USHORT nRet = 0;
104 if ( nOffset < nSliderXOffset )
105 return mpImpl->mnMinZoom;;
107 if ( nOffset > nControlWidth - nSliderXOffset )
108 return mpImpl->mnMaxZoom;
110 // check for snapping points:
111 USHORT nCount = 0;
112 std::vector< long >::iterator aSnappingPointIter;
113 for ( aSnappingPointIter = mpImpl->maSnappingPointOffsets.begin();
114 aSnappingPointIter != mpImpl->maSnappingPointOffsets.end();
115 ++aSnappingPointIter )
117 const long nCurrent = *aSnappingPointIter;
118 if ( Abs(nCurrent - nOffset) < nSnappingEpsilon )
120 nOffset = nCurrent;
121 nRet = mpImpl->maSnappingPointZooms[ nCount ];
122 break;
124 ++nCount;
127 if ( 0 == nRet )
129 if ( nOffset < nControlWidth / 2 )
131 // first half of slider
132 const long nFirstHalfRange = mpImpl->mnSliderCenter - mpImpl->mnMinZoom;
133 const long nHalfSliderWidth = nControlWidth/2 - nSliderXOffset;
134 const long nZoomPerSliderPixel = (1000 * nFirstHalfRange) / nHalfSliderWidth;
135 const long nOffsetToSliderLeft = nOffset - nSliderXOffset;
136 nRet = mpImpl->mnMinZoom + USHORT( nOffsetToSliderLeft * nZoomPerSliderPixel / 1000 );
138 else
140 // second half of slider
141 const long nSecondHalfRange = mpImpl->mnMaxZoom - mpImpl->mnSliderCenter;
142 const long nHalfSliderWidth = nControlWidth/2 - nSliderXOffset;
143 const long nZoomPerSliderPixel = 1000 * nSecondHalfRange / nHalfSliderWidth;
144 const long nOffsetToSliderCenter = nOffset - nControlWidth/2;
145 nRet = mpImpl->mnSliderCenter + USHORT( nOffsetToSliderCenter * nZoomPerSliderPixel / 1000 );
149 if ( nRet < mpImpl->mnMinZoom )
150 nRet = mpImpl->mnMinZoom;
151 else if ( nRet > mpImpl->mnMaxZoom )
152 nRet = mpImpl->mnMaxZoom;
154 return nRet;
157 // returns the offset to the left control border
158 long SvxZoomSliderControl::Zoom2Offset( USHORT nCurrentZoom ) const
160 const long nControlWidth = getControlRect().GetWidth();
161 long nRet = nSliderXOffset;
163 const long nHalfSliderWidth = nControlWidth/2 - nSliderXOffset;
165 if ( nCurrentZoom <= mpImpl->mnSliderCenter )
167 nCurrentZoom = nCurrentZoom - mpImpl->mnMinZoom;
168 const long nFirstHalfRange = mpImpl->mnSliderCenter - mpImpl->mnMinZoom;
169 const long nSliderPixelPerZoomPercent = 1000 * nHalfSliderWidth / nFirstHalfRange;
170 const long nOffset = (nSliderPixelPerZoomPercent * nCurrentZoom) / 1000;
171 nRet += nOffset;
173 else
175 nCurrentZoom = nCurrentZoom - mpImpl->mnSliderCenter;
176 const long nSecondHalfRange = mpImpl->mnMaxZoom - mpImpl->mnSliderCenter;
177 const long nSliderPixelPerZoomPercent = 1000 * nHalfSliderWidth / nSecondHalfRange;
178 const long nOffset = (nSliderPixelPerZoomPercent * nCurrentZoom) / 1000;
179 nRet += nHalfSliderWidth + nOffset;
182 return nRet;
185 // -----------------------------------------------------------------------
187 SvxZoomSliderControl::SvxZoomSliderControl( USHORT _nSlotId, USHORT _nId, StatusBar& _rStb ) :
188 SfxStatusBarControl( _nSlotId, _nId, _rStb ),
189 mpImpl( new SvxZoomSliderControl_Impl )
191 const sal_Bool bIsDark = GetStatusBar().GetBackground().GetColor().IsDark();
192 mpImpl->maSliderButton = Image( SVX_RES( bIsDark ? RID_SVXBMP_SLIDERBUTTON_HC : RID_SVXBMP_SLIDERBUTTON ) );
193 mpImpl->maIncreaseButton = Image( SVX_RES( bIsDark ? RID_SVXBMP_SLIDERINCREASE_HC : RID_SVXBMP_SLIDERINCREASE ) );
194 mpImpl->maDecreaseButton = Image( SVX_RES( bIsDark ? RID_SVXBMP_SLIDERDECREASE_HC : RID_SVXBMP_SLIDERDECREASE ) );
197 // -----------------------------------------------------------------------
199 SvxZoomSliderControl::~SvxZoomSliderControl()
201 delete mpImpl;
204 // -----------------------------------------------------------------------
206 void SvxZoomSliderControl::StateChanged( USHORT /*nSID*/, SfxItemState eState, const SfxPoolItem* pState )
208 if ( (SFX_ITEM_AVAILABLE != eState) || pState->ISA( SfxVoidItem ) )
210 GetStatusBar().SetItemText( GetId(), String() );
211 mpImpl->mbValuesSet = false;
213 else
215 OSL_ENSURE( pState->ISA( SvxZoomSliderItem ), "invalid item type: should be a SvxZoomSliderItem" );
216 mpImpl->mnCurrentZoom = static_cast<const SvxZoomSliderItem*>( pState )->GetValue();
217 mpImpl->mnMinZoom = static_cast<const SvxZoomSliderItem*>( pState )->GetMinZoom();
218 mpImpl->mnMaxZoom = static_cast<const SvxZoomSliderItem*>( pState )->GetMaxZoom();
219 mpImpl->mnSliderCenter= 100;
220 mpImpl->mbValuesSet = true;
222 if ( mpImpl->mnSliderCenter == mpImpl->mnMaxZoom )
223 mpImpl->mnSliderCenter = mpImpl->mnMinZoom + (USHORT)((mpImpl->mnMaxZoom - mpImpl->mnMinZoom) * 0.5);
226 DBG_ASSERT( mpImpl->mnMinZoom <= mpImpl->mnCurrentZoom &&
227 mpImpl->mnMinZoom < mpImpl->mnSliderCenter &&
228 mpImpl->mnMaxZoom >= mpImpl->mnCurrentZoom &&
229 mpImpl->mnMaxZoom > mpImpl->mnSliderCenter,
230 "Looks like the zoom slider item is corrupted" );
232 const com::sun::star::uno::Sequence < sal_Int32 > rSnappingPoints = static_cast<const SvxZoomSliderItem*>( pState )->GetSnappingPoints();
233 mpImpl->maSnappingPointOffsets.clear();
234 mpImpl->maSnappingPointZooms.clear();
236 // get all snapping points:
237 std::set< USHORT > aTmpSnappingPoints;
238 for ( USHORT j = 0; j < rSnappingPoints.getLength(); ++j )
240 const sal_Int32 nSnappingPoint = rSnappingPoints[j];
241 aTmpSnappingPoints.insert( (USHORT)nSnappingPoint );
244 // remove snapping points that are to close to each other:
245 std::set< USHORT >::iterator aSnappingPointIter;
246 long nLastOffset = 0;
248 for ( aSnappingPointIter = aTmpSnappingPoints.begin(); aSnappingPointIter != aTmpSnappingPoints.end(); ++aSnappingPointIter )
250 const USHORT nCurrent = *aSnappingPointIter;
251 const long nCurrentOffset = Zoom2Offset( nCurrent );
253 if ( nCurrentOffset - nLastOffset >= nSnappingPointsMinDist )
255 mpImpl->maSnappingPointOffsets.push_back( nCurrentOffset );
256 mpImpl->maSnappingPointZooms.push_back( nCurrent );
257 nLastOffset = nCurrentOffset;
262 if ( !mpImpl->mbOmitPaint && GetStatusBar().AreItemsVisible() )
263 GetStatusBar().SetItemData( GetId(), 0 ); // force repaint
266 // -----------------------------------------------------------------------
268 void SvxZoomSliderControl::Paint( const UserDrawEvent& rUsrEvt )
270 if ( !mpImpl->mbValuesSet || mpImpl->mbOmitPaint )
271 return;
273 const Rectangle aControlRect = getControlRect();
274 OutputDevice* pDev = rUsrEvt.GetDevice();
275 Rectangle aRect = rUsrEvt.GetRect();
276 Rectangle aSlider = aRect;
278 aSlider.Top() += (aControlRect.GetHeight() - nSliderHeight)/2 - 1;
279 aSlider.Bottom() = aSlider.Top() + nSliderHeight;
280 aSlider.Left() += nSliderXOffset;
281 aSlider.Right() -= nSliderXOffset;
283 Color aOldLineColor = pDev->GetLineColor();
284 Color aOldFillColor = pDev->GetFillColor();
286 pDev->SetLineColor( Color( COL_GRAY ) );
287 pDev->SetFillColor( Color( COL_GRAY ) );
289 // draw snapping points:
290 std::vector< long >::iterator aSnappingPointIter;
291 for ( aSnappingPointIter = mpImpl->maSnappingPointOffsets.begin();
292 aSnappingPointIter != mpImpl->maSnappingPointOffsets.end();
293 ++aSnappingPointIter )
295 Rectangle aSnapping( aRect );
296 aSnapping.Bottom() = aSlider.Top();
297 aSnapping.Top() = aSnapping.Bottom() - nSnappingHeight;
298 aSnapping.Left() += *aSnappingPointIter;
299 aSnapping.Right() = aSnapping.Left();
300 pDev->DrawRect( aSnapping );
302 aSnapping.Top() += nSnappingHeight + nSliderHeight;
303 aSnapping.Bottom() += nSnappingHeight + nSliderHeight;
304 pDev->DrawRect( aSnapping );
307 // draw slider
308 Rectangle aFirstLine( aSlider );
309 aFirstLine.Bottom() = aFirstLine.Top();
311 Rectangle aSecondLine( aSlider );
312 aSecondLine.Top() = aSecondLine.Bottom();
314 Rectangle aLeft( aSlider );
315 aLeft.Right() = aLeft.Left();
317 Rectangle aRight( aSlider );
318 aRight.Left() = aRight.Right();
320 pDev->SetLineColor( Color ( COL_WHITE ) );
321 pDev->SetFillColor( Color ( COL_WHITE ) );
322 pDev->DrawRect( aSecondLine );
323 pDev->DrawRect( aRight );
325 pDev->SetLineColor( Color( COL_GRAY ) );
326 pDev->SetFillColor( Color( COL_GRAY ) );
327 pDev->DrawRect( aFirstLine );
328 pDev->DrawRect( aLeft );
330 // draw slider button
331 Point aImagePoint = aRect.TopLeft();
332 aImagePoint.X() += Zoom2Offset( mpImpl->mnCurrentZoom );
333 aImagePoint.X() -= nButtonWidth/2;
334 aImagePoint.Y() += (aControlRect.GetHeight() - nButtonHeight)/2;
335 pDev->DrawImage( aImagePoint, mpImpl->maSliderButton );
337 // draw decrease button
338 aImagePoint = aRect.TopLeft();
339 aImagePoint.X() += (nSliderXOffset - nIncDecWidth)/2;
340 aImagePoint.Y() += (aControlRect.GetHeight() - nIncDecHeight)/2;
341 pDev->DrawImage( aImagePoint, mpImpl->maDecreaseButton );
343 // draw increase button
344 aImagePoint.X() = aRect.TopLeft().X() + aControlRect.GetWidth() - nIncDecWidth - (nSliderXOffset - nIncDecWidth)/2;
345 pDev->DrawImage( aImagePoint, mpImpl->maIncreaseButton );
347 pDev->SetLineColor( aOldLineColor );
348 pDev->SetFillColor( aOldFillColor );
351 // -----------------------------------------------------------------------
353 BOOL SvxZoomSliderControl::MouseButtonDown( const MouseEvent & rEvt )
355 if ( !mpImpl->mbValuesSet )
356 return TRUE;;
358 const Rectangle aControlRect = getControlRect();
359 const Point aPoint = rEvt.GetPosPixel();
360 const sal_Int32 nXDiff = aPoint.X() - aControlRect.Left();
362 const long nButtonLeftOffset = (nSliderXOffset - nIncDecWidth)/2;
363 const long nButtonRightOffset = (nSliderXOffset + nIncDecWidth)/2;
365 const long nOldZoom = mpImpl->mnCurrentZoom;
367 // click to - button
368 if ( nXDiff >= nButtonLeftOffset && nXDiff <= nButtonRightOffset )
369 mpImpl->mnCurrentZoom = mpImpl->mnCurrentZoom - 5;
370 // click to + button
371 else if ( nXDiff >= aControlRect.GetWidth() - nSliderXOffset + nButtonLeftOffset &&
372 nXDiff <= aControlRect.GetWidth() - nSliderXOffset + nButtonRightOffset )
373 mpImpl->mnCurrentZoom = mpImpl->mnCurrentZoom + 5;
374 // click to slider
375 else if( nXDiff >= nSliderXOffset && nXDiff <= aControlRect.GetWidth() - nSliderXOffset )
376 mpImpl->mnCurrentZoom = Offset2Zoom( nXDiff );
378 if ( mpImpl->mnCurrentZoom < mpImpl->mnMinZoom )
379 mpImpl->mnCurrentZoom = mpImpl->mnMinZoom;
380 else if ( mpImpl->mnCurrentZoom > mpImpl->mnMaxZoom )
381 mpImpl->mnCurrentZoom = mpImpl->mnMaxZoom;
383 if ( nOldZoom == mpImpl->mnCurrentZoom )
384 return TRUE;
386 if ( GetStatusBar().AreItemsVisible() )
387 GetStatusBar().SetItemData( GetId(), 0 ); // force repaint
389 mpImpl->mbOmitPaint = true; // optimization: paint before executing command,
390 // then omit painting which is triggered by the execute function
392 SvxZoomSliderItem aZoomSliderItem( mpImpl->mnCurrentZoom );
394 ::com::sun::star::uno::Any a;
395 aZoomSliderItem.QueryValue( a );
397 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aArgs( 1 );
398 aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ZoomSlider" ));
399 aArgs[0].Value = a;
401 execute( aArgs );
403 mpImpl->mbOmitPaint = false;
405 return TRUE;
408 // -----------------------------------------------------------------------
410 BOOL SvxZoomSliderControl::MouseMove( const MouseEvent & rEvt )
412 if ( !mpImpl->mbValuesSet )
413 return TRUE;;
415 const short nButtons = rEvt.GetButtons();
417 // check mouse move with button pressed
418 if ( 1 == nButtons )
420 const Rectangle aControlRect = getControlRect();
421 const Point aPoint = rEvt.GetPosPixel();
422 const sal_Int32 nXDiff = aPoint.X() - aControlRect.Left();
424 if ( nXDiff >= nSliderXOffset && nXDiff <= aControlRect.GetWidth() - nSliderXOffset )
426 mpImpl->mnCurrentZoom = Offset2Zoom( nXDiff );
428 if ( GetStatusBar().AreItemsVisible() )
429 GetStatusBar().SetItemData( GetId(), 0 ); // force repaint
431 mpImpl->mbOmitPaint = true; // optimization: paint before executing command,
432 // then omit painting which is triggered by the execute function
434 // commit state change
435 SvxZoomSliderItem aZoomSliderItem( mpImpl->mnCurrentZoom );
437 ::com::sun::star::uno::Any a;
438 aZoomSliderItem.QueryValue( a );
440 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aArgs( 1 );
441 aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ZoomSlider" ));
442 aArgs[0].Value = a;
444 execute( aArgs );
446 mpImpl->mbOmitPaint = false;
450 return TRUE;