fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / ui / cctrl / tbzoomsliderctrl.cxx
blob74898e336a6984c1b55fc921814a0eddcb8c612d
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 .
19 #include "tbzoomsliderctrl.hxx"
20 #include <vcl/image.hxx>
21 #include <vcl/toolbox.hxx>
22 #include <vcl/virdev.hxx>
23 #include <vcl/svapp.hxx>
24 #include <vcl/gradient.hxx>
25 #include <vcl/settings.hxx>
26 #include <svl/itemset.hxx>
27 #include <sfx2/viewfrm.hxx>
28 #include <sfx2/objsh.hxx>
29 #include <svx/zoomslideritem.hxx>
30 #include <svx/dialmgr.hxx>
31 #include <svx/dialogs.hrc>
32 #include <set>
33 #include "docsh.hxx"
34 #include "stlpool.hxx"
35 #include "scitems.hxx"
36 #include "printfun.hxx"
38 // class ScZoomSliderControl ---------------------------------------
40 SFX_IMPL_TOOLBOX_CONTROL( ScZoomSliderControl, SvxZoomSliderItem );
42 ScZoomSliderControl::ScZoomSliderControl(
43 sal_uInt16 nSlotId,
44 sal_uInt16 nId,
45 ToolBox& rTbx )
46 :SfxToolBoxControl( nSlotId, nId, rTbx )
48 rTbx.Invalidate();
51 ScZoomSliderControl::~ScZoomSliderControl()
56 void ScZoomSliderControl::StateChanged( sal_uInt16 /*nSID*/, SfxItemState eState,
57 const SfxPoolItem* pState )
59 sal_uInt16 nId = GetId();
60 ToolBox& rTbx = GetToolBox();
61 ScZoomSliderWnd* pBox = static_cast<ScZoomSliderWnd*>(rTbx.GetItemWindow( nId ));
62 OSL_ENSURE( pBox ,"Control not found!" );
64 if ( SfxItemState::DEFAULT != eState || pState->ISA( SfxVoidItem ) )
66 SvxZoomSliderItem aZoomSliderItem( 100 );
67 pBox->Disable();
68 pBox->UpdateFromItem( &aZoomSliderItem );
70 else
72 pBox->Enable();
73 OSL_ENSURE( pState->ISA( SvxZoomSliderItem ), "invalid item type" );
74 const SvxZoomSliderItem* pZoomSliderItem = dynamic_cast< const SvxZoomSliderItem* >( pState );
76 OSL_ENSURE( pZoomSliderItem, "Sc::ScZoomSliderControl::StateChanged(), wrong item type!" );
77 if( pZoomSliderItem )
78 pBox->UpdateFromItem( pZoomSliderItem );
82 VclPtr<vcl::Window> ScZoomSliderControl::CreateItemWindow( vcl::Window *pParent )
84 // #i98000# Don't try to get a value via SfxViewFrame::Current here.
85 // The view's value is always notified via StateChanged later.
86 VclPtrInstance<ScZoomSliderWnd> pSlider( pParent,
87 ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider >( m_xFrame->getController(),
88 ::com::sun::star::uno::UNO_QUERY ), m_xFrame, 100 );
89 return pSlider.get();
92 struct ScZoomSliderWnd::ScZoomSliderWnd_Impl
94 sal_uInt16 mnCurrentZoom;
95 sal_uInt16 mnMinZoom;
96 sal_uInt16 mnMaxZoom;
97 sal_uInt16 mnSliderCenter;
98 std::vector< long > maSnappingPointOffsets;
99 std::vector< sal_uInt16 > maSnappingPointZooms;
100 Image maSliderButton;
101 Image maIncreaseButton;
102 Image maDecreaseButton;
103 bool mbValuesSet;
104 bool mbOmitPaint;
106 ScZoomSliderWnd_Impl( sal_uInt16 nCurrentZoom ) :
107 mnCurrentZoom( nCurrentZoom ),
108 mnMinZoom( 10 ),
109 mnMaxZoom( 400 ),
110 mnSliderCenter( 100 ),
111 maSnappingPointOffsets(),
112 maSnappingPointZooms(),
113 maSliderButton(),
114 maIncreaseButton(),
115 maDecreaseButton(),
116 mbValuesSet( true ),
117 mbOmitPaint( false )
123 const long nButtonWidth = 10;
124 const long nButtonHeight = 10;
125 const long nIncDecWidth = 11;
126 const long nIncDecHeight = 11;
127 const long nSliderHeight = 2;
128 const long nSliderWidth = 4;
129 const long nSnappingHeight = 4;
130 const long nSliderXOffset = 20;
131 const long nSnappingEpsilon = 5; // snapping epsilon in pixels
132 const long nSnappingPointsMinDist = nSnappingEpsilon; // minimum distance of two adjacent snapping points
134 sal_uInt16 ScZoomSliderWnd::Offset2Zoom( long nOffset ) const
136 Size aSliderWindowSize = GetOutputSizePixel();
137 const long nControlWidth = aSliderWindowSize.Width();
138 sal_uInt16 nRet = 0;
140 if( nOffset < nSliderXOffset )
141 return mpImpl->mnMinZoom;
142 if( nOffset > nControlWidth - nSliderXOffset )
143 return mpImpl->mnMaxZoom;
145 // check for snapping points:
146 sal_uInt16 nCount = 0;
147 std::vector< long >::iterator aSnappingPointIter;
148 for ( aSnappingPointIter = mpImpl->maSnappingPointOffsets.begin();
149 aSnappingPointIter != mpImpl->maSnappingPointOffsets.end();
150 ++aSnappingPointIter )
152 const long nCurrent = *aSnappingPointIter;
153 if ( std::abs(nCurrent - nOffset) < nSnappingEpsilon )
155 nOffset = nCurrent;
156 nRet = mpImpl->maSnappingPointZooms[ nCount ];
157 break;
159 ++nCount;
162 if( 0 == nRet )
164 if( nOffset < nControlWidth / 2 )
166 // first half of slider
167 const long nFirstHalfRange = mpImpl->mnSliderCenter - mpImpl->mnMinZoom;
168 const long nHalfSliderWidth = nControlWidth/2 - nSliderXOffset;
169 const long nZoomPerSliderPixel = (1000 * nFirstHalfRange) / nHalfSliderWidth;
170 const long nOffsetToSliderLeft = nOffset - nSliderXOffset;
171 nRet = mpImpl->mnMinZoom + sal_uInt16( nOffsetToSliderLeft * nZoomPerSliderPixel / 1000 );
173 else
175 // second half of slider
176 const long nSecondHalfRange = mpImpl->mnMaxZoom - mpImpl->mnSliderCenter;
177 const long nHalfSliderWidth = nControlWidth/2 - nSliderXOffset;
178 const long nZoomPerSliderPixel = 1000 * nSecondHalfRange / nHalfSliderWidth;
179 const long nOffsetToSliderCenter = nOffset - nControlWidth/2;
180 nRet = mpImpl->mnSliderCenter + sal_uInt16( nOffsetToSliderCenter * nZoomPerSliderPixel / 1000 );
184 if( nRet < mpImpl->mnMinZoom )
185 return mpImpl->mnMinZoom;
187 else if( nRet > mpImpl->mnMaxZoom )
188 return mpImpl->mnMaxZoom;
190 return nRet;
193 long ScZoomSliderWnd::Zoom2Offset( sal_uInt16 nCurrentZoom ) const
195 Size aSliderWindowSize = GetOutputSizePixel();
196 const long nControlWidth = aSliderWindowSize.Width();
197 long nRect = nSliderXOffset;
199 const long nHalfSliderWidth = nControlWidth/2 - nSliderXOffset;
200 if( nCurrentZoom <= mpImpl->mnSliderCenter )
202 nCurrentZoom = nCurrentZoom - mpImpl->mnMinZoom;
203 const long nFirstHalfRange = mpImpl->mnSliderCenter - mpImpl->mnMinZoom;
204 const long nSliderPixelPerZoomPercent = 1000 * nHalfSliderWidth / nFirstHalfRange;
205 const long nOffset = (nSliderPixelPerZoomPercent * nCurrentZoom) / 1000;
206 nRect += nOffset;
208 else
210 nCurrentZoom = nCurrentZoom - mpImpl->mnSliderCenter;
211 const long nSecondHalfRange = mpImpl->mnMaxZoom - mpImpl->mnSliderCenter;
212 const long nSliderPixelPerZoomPercent = 1000 * nHalfSliderWidth / nSecondHalfRange;
213 const long nOffset = (nSliderPixelPerZoomPercent * nCurrentZoom) / 1000;
214 nRect += nHalfSliderWidth + nOffset;
216 return nRect;
219 ScZoomSliderWnd::ScZoomSliderWnd( vcl::Window* pParent, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider >& rDispatchProvider,
220 const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& _xFrame , sal_uInt16 nCurrentZoom ):
221 Window( pParent ),
222 mpImpl( new ScZoomSliderWnd_Impl( nCurrentZoom ) ),
223 aLogicalSize( 115, 40 ),
224 m_xDispatchProvider( rDispatchProvider ),
225 m_xFrame( _xFrame )
227 mpImpl->maSliderButton = Image( SVX_RES( RID_SVXBMP_SLIDERBUTTON ) );
228 mpImpl->maIncreaseButton = Image( SVX_RES( RID_SVXBMP_SLIDERINCREASE ) );
229 mpImpl->maDecreaseButton = Image( SVX_RES( RID_SVXBMP_SLIDERDECREASE ) );
230 Size aSliderSize = LogicToPixel( Size( aLogicalSize), MapMode( MAP_10TH_MM ) );
231 SetSizePixel( Size( aSliderSize.Width() * nSliderWidth-1, aSliderSize.Height() + nSliderHeight ) );
234 ScZoomSliderWnd::~ScZoomSliderWnd()
236 disposeOnce();
239 void ScZoomSliderWnd::dispose()
241 delete mpImpl;
242 vcl::Window::dispose();
245 void ScZoomSliderWnd::MouseButtonDown( const MouseEvent& rMEvt )
247 if ( !mpImpl->mbValuesSet )
248 return ;
249 Size aSliderWindowSize = GetOutputSizePixel();
251 const Point aPoint = rMEvt.GetPosPixel();
253 const long nButtonLeftOffset = ( nSliderXOffset - nIncDecWidth )/2;
254 const long nButtonRightOffset = ( nSliderXOffset + nIncDecWidth )/2;
256 const long nOldZoom = mpImpl->mnCurrentZoom;
258 // click to - button
259 if ( aPoint.X() >= nButtonLeftOffset && aPoint.X() <= nButtonRightOffset )
261 mpImpl->mnCurrentZoom = mpImpl->mnCurrentZoom - 5;
263 // click to + button
264 else if ( aPoint.X() >= aSliderWindowSize.Width() - nSliderXOffset + nButtonLeftOffset &&
265 aPoint.X() <= aSliderWindowSize.Width() - nSliderXOffset + nButtonRightOffset )
267 mpImpl->mnCurrentZoom = mpImpl->mnCurrentZoom + 5;
269 else if( aPoint.X() >= nSliderXOffset && aPoint.X() <= aSliderWindowSize.Width() - nSliderXOffset )
271 mpImpl->mnCurrentZoom = Offset2Zoom( aPoint.X() );
274 if( mpImpl->mnCurrentZoom < mpImpl->mnMinZoom )
275 mpImpl->mnCurrentZoom = mpImpl->mnMinZoom;
276 else if( mpImpl->mnCurrentZoom > mpImpl->mnMaxZoom )
277 mpImpl->mnCurrentZoom = mpImpl->mnMaxZoom;
279 if( nOldZoom == mpImpl->mnCurrentZoom )
280 return ;
282 Rectangle aRect( Point( 0, 0 ), aSliderWindowSize );
284 Invalidate(aRect);
285 mpImpl->mbOmitPaint = true;
287 SvxZoomSliderItem aZoomSliderItem( mpImpl->mnCurrentZoom );
289 ::com::sun::star::uno::Any a;
290 aZoomSliderItem.QueryValue( a );
292 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aArgs( 1 );
293 aArgs[0].Name = "ScalingFactor";
294 aArgs[0].Value = a;
296 SfxToolBoxControl::Dispatch( m_xDispatchProvider, OUString(".uno:ScalingFactor"), aArgs );
298 mpImpl->mbOmitPaint = false;
301 void ScZoomSliderWnd::MouseMove( const MouseEvent& rMEvt )
303 if ( !mpImpl->mbValuesSet )
304 return ;
306 Size aSliderWindowSize = GetOutputSizePixel();
307 const long nControlWidth = aSliderWindowSize.Width();
308 const short nButtons = rMEvt.GetButtons();
310 // check mouse move with button pressed
311 if ( 1 == nButtons )
313 const Point aPoint = rMEvt.GetPosPixel();
315 if ( aPoint.X() >= nSliderXOffset && aPoint.X() <= nControlWidth - nSliderXOffset )
317 mpImpl->mnCurrentZoom = Offset2Zoom( aPoint.X() );
319 Rectangle aRect(Point(0, 0), aSliderWindowSize);
320 Invalidate(aRect);
322 mpImpl->mbOmitPaint = true; // optimization: paint before executing command,
324 // commit state change
325 SvxZoomSliderItem aZoomSliderItem( mpImpl->mnCurrentZoom );
327 ::com::sun::star::uno::Any a;
328 aZoomSliderItem.QueryValue( a );
330 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aArgs( 1 );
331 aArgs[0].Name = "ScalingFactor";
332 aArgs[0].Value = a;
334 SfxToolBoxControl::Dispatch( m_xDispatchProvider, OUString(".uno:ScalingFactor"), aArgs );
336 mpImpl->mbOmitPaint = false;
341 void ScZoomSliderWnd::UpdateFromItem( const SvxZoomSliderItem* pZoomSliderItem )
343 if( pZoomSliderItem )
345 mpImpl->mnCurrentZoom = pZoomSliderItem->GetValue();
346 mpImpl->mnMinZoom = pZoomSliderItem->GetMinZoom();
347 mpImpl->mnMaxZoom = pZoomSliderItem->GetMaxZoom();
349 OSL_ENSURE( mpImpl->mnMinZoom <= mpImpl->mnCurrentZoom &&
350 mpImpl->mnMinZoom < mpImpl->mnSliderCenter &&
351 mpImpl->mnMaxZoom >= mpImpl->mnCurrentZoom &&
352 mpImpl->mnMaxZoom > mpImpl->mnSliderCenter,
353 "Looks like the zoom slider item is corrupted" );
354 const com::sun::star::uno::Sequence < sal_Int32 > rSnappingPoints = pZoomSliderItem->GetSnappingPoints();
355 mpImpl->maSnappingPointOffsets.clear();
356 mpImpl->maSnappingPointZooms.clear();
358 // get all snapping points:
359 std::set< sal_uInt16 > aTmpSnappingPoints;
360 for ( sal_uInt16 j = 0; j < rSnappingPoints.getLength(); ++j )
362 const sal_Int32 nSnappingPoint = rSnappingPoints[j];
363 aTmpSnappingPoints.insert( (sal_uInt16)nSnappingPoint );
366 // remove snapping points that are to close to each other:
367 std::set< sal_uInt16 >::iterator aSnappingPointIter;
368 long nLastOffset = 0;
370 for ( aSnappingPointIter = aTmpSnappingPoints.begin(); aSnappingPointIter != aTmpSnappingPoints.end(); ++aSnappingPointIter )
372 const sal_uInt16 nCurrent = *aSnappingPointIter;
373 const long nCurrentOffset = Zoom2Offset( nCurrent );
375 if ( nCurrentOffset - nLastOffset >= nSnappingPointsMinDist )
377 mpImpl->maSnappingPointOffsets.push_back( nCurrentOffset );
378 mpImpl->maSnappingPointZooms.push_back( nCurrent );
379 nLastOffset = nCurrentOffset;
384 Size aSliderWindowSize = GetOutputSizePixel();
385 Rectangle aRect(Point(0, 0), aSliderWindowSize);
387 if ( !mpImpl->mbOmitPaint )
388 Invalidate(aRect);
391 void ScZoomSliderWnd::Paint(vcl::RenderContext& rRenderContext, const Rectangle& rRect)
393 DoPaint(rRenderContext, rRect);
396 void ScZoomSliderWnd::DoPaint(vcl::RenderContext& rRenderContext, const Rectangle& /*rRect*/)
398 if (mpImpl->mbOmitPaint)
399 return;
401 Size aSliderWindowSize(GetOutputSizePixel());
402 Rectangle aRect(Point(0, 0), aSliderWindowSize);
404 ScopedVclPtrInstance< VirtualDevice > pVDev(rRenderContext);
405 pVDev->SetOutputSizePixel(aSliderWindowSize);
407 Rectangle aSlider = aRect;
409 aSlider.Top() += (aSliderWindowSize.Height() - nSliderHeight) / 2 - 1;
410 aSlider.Bottom() = aSlider.Top() + nSliderHeight;
411 aSlider.Left() += nSliderXOffset;
412 aSlider.Right() -= nSliderXOffset;
414 Rectangle aFirstLine(aSlider);
415 aFirstLine.Bottom() = aFirstLine.Top();
417 Rectangle aSecondLine(aSlider);
418 aSecondLine.Top() = aSecondLine.Bottom();
420 Rectangle aLeft(aSlider);
421 aLeft.Right() = aLeft.Left();
423 Rectangle aRight(aSlider);
424 aRight.Left() = aRight.Right();
426 // draw VirtualDevice's background color
427 Color aStartColor = rRenderContext.GetSettings().GetStyleSettings().GetFaceColor();
428 Color aEndColor = rRenderContext.GetSettings().GetStyleSettings().GetFaceColor();
430 if (aEndColor.IsDark())
431 aStartColor = aEndColor;
433 Gradient aGradient;
434 aGradient.SetAngle(0);
435 aGradient.SetStyle(GradientStyle_LINEAR);
437 aGradient.SetStartColor(aStartColor);
438 aGradient.SetEndColor(aEndColor);
439 pVDev->DrawGradient(aRect, aGradient);
441 // draw slider
442 pVDev->SetLineColor(Color(COL_WHITE));
443 pVDev->DrawRect(aSecondLine);
444 pVDev->DrawRect(aRight);
446 pVDev->SetLineColor(Color(COL_GRAY));
447 pVDev->DrawRect(aFirstLine);
448 pVDev->DrawRect(aLeft);
450 // draw snapping points:
451 std::vector<long>::iterator aSnappingPointIter;
452 for (aSnappingPointIter = mpImpl->maSnappingPointOffsets.begin();
453 aSnappingPointIter != mpImpl->maSnappingPointOffsets.end();
454 ++aSnappingPointIter)
456 pVDev->SetLineColor(Color(COL_GRAY));
457 Rectangle aSnapping(aRect);
458 aSnapping.Bottom() = aSlider.Top();
459 aSnapping.Top() = aSnapping.Bottom() - nSnappingHeight;
460 aSnapping.Left() += *aSnappingPointIter;
461 aSnapping.Right() = aSnapping.Left();
462 pVDev->DrawRect(aSnapping);
464 aSnapping.Top() += nSnappingHeight + nSliderHeight;
465 aSnapping.Bottom() += nSnappingHeight + nSliderHeight;
466 pVDev->DrawRect(aSnapping);
469 // draw slider button
470 Point aImagePoint = aRect.TopLeft();
471 aImagePoint.X() += Zoom2Offset(mpImpl->mnCurrentZoom);
472 aImagePoint.X() -= nButtonWidth / 2;
473 aImagePoint.Y() += (aSliderWindowSize.Height() - nButtonHeight) / 2;
474 pVDev->DrawImage(aImagePoint, mpImpl->maSliderButton);
476 // draw decrease button
477 aImagePoint = aRect.TopLeft();
478 aImagePoint.X() += (nSliderXOffset - nIncDecWidth) / 2;
479 aImagePoint.Y() += (aSliderWindowSize.Height() - nIncDecHeight) / 2;
480 pVDev->DrawImage(aImagePoint, mpImpl->maDecreaseButton);
482 // draw increase button
483 aImagePoint.X() = aRect.TopLeft().X() + aSliderWindowSize.Width() - nIncDecWidth - (nSliderXOffset - nIncDecWidth) / 2;
484 pVDev->DrawImage(aImagePoint, mpImpl->maIncreaseButton);
486 rRenderContext.DrawOutDev(Point(0, 0), aSliderWindowSize, Point(0, 0), aSliderWindowSize, *pVDev);
489 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */