fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / svx / source / stbctrls / zoomsliderctrl.cxx
blob94e2777fdf5950b958a54ee3c0002746903ced37
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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>
29 #include <basegfx/tools/zoomtools.hxx>
31 #include <set>
33 // -----------------------------------------------------------------------
35 SFX_IMPL_STATUSBAR_CONTROL( SvxZoomSliderControl, SvxZoomSliderItem );
37 // -----------------------------------------------------------------------
39 struct SvxZoomSliderControl::SvxZoomSliderControl_Impl
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;
53 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 mbOmitPaint( false ) {}
67 // -----------------------------------------------------------------------
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
79 // -----------------------------------------------------------------------
81 // nOffset referes to the origin of the control:
82 // + ----------- -
83 sal_uInt16 SvxZoomSliderControl::Offset2Zoom( long nOffset ) const
85 const long nControlWidth = getControlRect().GetWidth();
86 sal_uInt16 nRet = 0;
88 if ( nOffset < nSliderXOffset )
89 return mpImpl->mnMinZoom;
91 if ( nOffset > nControlWidth - nSliderXOffset )
92 return mpImpl->mnMaxZoom;
94 // check for snapping points:
95 sal_uInt16 nCount = 0;
96 std::vector< long >::iterator aSnappingPointIter;
97 for ( aSnappingPointIter = mpImpl->maSnappingPointOffsets.begin();
98 aSnappingPointIter != mpImpl->maSnappingPointOffsets.end();
99 ++aSnappingPointIter )
101 const long nCurrent = *aSnappingPointIter;
102 if ( std::abs(nCurrent - nOffset) < nSnappingEpsilon )
104 nOffset = nCurrent;
105 nRet = mpImpl->maSnappingPointZooms[ nCount ];
106 break;
108 ++nCount;
111 if ( 0 == nRet )
113 if ( nOffset < nControlWidth / 2 )
115 // first half of slider
116 const long nFirstHalfRange = mpImpl->mnSliderCenter - mpImpl->mnMinZoom;
117 const long nHalfSliderWidth = nControlWidth/2 - nSliderXOffset;
118 const long nZoomPerSliderPixel = (1000 * nFirstHalfRange) / nHalfSliderWidth;
119 const long nOffsetToSliderLeft = nOffset - nSliderXOffset;
120 nRet = mpImpl->mnMinZoom + sal_uInt16( nOffsetToSliderLeft * nZoomPerSliderPixel / 1000 );
122 else
124 // second half of slider
125 const long nSecondHalfRange = mpImpl->mnMaxZoom - mpImpl->mnSliderCenter;
126 const long nHalfSliderWidth = nControlWidth/2 - nSliderXOffset;
127 const long nZoomPerSliderPixel = 1000 * nSecondHalfRange / nHalfSliderWidth;
128 const long nOffsetToSliderCenter = nOffset - nControlWidth/2;
129 nRet = mpImpl->mnSliderCenter + sal_uInt16( nOffsetToSliderCenter * nZoomPerSliderPixel / 1000 );
133 if ( nRet < mpImpl->mnMinZoom )
134 nRet = mpImpl->mnMinZoom;
135 else if ( nRet > mpImpl->mnMaxZoom )
136 nRet = mpImpl->mnMaxZoom;
138 return nRet;
141 // returns the offset to the left control border
142 long SvxZoomSliderControl::Zoom2Offset( sal_uInt16 nCurrentZoom ) const
144 const long nControlWidth = getControlRect().GetWidth();
145 long nRet = nSliderXOffset;
147 const long nHalfSliderWidth = nControlWidth/2 - nSliderXOffset;
149 if ( nCurrentZoom <= mpImpl->mnSliderCenter )
151 nCurrentZoom = nCurrentZoom - mpImpl->mnMinZoom;
152 const long nFirstHalfRange = mpImpl->mnSliderCenter - mpImpl->mnMinZoom;
153 const long nSliderPixelPerZoomPercent = 1000 * nHalfSliderWidth / nFirstHalfRange;
154 const long nOffset = (nSliderPixelPerZoomPercent * nCurrentZoom) / 1000;
155 nRet += nOffset;
157 else
159 nCurrentZoom = nCurrentZoom - mpImpl->mnSliderCenter;
160 const long nSecondHalfRange = mpImpl->mnMaxZoom - mpImpl->mnSliderCenter;
161 const long nSliderPixelPerZoomPercent = 1000 * nHalfSliderWidth / nSecondHalfRange;
162 const long nOffset = (nSliderPixelPerZoomPercent * nCurrentZoom) / 1000;
163 nRet += nHalfSliderWidth + nOffset;
166 return nRet;
169 // -----------------------------------------------------------------------
171 SvxZoomSliderControl::SvxZoomSliderControl( sal_uInt16 _nSlotId, sal_uInt16 _nId, StatusBar& _rStb ) :
172 SfxStatusBarControl( _nSlotId, _nId, _rStb ),
173 mpImpl( new SvxZoomSliderControl_Impl )
175 mpImpl->maSliderButton = Image( SVX_RES( RID_SVXBMP_SLIDERBUTTON ) );
176 mpImpl->maIncreaseButton = Image( SVX_RES( RID_SVXBMP_SLIDERINCREASE ) );
177 mpImpl->maDecreaseButton = Image( SVX_RES( RID_SVXBMP_SLIDERDECREASE ) );
180 // -----------------------------------------------------------------------
182 SvxZoomSliderControl::~SvxZoomSliderControl()
184 delete mpImpl;
187 // -----------------------------------------------------------------------
189 void SvxZoomSliderControl::StateChanged( sal_uInt16 /*nSID*/, SfxItemState eState, const SfxPoolItem* pState )
191 if ( (SFX_ITEM_AVAILABLE != eState) || pState->ISA( SfxVoidItem ) )
193 GetStatusBar().SetItemText( GetId(), String() );
194 mpImpl->mbValuesSet = false;
196 else
198 OSL_ENSURE( pState->ISA( SvxZoomSliderItem ), "invalid item type: should be a SvxZoomSliderItem" );
199 mpImpl->mnCurrentZoom = static_cast<const SvxZoomSliderItem*>( pState )->GetValue();
200 mpImpl->mnMinZoom = static_cast<const SvxZoomSliderItem*>( pState )->GetMinZoom();
201 mpImpl->mnMaxZoom = static_cast<const SvxZoomSliderItem*>( pState )->GetMaxZoom();
202 mpImpl->mnSliderCenter= 100;
203 mpImpl->mbValuesSet = true;
205 if ( mpImpl->mnSliderCenter == mpImpl->mnMaxZoom )
206 mpImpl->mnSliderCenter = mpImpl->mnMinZoom + (sal_uInt16)((mpImpl->mnMaxZoom - mpImpl->mnMinZoom) * 0.5);
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" );
215 const com::sun::star::uno::Sequence < sal_Int32 > rSnappingPoints = static_cast<const SvxZoomSliderItem*>( pState )->GetSnappingPoints();
216 mpImpl->maSnappingPointOffsets.clear();
217 mpImpl->maSnappingPointZooms.clear();
219 // get all snapping points:
220 std::set< sal_uInt16 > aTmpSnappingPoints;
221 for ( sal_uInt16 j = 0; j < rSnappingPoints.getLength(); ++j )
223 const sal_Int32 nSnappingPoint = rSnappingPoints[j];
224 aTmpSnappingPoints.insert( (sal_uInt16)nSnappingPoint );
227 // remove snapping points that are to close to each other:
228 std::set< sal_uInt16 >::iterator aSnappingPointIter;
229 long nLastOffset = 0;
231 for ( aSnappingPointIter = aTmpSnappingPoints.begin(); aSnappingPointIter != aTmpSnappingPoints.end(); ++aSnappingPointIter )
233 const sal_uInt16 nCurrent = *aSnappingPointIter;
234 const long nCurrentOffset = Zoom2Offset( nCurrent );
236 if ( nCurrentOffset - nLastOffset >= nSnappingPointsMinDist )
238 mpImpl->maSnappingPointOffsets.push_back( nCurrentOffset );
239 mpImpl->maSnappingPointZooms.push_back( nCurrent );
240 nLastOffset = nCurrentOffset;
245 if ( !mpImpl->mbOmitPaint && GetStatusBar().AreItemsVisible() )
246 GetStatusBar().SetItemData( GetId(), 0 ); // force repaint
249 // -----------------------------------------------------------------------
251 void SvxZoomSliderControl::Paint( const UserDrawEvent& rUsrEvt )
253 if ( !mpImpl->mbValuesSet || mpImpl->mbOmitPaint )
254 return;
256 const Rectangle aControlRect = getControlRect();
257 OutputDevice* pDev = rUsrEvt.GetDevice();
258 Rectangle aRect = rUsrEvt.GetRect();
259 Rectangle aSlider = aRect;
261 aSlider.Top() += (aControlRect.GetHeight() - nSliderHeight)/2;
262 aSlider.Bottom() = aSlider.Top() + nSliderHeight - 1;
263 aSlider.Left() += nSliderXOffset;
264 aSlider.Right() -= nSliderXOffset;
266 Color aOldLineColor = pDev->GetLineColor();
267 Color aOldFillColor = pDev->GetFillColor();
269 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
270 pDev->SetLineColor( rStyleSettings.GetShadowColor() );
271 pDev->SetFillColor( rStyleSettings.GetShadowColor() );
273 // draw snapping points:
274 std::vector< long >::iterator aSnappingPointIter;
275 for ( aSnappingPointIter = mpImpl->maSnappingPointOffsets.begin();
276 aSnappingPointIter != mpImpl->maSnappingPointOffsets.end();
277 ++aSnappingPointIter )
279 long nSnapPosX = aRect.Left() + *aSnappingPointIter;
281 pDev->DrawRect( Rectangle( nSnapPosX - 1, aSlider.Top() - nSnappingHeight,
282 nSnapPosX, aSlider.Bottom() + nSnappingHeight ) );
285 // draw slider
286 pDev->DrawRect( aSlider );
288 // draw slider button
289 Point aImagePoint = aRect.TopLeft();
290 aImagePoint.X() += Zoom2Offset( mpImpl->mnCurrentZoom );
291 aImagePoint.X() -= nButtonWidth/2;
292 aImagePoint.Y() += (aControlRect.GetHeight() - nButtonHeight)/2;
293 pDev->DrawImage( aImagePoint, mpImpl->maSliderButton );
295 // draw decrease button
296 aImagePoint = aRect.TopLeft();
297 aImagePoint.X() += (nSliderXOffset - nIncDecWidth)/2;
298 aImagePoint.Y() += (aControlRect.GetHeight() - nIncDecHeight)/2;
299 pDev->DrawImage( aImagePoint, mpImpl->maDecreaseButton );
301 // draw increase button
302 aImagePoint.X() = aRect.TopLeft().X() + aControlRect.GetWidth() - nIncDecWidth - (nSliderXOffset - nIncDecWidth)/2;
303 pDev->DrawImage( aImagePoint, mpImpl->maIncreaseButton );
305 pDev->SetLineColor( aOldLineColor );
306 pDev->SetFillColor( aOldFillColor );
309 // -----------------------------------------------------------------------
311 sal_Bool SvxZoomSliderControl::MouseButtonDown( const MouseEvent & rEvt )
313 if ( !mpImpl->mbValuesSet )
314 return sal_True;
316 const Rectangle aControlRect = getControlRect();
317 const Point aPoint = rEvt.GetPosPixel();
318 const sal_Int32 nXDiff = aPoint.X() - aControlRect.Left();
320 const long nButtonLeftOffset = (nSliderXOffset - nIncDecWidth)/2;
321 const long nButtonRightOffset = (nSliderXOffset + nIncDecWidth)/2;
323 const long nOldZoom = mpImpl->mnCurrentZoom;
325 // click to - button
326 if ( nXDiff >= nButtonLeftOffset && nXDiff <= nButtonRightOffset )
327 mpImpl->mnCurrentZoom = basegfx::zoomtools::zoomOut( static_cast<int>(mpImpl->mnCurrentZoom) );
328 // click to + button
329 else if ( nXDiff >= aControlRect.GetWidth() - nSliderXOffset + nButtonLeftOffset &&
330 nXDiff <= aControlRect.GetWidth() - nSliderXOffset + nButtonRightOffset )
331 mpImpl->mnCurrentZoom = basegfx::zoomtools::zoomIn( static_cast<int>(mpImpl->mnCurrentZoom) );
332 // click to slider
333 else if( nXDiff >= nSliderXOffset && nXDiff <= aControlRect.GetWidth() - nSliderXOffset )
334 mpImpl->mnCurrentZoom = Offset2Zoom( nXDiff );
336 if ( mpImpl->mnCurrentZoom < mpImpl->mnMinZoom )
337 mpImpl->mnCurrentZoom = mpImpl->mnMinZoom;
338 else if ( mpImpl->mnCurrentZoom > mpImpl->mnMaxZoom )
339 mpImpl->mnCurrentZoom = mpImpl->mnMaxZoom;
341 if ( nOldZoom == mpImpl->mnCurrentZoom )
342 return sal_True;
344 if ( GetStatusBar().AreItemsVisible() )
345 GetStatusBar().SetItemData( GetId(), 0 ); // force repaint
347 mpImpl->mbOmitPaint = true; // optimization: paint before executing command,
348 // then omit painting which is triggered by the execute function
350 SvxZoomSliderItem aZoomSliderItem( mpImpl->mnCurrentZoom );
352 ::com::sun::star::uno::Any a;
353 aZoomSliderItem.QueryValue( a );
355 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aArgs( 1 );
356 aArgs[0].Name = OUString( "ZoomSlider" );
357 aArgs[0].Value = a;
359 execute( aArgs );
361 mpImpl->mbOmitPaint = false;
363 return sal_True;
366 // -----------------------------------------------------------------------
368 sal_Bool SvxZoomSliderControl::MouseMove( const MouseEvent & rEvt )
370 if ( !mpImpl->mbValuesSet )
371 return sal_True;
373 const short nButtons = rEvt.GetButtons();
375 // check mouse move with button pressed
376 if ( 1 == nButtons )
378 const Rectangle aControlRect = getControlRect();
379 const Point aPoint = rEvt.GetPosPixel();
380 const sal_Int32 nXDiff = aPoint.X() - aControlRect.Left();
382 if ( nXDiff >= nSliderXOffset && nXDiff <= aControlRect.GetWidth() - nSliderXOffset )
384 mpImpl->mnCurrentZoom = Offset2Zoom( nXDiff );
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 // commit state change
393 SvxZoomSliderItem aZoomSliderItem( mpImpl->mnCurrentZoom );
395 ::com::sun::star::uno::Any a;
396 aZoomSliderItem.QueryValue( a );
398 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aArgs( 1 );
399 aArgs[0].Name = OUString( "ZoomSlider" );
400 aArgs[0].Value = a;
402 execute( aArgs );
404 mpImpl->mbOmitPaint = false;
408 return sal_True;
411 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */