update dev300-m58
[ooovba.git] / svtools / source / control / scrwin.cxx
blob77830dd0fcfbdcf7e4c0dfab391a72b9be9d737d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: scrwin.cxx,v $
10 * $Revision: 1.5 $
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_svtools.hxx"
34 #define _SVT_SCRWIN_CXX
35 #include <scrwin.hxx>
37 //===================================================================
39 void ScrollableWindow::ImpInitialize( ScrollableWindowFlags nFlags )
41 bHandleDragging = (BOOL) ( nFlags & SCRWIN_THUMBDRAGGING );
42 bVCenter = (nFlags & SCRWIN_VCENTER) == SCRWIN_VCENTER;
43 bHCenter = (nFlags & SCRWIN_HCENTER) == SCRWIN_HCENTER;
44 bScrolling = FALSE;
46 // set the handlers for the scrollbars
47 aVScroll.SetScrollHdl( LINK(this, ScrollableWindow, ScrollHdl) );
48 aHScroll.SetScrollHdl( LINK(this, ScrollableWindow, ScrollHdl) );
49 aVScroll.SetEndScrollHdl( LINK(this, ScrollableWindow, EndScrollHdl) );
50 aHScroll.SetEndScrollHdl( LINK(this, ScrollableWindow, EndScrollHdl) );
52 nColumnPixW = nLinePixH = GetSettings().GetStyleSettings().GetScrollBarSize();
55 //-------------------------------------------------------------------
57 ScrollableWindow::ScrollableWindow( Window* pParent, WinBits nBits,
58 ScrollableWindowFlags nFlags ) :
59 Window( pParent, WinBits(nBits|WB_CLIPCHILDREN) ),
60 aVScroll( this, WinBits(WB_VSCROLL | WB_DRAG) ),
61 aHScroll( this, WinBits(WB_HSCROLL | WB_DRAG) ),
62 aCornerWin( this )
64 ImpInitialize( nFlags );
67 //-------------------------------------------------------------------
69 ScrollableWindow::ScrollableWindow( Window* pParent, const ResId& rId,
70 ScrollableWindowFlags nFlags ) :
71 Window( pParent, rId ),
72 aVScroll( this, WinBits(WB_VSCROLL | WB_DRAG) ),
73 aHScroll( this, WinBits(WB_HSCROLL | WB_DRAG) ),
74 aCornerWin( this )
76 ImpInitialize( nFlags );
79 // -----------------------------------------------------------------------
81 void ScrollableWindow::Command( const CommandEvent& rCEvt )
83 if ( (rCEvt.GetCommand() == COMMAND_WHEEL) ||
84 (rCEvt.GetCommand() == COMMAND_STARTAUTOSCROLL) ||
85 (rCEvt.GetCommand() == COMMAND_AUTOSCROLL) )
87 ScrollBar* pHScrBar;
88 ScrollBar* pVScrBar;
89 if ( aHScroll.IsVisible() )
90 pHScrBar = &aHScroll;
91 else
92 pHScrBar = NULL;
93 if ( aVScroll.IsVisible() )
94 pVScrBar = &aVScroll;
95 else
96 pVScrBar = NULL;
97 if ( HandleScrollCommand( rCEvt, pHScrBar, pVScrBar ) )
98 return;
101 Window::Command( rCEvt );
104 //-------------------------------------------------------------------
106 void ScrollableWindow::DataChanged( const DataChangedEvent& rDCEvt )
108 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
109 (rDCEvt.GetFlags() & SETTINGS_STYLE) )
111 Resize();
112 Invalidate();
115 Window::DataChanged( rDCEvt );
118 //-------------------------------------------------------------------
120 Size __EXPORT ScrollableWindow::GetOutputSizePixel() const
122 Size aSz( Window::GetOutputSizePixel() );
124 long nTmp = GetSettings().GetStyleSettings().GetScrollBarSize();
125 if ( aHScroll.IsVisible() )
126 aSz.Height() -= nTmp;
127 if ( aVScroll.IsVisible() )
128 aSz.Width() -= nTmp;
129 return aSz;
132 //-------------------------------------------------------------------
134 Size ScrollableWindow::GetOutputSize() const
136 return PixelToLogic( GetOutputSizePixel() );
139 //-------------------------------------------------------------------
141 IMPL_LINK( ScrollableWindow, EndScrollHdl, ScrollBar *, pScroll )
143 // notify the start of scrolling, if not already scrolling
144 if ( !bScrolling )
145 StartScroll(), bScrolling = TRUE;
147 // get the delta in logic coordinates
148 Size aDelta( PixelToLogic( Size( aHScroll.GetDelta(), aVScroll.GetDelta() ) ) );
150 // scroll the window, if this is not already done
151 if ( !bHandleDragging )
153 if ( pScroll == &aHScroll )
154 Scroll( aDelta.Width(), 0 );
155 else
156 Scroll( 0, aDelta.Height() );
159 // notify the end of scrolling
160 bScrolling = FALSE;
161 EndScroll( aDelta.Width(), aDelta.Height() );
162 return 0;
165 //-------------------------------------------------------------------
167 IMPL_LINK( ScrollableWindow, ScrollHdl, ScrollBar *, pScroll )
169 // notify the start of scrolling, if not already scrolling
170 if ( !bScrolling )
171 StartScroll(), bScrolling = TRUE;
173 if ( bHandleDragging )
175 // get the delta in logic coordinates
176 Size aDelta( PixelToLogic(
177 Size( aHScroll.GetDelta(), aVScroll.GetDelta() ) ) );
178 if ( pScroll == &aHScroll )
179 Scroll( aDelta.Width(), 0 );
180 else
181 Scroll( 0, aDelta.Height() );
183 return 0;
186 //-------------------------------------------------------------------
188 void __EXPORT ScrollableWindow::Resize()
190 // get the new output-size in pixel
191 Size aOutPixSz = Window::GetOutputSizePixel();
193 // determine the size of the output-area and if we need scrollbars
194 const long nScrSize = GetSettings().GetStyleSettings().GetScrollBarSize();
195 BOOL bVVisible = FALSE; // by default no vertical-ScrollBar
196 BOOL bHVisible = FALSE; // by default no horizontal-ScrollBar
197 BOOL bChanged; // determines if a visiblility was changed
200 bChanged = FALSE;
202 // does we need a vertical ScrollBar
203 if ( aOutPixSz.Width() < aTotPixSz.Width() && !bHVisible )
204 { bHVisible = TRUE;
205 aOutPixSz.Height() -= nScrSize;
206 bChanged = TRUE;
209 // does we need a horizontal ScrollBar
210 if ( aOutPixSz.Height() < aTotPixSz.Height() && !bVVisible )
211 { bVVisible = TRUE;
212 aOutPixSz.Width() -= nScrSize;
213 bChanged = TRUE;
217 while ( bChanged ); // until no visibility has changed
219 // store the old offset and map-mode
220 MapMode aMap( GetMapMode() );
221 Point aOldPixOffset( aPixOffset );
223 // justify (right/bottom borders should never exceed the virtual window)
224 Size aPixDelta;
225 if ( aPixOffset.X() < 0 &&
226 aPixOffset.X() + aTotPixSz.Width() < aOutPixSz.Width() )
227 aPixDelta.Width() =
228 aOutPixSz.Width() - ( aPixOffset.X() + aTotPixSz.Width() );
229 if ( aPixOffset.Y() < 0 &&
230 aPixOffset.Y() + aTotPixSz.Height() < aOutPixSz.Height() )
231 aPixDelta.Height() =
232 aOutPixSz.Height() - ( aPixOffset.Y() + aTotPixSz.Height() );
233 if ( aPixDelta.Width() || aPixDelta.Height() )
235 aPixOffset.X() += aPixDelta.Width();
236 aPixOffset.Y() += aPixDelta.Height();
239 // for axis without scrollbar restore the origin
240 if ( !bVVisible || !bHVisible )
242 aPixOffset = Point(
243 bHVisible
244 ? aPixOffset.X()
245 : ( bHCenter
246 ? (aOutPixSz.Width()-aTotPixSz.Width()) / 2
247 : 0 ),
248 bVVisible
249 ? aPixOffset.Y()
250 : ( bVCenter
251 ? (aOutPixSz.Height()-aTotPixSz.Height()) / 2
252 : 0 ) );
254 if ( bHVisible && !aHScroll.IsVisible() )
255 aPixOffset.X() = 0;
256 if ( bVVisible && !aVScroll.IsVisible() )
257 aPixOffset.Y() = 0;
259 // select the shifted map-mode
260 if ( aPixOffset != aOldPixOffset )
262 Window::SetMapMode( MapMode( MAP_PIXEL ) );
263 Window::Scroll(
264 aPixOffset.X() - aOldPixOffset.X(),
265 aPixOffset.Y() - aOldPixOffset.Y() );
266 SetMapMode( aMap );
269 // show or hide scrollbars
270 aVScroll.Show( bVVisible );
271 aHScroll.Show( bHVisible );
273 // disable painting in the corner between the scrollbars
274 if ( bVVisible && bHVisible )
276 aCornerWin.SetPosSizePixel(Point(aOutPixSz.Width(), aOutPixSz.Height()),
277 Size(nScrSize, nScrSize) );
278 aCornerWin.Show();
280 else
281 aCornerWin.Hide();
283 // resize scrollbars and set their ranges
284 if ( bHVisible )
286 aHScroll.SetPosSizePixel(
287 Point( 0, aOutPixSz.Height() ),
288 Size( aOutPixSz.Width(), nScrSize ) );
289 aHScroll.SetRange( Range( 0, aTotPixSz.Width() ) );
290 aHScroll.SetPageSize( aOutPixSz.Width() );
291 aHScroll.SetVisibleSize( aOutPixSz.Width() );
292 aHScroll.SetLineSize( nColumnPixW );
293 aHScroll.SetThumbPos( -aPixOffset.X() );
295 if ( bVVisible )
297 aVScroll.SetPosSizePixel(
298 Point( aOutPixSz.Width(), 0 ),
299 Size( nScrSize,aOutPixSz.Height() ) );
300 aVScroll.SetRange( Range( 0, aTotPixSz.Height() ) );
301 aVScroll.SetPageSize( aOutPixSz.Height() );
302 aVScroll.SetVisibleSize( aOutPixSz.Height() );
303 aVScroll.SetLineSize( nLinePixH );
304 aVScroll.SetThumbPos( -aPixOffset.Y() );
308 //-------------------------------------------------------------------
310 void __EXPORT ScrollableWindow::StartScroll()
314 //-------------------------------------------------------------------
316 void __EXPORT ScrollableWindow::EndScroll( long, long )
320 //-------------------------------------------------------------------
322 void ScrollableWindow::SetMapMode( const MapMode& rNewMapMode )
324 MapMode aMap( rNewMapMode );
325 aMap.SetOrigin( aMap.GetOrigin() + PixelToLogic( aPixOffset, aMap ) );
326 Window::SetMapMode( aMap );
329 //-------------------------------------------------------------------
331 MapMode ScrollableWindow::GetMapMode() const
333 MapMode aMap( Window::GetMapMode() );
334 aMap.SetOrigin( aMap.GetOrigin() - PixelToLogic( aPixOffset ) );
335 return aMap;
338 //-------------------------------------------------------------------
340 void ScrollableWindow::SetTotalSize( const Size& rNewSize )
342 aTotPixSz = LogicToPixel( rNewSize );
343 ScrollableWindow::Resize();
346 //-------------------------------------------------------------------
348 void ScrollableWindow::SetVisibleSize( const Size& rNewSize )
350 // get the rectangle, we wish to view
351 Rectangle aWish( Point(0, 0), LogicToPixel(rNewSize) );
353 // get maximum rectangle for us from our parent-window (subst our border!)
354 Rectangle aMax( Point(0, 0), GetParent()->GetOutputSizePixel() );
355 aMax.Left() -= ( Window::GetSizePixel().Width() -
356 Window::GetOutputSizePixel().Width() );
357 aMax.Bottom() -= (Window::GetSizePixel().Height() -
358 Window::GetOutputSizePixel().Height());
360 Size aWill( aWish.GetIntersection(aMax).GetSize() );
361 BOOL bHScroll = FALSE;
362 const long nScrSize = GetSettings().GetStyleSettings().GetScrollBarSize();
363 if ( aWill.Width() < aWish.GetSize().Width() )
364 { bHScroll = TRUE;
365 aWill.Height() =
366 Min( aWill.Height()+nScrSize, aMax.GetSize().Height() );
368 if ( aWill.Height() < aWish.GetSize().Height() )
369 aWill.Width() =
370 Min( aWill.Width()+nScrSize, aMax.GetSize().Width() );
371 if ( !bHScroll && (aWill.Width() < aWish.GetSize().Width()) )
372 aWill.Height() =
373 Min( aWill.Height()+nScrSize, aMax.GetSize().Height() );
374 Window::SetOutputSizePixel( aWill );
377 //-------------------------------------------------------------------
379 BOOL ScrollableWindow::MakeVisible( const Rectangle& rTarget, BOOL bSloppy )
381 Rectangle aTarget;
382 Rectangle aTotRect( Point(0, 0), PixelToLogic( aTotPixSz ) );
384 if ( bSloppy )
386 aTarget = rTarget;
388 // at maximum to right border
389 if ( aTarget.Right() > aTotRect.Right() )
391 long nDelta = aTarget.Right() - aTotRect.Right();
392 aTarget.Left() -= nDelta;
393 aTarget.Right() -= nDelta;
395 // too wide?
396 if ( aTarget.Left() < aTotRect.Left() )
397 aTarget.Left() = aTotRect.Left();
400 // at maximum to bottom border
401 if ( aTarget.Bottom() > aTotRect.Bottom() )
403 long nDelta = aTarget.Bottom() - aTotRect.Bottom();
404 aTarget.Top() -= nDelta;
405 aTarget.Bottom() -= nDelta;
407 // too high?
408 if ( aTarget.Top() < aTotRect.Top() )
409 aTarget.Top() = aTotRect.Top();
412 // at maximum to left border
413 if ( aTarget.Left() < aTotRect.Left() )
415 long nDelta = aTarget.Left() - aTotRect.Left();
416 aTarget.Right() -= nDelta;
417 aTarget.Left() -= nDelta;
419 // too wide?
420 if ( aTarget.Right() > aTotRect.Right() )
421 aTarget.Right() = aTotRect.Right();
424 // at maximum to top border
425 if ( aTarget.Top() < aTotRect.Top() )
427 long nDelta = aTarget.Top() - aTotRect.Top();
428 aTarget.Bottom() -= nDelta;
429 aTarget.Top() -= nDelta;
431 // too high?
432 if ( aTarget.Bottom() > aTotRect.Bottom() )
433 aTarget.Bottom() = aTotRect.Bottom();
436 else
437 aTarget = rTarget.GetIntersection( aTotRect );
439 // is the area already visible?
440 Rectangle aVisArea( GetVisibleArea() );
441 if ( aVisArea.IsInside(rTarget) )
442 return TRUE;
444 // is there somewhat to scroll?
445 if ( aVisArea.TopLeft() != aTarget.TopLeft() )
447 Rectangle aBox( aTarget.GetUnion(aVisArea) );
448 long nDeltaX = ( aBox.Right() - aVisArea.Right() ) +
449 ( aBox.Left() - aVisArea.Left() );
450 long nDeltaY = ( aBox.Top() - aVisArea.Top() ) +
451 ( aBox.Bottom() - aVisArea.Bottom() );
452 Scroll( nDeltaX, nDeltaY );
455 // determine if the target is completely visible
456 return aVisArea.GetWidth() >= aTarget.GetWidth() &&
457 aVisArea.GetHeight() >= aTarget.GetHeight();
460 //-------------------------------------------------------------------
462 Rectangle ScrollableWindow::GetVisibleArea() const
464 Point aTopLeft( PixelToLogic( Point() ) );
465 Size aSz( GetOutputSize() );
466 return Rectangle( aTopLeft, aSz );
469 //-------------------------------------------------------------------
471 void ScrollableWindow::SetLineSize( ULONG nHorz, ULONG nVert )
473 Size aPixSz( LogicToPixel( Size(nHorz, nVert) ) );
474 nColumnPixW = aPixSz.Width();
475 nLinePixH = aPixSz.Height();
476 aVScroll.SetLineSize( nLinePixH );
477 aHScroll.SetLineSize( nColumnPixW );
480 //-------------------------------------------------------------------
482 void ScrollableWindow::Scroll( long nDeltaX, long nDeltaY, USHORT )
484 if ( !bScrolling )
485 StartScroll();
487 // get the delta in pixel
488 Size aDeltaPix( LogicToPixel( Size(nDeltaX, nDeltaY) ) );
489 Size aOutPixSz( GetOutputSizePixel() );
490 MapMode aMap( GetMapMode() );
491 Point aNewPixOffset( aPixOffset );
493 // scrolling horizontally?
494 if ( nDeltaX != 0 )
496 aNewPixOffset.X() -= aDeltaPix.Width();
497 if ( ( aOutPixSz.Width() - aNewPixOffset.X() ) > aTotPixSz.Width() )
498 aNewPixOffset.X() = - ( aTotPixSz.Width() - aOutPixSz.Width() );
499 else if ( aNewPixOffset.X() > 0 )
500 aNewPixOffset.X() = 0;
503 // scrolling vertically?
504 if ( nDeltaY != 0 )
506 aNewPixOffset.Y() -= aDeltaPix.Height();
507 if ( ( aOutPixSz.Height() - aNewPixOffset.Y() ) > aTotPixSz.Height() )
508 aNewPixOffset.Y() = - ( aTotPixSz.Height() - aOutPixSz.Height() );
509 else if ( aNewPixOffset.Y() > 0 )
510 aNewPixOffset.Y() = 0;
513 // recompute the logical scroll units
514 aDeltaPix.Width() = aPixOffset.X() - aNewPixOffset.X();
515 aDeltaPix.Height() = aPixOffset.Y() - aNewPixOffset.Y();
516 Size aDelta( PixelToLogic(aDeltaPix) );
517 nDeltaX = aDelta.Width();
518 nDeltaY = aDelta.Height();
519 aPixOffset = aNewPixOffset;
521 // scrolling?
522 if ( nDeltaX != 0 || nDeltaY != 0 )
524 Update();
526 // does the new area overlap the old one?
527 if ( Abs( (int)aDeltaPix.Height() ) < aOutPixSz.Height() ||
528 Abs( (int)aDeltaPix.Width() ) < aOutPixSz.Width() )
530 // scroll the overlapping area
531 SetMapMode( aMap );
533 // never scroll the scrollbars itself!
534 Window::Scroll(-nDeltaX, -nDeltaY,
535 PixelToLogic( Rectangle( Point(0, 0), aOutPixSz ) ) );
537 else
539 // repaint all
540 SetMapMode( aMap );
541 Invalidate();
544 Update();
547 if ( !bScrolling )
549 EndScroll( nDeltaX, nDeltaY );
550 if ( nDeltaX )
551 aHScroll.SetThumbPos( -aPixOffset.X() );
552 if ( nDeltaY )
553 aVScroll.SetThumbPos( -aPixOffset.Y() );
557 //-------------------------------------------------------------------
559 void ScrollableWindow::ScrollLines( long nLinesX, long nLinesY )
561 Size aDelta( PixelToLogic( Size( nColumnPixW, nLinePixH ) ) );
562 Scroll( aDelta.Width()*nLinesX, aDelta.Height()*nLinesY );
565 //-------------------------------------------------------------------
567 void ScrollableWindow::ScrollPages( long nPagesX, ULONG nOverlapX,
568 long nPagesY, ULONG nOverlapY )
570 Size aOutSz( GetVisibleArea().GetSize() );
571 Scroll( nPagesX * aOutSz.Width() + (nPagesX>0 ? 1 : -1) * nOverlapX,
572 nPagesY * aOutSz.Height() + (nPagesY>0 ? 1 : -1) * nOverlapY );