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: scrwin.cxx,v $
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
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
;
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
) ),
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
) ),
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
) )
89 if ( aHScroll
.IsVisible() )
93 if ( aVScroll
.IsVisible() )
97 if ( HandleScrollCommand( rCEvt
, pHScrBar
, pVScrBar
) )
101 Window::Command( rCEvt
);
104 //-------------------------------------------------------------------
106 void ScrollableWindow::DataChanged( const DataChangedEvent
& rDCEvt
)
108 if ( (rDCEvt
.GetType() == DATACHANGED_SETTINGS
) &&
109 (rDCEvt
.GetFlags() & SETTINGS_STYLE
) )
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() )
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
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 );
156 Scroll( 0, aDelta
.Height() );
159 // notify the end of scrolling
161 EndScroll( aDelta
.Width(), aDelta
.Height() );
165 //-------------------------------------------------------------------
167 IMPL_LINK( ScrollableWindow
, ScrollHdl
, ScrollBar
*, pScroll
)
169 // notify the start of scrolling, if not already scrolling
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 );
181 Scroll( 0, aDelta
.Height() );
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
202 // does we need a vertical ScrollBar
203 if ( aOutPixSz
.Width() < aTotPixSz
.Width() && !bHVisible
)
205 aOutPixSz
.Height() -= nScrSize
;
209 // does we need a horizontal ScrollBar
210 if ( aOutPixSz
.Height() < aTotPixSz
.Height() && !bVVisible
)
212 aOutPixSz
.Width() -= nScrSize
;
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)
225 if ( aPixOffset
.X() < 0 &&
226 aPixOffset
.X() + aTotPixSz
.Width() < aOutPixSz
.Width() )
228 aOutPixSz
.Width() - ( aPixOffset
.X() + aTotPixSz
.Width() );
229 if ( aPixOffset
.Y() < 0 &&
230 aPixOffset
.Y() + aTotPixSz
.Height() < aOutPixSz
.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
)
246 ? (aOutPixSz
.Width()-aTotPixSz
.Width()) / 2
251 ? (aOutPixSz
.Height()-aTotPixSz
.Height()) / 2
254 if ( bHVisible
&& !aHScroll
.IsVisible() )
256 if ( bVVisible
&& !aVScroll
.IsVisible() )
259 // select the shifted map-mode
260 if ( aPixOffset
!= aOldPixOffset
)
262 Window::SetMapMode( MapMode( MAP_PIXEL
) );
264 aPixOffset
.X() - aOldPixOffset
.X(),
265 aPixOffset
.Y() - aOldPixOffset
.Y() );
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
) );
283 // resize scrollbars and set their ranges
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() );
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
) );
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() )
366 Min( aWill
.Height()+nScrSize
, aMax
.GetSize().Height() );
368 if ( aWill
.Height() < aWish
.GetSize().Height() )
370 Min( aWill
.Width()+nScrSize
, aMax
.GetSize().Width() );
371 if ( !bHScroll
&& (aWill
.Width() < aWish
.GetSize().Width()) )
373 Min( aWill
.Height()+nScrSize
, aMax
.GetSize().Height() );
374 Window::SetOutputSizePixel( aWill
);
377 //-------------------------------------------------------------------
379 BOOL
ScrollableWindow::MakeVisible( const Rectangle
& rTarget
, BOOL bSloppy
)
382 Rectangle
aTotRect( Point(0, 0), PixelToLogic( aTotPixSz
) );
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
;
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
;
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
;
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
;
432 if ( aTarget
.Bottom() > aTotRect
.Bottom() )
433 aTarget
.Bottom() = aTotRect
.Bottom();
437 aTarget
= rTarget
.GetIntersection( aTotRect
);
439 // is the area already visible?
440 Rectangle
aVisArea( GetVisibleArea() );
441 if ( aVisArea
.IsInside(rTarget
) )
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
)
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?
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?
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
;
522 if ( nDeltaX
!= 0 || nDeltaY
!= 0 )
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
533 // never scroll the scrollbars itself!
534 Window::Scroll(-nDeltaX
, -nDeltaY
,
535 PixelToLogic( Rectangle( Point(0, 0), aOutPixSz
) ) );
549 EndScroll( nDeltaX
, nDeltaY
);
551 aHScroll
.SetThumbPos( -aPixOffset
.X() );
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
);