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>
21 #include <vcl/settings.hxx>
25 void ScrollableWindow::ImpInitialize( ScrollableWindowFlags nFlags
)
27 bHandleDragging
= bool( nFlags
& ScrollableWindowFlags::THUMBDRAGGING
);
28 bVCenter
= bool(nFlags
& ScrollableWindowFlags::VCENTER
);
29 bHCenter
= bool(nFlags
& ScrollableWindowFlags::HCENTER
);
32 // set the handlers for the scrollbars
33 aVScroll
->SetScrollHdl( LINK(this, ScrollableWindow
, ScrollHdl
) );
34 aHScroll
->SetScrollHdl( LINK(this, ScrollableWindow
, ScrollHdl
) );
35 aVScroll
->SetEndScrollHdl( LINK(this, ScrollableWindow
, EndScrollHdl
) );
36 aHScroll
->SetEndScrollHdl( LINK(this, ScrollableWindow
, EndScrollHdl
) );
38 nColumnPixW
= nLinePixH
= GetSettings().GetStyleSettings().GetScrollBarSize();
43 ScrollableWindow::ScrollableWindow( vcl::Window
* pParent
, WinBits nBits
,
44 ScrollableWindowFlags nFlags
) :
45 Window( pParent
, WinBits(nBits
|WB_CLIPCHILDREN
) ),
46 aVScroll( VclPtr
<ScrollBar
>::Create(this, WinBits(WB_VSCROLL
| WB_DRAG
)) ),
47 aHScroll( VclPtr
<ScrollBar
>::Create(this, WinBits(WB_HSCROLL
| WB_DRAG
)) ),
48 aCornerWin( VclPtr
<ScrollBarBox
>::Create(this) )
50 ImpInitialize( nFlags
);
54 ScrollableWindow::~ScrollableWindow()
59 void ScrollableWindow::dispose()
61 aVScroll
.disposeAndClear();
62 aHScroll
.disposeAndClear();
63 aCornerWin
.disposeAndClear();
68 void ScrollableWindow::Command( const CommandEvent
& rCEvt
)
70 if ( (rCEvt
.GetCommand() == CommandEventId::Wheel
) ||
71 (rCEvt
.GetCommand() == CommandEventId::StartAutoScroll
) ||
72 (rCEvt
.GetCommand() == CommandEventId::AutoScroll
) )
76 if ( aHScroll
->IsVisible() )
77 pHScrBar
= aHScroll
.get();
80 if ( aVScroll
->IsVisible() )
81 pVScrBar
= aVScroll
.get();
84 if ( HandleScrollCommand( rCEvt
, pHScrBar
, pVScrBar
) )
88 Window::Command( rCEvt
);
93 void ScrollableWindow::DataChanged( const DataChangedEvent
& rDCEvt
)
95 if ( (rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) &&
96 (rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
) )
102 Window::DataChanged( rDCEvt
);
107 Size
ScrollableWindow::GetOutputSizePixel() const
109 Size
aSz( Window::GetOutputSizePixel() );
111 long nTmp
= GetSettings().GetStyleSettings().GetScrollBarSize();
112 if ( aHScroll
->IsVisible() )
113 aSz
.Height() -= nTmp
;
114 if ( aVScroll
->IsVisible() )
121 IMPL_LINK( ScrollableWindow
, EndScrollHdl
, ScrollBar
*, pScroll
)
123 // notify the start of scrolling, if not already scrolling
127 // get the delta in logic coordinates
128 Size
aDelta( PixelToLogic( Size( aHScroll
->GetDelta(), aVScroll
->GetDelta() ) ) );
130 // scroll the window, if this is not already done
131 if ( !bHandleDragging
)
133 if ( pScroll
== aHScroll
.get() )
134 Scroll( aDelta
.Width(), 0 );
136 Scroll( 0, aDelta
.Height() );
139 // notify the end of scrolling
146 IMPL_LINK( ScrollableWindow
, ScrollHdl
, ScrollBar
*, pScroll
)
148 // notify the start of scrolling, if not already scrolling
152 if ( bHandleDragging
)
154 // get the delta in logic coordinates
155 Size
aDelta( PixelToLogic(
156 Size( aHScroll
->GetDelta(), aVScroll
->GetDelta() ) ) );
157 if ( pScroll
== aHScroll
.get() )
158 Scroll( aDelta
.Width(), 0 );
160 Scroll( 0, aDelta
.Height() );
167 void ScrollableWindow::Resize()
169 // get the new output-size in pixel
170 Size aOutPixSz
= Window::GetOutputSizePixel();
172 // determine the size of the output-area and if we need scrollbars
173 const long nScrSize
= GetSettings().GetStyleSettings().GetScrollBarSize();
174 bool bVVisible
= false; // by default no vertical-ScrollBar
175 bool bHVisible
= false; // by default no horizontal-ScrollBar
176 bool bChanged
; // determines if a visiblility was changed
181 // does we need a vertical ScrollBar
182 if ( aOutPixSz
.Width() < aTotPixSz
.Width() && !bHVisible
)
185 aOutPixSz
.Height() -= nScrSize
;
189 // does we need a horizontal ScrollBar
190 if ( aOutPixSz
.Height() < aTotPixSz
.Height() && !bVVisible
)
193 aOutPixSz
.Width() -= nScrSize
;
198 while ( bChanged
); // until no visibility has changed
200 // store the old offset and map-mode
201 MapMode
aMap( GetMapMode() );
202 Point
aOldPixOffset( aPixOffset
);
204 // justify (right/bottom borders should never exceed the virtual window)
206 if ( aPixOffset
.X() < 0 &&
207 aPixOffset
.X() + aTotPixSz
.Width() < aOutPixSz
.Width() )
209 aOutPixSz
.Width() - ( aPixOffset
.X() + aTotPixSz
.Width() );
210 if ( aPixOffset
.Y() < 0 &&
211 aPixOffset
.Y() + aTotPixSz
.Height() < aOutPixSz
.Height() )
213 aOutPixSz
.Height() - ( aPixOffset
.Y() + aTotPixSz
.Height() );
214 if ( aPixDelta
.Width() || aPixDelta
.Height() )
216 aPixOffset
.X() += aPixDelta
.Width();
217 aPixOffset
.Y() += aPixDelta
.Height();
220 // for axis without scrollbar restore the origin
221 if ( !bVVisible
|| !bHVisible
)
227 ? (aOutPixSz
.Width()-aTotPixSz
.Width()) / 2
232 ? (aOutPixSz
.Height()-aTotPixSz
.Height()) / 2
235 if ( bHVisible
&& !aHScroll
->IsVisible() )
237 if ( bVVisible
&& !aVScroll
->IsVisible() )
240 // select the shifted map-mode
241 if ( aPixOffset
!= aOldPixOffset
)
243 Window::SetMapMode( MapMode( MAP_PIXEL
) );
245 aPixOffset
.X() - aOldPixOffset
.X(),
246 aPixOffset
.Y() - aOldPixOffset
.Y() );
250 // show or hide scrollbars
251 aVScroll
->Show( bVVisible
);
252 aHScroll
->Show( bHVisible
);
254 // disable painting in the corner between the scrollbars
255 if ( bVVisible
&& bHVisible
)
257 aCornerWin
->SetPosSizePixel(Point(aOutPixSz
.Width(), aOutPixSz
.Height()),
258 Size(nScrSize
, nScrSize
) );
264 // resize scrollbars and set their ranges
267 aHScroll
->SetPosSizePixel(
268 Point( 0, aOutPixSz
.Height() ),
269 Size( aOutPixSz
.Width(), nScrSize
) );
270 aHScroll
->SetRange( Range( 0, aTotPixSz
.Width() ) );
271 aHScroll
->SetPageSize( aOutPixSz
.Width() );
272 aHScroll
->SetVisibleSize( aOutPixSz
.Width() );
273 aHScroll
->SetLineSize( nColumnPixW
);
274 aHScroll
->SetThumbPos( -aPixOffset
.X() );
278 aVScroll
->SetPosSizePixel(
279 Point( aOutPixSz
.Width(), 0 ),
280 Size( nScrSize
,aOutPixSz
.Height() ) );
281 aVScroll
->SetRange( Range( 0, aTotPixSz
.Height() ) );
282 aVScroll
->SetPageSize( aOutPixSz
.Height() );
283 aVScroll
->SetVisibleSize( aOutPixSz
.Height() );
284 aVScroll
->SetLineSize( nLinePixH
);
285 aVScroll
->SetThumbPos( -aPixOffset
.Y() );
291 void ScrollableWindow::SetMapMode( const MapMode
& rNewMapMode
)
293 MapMode
aMap( rNewMapMode
);
294 aMap
.SetOrigin( aMap
.GetOrigin() + PixelToLogic( aPixOffset
, aMap
) );
295 Window::SetMapMode( aMap
);
300 MapMode
ScrollableWindow::GetMapMode() const
302 MapMode
aMap( Window::GetMapMode() );
303 aMap
.SetOrigin( aMap
.GetOrigin() - PixelToLogic( aPixOffset
) );
309 void ScrollableWindow::SetTotalSize( const Size
& rNewSize
)
311 aTotPixSz
= LogicToPixel( rNewSize
);
312 ScrollableWindow::Resize();
317 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
) ) );
382 aHScroll
->SetThumbPos( -aPixOffset
.X() );
384 aVScroll
->SetThumbPos( -aPixOffset
.Y() );
389 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */