1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #include "precompiled_sc.hxx"
25 #ifndef _SC_ZOOMSLIDERTBCONTRL_HXX
26 #include "tbzoomsliderctrl.hxx"
27 #endif
28 #ifndef _SV_IMAGE_HXX
29 #include <vcl/image.hxx>
30 #endif
31 #ifndef _SV_TOOLBOX_HXX
32 #include <vcl/toolbox.hxx>
33 #endif
34 #ifndef _SV_SVAPP_HXX
35 #include <vcl/svapp.hxx>
36 #endif
37 #ifndef _SV_GRADIENT_HXX
38 #include <vcl/gradient.hxx>
39 #endif
40 #include <svl/itemset.hxx>
41 #include <sfx2/viewfrm.hxx>
42 #include <sfx2/objsh.hxx>
43 #include <svx/zoomslideritem.hxx>
44 #include <svx/dialmgr.hxx>
45 #include <svx/dialogs.hrc>
46 #include <set>
47 #include "docsh.hxx"
48 #include "stlpool.hxx"
49 #include "scitems.hxx"
50 #include "printfun.hxx"
51
52 //========================================================================
53 // class ScZoomSliderControl ---------------------------------------
54 //========================================================================
55
56 // -----------------------------------------------------------------------
57
58 SFX_IMPL_TOOLBOX_CONTROL( ScZoomSliderControl, SvxZoomSliderItem );
59
60 // -----------------------------------------------------------------------
61
ScZoomSliderControl(sal_uInt16 nSlotId,sal_uInt16 nId,ToolBox & rTbx)62 ScZoomSliderControl::ScZoomSliderControl(
63 sal_uInt16 nSlotId,
64 sal_uInt16 nId,
65 ToolBox& rTbx )
66 :SfxToolBoxControl( nSlotId, nId, rTbx )
67 {
68 rTbx.Invalidate();
69 }
70
71 // -----------------------------------------------------------------------
72
~ScZoomSliderControl()73 __EXPORT ScZoomSliderControl::~ScZoomSliderControl()
74 {
75
76 }
77
78 // -----------------------------------------------------------------------
79
StateChanged(sal_uInt16,SfxItemState eState,const SfxPoolItem * pState)80 void ScZoomSliderControl::StateChanged( sal_uInt16 /*nSID*/, SfxItemState eState,
81 const SfxPoolItem* pState )
82 {
83 sal_uInt16 nId = GetId();
84 ToolBox& rTbx = GetToolBox();
85 ScZoomSliderWnd* pBox = (ScZoomSliderWnd*)(rTbx.GetItemWindow( nId ));
86 DBG_ASSERT( pBox ,"Control not found!" );
87
88 if ( SFX_ITEM_AVAILABLE != eState || pState->ISA( SfxVoidItem ) )
89 {
90 SvxZoomSliderItem aZoomSliderItem( 100 );
91 pBox->Disable();
92 pBox->UpdateFromItem( &aZoomSliderItem );
93 }
94 else
95 {
96 pBox->Enable();
97 DBG_ASSERT( pState->ISA( SvxZoomSliderItem ), "invalid item type" );
98 const SvxZoomSliderItem* pZoomSliderItem = dynamic_cast< const SvxZoomSliderItem* >( pState );
99
100 DBG_ASSERT( pZoomSliderItem, "Sc::ScZoomSliderControl::StateChanged(), wrong item type!" );
101 if( pZoomSliderItem )
102 pBox->UpdateFromItem( pZoomSliderItem );
103 }
104 }
105
106 // -----------------------------------------------------------------------
107
CreateItemWindow(Window * pParent)108 Window* ScZoomSliderControl::CreateItemWindow( Window *pParent )
109 {
110 // #i98000# Don't try to get a value via SfxViewFrame::Current here.
111 // The view's value is always notified via StateChanged later.
112 ScZoomSliderWnd* pSlider = new ScZoomSliderWnd( pParent,
113 ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider >( m_xFrame->getController(),
114 ::com::sun::star::uno::UNO_QUERY ), m_xFrame, 100 );
115 return pSlider;
116 }
117
118 // -----------------------------------------------------------------------
119
120 struct ScZoomSliderWnd::ScZoomSliderWnd_Impl
121 {
122 sal_uInt16 mnCurrentZoom;
123 sal_uInt16 mnMinZoom;
124 sal_uInt16 mnMaxZoom;
125 sal_uInt16 mnSliderCenter;
126 std::vector< long > maSnappingPointOffsets;
127 std::vector< sal_uInt16 > maSnappingPointZooms;
128 Image maSliderButton;
129 Image maIncreaseButton;
130 Image maDecreaseButton;
131 bool mbValuesSet;
132 bool mbOmitPaint;
133
ScZoomSliderWnd_ImplScZoomSliderWnd::ScZoomSliderWnd_Impl134 ScZoomSliderWnd_Impl( sal_uInt16 nCurrentZoom ) :
135 mnCurrentZoom( nCurrentZoom ),
136 mnMinZoom( 10 ),
137 mnMaxZoom( 400 ),
138 mnSliderCenter( 100 ),
139 maSnappingPointOffsets(),
140 maSnappingPointZooms(),
141 maSliderButton(),
142 maIncreaseButton(),
143 maDecreaseButton(),
144 mbValuesSet( true ),
145 mbOmitPaint( false )
146 {
147
148 }
149 };
150
151 // -----------------------------------------------------------------------
152
153 const long nButtonWidth = 10;
154 const long nButtonHeight = 10;
155 const long nIncDecWidth = 11;
156 const long nIncDecHeight = 11;
157 const long nSliderHeight = 2; //
158 const long nSliderWidth = 4; //
159 const long nSnappingHeight = 4;
160 const long nSliderXOffset = 20;
161 const long nSnappingEpsilon = 5; // snapping epsilon in pixels
162 const long nSnappingPointsMinDist = nSnappingEpsilon; // minimum distance of two adjacent snapping points
163
164
165 // -----------------------------------------------------------------------
166
Offset2Zoom(long nOffset) const167 sal_uInt16 ScZoomSliderWnd::Offset2Zoom( long nOffset ) const
168 {
169 Size aSliderWindowSize = GetOutputSizePixel();
170 const long nControlWidth = aSliderWindowSize.Width();
171 sal_uInt16 nRet = 0;
172
173 if( nOffset < nSliderXOffset )
174 return mpImpl->mnMinZoom;
175 if( nOffset > nControlWidth - nSliderXOffset )
176 return mpImpl->mnMaxZoom;
177
178 // check for snapping points:
179 sal_uInt16 nCount = 0;
180 std::vector< long >::iterator aSnappingPointIter;
181 for ( aSnappingPointIter = mpImpl->maSnappingPointOffsets.begin();
182 aSnappingPointIter != mpImpl->maSnappingPointOffsets.end();
183 ++aSnappingPointIter )
184 {
185 const long nCurrent = *aSnappingPointIter;
186 if ( Abs(nCurrent - nOffset) < nSnappingEpsilon )
187 {
188 nOffset = nCurrent;
189 nRet = mpImpl->maSnappingPointZooms[ nCount ];
190 break;
191 }
192 ++nCount;
193 }
194
195 if( 0 == nRet )
196 {
197 if( nOffset < nControlWidth / 2 )
198 {
199 // first half of slider
200 const long nFirstHalfRange = mpImpl->mnSliderCenter - mpImpl->mnMinZoom;
201 const long nHalfSliderWidth = nControlWidth/2 - nSliderXOffset;
202 const long nZoomPerSliderPixel = (1000 * nFirstHalfRange) / nHalfSliderWidth;
203 const long nOffsetToSliderLeft = nOffset - nSliderXOffset;
204 nRet = mpImpl->mnMinZoom + sal_uInt16( nOffsetToSliderLeft * nZoomPerSliderPixel / 1000 );
205 }
206 else
207 {
208 // second half of slider
209 const long nSecondHalfRange = mpImpl->mnMaxZoom - mpImpl->mnSliderCenter;
210 const long nHalfSliderWidth = nControlWidth/2 - nSliderXOffset;
211 const long nZoomPerSliderPixel = 1000 * nSecondHalfRange / nHalfSliderWidth;
212 const long nOffsetToSliderCenter = nOffset - nControlWidth/2;
213 nRet = mpImpl->mnSliderCenter + sal_uInt16( nOffsetToSliderCenter * nZoomPerSliderPixel / 1000 );
214 }
215 }
216
217 if( nRet < mpImpl->mnMinZoom )
218 return mpImpl->mnMinZoom;
219
220 else if( nRet > mpImpl->mnMaxZoom )
221 return mpImpl->mnMaxZoom;
222
223 return nRet;
224 }
225
226 // -----------------------------------------------------------------------
227
Zoom2Offset(sal_uInt16 nCurrentZoom) const228 long ScZoomSliderWnd::Zoom2Offset( sal_uInt16 nCurrentZoom ) const
229 {
230 Size aSliderWindowSize = GetOutputSizePixel();
231 const long nControlWidth = aSliderWindowSize.Width();
232 long nRect = nSliderXOffset;
233
234 const long nHalfSliderWidth = nControlWidth/2 - nSliderXOffset;
235 if( nCurrentZoom <= mpImpl->mnSliderCenter )
236 {
237 nCurrentZoom = nCurrentZoom - mpImpl->mnMinZoom;
238 const long nFirstHalfRange = mpImpl->mnSliderCenter - mpImpl->mnMinZoom;
239 const long nSliderPixelPerZoomPercent = 1000 * nHalfSliderWidth / nFirstHalfRange;
240 const long nOffset = (nSliderPixelPerZoomPercent * nCurrentZoom) / 1000;
241 nRect += nOffset;
242 }
243 else
244 {
245 nCurrentZoom = nCurrentZoom - mpImpl->mnSliderCenter;
246 const long nSecondHalfRange = mpImpl->mnMaxZoom - mpImpl->mnSliderCenter;
247 const long nSliderPixelPerZoomPercent = 1000 * nHalfSliderWidth / nSecondHalfRange;
248 const long nOffset = (nSliderPixelPerZoomPercent * nCurrentZoom) / 1000;
249 nRect += nHalfSliderWidth + nOffset;
250 }
251 return nRect;
252 }
253
254 // -----------------------------------------------------------------------
255
256
ScZoomSliderWnd(Window * pParent,const::com::sun::star::uno::Reference<::com::sun::star::frame::XDispatchProvider> & rDispatchProvider,const::com::sun::star::uno::Reference<::com::sun::star::frame::XFrame> & _xFrame,sal_uInt16 nCurrentZoom)257 ScZoomSliderWnd::ScZoomSliderWnd( Window* pParent, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider >& rDispatchProvider,
258 const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& _xFrame , sal_uInt16 nCurrentZoom ):
259 Window( pParent ),
260 mpImpl( new ScZoomSliderWnd_Impl( nCurrentZoom ) ),
261 aLogicalSize( 115, 40 ),
262 m_xDispatchProvider( rDispatchProvider ),
263 m_xFrame( _xFrame )
264 {
265 sal_Bool bIsHC = GetSettings().GetStyleSettings().GetHighContrastMode();
266 mpImpl->maSliderButton = Image( SVX_RES( bIsHC ? RID_SVXBMP_SLIDERBUTTON_HC : RID_SVXBMP_SLIDERBUTTON ) );
267 mpImpl->maIncreaseButton = Image( SVX_RES( bIsHC ? RID_SVXBMP_SLIDERINCREASE_HC : RID_SVXBMP_SLIDERINCREASE ) );
268 mpImpl->maDecreaseButton = Image( SVX_RES( bIsHC ? RID_SVXBMP_SLIDERDECREASE_HC : RID_SVXBMP_SLIDERDECREASE ) );
269 Size aSliderSize = LogicToPixel( Size( aLogicalSize), MapMode( MAP_10TH_MM ) );
270 SetSizePixel( Size( aSliderSize.Width() * nSliderWidth-1, aSliderSize.Height() + nSliderHeight ) );
271 }
272
273 // -----------------------------------------------------------------------
274
~ScZoomSliderWnd()275 ScZoomSliderWnd::~ScZoomSliderWnd()
276 {
277 delete mpImpl;
278 }
279
280 // -----------------------------------------------------------------------
281
MouseButtonDown(const MouseEvent & rMEvt)282 void ScZoomSliderWnd::MouseButtonDown( const MouseEvent& rMEvt )
283 {
284 if ( !mpImpl->mbValuesSet )
285 return ;
286 Size aSliderWindowSize = GetOutputSizePixel();
287
288 const Point aPoint = rMEvt.GetPosPixel();
289
290 const long nButtonLeftOffset = ( nSliderXOffset - nIncDecWidth )/2;
291 const long nButtonRightOffset = ( nSliderXOffset + nIncDecWidth )/2;
292
293 const long nOldZoom = mpImpl->mnCurrentZoom;
294
295 // click to - button
296 if ( aPoint.X() >= nButtonLeftOffset && aPoint.X() <= nButtonRightOffset )
297 {
298 mpImpl->mnCurrentZoom = mpImpl->mnCurrentZoom - 5;
299 }
300 // click to + button
301 else if ( aPoint.X() >= aSliderWindowSize.Width() - nSliderXOffset + nButtonLeftOffset &&
302 aPoint.X() <= aSliderWindowSize.Width() - nSliderXOffset + nButtonRightOffset )
303 {
304 mpImpl->mnCurrentZoom = mpImpl->mnCurrentZoom + 5;
305 }
306 else if( aPoint.X() >= nSliderXOffset && aPoint.X() <= aSliderWindowSize.Width() - nSliderXOffset )
307 {
308 mpImpl->mnCurrentZoom = Offset2Zoom( aPoint.X() );
309 }
310
311 if( mpImpl->mnCurrentZoom < mpImpl->mnMinZoom )
312 mpImpl->mnCurrentZoom = mpImpl->mnMinZoom;
313 else if( mpImpl->mnCurrentZoom > mpImpl->mnMaxZoom )
314 mpImpl->mnCurrentZoom = mpImpl->mnMaxZoom;
315
316 if( nOldZoom == mpImpl->mnCurrentZoom )
317 return ;
318
319 Rectangle aRect( Point( 0, 0 ), aSliderWindowSize );
320
321 Paint( aRect );
322 mpImpl->mbOmitPaint = true;
323
324 SvxZoomSliderItem aZoomSliderItem( mpImpl->mnCurrentZoom );
325
326 ::com::sun::star::uno::Any a;
327 aZoomSliderItem.QueryValue( a );
328
329 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aArgs( 1 );
330 aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ScalingFactor" ));
331 aArgs[0].Value = a;
332
333 SfxToolBoxControl::Dispatch( m_xDispatchProvider, String::CreateFromAscii(".uno:ScalingFactor"), aArgs );
334
335 mpImpl->mbOmitPaint = false;
336 }
337
338 // -----------------------------------------------------------------------
339
MouseMove(const MouseEvent & rMEvt)340 void ScZoomSliderWnd::MouseMove( const MouseEvent& rMEvt )
341 {
342 if ( !mpImpl->mbValuesSet )
343 return ;
344
345 Size aSliderWindowSize = GetOutputSizePixel();
346 const long nControlWidth = aSliderWindowSize.Width();
347 const short nButtons = rMEvt.GetButtons();
348
349 // check mouse move with button pressed
350 if ( 1 == nButtons )
351 {
352 const Point aPoint = rMEvt.GetPosPixel();
353
354 if ( aPoint.X() >= nSliderXOffset && aPoint.X() <= nControlWidth - nSliderXOffset )
355 {
356 mpImpl->mnCurrentZoom = Offset2Zoom( aPoint.X() );
357
358 Rectangle aRect( Point( 0, 0 ), aSliderWindowSize );
359 Paint( aRect );
360
361 mpImpl->mbOmitPaint = true; // optimization: paint before executing command,
362
363 // commit state change
364 SvxZoomSliderItem aZoomSliderItem( mpImpl->mnCurrentZoom );
365
366 ::com::sun::star::uno::Any a;
367 aZoomSliderItem.QueryValue( a );
368
369 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aArgs( 1 );
370 aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ScalingFactor" ));
371 aArgs[0].Value = a;
372
373 SfxToolBoxControl::Dispatch( m_xDispatchProvider, String::CreateFromAscii(".uno:ScalingFactor"), aArgs );
374
375 mpImpl->mbOmitPaint = false;
376 }
377 }
378 }
379
380 // -----------------------------------------------------------------------
381
UpdateFromItem(const SvxZoomSliderItem * pZoomSliderItem)382 void ScZoomSliderWnd::UpdateFromItem( const SvxZoomSliderItem* pZoomSliderItem )
383 {
384 if( pZoomSliderItem )
385 {
386 mpImpl->mnCurrentZoom = pZoomSliderItem->GetValue();
387 mpImpl->mnMinZoom = pZoomSliderItem->GetMinZoom();
388 mpImpl->mnMaxZoom = pZoomSliderItem->GetMaxZoom();
389
390 DBG_ASSERT( mpImpl->mnMinZoom <= mpImpl->mnCurrentZoom &&
391 mpImpl->mnMinZoom < mpImpl->mnSliderCenter &&
392 mpImpl->mnMaxZoom >= mpImpl->mnCurrentZoom &&
393 mpImpl->mnMaxZoom > mpImpl->mnSliderCenter,
394 "Looks like the zoom slider item is corrupted" );
395 const com::sun::star::uno::Sequence < sal_Int32 > rSnappingPoints = pZoomSliderItem->GetSnappingPoints();
396 mpImpl->maSnappingPointOffsets.clear();
397 mpImpl->maSnappingPointZooms.clear();
398
399 // get all snapping points:
400 std::set< sal_uInt16 > aTmpSnappingPoints;
401 for ( sal_uInt16 j = 0; j < rSnappingPoints.getLength(); ++j )
402 {
403 const sal_Int32 nSnappingPoint = rSnappingPoints[j];
404 aTmpSnappingPoints.insert( (sal_uInt16)nSnappingPoint );
405 }
406
407 // remove snapping points that are to close to each other:
408 std::set< sal_uInt16 >::iterator aSnappingPointIter;
409 long nLastOffset = 0;
410
411 for ( aSnappingPointIter = aTmpSnappingPoints.begin(); aSnappingPointIter != aTmpSnappingPoints.end(); ++aSnappingPointIter )
412 {
413 const sal_uInt16 nCurrent = *aSnappingPointIter;
414 const long nCurrentOffset = Zoom2Offset( nCurrent );
415
416 if ( nCurrentOffset - nLastOffset >= nSnappingPointsMinDist )
417 {
418 mpImpl->maSnappingPointOffsets.push_back( nCurrentOffset );
419 mpImpl->maSnappingPointZooms.push_back( nCurrent );
420 nLastOffset = nCurrentOffset;
421 }
422 }
423 }
424
425 Size aSliderWindowSize = GetOutputSizePixel();
426 Rectangle aRect( Point( 0, 0 ), aSliderWindowSize );
427
428 if ( !mpImpl->mbOmitPaint )
429 Paint(aRect);
430 }
431
432 // -----------------------------------------------------------------------
433
Paint(const Rectangle & rRect)434 void ScZoomSliderWnd::Paint( const Rectangle& rRect )
435 {
436 DoPaint( rRect );
437 }
438
439 // -----------------------------------------------------------------------
440
DoPaint(const Rectangle &)441 void ScZoomSliderWnd::DoPaint( const Rectangle& /*rRect*/ )
442 {
443 if( mpImpl->mbOmitPaint )
444 return;
445
446 Size aSliderWindowSize = GetOutputSizePixel();
447 Rectangle aRect( Point( 0, 0 ), aSliderWindowSize );
448
449 VirtualDevice* pVDev = new VirtualDevice( *this );
450 pVDev->SetOutputSizePixel( aSliderWindowSize );
451
452 Rectangle aSlider = aRect;
453
454 aSlider.Top() += ( aSliderWindowSize.Height() - nSliderHeight )/2 - 1;
455 aSlider.Bottom() = aSlider.Top() + nSliderHeight;
456 aSlider.Left() += nSliderXOffset;
457 aSlider.Right() -= nSliderXOffset;
458
459 Rectangle aFirstLine( aSlider );
460 aFirstLine.Bottom() = aFirstLine.Top();
461
462 Rectangle aSecondLine( aSlider );
463 aSecondLine.Top() = aSecondLine.Bottom();
464
465 Rectangle aLeft( aSlider );
466 aLeft.Right() = aLeft.Left();
467
468 Rectangle aRight( aSlider );
469 aRight.Left() = aRight.Right();
470
471 // draw VirtualDevice's background color
472 Color aStartColor,aEndColor;
473 aStartColor = GetSettings().GetStyleSettings().GetFaceColor();
474 aEndColor = GetSettings().GetStyleSettings().GetFaceColor();
475 if( aEndColor.IsDark() )
476 aStartColor = aEndColor;
477
478 Gradient g;
479 g.SetAngle( 0 );
480 g.SetStyle( GRADIENT_LINEAR );
481
482 g.SetStartColor( aStartColor );
483 g.SetEndColor( aEndColor );
484 pVDev->DrawGradient( aRect, g );
485
486 // draw slider
487 pVDev->SetLineColor( Color ( COL_GRAY ) );
488 pVDev->DrawRect( aSecondLine );
489 pVDev->DrawRect( aRight );
490
491 pVDev->SetLineColor( Color ( COL_GRAY ) );
492 pVDev->DrawRect( aFirstLine );
493 pVDev->DrawRect( aLeft );
494
495 // draw snapping points:
496 std::vector< long >::iterator aSnappingPointIter;
497 for ( aSnappingPointIter = mpImpl->maSnappingPointOffsets.begin();
498 aSnappingPointIter != mpImpl->maSnappingPointOffsets.end();
499 ++aSnappingPointIter )
500 {
501 pVDev->SetLineColor( Color( COL_GRAY ) );
502 Rectangle aSnapping( aRect );
503 aSnapping.Bottom() = aSlider.Top();
504 aSnapping.Top() = aSnapping.Bottom() - nSnappingHeight;
505 aSnapping.Left() += *aSnappingPointIter;
506 aSnapping.Right() = aSnapping.Left();
507 pVDev->DrawRect( aSnapping );
508
509 aSnapping.Top() += nSnappingHeight + nSliderHeight;
510 aSnapping.Bottom() += nSnappingHeight + nSliderHeight;
511 pVDev->DrawRect( aSnapping );
512 }
513
514 // draw slider button
515 Point aImagePoint = aRect.TopLeft();
516 aImagePoint.X() += Zoom2Offset( mpImpl->mnCurrentZoom );
517 aImagePoint.X() -= nButtonWidth/2;
518 aImagePoint.Y() += ( aSliderWindowSize.Height() - nButtonHeight)/2;
519 pVDev->DrawImage( aImagePoint, mpImpl->maSliderButton );
520
521 // draw decrease button
522 aImagePoint = aRect.TopLeft();
523 aImagePoint.X() += (nSliderXOffset - nIncDecWidth)/2;
524 aImagePoint.Y() += ( aSliderWindowSize.Height() - nIncDecHeight)/2;
525 pVDev->DrawImage( aImagePoint, mpImpl->maDecreaseButton );
526
527 // draw increase button
528 aImagePoint.X() = aRect.TopLeft().X() + aSliderWindowSize.Width() - nIncDecWidth - (nSliderXOffset - nIncDecWidth)/2;
529 pVDev->DrawImage( aImagePoint, mpImpl->maIncreaseButton );
530
531 DrawOutDev( Point(0, 0), aSliderWindowSize, Point(0, 0), aSliderWindowSize, *pVDev );
532
533 delete pVDev;
534 }
535
536 // -----------------------------------------------------------------------
537