Bump version to 5.0-14
[LibreOffice.git] / svtools / source / control / scrwin.cxx
blob3f716b00ca46b2abb1c17ba10ac9ce3fcd129a9a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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);
30 bScrolling = false;
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()
56 disposeOnce();
59 void ScrollableWindow::dispose()
61 aVScroll.disposeAndClear();
62 aHScroll.disposeAndClear();
63 aCornerWin.disposeAndClear();
64 Window::dispose();
68 void ScrollableWindow::Command( const CommandEvent& rCEvt )
70 if ( (rCEvt.GetCommand() == CommandEventId::Wheel) ||
71 (rCEvt.GetCommand() == CommandEventId::StartAutoScroll) ||
72 (rCEvt.GetCommand() == CommandEventId::AutoScroll) )
74 ScrollBar* pHScrBar;
75 ScrollBar* pVScrBar;
76 if ( aHScroll->IsVisible() )
77 pHScrBar = aHScroll.get();
78 else
79 pHScrBar = NULL;
80 if ( aVScroll->IsVisible() )
81 pVScrBar = aVScroll.get();
82 else
83 pVScrBar = NULL;
84 if ( HandleScrollCommand( rCEvt, pHScrBar, pVScrBar ) )
85 return;
88 Window::Command( rCEvt );
93 void ScrollableWindow::DataChanged( const DataChangedEvent& rDCEvt )
95 if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
96 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
98 Resize();
99 Invalidate();
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() )
115 aSz.Width() -= nTmp;
116 return aSz;
121 IMPL_LINK( ScrollableWindow, EndScrollHdl, ScrollBar *, pScroll )
123 // notify the start of scrolling, if not already scrolling
124 if ( !bScrolling )
125 bScrolling = true;
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 );
135 else
136 Scroll( 0, aDelta.Height() );
139 // notify the end of scrolling
140 bScrolling = false;
141 return 0;
146 IMPL_LINK( ScrollableWindow, ScrollHdl, ScrollBar *, pScroll )
148 // notify the start of scrolling, if not already scrolling
149 if ( !bScrolling )
150 bScrolling = true;
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 );
159 else
160 Scroll( 0, aDelta.Height() );
162 return 0;
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
179 bChanged = false;
181 // does we need a vertical ScrollBar
182 if ( aOutPixSz.Width() < aTotPixSz.Width() && !bHVisible )
184 bHVisible = true;
185 aOutPixSz.Height() -= nScrSize;
186 bChanged = true;
189 // does we need a horizontal ScrollBar
190 if ( aOutPixSz.Height() < aTotPixSz.Height() && !bVVisible )
192 bVVisible = true;
193 aOutPixSz.Width() -= nScrSize;
194 bChanged = true;
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)
205 Size aPixDelta;
206 if ( aPixOffset.X() < 0 &&
207 aPixOffset.X() + aTotPixSz.Width() < aOutPixSz.Width() )
208 aPixDelta.Width() =
209 aOutPixSz.Width() - ( aPixOffset.X() + aTotPixSz.Width() );
210 if ( aPixOffset.Y() < 0 &&
211 aPixOffset.Y() + aTotPixSz.Height() < aOutPixSz.Height() )
212 aPixDelta.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 )
223 aPixOffset = Point(
224 bHVisible
225 ? aPixOffset.X()
226 : ( bHCenter
227 ? (aOutPixSz.Width()-aTotPixSz.Width()) / 2
228 : 0 ),
229 bVVisible
230 ? aPixOffset.Y()
231 : ( bVCenter
232 ? (aOutPixSz.Height()-aTotPixSz.Height()) / 2
233 : 0 ) );
235 if ( bHVisible && !aHScroll->IsVisible() )
236 aPixOffset.X() = 0;
237 if ( bVVisible && !aVScroll->IsVisible() )
238 aPixOffset.Y() = 0;
240 // select the shifted map-mode
241 if ( aPixOffset != aOldPixOffset )
243 Window::SetMapMode( MapMode( MAP_PIXEL ) );
244 Window::Scroll(
245 aPixOffset.X() - aOldPixOffset.X(),
246 aPixOffset.Y() - aOldPixOffset.Y() );
247 SetMapMode( aMap );
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) );
259 aCornerWin->Show();
261 else
262 aCornerWin->Hide();
264 // resize scrollbars and set their ranges
265 if ( bHVisible )
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() );
276 if ( bVVisible )
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 ) );
304 return aMap;
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?
326 if ( nDeltaX != 0 )
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?
336 if ( nDeltaY != 0 )
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;
353 // scrolling?
354 if ( nDeltaX != 0 || nDeltaY != 0 )
356 Update();
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
363 SetMapMode( aMap );
365 // never scroll the scrollbars itself!
366 Window::Scroll(-nDeltaX, -nDeltaY,
367 PixelToLogic( Rectangle( Point(0, 0), aOutPixSz ) ) );
369 else
371 // repaint all
372 SetMapMode( aMap );
373 Invalidate();
376 Update();
379 if ( !bScrolling )
381 if ( nDeltaX )
382 aHScroll->SetThumbPos( -aPixOffset.X() );
383 if ( nDeltaY )
384 aVScroll->SetThumbPos( -aPixOffset.Y() );
389 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */