sync master with lastest vba changes
[ooovba.git] / sc / source / ui / cctrl / tbzoomsliderctrl.cxx
blob379fbb20e44b20876fa2708192cefbd2a36bf750
1 /*************************************************************************
3 * OpenOffice.org - a multi-platform office productivity suite
5 * $RCSfile: tbzoomsliderctrl.cxx,v $
7 * $Revision: 1.1 $
9 * last change: $Author: maoyg $ $Date: 2008/04/25 10:08:08 $
11 * The Contents of this file are made available subject to
12 * the terms of GNU Lesser General Public License Version 2.1.
15 * GNU Lesser General Public License Version 2.1
16 * =============================================
17 * Copyright 2005 by Sun Microsystems, Inc.
18 * 901 San Antonio Road, Palo Alto, CA 94303, USA
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License version 2.1, as published by the Free Software Foundation.
24 * This library is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Lesser General Public License for more details.
29 * You should have received a copy of the GNU Lesser General Public
30 * License along with this library; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
32 * MA 02111-1307 USA
34 ************************************************************************/
35 #include "precompiled_sc.hxx"
36 #ifndef _SC_ZOOMSLIDERTBCONTRL_HXX
37 #include "tbzoomsliderctrl.hxx"
38 #endif
39 #ifndef _SV_IMAGE_HXX
40 #include <vcl/image.hxx>
41 #endif
42 #ifndef _SV_TOOLBOX_HXX
43 #include <vcl/toolbox.hxx>
44 #endif
45 #ifndef _SV_SVAPP_HXX
46 #include <vcl/svapp.hxx>
47 #endif
48 #ifndef _SV_GRADIENT_HXX
49 #include <vcl/gradient.hxx>
50 #endif
51 #include <svtools/itemset.hxx>
52 #include <sfx2/viewfrm.hxx>
53 #include <sfx2/objsh.hxx>
54 #include <svx/zoomslideritem.hxx>
55 #include <svx/dialmgr.hxx>
56 #include <svx/dialogs.hrc>
57 #include <set>
58 #include "docsh.hxx"
59 #include "stlpool.hxx"
60 #include "scitems.hxx"
61 #include "printfun.hxx"
63 //========================================================================
64 // class ScZoomSliderControl ---------------------------------------
65 //========================================================================
67 // -----------------------------------------------------------------------
69 SFX_IMPL_TOOLBOX_CONTROL( ScZoomSliderControl, SvxZoomSliderItem );
71 // -----------------------------------------------------------------------
73 ScZoomSliderControl::ScZoomSliderControl(
74 USHORT nSlotId,
75 USHORT nId,
76 ToolBox& rTbx )
77 :SfxToolBoxControl( nSlotId, nId, rTbx )
79 rTbx.Invalidate();
82 // -----------------------------------------------------------------------
84 __EXPORT ScZoomSliderControl::~ScZoomSliderControl()
89 // -----------------------------------------------------------------------
91 void ScZoomSliderControl::StateChanged( USHORT /*nSID*/, SfxItemState eState,
92 const SfxPoolItem* pState )
94 USHORT nId = GetId();
95 ToolBox& rTbx = GetToolBox();
96 ScZoomSliderWnd* pBox = (ScZoomSliderWnd*)(rTbx.GetItemWindow( nId ));
97 DBG_ASSERT( pBox ,"Control not found!" );
99 if ( SFX_ITEM_AVAILABLE != eState || pState->ISA( SfxVoidItem ) )
101 SvxZoomSliderItem aZoomSliderItem( 100 );
102 pBox->Disable();
103 pBox->UpdateFromItem( &aZoomSliderItem );
105 else
107 pBox->Enable();
108 DBG_ASSERT( pState->ISA( SvxZoomSliderItem ), "invalid item type" );
109 const SvxZoomSliderItem* pZoomSliderItem = dynamic_cast< const SvxZoomSliderItem* >( pState );
111 DBG_ASSERT( pZoomSliderItem, "Sc::ScZoomSliderControl::StateChanged(), wrong item type!" );
112 if( pZoomSliderItem )
113 pBox->UpdateFromItem( pZoomSliderItem );
117 // -----------------------------------------------------------------------
119 Window* ScZoomSliderControl::CreateItemWindow( Window *pParent )
121 // #i98000# Don't try to get a value via SfxViewFrame::Current here.
122 // The view's value is always notified via StateChanged later.
123 ScZoomSliderWnd* pSlider = new ScZoomSliderWnd( pParent,
124 ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider >( m_xFrame->getController(),
125 ::com::sun::star::uno::UNO_QUERY ), m_xFrame, 100 );
126 return pSlider;
129 // -----------------------------------------------------------------------
131 struct ScZoomSliderWnd::ScZoomSliderWnd_Impl
133 USHORT mnCurrentZoom;
134 USHORT mnMinZoom;
135 USHORT mnMaxZoom;
136 USHORT mnSliderCenter;
137 std::vector< long > maSnappingPointOffsets;
138 std::vector< USHORT > maSnappingPointZooms;
139 Image maSliderButton;
140 Image maIncreaseButton;
141 Image maDecreaseButton;
142 bool mbValuesSet;
143 bool mbOmitPaint;
145 ScZoomSliderWnd_Impl( USHORT nCurrentZoom ) :
146 mnCurrentZoom( nCurrentZoom ),
147 mnMinZoom( 10 ),
148 mnMaxZoom( 400 ),
149 mnSliderCenter( 100 ),
150 maSnappingPointOffsets(),
151 maSnappingPointZooms(),
152 maSliderButton(),
153 maIncreaseButton(),
154 maDecreaseButton(),
155 mbValuesSet( true ),
156 mbOmitPaint( false )
162 // -----------------------------------------------------------------------
164 const long nButtonWidth = 10;
165 const long nButtonHeight = 10;
166 const long nIncDecWidth = 11;
167 const long nIncDecHeight = 11;
168 const long nSliderHeight = 2; //
169 const long nSliderWidth = 4; //
170 const long nSnappingHeight = 4;
171 const long nSliderXOffset = 20;
172 const long nSnappingEpsilon = 5; // snapping epsilon in pixels
173 const long nSnappingPointsMinDist = nSnappingEpsilon; // minimum distance of two adjacent snapping points
176 // -----------------------------------------------------------------------
178 USHORT ScZoomSliderWnd::Offset2Zoom( long nOffset ) const
180 Size aSliderWindowSize = GetOutputSizePixel();
181 const long nControlWidth = aSliderWindowSize.Width();
182 USHORT nRet = 0;
184 if( nOffset < nSliderXOffset )
185 return mpImpl->mnMinZoom;
186 if( nOffset > nControlWidth - nSliderXOffset )
187 return mpImpl->mnMaxZoom;
189 // check for snapping points:
190 USHORT nCount = 0;
191 std::vector< long >::iterator aSnappingPointIter;
192 for ( aSnappingPointIter = mpImpl->maSnappingPointOffsets.begin();
193 aSnappingPointIter != mpImpl->maSnappingPointOffsets.end();
194 ++aSnappingPointIter )
196 const long nCurrent = *aSnappingPointIter;
197 if ( Abs(nCurrent - nOffset) < nSnappingEpsilon )
199 nOffset = nCurrent;
200 nRet = mpImpl->maSnappingPointZooms[ nCount ];
201 break;
203 ++nCount;
206 if( 0 == nRet )
208 if( nOffset < nControlWidth / 2 )
210 // first half of slider
211 const long nFirstHalfRange = mpImpl->mnSliderCenter - mpImpl->mnMinZoom;
212 const long nHalfSliderWidth = nControlWidth/2 - nSliderXOffset;
213 const long nZoomPerSliderPixel = (1000 * nFirstHalfRange) / nHalfSliderWidth;
214 const long nOffsetToSliderLeft = nOffset - nSliderXOffset;
215 nRet = mpImpl->mnMinZoom + USHORT( nOffsetToSliderLeft * nZoomPerSliderPixel / 1000 );
217 else
219 // second half of slider
220 const long nSecondHalfRange = mpImpl->mnMaxZoom - mpImpl->mnSliderCenter;
221 const long nHalfSliderWidth = nControlWidth/2 - nSliderXOffset;
222 const long nZoomPerSliderPixel = 1000 * nSecondHalfRange / nHalfSliderWidth;
223 const long nOffsetToSliderCenter = nOffset - nControlWidth/2;
224 nRet = mpImpl->mnSliderCenter + USHORT( nOffsetToSliderCenter * nZoomPerSliderPixel / 1000 );
228 if( nRet < mpImpl->mnMinZoom )
229 return mpImpl->mnMinZoom;
231 else if( nRet > mpImpl->mnMaxZoom )
232 return mpImpl->mnMaxZoom;
234 return nRet;
237 // -----------------------------------------------------------------------
239 long ScZoomSliderWnd::Zoom2Offset( USHORT nCurrentZoom ) const
241 Size aSliderWindowSize = GetOutputSizePixel();
242 const long nControlWidth = aSliderWindowSize.Width();
243 long nRect = nSliderXOffset;
245 const long nHalfSliderWidth = nControlWidth/2 - nSliderXOffset;
246 if( nCurrentZoom <= mpImpl->mnSliderCenter )
248 nCurrentZoom = nCurrentZoom - mpImpl->mnMinZoom;
249 const long nFirstHalfRange = mpImpl->mnSliderCenter - mpImpl->mnMinZoom;
250 const long nSliderPixelPerZoomPercent = 1000 * nHalfSliderWidth / nFirstHalfRange;
251 const long nOffset = (nSliderPixelPerZoomPercent * nCurrentZoom) / 1000;
252 nRect += nOffset;
254 else
256 nCurrentZoom = nCurrentZoom - mpImpl->mnSliderCenter;
257 const long nSecondHalfRange = mpImpl->mnMaxZoom - mpImpl->mnSliderCenter;
258 const long nSliderPixelPerZoomPercent = 1000 * nHalfSliderWidth / nSecondHalfRange;
259 const long nOffset = (nSliderPixelPerZoomPercent * nCurrentZoom) / 1000;
260 nRect += nHalfSliderWidth + nOffset;
262 return nRect;
265 // -----------------------------------------------------------------------
268 ScZoomSliderWnd::ScZoomSliderWnd( Window* pParent, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider >& rDispatchProvider,
269 const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& _xFrame , USHORT nCurrentZoom ):
270 Window( pParent ),
271 mpImpl( new ScZoomSliderWnd_Impl( nCurrentZoom ) ),
272 aLogicalSize( 115, 40 ),
273 m_xDispatchProvider( rDispatchProvider ),
274 m_xFrame( _xFrame )
276 BOOL bIsDark = GetSettings().GetStyleSettings().GetFaceColor().IsDark();
277 mpImpl->maSliderButton = Image( SVX_RES( bIsDark ? RID_SVXBMP_SLIDERBUTTON_HC : RID_SVXBMP_SLIDERBUTTON ) );
278 mpImpl->maIncreaseButton = Image( SVX_RES( bIsDark ? RID_SVXBMP_SLIDERINCREASE_HC : RID_SVXBMP_SLIDERINCREASE ) );
279 mpImpl->maDecreaseButton = Image( SVX_RES( bIsDark ? RID_SVXBMP_SLIDERDECREASE_HC : RID_SVXBMP_SLIDERDECREASE ) );
280 Size aSliderSize = LogicToPixel( Size( aLogicalSize), MapMode( MAP_10TH_MM ) );
281 SetSizePixel( Size( aSliderSize.Width() * nSliderWidth-1, aSliderSize.Height() + nSliderHeight ) );
284 // -----------------------------------------------------------------------
286 ScZoomSliderWnd::~ScZoomSliderWnd()
288 delete mpImpl;
291 // -----------------------------------------------------------------------
293 void ScZoomSliderWnd::MouseButtonDown( const MouseEvent& rMEvt )
295 if ( !mpImpl->mbValuesSet )
296 return ;
297 Size aSliderWindowSize = GetOutputSizePixel();
299 const Point aPoint = rMEvt.GetPosPixel();
301 const long nButtonLeftOffset = ( nSliderXOffset - nIncDecWidth )/2;
302 const long nButtonRightOffset = ( nSliderXOffset + nIncDecWidth )/2;
304 const long nOldZoom = mpImpl->mnCurrentZoom;
306 // click to - button
307 if ( aPoint.X() >= nButtonLeftOffset && aPoint.X() <= nButtonRightOffset )
309 mpImpl->mnCurrentZoom = mpImpl->mnCurrentZoom - 5;
311 // click to + button
312 else if ( aPoint.X() >= aSliderWindowSize.Width() - nSliderXOffset + nButtonLeftOffset &&
313 aPoint.X() <= aSliderWindowSize.Width() - nSliderXOffset + nButtonRightOffset )
315 mpImpl->mnCurrentZoom = mpImpl->mnCurrentZoom + 5;
317 else if( aPoint.X() >= nSliderXOffset && aPoint.X() <= aSliderWindowSize.Width() - nSliderXOffset )
319 mpImpl->mnCurrentZoom = Offset2Zoom( aPoint.X() );
322 if( mpImpl->mnCurrentZoom < mpImpl->mnMinZoom )
323 mpImpl->mnCurrentZoom = mpImpl->mnMinZoom;
324 else if( mpImpl->mnCurrentZoom > mpImpl->mnMaxZoom )
325 mpImpl->mnCurrentZoom = mpImpl->mnMaxZoom;
327 if( nOldZoom == mpImpl->mnCurrentZoom )
328 return ;
330 Rectangle aRect( Point( 0, 0 ), aSliderWindowSize );
332 Paint( aRect );
333 mpImpl->mbOmitPaint = true;
335 SvxZoomSliderItem aZoomSliderItem( mpImpl->mnCurrentZoom );
337 ::com::sun::star::uno::Any a;
338 aZoomSliderItem.QueryValue( a );
340 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aArgs( 1 );
341 aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ScalingFactor" ));
342 aArgs[0].Value = a;
344 SfxToolBoxControl::Dispatch( m_xDispatchProvider, String::CreateFromAscii(".uno:ScalingFactor"), aArgs );
346 mpImpl->mbOmitPaint = false;
349 // -----------------------------------------------------------------------
351 void ScZoomSliderWnd::MouseMove( const MouseEvent& rMEvt )
353 if ( !mpImpl->mbValuesSet )
354 return ;
356 Size aSliderWindowSize = GetOutputSizePixel();
357 const long nControlWidth = aSliderWindowSize.Width();
358 const short nButtons = rMEvt.GetButtons();
360 // check mouse move with button pressed
361 if ( 1 == nButtons )
363 const Point aPoint = rMEvt.GetPosPixel();
365 if ( aPoint.X() >= nSliderXOffset && aPoint.X() <= nControlWidth - nSliderXOffset )
367 mpImpl->mnCurrentZoom = Offset2Zoom( aPoint.X() );
369 Rectangle aRect( Point( 0, 0 ), aSliderWindowSize );
370 Paint( aRect );
372 mpImpl->mbOmitPaint = true; // optimization: paint before executing command,
374 // commit state change
375 SvxZoomSliderItem aZoomSliderItem( mpImpl->mnCurrentZoom );
377 ::com::sun::star::uno::Any a;
378 aZoomSliderItem.QueryValue( a );
380 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aArgs( 1 );
381 aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ScalingFactor" ));
382 aArgs[0].Value = a;
384 SfxToolBoxControl::Dispatch( m_xDispatchProvider, String::CreateFromAscii(".uno:ScalingFactor"), aArgs );
386 mpImpl->mbOmitPaint = false;
391 // -----------------------------------------------------------------------
393 void ScZoomSliderWnd::UpdateFromItem( const SvxZoomSliderItem* pZoomSliderItem )
395 if( pZoomSliderItem )
397 mpImpl->mnCurrentZoom = pZoomSliderItem->GetValue();
398 mpImpl->mnMinZoom = pZoomSliderItem->GetMinZoom();
399 mpImpl->mnMaxZoom = pZoomSliderItem->GetMaxZoom();
401 DBG_ASSERT( mpImpl->mnMinZoom <= mpImpl->mnCurrentZoom &&
402 mpImpl->mnMinZoom < mpImpl->mnSliderCenter &&
403 mpImpl->mnMaxZoom >= mpImpl->mnCurrentZoom &&
404 mpImpl->mnMaxZoom > mpImpl->mnSliderCenter,
405 "Looks like the zoom slider item is corrupted" );
406 const com::sun::star::uno::Sequence < sal_Int32 > rSnappingPoints = pZoomSliderItem->GetSnappingPoints();
407 mpImpl->maSnappingPointOffsets.clear();
408 mpImpl->maSnappingPointZooms.clear();
410 // get all snapping points:
411 std::set< USHORT > aTmpSnappingPoints;
412 for ( USHORT j = 0; j < rSnappingPoints.getLength(); ++j )
414 const sal_Int32 nSnappingPoint = rSnappingPoints[j];
415 aTmpSnappingPoints.insert( (USHORT)nSnappingPoint );
418 // remove snapping points that are to close to each other:
419 std::set< USHORT >::iterator aSnappingPointIter;
420 long nLastOffset = 0;
422 for ( aSnappingPointIter = aTmpSnappingPoints.begin(); aSnappingPointIter != aTmpSnappingPoints.end(); ++aSnappingPointIter )
424 const USHORT nCurrent = *aSnappingPointIter;
425 const long nCurrentOffset = Zoom2Offset( nCurrent );
427 if ( nCurrentOffset - nLastOffset >= nSnappingPointsMinDist )
429 mpImpl->maSnappingPointOffsets.push_back( nCurrentOffset );
430 mpImpl->maSnappingPointZooms.push_back( nCurrent );
431 nLastOffset = nCurrentOffset;
436 Size aSliderWindowSize = GetOutputSizePixel();
437 Rectangle aRect( Point( 0, 0 ), aSliderWindowSize );
439 if ( !mpImpl->mbOmitPaint )
440 Paint(aRect);
443 // -----------------------------------------------------------------------
445 void ScZoomSliderWnd::Paint( const Rectangle& rRect )
447 DoPaint( rRect );
450 // -----------------------------------------------------------------------
452 void ScZoomSliderWnd::DoPaint( const Rectangle& /*rRect*/ )
454 if( mpImpl->mbOmitPaint )
455 return;
457 Size aSliderWindowSize = GetOutputSizePixel();
458 Rectangle aRect( Point( 0, 0 ), aSliderWindowSize );
460 VirtualDevice* pVDev = new VirtualDevice( *this );
461 pVDev->SetOutputSizePixel( aSliderWindowSize );
463 Rectangle aSlider = aRect;
465 aSlider.Top() += ( aSliderWindowSize.Height() - nSliderHeight )/2 - 1;
466 aSlider.Bottom() = aSlider.Top() + nSliderHeight;
467 aSlider.Left() += nSliderXOffset;
468 aSlider.Right() -= nSliderXOffset;
470 Rectangle aFirstLine( aSlider );
471 aFirstLine.Bottom() = aFirstLine.Top();
473 Rectangle aSecondLine( aSlider );
474 aSecondLine.Top() = aSecondLine.Bottom();
476 Rectangle aLeft( aSlider );
477 aLeft.Right() = aLeft.Left();
479 Rectangle aRight( aSlider );
480 aRight.Left() = aRight.Right();
482 // draw VirtualDevice's background color
483 Color aStartColor,aEndColor;
484 aStartColor = GetSettings().GetStyleSettings().GetFaceColor();
485 aEndColor = GetSettings().GetStyleSettings().GetFaceColor();
486 if( aEndColor.IsDark() )
487 aStartColor = aEndColor;
489 Gradient g;
490 g.SetAngle( 0 );
491 g.SetStyle( GRADIENT_LINEAR );
493 g.SetStartColor( aStartColor );
494 g.SetEndColor( aEndColor );
495 pVDev->DrawGradient( aRect, g );
497 // draw slider
498 pVDev->SetLineColor( Color ( COL_WHITE ) );
499 pVDev->DrawRect( aSecondLine );
500 pVDev->DrawRect( aRight );
502 pVDev->SetLineColor( Color( COL_GRAY ) );
503 pVDev->DrawRect( aFirstLine );
504 pVDev->DrawRect( aLeft );
506 // draw snapping points:
507 std::vector< long >::iterator aSnappingPointIter;
508 for ( aSnappingPointIter = mpImpl->maSnappingPointOffsets.begin();
509 aSnappingPointIter != mpImpl->maSnappingPointOffsets.end();
510 ++aSnappingPointIter )
512 pVDev->SetLineColor( Color( COL_GRAY ) );
513 Rectangle aSnapping( aRect );
514 aSnapping.Bottom() = aSlider.Top();
515 aSnapping.Top() = aSnapping.Bottom() - nSnappingHeight;
516 aSnapping.Left() += *aSnappingPointIter;
517 aSnapping.Right() = aSnapping.Left();
518 pVDev->DrawRect( aSnapping );
520 aSnapping.Top() += nSnappingHeight + nSliderHeight;
521 aSnapping.Bottom() += nSnappingHeight + nSliderHeight;
522 pVDev->DrawRect( aSnapping );
525 // draw slider button
526 Point aImagePoint = aRect.TopLeft();
527 aImagePoint.X() += Zoom2Offset( mpImpl->mnCurrentZoom );
528 aImagePoint.X() -= nButtonWidth/2;
529 aImagePoint.Y() += ( aSliderWindowSize.Height() - nButtonHeight)/2;
530 pVDev->DrawImage( aImagePoint, mpImpl->maSliderButton );
532 // draw decrease button
533 aImagePoint = aRect.TopLeft();
534 aImagePoint.X() += (nSliderXOffset - nIncDecWidth)/2;
535 aImagePoint.Y() += ( aSliderWindowSize.Height() - nIncDecHeight)/2;
536 pVDev->DrawImage( aImagePoint, mpImpl->maDecreaseButton );
538 // draw increase button
539 aImagePoint.X() = aRect.TopLeft().X() + aSliderWindowSize.Width() - nIncDecWidth - (nSliderXOffset - nIncDecWidth)/2;
540 pVDev->DrawImage( aImagePoint, mpImpl->maIncreaseButton );
542 DrawOutDev( Point(0, 0), aSliderWindowSize, Point(0, 0), aSliderWindowSize, *pVDev );
544 delete pVDev;
548 // -----------------------------------------------------------------------