Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 :
21 : #define _SVT_SCRWIN_CXX
22 : #include <svtools/scrwin.hxx>
23 :
24 : //===================================================================
25 :
26 4 : void ScrollableWindow::ImpInitialize( ScrollableWindowFlags nFlags )
27 : {
28 4 : bHandleDragging = (sal_Bool) ( nFlags & SCRWIN_THUMBDRAGGING );
29 4 : bVCenter = (nFlags & SCRWIN_VCENTER) == SCRWIN_VCENTER;
30 4 : bHCenter = (nFlags & SCRWIN_HCENTER) == SCRWIN_HCENTER;
31 4 : bScrolling = sal_False;
32 :
33 : // set the handlers for the scrollbars
34 4 : aVScroll.SetScrollHdl( LINK(this, ScrollableWindow, ScrollHdl) );
35 4 : aHScroll.SetScrollHdl( LINK(this, ScrollableWindow, ScrollHdl) );
36 4 : aVScroll.SetEndScrollHdl( LINK(this, ScrollableWindow, EndScrollHdl) );
37 4 : aHScroll.SetEndScrollHdl( LINK(this, ScrollableWindow, EndScrollHdl) );
38 :
39 4 : nColumnPixW = nLinePixH = GetSettings().GetStyleSettings().GetScrollBarSize();
40 4 : }
41 :
42 : //-------------------------------------------------------------------
43 :
44 4 : ScrollableWindow::ScrollableWindow( Window* pParent, WinBits nBits,
45 : ScrollableWindowFlags nFlags ) :
46 : Window( pParent, WinBits(nBits|WB_CLIPCHILDREN) ),
47 : aVScroll( this, WinBits(WB_VSCROLL | WB_DRAG) ),
48 : aHScroll( this, WinBits(WB_HSCROLL | WB_DRAG) ),
49 4 : aCornerWin( this )
50 : {
51 4 : ImpInitialize( nFlags );
52 4 : }
53 :
54 : // -----------------------------------------------------------------------
55 :
56 0 : void ScrollableWindow::Command( const CommandEvent& rCEvt )
57 : {
58 0 : if ( (rCEvt.GetCommand() == COMMAND_WHEEL) ||
59 0 : (rCEvt.GetCommand() == COMMAND_STARTAUTOSCROLL) ||
60 0 : (rCEvt.GetCommand() == COMMAND_AUTOSCROLL) )
61 : {
62 : ScrollBar* pHScrBar;
63 : ScrollBar* pVScrBar;
64 0 : if ( aHScroll.IsVisible() )
65 0 : pHScrBar = &aHScroll;
66 : else
67 0 : pHScrBar = NULL;
68 0 : if ( aVScroll.IsVisible() )
69 0 : pVScrBar = &aVScroll;
70 : else
71 0 : pVScrBar = NULL;
72 0 : if ( HandleScrollCommand( rCEvt, pHScrBar, pVScrBar ) )
73 0 : return;
74 : }
75 :
76 0 : Window::Command( rCEvt );
77 : }
78 :
79 : //-------------------------------------------------------------------
80 :
81 0 : void ScrollableWindow::DataChanged( const DataChangedEvent& rDCEvt )
82 : {
83 0 : if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
84 0 : (rDCEvt.GetFlags() & SETTINGS_STYLE) )
85 : {
86 0 : Resize();
87 0 : Invalidate();
88 : }
89 :
90 0 : Window::DataChanged( rDCEvt );
91 0 : }
92 :
93 : //-------------------------------------------------------------------
94 :
95 0 : Size ScrollableWindow::GetOutputSizePixel() const
96 : {
97 0 : Size aSz( Window::GetOutputSizePixel() );
98 :
99 0 : long nTmp = GetSettings().GetStyleSettings().GetScrollBarSize();
100 0 : if ( aHScroll.IsVisible() )
101 0 : aSz.Height() -= nTmp;
102 0 : if ( aVScroll.IsVisible() )
103 0 : aSz.Width() -= nTmp;
104 0 : return aSz;
105 : }
106 :
107 : //-------------------------------------------------------------------
108 :
109 0 : IMPL_LINK( ScrollableWindow, EndScrollHdl, ScrollBar *, pScroll )
110 : {
111 : // notify the start of scrolling, if not already scrolling
112 0 : if ( !bScrolling )
113 0 : StartScroll(), bScrolling = sal_True;
114 :
115 : // get the delta in logic coordinates
116 0 : Size aDelta( PixelToLogic( Size( aHScroll.GetDelta(), aVScroll.GetDelta() ) ) );
117 :
118 : // scroll the window, if this is not already done
119 0 : if ( !bHandleDragging )
120 : {
121 0 : if ( pScroll == &aHScroll )
122 0 : Scroll( aDelta.Width(), 0 );
123 : else
124 0 : Scroll( 0, aDelta.Height() );
125 : }
126 :
127 : // notify the end of scrolling
128 0 : bScrolling = sal_False;
129 0 : EndScroll( aDelta.Width(), aDelta.Height() );
130 0 : return 0;
131 : }
132 :
133 : //-------------------------------------------------------------------
134 :
135 0 : IMPL_LINK( ScrollableWindow, ScrollHdl, ScrollBar *, pScroll )
136 : {
137 : // notify the start of scrolling, if not already scrolling
138 0 : if ( !bScrolling )
139 0 : StartScroll(), bScrolling = sal_True;
140 :
141 0 : if ( bHandleDragging )
142 : {
143 : // get the delta in logic coordinates
144 : Size aDelta( PixelToLogic(
145 0 : Size( aHScroll.GetDelta(), aVScroll.GetDelta() ) ) );
146 0 : if ( pScroll == &aHScroll )
147 0 : Scroll( aDelta.Width(), 0 );
148 : else
149 0 : Scroll( 0, aDelta.Height() );
150 : }
151 0 : return 0;
152 : }
153 :
154 : //-------------------------------------------------------------------
155 :
156 16 : void ScrollableWindow::Resize()
157 : {
158 : // get the new output-size in pixel
159 16 : Size aOutPixSz = Window::GetOutputSizePixel();
160 :
161 : // determine the size of the output-area and if we need scrollbars
162 16 : const long nScrSize = GetSettings().GetStyleSettings().GetScrollBarSize();
163 16 : sal_Bool bVVisible = sal_False; // by default no vertical-ScrollBar
164 16 : sal_Bool bHVisible = sal_False; // by default no horizontal-ScrollBar
165 : sal_Bool bChanged; // determines if a visiblility was changed
166 24 : do
167 : {
168 24 : bChanged = sal_False;
169 :
170 : // does we need a vertical ScrollBar
171 24 : if ( aOutPixSz.Width() < aTotPixSz.Width() && !bHVisible )
172 8 : { bHVisible = sal_True;
173 8 : aOutPixSz.Height() -= nScrSize;
174 8 : bChanged = sal_True;
175 : }
176 :
177 : // does we need a horizontal ScrollBar
178 24 : if ( aOutPixSz.Height() < aTotPixSz.Height() && !bVVisible )
179 8 : { bVVisible = sal_True;
180 8 : aOutPixSz.Width() -= nScrSize;
181 8 : bChanged = sal_True;
182 : }
183 :
184 : }
185 : while ( bChanged ); // until no visibility has changed
186 :
187 : // store the old offset and map-mode
188 16 : MapMode aMap( GetMapMode() );
189 16 : Point aOldPixOffset( aPixOffset );
190 :
191 : // justify (right/bottom borders should never exceed the virtual window)
192 16 : Size aPixDelta;
193 16 : if ( aPixOffset.X() < 0 &&
194 0 : aPixOffset.X() + aTotPixSz.Width() < aOutPixSz.Width() )
195 0 : aPixDelta.Width() =
196 0 : aOutPixSz.Width() - ( aPixOffset.X() + aTotPixSz.Width() );
197 16 : if ( aPixOffset.Y() < 0 &&
198 0 : aPixOffset.Y() + aTotPixSz.Height() < aOutPixSz.Height() )
199 0 : aPixDelta.Height() =
200 0 : aOutPixSz.Height() - ( aPixOffset.Y() + aTotPixSz.Height() );
201 16 : if ( aPixDelta.Width() || aPixDelta.Height() )
202 : {
203 0 : aPixOffset.X() += aPixDelta.Width();
204 0 : aPixOffset.Y() += aPixDelta.Height();
205 : }
206 :
207 : // for axis without scrollbar restore the origin
208 16 : if ( !bVVisible || !bHVisible )
209 : {
210 : aPixOffset = Point(
211 : bHVisible
212 0 : ? aPixOffset.X()
213 : : ( bHCenter
214 16 : ? (aOutPixSz.Width()-aTotPixSz.Width()) / 2
215 : : 0 ),
216 : bVVisible
217 0 : ? aPixOffset.Y()
218 : : ( bVCenter
219 16 : ? (aOutPixSz.Height()-aTotPixSz.Height()) / 2
220 40 : : 0 ) );
221 : }
222 16 : if ( bHVisible && !aHScroll.IsVisible() )
223 4 : aPixOffset.X() = 0;
224 16 : if ( bVVisible && !aVScroll.IsVisible() )
225 4 : aPixOffset.Y() = 0;
226 :
227 : // select the shifted map-mode
228 16 : if ( aPixOffset != aOldPixOffset )
229 : {
230 8 : Window::SetMapMode( MapMode( MAP_PIXEL ) );
231 : Window::Scroll(
232 16 : aPixOffset.X() - aOldPixOffset.X(),
233 24 : aPixOffset.Y() - aOldPixOffset.Y() );
234 8 : SetMapMode( aMap );
235 : }
236 :
237 : // show or hide scrollbars
238 16 : aVScroll.Show( bVVisible );
239 16 : aHScroll.Show( bHVisible );
240 :
241 : // disable painting in the corner between the scrollbars
242 16 : if ( bVVisible && bHVisible )
243 : {
244 16 : aCornerWin.SetPosSizePixel(Point(aOutPixSz.Width(), aOutPixSz.Height()),
245 24 : Size(nScrSize, nScrSize) );
246 8 : aCornerWin.Show();
247 : }
248 : else
249 8 : aCornerWin.Hide();
250 :
251 : // resize scrollbars and set their ranges
252 16 : if ( bHVisible )
253 : {
254 : aHScroll.SetPosSizePixel(
255 8 : Point( 0, aOutPixSz.Height() ),
256 16 : Size( aOutPixSz.Width(), nScrSize ) );
257 8 : aHScroll.SetRange( Range( 0, aTotPixSz.Width() ) );
258 8 : aHScroll.SetPageSize( aOutPixSz.Width() );
259 8 : aHScroll.SetVisibleSize( aOutPixSz.Width() );
260 8 : aHScroll.SetLineSize( nColumnPixW );
261 8 : aHScroll.SetThumbPos( -aPixOffset.X() );
262 : }
263 16 : if ( bVVisible )
264 : {
265 : aVScroll.SetPosSizePixel(
266 8 : Point( aOutPixSz.Width(), 0 ),
267 16 : Size( nScrSize,aOutPixSz.Height() ) );
268 8 : aVScroll.SetRange( Range( 0, aTotPixSz.Height() ) );
269 8 : aVScroll.SetPageSize( aOutPixSz.Height() );
270 8 : aVScroll.SetVisibleSize( aOutPixSz.Height() );
271 8 : aVScroll.SetLineSize( nLinePixH );
272 8 : aVScroll.SetThumbPos( -aPixOffset.Y() );
273 16 : }
274 16 : }
275 :
276 : //-------------------------------------------------------------------
277 :
278 0 : void ScrollableWindow::StartScroll()
279 : {
280 0 : }
281 :
282 : //-------------------------------------------------------------------
283 :
284 0 : void ScrollableWindow::EndScroll( long, long )
285 : {
286 0 : }
287 :
288 : //-------------------------------------------------------------------
289 :
290 24 : void ScrollableWindow::SetMapMode( const MapMode& rNewMapMode )
291 : {
292 24 : MapMode aMap( rNewMapMode );
293 24 : aMap.SetOrigin( aMap.GetOrigin() + PixelToLogic( aPixOffset, aMap ) );
294 24 : Window::SetMapMode( aMap );
295 24 : }
296 :
297 : //-------------------------------------------------------------------
298 :
299 16 : MapMode ScrollableWindow::GetMapMode() const
300 : {
301 16 : MapMode aMap( Window::GetMapMode() );
302 16 : aMap.SetOrigin( aMap.GetOrigin() - PixelToLogic( aPixOffset ) );
303 16 : return aMap;
304 : }
305 :
306 : //-------------------------------------------------------------------
307 :
308 11 : void ScrollableWindow::SetTotalSize( const Size& rNewSize )
309 : {
310 11 : aTotPixSz = LogicToPixel( rNewSize );
311 11 : ScrollableWindow::Resize();
312 11 : }
313 :
314 : //-------------------------------------------------------------------
315 :
316 0 : void ScrollableWindow::Scroll( long nDeltaX, long nDeltaY, sal_uInt16 )
317 : {
318 0 : if ( !bScrolling )
319 0 : StartScroll();
320 :
321 : // get the delta in pixel
322 0 : Size aDeltaPix( LogicToPixel( Size(nDeltaX, nDeltaY) ) );
323 0 : Size aOutPixSz( GetOutputSizePixel() );
324 0 : MapMode aMap( GetMapMode() );
325 0 : Point aNewPixOffset( aPixOffset );
326 :
327 : // scrolling horizontally?
328 0 : if ( nDeltaX != 0 )
329 : {
330 0 : aNewPixOffset.X() -= aDeltaPix.Width();
331 0 : if ( ( aOutPixSz.Width() - aNewPixOffset.X() ) > aTotPixSz.Width() )
332 0 : aNewPixOffset.X() = - ( aTotPixSz.Width() - aOutPixSz.Width() );
333 0 : else if ( aNewPixOffset.X() > 0 )
334 0 : aNewPixOffset.X() = 0;
335 : }
336 :
337 : // scrolling vertically?
338 0 : if ( nDeltaY != 0 )
339 : {
340 0 : aNewPixOffset.Y() -= aDeltaPix.Height();
341 0 : if ( ( aOutPixSz.Height() - aNewPixOffset.Y() ) > aTotPixSz.Height() )
342 0 : aNewPixOffset.Y() = - ( aTotPixSz.Height() - aOutPixSz.Height() );
343 0 : else if ( aNewPixOffset.Y() > 0 )
344 0 : aNewPixOffset.Y() = 0;
345 : }
346 :
347 : // recompute the logical scroll units
348 0 : aDeltaPix.Width() = aPixOffset.X() - aNewPixOffset.X();
349 0 : aDeltaPix.Height() = aPixOffset.Y() - aNewPixOffset.Y();
350 0 : Size aDelta( PixelToLogic(aDeltaPix) );
351 0 : nDeltaX = aDelta.Width();
352 0 : nDeltaY = aDelta.Height();
353 0 : aPixOffset = aNewPixOffset;
354 :
355 : // scrolling?
356 0 : if ( nDeltaX != 0 || nDeltaY != 0 )
357 : {
358 0 : Update();
359 :
360 : // does the new area overlap the old one?
361 0 : if ( Abs( (int)aDeltaPix.Height() ) < aOutPixSz.Height() ||
362 0 : Abs( (int)aDeltaPix.Width() ) < aOutPixSz.Width() )
363 : {
364 : // scroll the overlapping area
365 0 : SetMapMode( aMap );
366 :
367 : // never scroll the scrollbars itself!
368 : Window::Scroll(-nDeltaX, -nDeltaY,
369 0 : PixelToLogic( Rectangle( Point(0, 0), aOutPixSz ) ) );
370 : }
371 : else
372 : {
373 : // repaint all
374 0 : SetMapMode( aMap );
375 0 : Invalidate();
376 : }
377 :
378 0 : Update();
379 : }
380 :
381 0 : if ( !bScrolling )
382 : {
383 0 : EndScroll( nDeltaX, nDeltaY );
384 0 : if ( nDeltaX )
385 0 : aHScroll.SetThumbPos( -aPixOffset.X() );
386 0 : if ( nDeltaY )
387 0 : aVScroll.SetThumbPos( -aPixOffset.Y() );
388 0 : }
389 0 : }
390 :
391 :
392 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|