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 <vcl/commandevent.hxx>
21 #include <vcl/event.hxx>
22 #include <vcl/settings.hxx>
23 #include <vcl/scrbar.hxx>
26 ScrollableWindow::ScrollableWindow( vcl::Window
* pParent
) :
27 Window( pParent
, WB_CLIPCHILDREN
),
28 aVScroll( VclPtr
<ScrollBar
>::Create(this, WinBits(WB_VSCROLL
| WB_DRAG
)) ),
29 aHScroll( VclPtr
<ScrollBar
>::Create(this, WinBits(WB_HSCROLL
| WB_DRAG
)) ),
30 aCornerWin( VclPtr
<ScrollBarBox
>::Create(this) )
34 // set the handlers for the scrollbars
35 aVScroll
->SetScrollHdl( LINK(this, ScrollableWindow
, ScrollHdl
) );
36 aHScroll
->SetScrollHdl( LINK(this, ScrollableWindow
, ScrollHdl
) );
37 aVScroll
->SetEndScrollHdl( LINK(this, ScrollableWindow
, EndScrollHdl
) );
38 aHScroll
->SetEndScrollHdl( LINK(this, ScrollableWindow
, EndScrollHdl
) );
40 nColumnPixW
= nLinePixH
= GetSettings().GetStyleSettings().GetScrollBarSize();
44 ScrollableWindow::~ScrollableWindow()
49 void ScrollableWindow::dispose()
51 aVScroll
.disposeAndClear();
52 aHScroll
.disposeAndClear();
53 aCornerWin
.disposeAndClear();
58 void ScrollableWindow::Command( const CommandEvent
& rCEvt
)
60 if ( (rCEvt
.GetCommand() == CommandEventId::Wheel
) ||
61 (rCEvt
.GetCommand() == CommandEventId::StartAutoScroll
) ||
62 (rCEvt
.GetCommand() == CommandEventId::AutoScroll
) )
66 if ( aHScroll
->IsVisible() )
67 pHScrBar
= aHScroll
.get();
70 if ( aVScroll
->IsVisible() )
71 pVScrBar
= aVScroll
.get();
74 if ( HandleScrollCommand( rCEvt
, pHScrBar
, pVScrBar
) )
78 Window::Command( rCEvt
);
82 void ScrollableWindow::DataChanged( const DataChangedEvent
& rDCEvt
)
84 if ( (rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) &&
85 (rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
) )
91 Window::DataChanged( rDCEvt
);
95 Size
ScrollableWindow::GetOutputSizePixel() const
97 Size
aSz( Window::GetOutputSizePixel() );
99 tools::Long nTmp
= GetSettings().GetStyleSettings().GetScrollBarSize();
100 if ( aHScroll
->IsVisible() )
101 aSz
.AdjustHeight( -nTmp
);
102 if ( aVScroll
->IsVisible() )
103 aSz
.AdjustWidth( -nTmp
);
108 IMPL_LINK( ScrollableWindow
, EndScrollHdl
, ScrollBar
*, /*pScroll*/, void )
110 // notify the end of scrolling
115 IMPL_LINK( ScrollableWindow
, ScrollHdl
, ScrollBar
*, pScroll
, void )
117 // notify the start of scrolling, if not already scrolling
121 // get the delta in logic coordinates
122 Size
aDelta( PixelToLogic(
123 Size( aHScroll
->GetDelta(), aVScroll
->GetDelta() ) ) );
124 if ( pScroll
== aHScroll
.get() )
125 Scroll( aDelta
.Width(), 0 );
127 Scroll( 0, aDelta
.Height() );
131 void ScrollableWindow::Resize()
133 // get the new output-size in pixel
134 Size aOutPixSz
= Window::GetOutputSizePixel();
136 // determine the size of the output-area and if we need scrollbars
137 const tools::Long nScrSize
= GetSettings().GetStyleSettings().GetScrollBarSize();
138 bool bVVisible
= false; // by default no vertical-ScrollBar
139 bool bHVisible
= false; // by default no horizontal-ScrollBar
140 bool bChanged
; // determines if a visiblility was changed
145 // does we need a vertical ScrollBar
146 if ( aOutPixSz
.Width() < aTotPixSz
.Width() && !bHVisible
)
149 aOutPixSz
.AdjustHeight( -nScrSize
);
153 // does we need a horizontal ScrollBar
154 if ( aOutPixSz
.Height() < aTotPixSz
.Height() && !bVVisible
)
157 aOutPixSz
.AdjustWidth( -nScrSize
);
162 while ( bChanged
); // until no visibility has changed
164 // store the old offset and map-mode
165 MapMode
aMap( GetMapMode() );
166 Point
aOldPixOffset( aPixOffset
);
168 // justify (right/bottom borders should never exceed the virtual window)
170 if ( aPixOffset
.X() < 0 &&
171 aPixOffset
.X() + aTotPixSz
.Width() < aOutPixSz
.Width() )
173 aOutPixSz
.Width() - ( aPixOffset
.X() + aTotPixSz
.Width() ) );
174 if ( aPixOffset
.Y() < 0 &&
175 aPixOffset
.Y() + aTotPixSz
.Height() < aOutPixSz
.Height() )
177 aOutPixSz
.Height() - ( aPixOffset
.Y() + aTotPixSz
.Height() ) );
178 if ( aPixDelta
.Width() || aPixDelta
.Height() )
180 aPixOffset
.AdjustX(aPixDelta
.Width() );
181 aPixOffset
.AdjustY(aPixDelta
.Height() );
184 // for axis without scrollbar restore the origin
185 if ( !bVVisible
|| !bHVisible
)
190 : (aOutPixSz
.Width()-aTotPixSz
.Width()) / 2,
193 : (aOutPixSz
.Height()-aTotPixSz
.Height()) / 2 );
195 if ( bHVisible
&& !aHScroll
->IsVisible() )
196 aPixOffset
.setX( 0 );
197 if ( bVVisible
&& !aVScroll
->IsVisible() )
198 aPixOffset
.setY( 0 );
200 // select the shifted map-mode
201 if ( aPixOffset
!= aOldPixOffset
)
203 Window::SetMapMode( MapMode( MapUnit::MapPixel
) );
205 aPixOffset
.X() - aOldPixOffset
.X(),
206 aPixOffset
.Y() - aOldPixOffset
.Y() );
210 // show or hide scrollbars
211 aVScroll
->Show( bVVisible
);
212 aHScroll
->Show( bHVisible
);
214 // disable painting in the corner between the scrollbars
215 if ( bVVisible
&& bHVisible
)
217 aCornerWin
->SetPosSizePixel(Point(aOutPixSz
.Width(), aOutPixSz
.Height()),
218 Size(nScrSize
, nScrSize
) );
224 // resize scrollbars and set their ranges
227 aHScroll
->SetPosSizePixel(
228 Point( 0, aOutPixSz
.Height() ),
229 Size( aOutPixSz
.Width(), nScrSize
) );
230 aHScroll
->SetRange( Range( 0, aTotPixSz
.Width() ) );
231 aHScroll
->SetPageSize( aOutPixSz
.Width() );
232 aHScroll
->SetVisibleSize( aOutPixSz
.Width() );
233 aHScroll
->SetLineSize( nColumnPixW
);
234 aHScroll
->SetThumbPos( -aPixOffset
.X() );
238 aVScroll
->SetPosSizePixel(
239 Point( aOutPixSz
.Width(), 0 ),
240 Size( nScrSize
,aOutPixSz
.Height() ) );
241 aVScroll
->SetRange( Range( 0, aTotPixSz
.Height() ) );
242 aVScroll
->SetPageSize( aOutPixSz
.Height() );
243 aVScroll
->SetVisibleSize( aOutPixSz
.Height() );
244 aVScroll
->SetLineSize( nLinePixH
);
245 aVScroll
->SetThumbPos( -aPixOffset
.Y() );
250 void ScrollableWindow::SetMapMode( const MapMode
& rNewMapMode
)
252 MapMode
aMap( rNewMapMode
);
253 aMap
.SetOrigin( aMap
.GetOrigin() + PixelToLogic( aPixOffset
, aMap
) );
254 Window::SetMapMode( aMap
);
258 MapMode
ScrollableWindow::GetMapMode() const
260 MapMode
aMap( Window::GetMapMode() );
261 aMap
.SetOrigin( aMap
.GetOrigin() - PixelToLogic( aPixOffset
) );
266 void ScrollableWindow::SetTotalSize( const Size
& rNewSize
)
268 aTotPixSz
= LogicToPixel( rNewSize
);
269 ScrollableWindow::Resize();
273 void ScrollableWindow::Scroll( tools::Long nDeltaX
, tools::Long nDeltaY
, ScrollFlags
)
275 // get the delta in pixel
276 Size
aDeltaPix( LogicToPixel( Size(nDeltaX
, nDeltaY
) ) );
277 Size
aOutPixSz( GetOutputSizePixel() );
278 MapMode
aMap( GetMapMode() );
279 Point
aNewPixOffset( aPixOffset
);
281 // scrolling horizontally?
284 aNewPixOffset
.AdjustX( -(aDeltaPix
.Width()) );
285 if ( ( aOutPixSz
.Width() - aNewPixOffset
.X() ) > aTotPixSz
.Width() )
286 aNewPixOffset
.setX( - ( aTotPixSz
.Width() - aOutPixSz
.Width() ) );
287 else if ( aNewPixOffset
.X() > 0 )
288 aNewPixOffset
.setX( 0 );
291 // scrolling vertically?
294 aNewPixOffset
.AdjustY( -(aDeltaPix
.Height()) );
295 if ( ( aOutPixSz
.Height() - aNewPixOffset
.Y() ) > aTotPixSz
.Height() )
296 aNewPixOffset
.setY( - ( aTotPixSz
.Height() - aOutPixSz
.Height() ) );
297 else if ( aNewPixOffset
.Y() > 0 )
298 aNewPixOffset
.setY( 0 );
301 // recompute the logical scroll units
302 aDeltaPix
.setWidth( aPixOffset
.X() - aNewPixOffset
.X() );
303 aDeltaPix
.setHeight( aPixOffset
.Y() - aNewPixOffset
.Y() );
304 Size
aDelta( PixelToLogic(aDeltaPix
) );
305 nDeltaX
= aDelta
.Width();
306 nDeltaY
= aDelta
.Height();
307 aPixOffset
= aNewPixOffset
;
310 if ( nDeltaX
!= 0 || nDeltaY
!= 0 )
314 // does the new area overlap the old one?
315 if ( std::abs( static_cast<int>(aDeltaPix
.Height()) ) < aOutPixSz
.Height() ||
316 std::abs( static_cast<int>(aDeltaPix
.Width()) ) < aOutPixSz
.Width() )
318 // scroll the overlapping area
321 // never scroll the scrollbars itself!
322 Window::Scroll(-nDeltaX
, -nDeltaY
,
323 PixelToLogic( tools::Rectangle( Point(0, 0), aOutPixSz
) ) );
338 aHScroll
->SetThumbPos( -aPixOffset
.X() );
340 aVScroll
->SetThumbPos( -aPixOffset
.Y() );
345 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */