1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <svtools/scrwin.hxx>
22 //===================================================================
24 void ScrollableWindow::ImpInitialize( ScrollableWindowFlags nFlags
)
26 bHandleDragging
= (sal_Bool
) ( nFlags
& SCRWIN_THUMBDRAGGING
);
27 bVCenter
= (nFlags
& SCRWIN_VCENTER
) == SCRWIN_VCENTER
;
28 bHCenter
= (nFlags
& SCRWIN_HCENTER
) == SCRWIN_HCENTER
;
29 bScrolling
= sal_False
;
31 // set the handlers for the scrollbars
32 aVScroll
.SetScrollHdl( LINK(this, ScrollableWindow
, ScrollHdl
) );
33 aHScroll
.SetScrollHdl( LINK(this, ScrollableWindow
, ScrollHdl
) );
34 aVScroll
.SetEndScrollHdl( LINK(this, ScrollableWindow
, EndScrollHdl
) );
35 aHScroll
.SetEndScrollHdl( LINK(this, ScrollableWindow
, EndScrollHdl
) );
37 nColumnPixW
= nLinePixH
= GetSettings().GetStyleSettings().GetScrollBarSize();
40 //-------------------------------------------------------------------
42 ScrollableWindow::ScrollableWindow( Window
* pParent
, WinBits nBits
,
43 ScrollableWindowFlags nFlags
) :
44 Window( pParent
, WinBits(nBits
|WB_CLIPCHILDREN
) ),
45 aVScroll( this, WinBits(WB_VSCROLL
| WB_DRAG
) ),
46 aHScroll( this, WinBits(WB_HSCROLL
| WB_DRAG
) ),
49 ImpInitialize( nFlags
);
52 // -----------------------------------------------------------------------
54 void ScrollableWindow::Command( const CommandEvent
& rCEvt
)
56 if ( (rCEvt
.GetCommand() == COMMAND_WHEEL
) ||
57 (rCEvt
.GetCommand() == COMMAND_STARTAUTOSCROLL
) ||
58 (rCEvt
.GetCommand() == COMMAND_AUTOSCROLL
) )
62 if ( aHScroll
.IsVisible() )
66 if ( aVScroll
.IsVisible() )
70 if ( HandleScrollCommand( rCEvt
, pHScrBar
, pVScrBar
) )
74 Window::Command( rCEvt
);
77 //-------------------------------------------------------------------
79 void ScrollableWindow::DataChanged( const DataChangedEvent
& rDCEvt
)
81 if ( (rDCEvt
.GetType() == DATACHANGED_SETTINGS
) &&
82 (rDCEvt
.GetFlags() & SETTINGS_STYLE
) )
88 Window::DataChanged( rDCEvt
);
91 //-------------------------------------------------------------------
93 Size
ScrollableWindow::GetOutputSizePixel() const
95 Size
aSz( Window::GetOutputSizePixel() );
97 long nTmp
= GetSettings().GetStyleSettings().GetScrollBarSize();
98 if ( aHScroll
.IsVisible() )
100 if ( aVScroll
.IsVisible() )
105 //-------------------------------------------------------------------
107 IMPL_LINK( ScrollableWindow
, EndScrollHdl
, ScrollBar
*, pScroll
)
109 // notify the start of scrolling, if not already scrolling
111 StartScroll(), bScrolling
= sal_True
;
113 // get the delta in logic coordinates
114 Size
aDelta( PixelToLogic( Size( aHScroll
.GetDelta(), aVScroll
.GetDelta() ) ) );
116 // scroll the window, if this is not already done
117 if ( !bHandleDragging
)
119 if ( pScroll
== &aHScroll
)
120 Scroll( aDelta
.Width(), 0 );
122 Scroll( 0, aDelta
.Height() );
125 // notify the end of scrolling
126 bScrolling
= sal_False
;
127 EndScroll( aDelta
.Width(), aDelta
.Height() );
131 //-------------------------------------------------------------------
133 IMPL_LINK( ScrollableWindow
, ScrollHdl
, ScrollBar
*, pScroll
)
135 // notify the start of scrolling, if not already scrolling
137 StartScroll(), bScrolling
= sal_True
;
139 if ( bHandleDragging
)
141 // get the delta in logic coordinates
142 Size
aDelta( PixelToLogic(
143 Size( aHScroll
.GetDelta(), aVScroll
.GetDelta() ) ) );
144 if ( pScroll
== &aHScroll
)
145 Scroll( aDelta
.Width(), 0 );
147 Scroll( 0, aDelta
.Height() );
152 //-------------------------------------------------------------------
154 void ScrollableWindow::Resize()
156 // get the new output-size in pixel
157 Size aOutPixSz
= Window::GetOutputSizePixel();
159 // determine the size of the output-area and if we need scrollbars
160 const long nScrSize
= GetSettings().GetStyleSettings().GetScrollBarSize();
161 sal_Bool bVVisible
= sal_False
; // by default no vertical-ScrollBar
162 sal_Bool bHVisible
= sal_False
; // by default no horizontal-ScrollBar
163 sal_Bool bChanged
; // determines if a visiblility was changed
166 bChanged
= sal_False
;
168 // does we need a vertical ScrollBar
169 if ( aOutPixSz
.Width() < aTotPixSz
.Width() && !bHVisible
)
170 { bHVisible
= sal_True
;
171 aOutPixSz
.Height() -= nScrSize
;
175 // does we need a horizontal ScrollBar
176 if ( aOutPixSz
.Height() < aTotPixSz
.Height() && !bVVisible
)
177 { bVVisible
= sal_True
;
178 aOutPixSz
.Width() -= nScrSize
;
183 while ( bChanged
); // until no visibility has changed
185 // store the old offset and map-mode
186 MapMode
aMap( GetMapMode() );
187 Point
aOldPixOffset( aPixOffset
);
189 // justify (right/bottom borders should never exceed the virtual window)
191 if ( aPixOffset
.X() < 0 &&
192 aPixOffset
.X() + aTotPixSz
.Width() < aOutPixSz
.Width() )
194 aOutPixSz
.Width() - ( aPixOffset
.X() + aTotPixSz
.Width() );
195 if ( aPixOffset
.Y() < 0 &&
196 aPixOffset
.Y() + aTotPixSz
.Height() < aOutPixSz
.Height() )
198 aOutPixSz
.Height() - ( aPixOffset
.Y() + aTotPixSz
.Height() );
199 if ( aPixDelta
.Width() || aPixDelta
.Height() )
201 aPixOffset
.X() += aPixDelta
.Width();
202 aPixOffset
.Y() += aPixDelta
.Height();
205 // for axis without scrollbar restore the origin
206 if ( !bVVisible
|| !bHVisible
)
212 ? (aOutPixSz
.Width()-aTotPixSz
.Width()) / 2
217 ? (aOutPixSz
.Height()-aTotPixSz
.Height()) / 2
220 if ( bHVisible
&& !aHScroll
.IsVisible() )
222 if ( bVVisible
&& !aVScroll
.IsVisible() )
225 // select the shifted map-mode
226 if ( aPixOffset
!= aOldPixOffset
)
228 Window::SetMapMode( MapMode( MAP_PIXEL
) );
230 aPixOffset
.X() - aOldPixOffset
.X(),
231 aPixOffset
.Y() - aOldPixOffset
.Y() );
235 // show or hide scrollbars
236 aVScroll
.Show( bVVisible
);
237 aHScroll
.Show( bHVisible
);
239 // disable painting in the corner between the scrollbars
240 if ( bVVisible
&& bHVisible
)
242 aCornerWin
.SetPosSizePixel(Point(aOutPixSz
.Width(), aOutPixSz
.Height()),
243 Size(nScrSize
, nScrSize
) );
249 // resize scrollbars and set their ranges
252 aHScroll
.SetPosSizePixel(
253 Point( 0, aOutPixSz
.Height() ),
254 Size( aOutPixSz
.Width(), nScrSize
) );
255 aHScroll
.SetRange( Range( 0, aTotPixSz
.Width() ) );
256 aHScroll
.SetPageSize( aOutPixSz
.Width() );
257 aHScroll
.SetVisibleSize( aOutPixSz
.Width() );
258 aHScroll
.SetLineSize( nColumnPixW
);
259 aHScroll
.SetThumbPos( -aPixOffset
.X() );
263 aVScroll
.SetPosSizePixel(
264 Point( aOutPixSz
.Width(), 0 ),
265 Size( nScrSize
,aOutPixSz
.Height() ) );
266 aVScroll
.SetRange( Range( 0, aTotPixSz
.Height() ) );
267 aVScroll
.SetPageSize( aOutPixSz
.Height() );
268 aVScroll
.SetVisibleSize( aOutPixSz
.Height() );
269 aVScroll
.SetLineSize( nLinePixH
);
270 aVScroll
.SetThumbPos( -aPixOffset
.Y() );
274 //-------------------------------------------------------------------
276 void ScrollableWindow::StartScroll()
280 //-------------------------------------------------------------------
282 void ScrollableWindow::EndScroll( long, long )
286 //-------------------------------------------------------------------
288 void ScrollableWindow::SetMapMode( const MapMode
& rNewMapMode
)
290 MapMode
aMap( rNewMapMode
);
291 aMap
.SetOrigin( aMap
.GetOrigin() + PixelToLogic( aPixOffset
, aMap
) );
292 Window::SetMapMode( aMap
);
295 //-------------------------------------------------------------------
297 MapMode
ScrollableWindow::GetMapMode() const
299 MapMode
aMap( Window::GetMapMode() );
300 aMap
.SetOrigin( aMap
.GetOrigin() - PixelToLogic( aPixOffset
) );
304 //-------------------------------------------------------------------
306 void ScrollableWindow::SetTotalSize( const Size
& rNewSize
)
308 aTotPixSz
= LogicToPixel( rNewSize
);
309 ScrollableWindow::Resize();
312 //-------------------------------------------------------------------
314 void ScrollableWindow::Scroll( long nDeltaX
, long nDeltaY
, sal_uInt16
)
319 // get the delta in pixel
320 Size
aDeltaPix( LogicToPixel( Size(nDeltaX
, nDeltaY
) ) );
321 Size
aOutPixSz( GetOutputSizePixel() );
322 MapMode
aMap( GetMapMode() );
323 Point
aNewPixOffset( aPixOffset
);
325 // scrolling horizontally?
328 aNewPixOffset
.X() -= aDeltaPix
.Width();
329 if ( ( aOutPixSz
.Width() - aNewPixOffset
.X() ) > aTotPixSz
.Width() )
330 aNewPixOffset
.X() = - ( aTotPixSz
.Width() - aOutPixSz
.Width() );
331 else if ( aNewPixOffset
.X() > 0 )
332 aNewPixOffset
.X() = 0;
335 // scrolling vertically?
338 aNewPixOffset
.Y() -= aDeltaPix
.Height();
339 if ( ( aOutPixSz
.Height() - aNewPixOffset
.Y() ) > aTotPixSz
.Height() )
340 aNewPixOffset
.Y() = - ( aTotPixSz
.Height() - aOutPixSz
.Height() );
341 else if ( aNewPixOffset
.Y() > 0 )
342 aNewPixOffset
.Y() = 0;
345 // recompute the logical scroll units
346 aDeltaPix
.Width() = aPixOffset
.X() - aNewPixOffset
.X();
347 aDeltaPix
.Height() = aPixOffset
.Y() - aNewPixOffset
.Y();
348 Size
aDelta( PixelToLogic(aDeltaPix
) );
349 nDeltaX
= aDelta
.Width();
350 nDeltaY
= aDelta
.Height();
351 aPixOffset
= aNewPixOffset
;
354 if ( nDeltaX
!= 0 || nDeltaY
!= 0 )
358 // does the new area overlap the old one?
359 if ( std::abs( (int)aDeltaPix
.Height() ) < aOutPixSz
.Height() ||
360 std::abs( (int)aDeltaPix
.Width() ) < aOutPixSz
.Width() )
362 // scroll the overlapping area
365 // never scroll the scrollbars itself!
366 Window::Scroll(-nDeltaX
, -nDeltaY
,
367 PixelToLogic( Rectangle( Point(0, 0), aOutPixSz
) ) );
381 EndScroll( nDeltaX
, nDeltaY
);
383 aHScroll
.SetThumbPos( -aPixOffset
.X() );
385 aVScroll
.SetThumbPos( -aPixOffset
.Y() );
390 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */