1 /*************************************************************************
3 * OpenOffice.org - a multi-platform office productivity suite
5 * $RCSfile: tbzoomsliderctrl.cxx,v $
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,
34 ************************************************************************/
35 #include "precompiled_sc.hxx"
36 #ifndef _SC_ZOOMSLIDERTBCONTRL_HXX
37 #include "tbzoomsliderctrl.hxx"
40 #include <vcl/image.hxx>
42 #ifndef _SV_TOOLBOX_HXX
43 #include <vcl/toolbox.hxx>
46 #include <vcl/svapp.hxx>
48 #ifndef _SV_GRADIENT_HXX
49 #include <vcl/gradient.hxx>
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>
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(
77 :SfxToolBoxControl( nSlotId
, nId
, rTbx
)
82 // -----------------------------------------------------------------------
84 __EXPORT
ScZoomSliderControl::~ScZoomSliderControl()
89 // -----------------------------------------------------------------------
91 void ScZoomSliderControl::StateChanged( USHORT
/*nSID*/, SfxItemState eState
,
92 const SfxPoolItem
* pState
)
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 );
103 pBox
->UpdateFromItem( &aZoomSliderItem
);
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 );
129 // -----------------------------------------------------------------------
131 struct ScZoomSliderWnd::ScZoomSliderWnd_Impl
133 USHORT mnCurrentZoom
;
136 USHORT mnSliderCenter
;
137 std::vector
< long > maSnappingPointOffsets
;
138 std::vector
< USHORT
> maSnappingPointZooms
;
139 Image maSliderButton
;
140 Image maIncreaseButton
;
141 Image maDecreaseButton
;
145 ScZoomSliderWnd_Impl( USHORT nCurrentZoom
) :
146 mnCurrentZoom( nCurrentZoom
),
149 mnSliderCenter( 100 ),
150 maSnappingPointOffsets(),
151 maSnappingPointZooms(),
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();
184 if( nOffset
< nSliderXOffset
)
185 return mpImpl
->mnMinZoom
;
186 if( nOffset
> nControlWidth
- nSliderXOffset
)
187 return mpImpl
->mnMaxZoom
;
189 // check for snapping points:
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
)
200 nRet
= mpImpl
->maSnappingPointZooms
[ nCount
];
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 );
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
;
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;
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
;
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
):
271 mpImpl( new ScZoomSliderWnd_Impl( nCurrentZoom
) ),
272 aLogicalSize( 115, 40 ),
273 m_xDispatchProvider( rDispatchProvider
),
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()
291 // -----------------------------------------------------------------------
293 void ScZoomSliderWnd::MouseButtonDown( const MouseEvent
& rMEvt
)
295 if ( !mpImpl
->mbValuesSet
)
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
;
307 if ( aPoint
.X() >= nButtonLeftOffset
&& aPoint
.X() <= nButtonRightOffset
)
309 mpImpl
->mnCurrentZoom
= mpImpl
->mnCurrentZoom
- 5;
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
)
330 Rectangle
aRect( Point( 0, 0 ), aSliderWindowSize
);
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" ));
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
)
356 Size aSliderWindowSize
= GetOutputSizePixel();
357 const long nControlWidth
= aSliderWindowSize
.Width();
358 const short nButtons
= rMEvt
.GetButtons();
360 // check mouse move with button pressed
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
);
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" ));
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
)
443 // -----------------------------------------------------------------------
445 void ScZoomSliderWnd::Paint( const Rectangle
& rRect
)
450 // -----------------------------------------------------------------------
452 void ScZoomSliderWnd::DoPaint( const Rectangle
& /*rRect*/ )
454 if( mpImpl
->mbOmitPaint
)
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
;
491 g
.SetStyle( GRADIENT_LINEAR
);
493 g
.SetStartColor( aStartColor
);
494 g
.SetEndColor( aEndColor
);
495 pVDev
->DrawGradient( aRect
, g
);
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
);
548 // -----------------------------------------------------------------------