1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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>
39 #ifndef _MENU_HXX //autogen
40 #include <vcl/menu.hxx>
42 #include <vcl/image.hxx>
43 #include <svx/zoomslideritem.hxx>
44 #include <svx/dialmgr.hxx>
45 #include <svx/dialogs.hrc>
49 // -----------------------------------------------------------------------
51 SFX_IMPL_STATUSBAR_CONTROL( SvxZoomSliderControl
, SvxZoomSliderItem
);
53 // -----------------------------------------------------------------------
55 struct SvxZoomSliderControl::SvxZoomSliderControl_Impl
60 USHORT mnSliderCenter
;
61 std::vector
< long > maSnappingPointOffsets
;
62 std::vector
< USHORT
> maSnappingPointZooms
;
64 Image maIncreaseButton
;
65 Image maDecreaseButton
;
69 SvxZoomSliderControl_Impl() :
74 maSnappingPointOffsets(),
75 maSnappingPointZooms(),
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:
99 USHORT
SvxZoomSliderControl::Offset2Zoom( long nOffset
) const
101 const long nControlWidth
= getControlRect().GetWidth();
104 if ( nOffset
< nSliderXOffset
)
105 return mpImpl
->mnMinZoom
;;
107 if ( nOffset
> nControlWidth
- nSliderXOffset
)
108 return mpImpl
->mnMaxZoom
;
110 // check for snapping points:
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
)
121 nRet
= mpImpl
->maSnappingPointZooms
[ nCount
];
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 );
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
;
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;
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
;
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()
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;
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
)
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
);
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
)
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
;
368 if ( nXDiff
>= nButtonLeftOffset
&& nXDiff
<= nButtonRightOffset
)
369 mpImpl
->mnCurrentZoom
= mpImpl
->mnCurrentZoom
- 5;
371 else if ( nXDiff
>= aControlRect
.GetWidth() - nSliderXOffset
+ nButtonLeftOffset
&&
372 nXDiff
<= aControlRect
.GetWidth() - nSliderXOffset
+ nButtonRightOffset
)
373 mpImpl
->mnCurrentZoom
= mpImpl
->mnCurrentZoom
+ 5;
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
)
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" ));
403 mpImpl
->mbOmitPaint
= false;
408 // -----------------------------------------------------------------------
410 BOOL
SvxZoomSliderControl::MouseMove( const MouseEvent
& rEvt
)
412 if ( !mpImpl
->mbValuesSet
)
415 const short nButtons
= rEvt
.GetButtons();
417 // check mouse move with button pressed
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" ));
446 mpImpl
->mbOmitPaint
= false;