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 : #include <tools/rc.h>
21 : #include <vcl/event.hxx>
22 : #include <vcl/decoview.hxx>
23 : #include <vcl/slider.hxx>
24 : #include <vcl/settings.hxx>
25 :
26 : #include "thumbpos.hxx"
27 :
28 : #define SLIDER_DRAW_THUMB ((sal_uInt16)0x0001)
29 : #define SLIDER_DRAW_CHANNEL1 ((sal_uInt16)0x0002)
30 : #define SLIDER_DRAW_CHANNEL2 ((sal_uInt16)0x0004)
31 : #define SLIDER_DRAW_CHANNEL (SLIDER_DRAW_CHANNEL1 | SLIDER_DRAW_CHANNEL2)
32 : #define SLIDER_DRAW_ALL (SLIDER_DRAW_THUMB | SLIDER_DRAW_CHANNEL)
33 :
34 : #define SLIDER_STATE_CHANNEL1_DOWN ((sal_uInt16)0x0001)
35 : #define SLIDER_STATE_CHANNEL2_DOWN ((sal_uInt16)0x0002)
36 : #define SLIDER_STATE_THUMB_DOWN ((sal_uInt16)0x0004)
37 :
38 : #define SLIDER_THUMB_SIZE 9
39 : #define SLIDER_THUMB_HALFSIZE 4
40 : #define SLIDER_CHANNEL_OFFSET 0
41 : #define SLIDER_CHANNEL_SIZE 4
42 : #define SLIDER_CHANNEL_HALFSIZE 2
43 :
44 : #define SLIDER_HEIGHT 16
45 :
46 : #define SLIDER_VIEW_STYLE (WB_3DLOOK | WB_HORZ | WB_VERT)
47 :
48 0 : void Slider::ImplInit( vcl::Window* pParent, WinBits nStyle )
49 : {
50 0 : mnThumbPixOffset = 0;
51 0 : mnThumbPixRange = 0;
52 0 : mnThumbPixPos = 0; // between mnThumbPixOffset and mnThumbPixOffset+mnThumbPixRange
53 0 : mnChannelPixOffset = 0;
54 0 : mnChannelPixRange = 0;
55 0 : mnChannelPixTop = 0;
56 0 : mnChannelPixBottom = 0;
57 :
58 0 : mnMinRange = 0;
59 0 : mnMaxRange = 100;
60 0 : mnThumbPos = 0;
61 0 : mnLineSize = 1;
62 0 : mnPageSize = 1;
63 0 : mnDelta = 0;
64 0 : mnDragDraw = 0;
65 0 : mnDrawFlags = SLIDER_DRAW_ALL;
66 0 : mnStateFlags = 0;
67 0 : meScrollType = SCROLL_DONTKNOW;
68 0 : mbCalcSize = true;
69 0 : mbFullDrag = true;
70 :
71 0 : mpLinkedField = nullptr;
72 :
73 0 : Control::ImplInit( pParent, nStyle, NULL );
74 :
75 0 : ImplInitSettings();
76 0 : SetSizePixel( CalcWindowSizePixel() );
77 0 : }
78 :
79 0 : Slider::Slider( vcl::Window* pParent, WinBits nStyle ) :
80 0 : Control(WINDOW_SLIDER)
81 : {
82 0 : ImplInit( pParent, nStyle );
83 0 : }
84 :
85 0 : Slider::~Slider()
86 : {
87 0 : disposeOnce();
88 0 : }
89 :
90 0 : void Slider::dispose()
91 : {
92 0 : mpLinkedField.clear();
93 0 : Control::dispose();
94 0 : }
95 :
96 0 : void Slider::ImplInitSettings()
97 : {
98 0 : vcl::Window* pParent = GetParent();
99 0 : if ( pParent->IsChildTransparentModeEnabled() && !IsControlBackground() )
100 : {
101 0 : EnableChildTransparentMode( true );
102 0 : SetParentClipMode( ParentClipMode::NoClip );
103 0 : SetPaintTransparent( true );
104 0 : SetBackground();
105 : }
106 : else
107 : {
108 0 : EnableChildTransparentMode( false );
109 0 : SetParentClipMode( ParentClipMode::NONE );
110 0 : SetPaintTransparent( false );
111 :
112 0 : if ( IsControlBackground() )
113 0 : SetBackground( GetControlBackground() );
114 : else
115 0 : SetBackground( pParent->GetBackground() );
116 : }
117 0 : }
118 :
119 0 : void Slider::ImplUpdateRects( bool bUpdate )
120 : {
121 0 : Rectangle aOldThumbRect = maThumbRect;
122 0 : bool bInvalidateAll = false;
123 :
124 0 : if ( mnThumbPixRange )
125 : {
126 0 : if ( GetStyle() & WB_HORZ )
127 : {
128 0 : maThumbRect.Left() = mnThumbPixPos-SLIDER_THUMB_HALFSIZE;
129 0 : maThumbRect.Right() = maThumbRect.Left()+SLIDER_THUMB_SIZE-1;
130 0 : if ( mnChannelPixOffset < maThumbRect.Left() )
131 : {
132 0 : maChannel1Rect.Left() = mnChannelPixOffset;
133 0 : maChannel1Rect.Right() = maThumbRect.Left()-1;
134 0 : maChannel1Rect.Top() = mnChannelPixTop;
135 0 : maChannel1Rect.Bottom() = mnChannelPixBottom;
136 : }
137 : else
138 0 : maChannel1Rect.SetEmpty();
139 0 : if ( mnChannelPixOffset+mnChannelPixRange-1 > maThumbRect.Right() )
140 : {
141 0 : maChannel2Rect.Left() = maThumbRect.Right()+1;
142 0 : maChannel2Rect.Right() = mnChannelPixOffset+mnChannelPixRange-1;
143 0 : maChannel2Rect.Top() = mnChannelPixTop;
144 0 : maChannel2Rect.Bottom() = mnChannelPixBottom;
145 : }
146 : else
147 0 : maChannel2Rect.SetEmpty();
148 :
149 0 : const Rectangle aControlRegion( Rectangle( Point(0,0), Size( SLIDER_THUMB_SIZE, 10 ) ) );
150 0 : Rectangle aThumbBounds, aThumbContent;
151 0 : if ( GetNativeControlRegion( CTRL_SLIDER, PART_THUMB_HORZ,
152 : aControlRegion, ControlState::NONE, ImplControlValue(), OUString(),
153 0 : aThumbBounds, aThumbContent ) )
154 : {
155 0 : maThumbRect.Left() = mnThumbPixPos - aThumbBounds.GetWidth()/2;
156 0 : maThumbRect.Right() = maThumbRect.Left() + aThumbBounds.GetWidth() - 1;
157 0 : bInvalidateAll = true;
158 : }
159 : }
160 : else
161 : {
162 0 : maThumbRect.Top() = mnThumbPixPos-SLIDER_THUMB_HALFSIZE;
163 0 : maThumbRect.Bottom() = maThumbRect.Top()+SLIDER_THUMB_SIZE-1;
164 0 : if ( mnChannelPixOffset < maThumbRect.Top() )
165 : {
166 0 : maChannel1Rect.Top() = mnChannelPixOffset;
167 0 : maChannel1Rect.Bottom() = maThumbRect.Top()-1;
168 0 : maChannel1Rect.Left() = mnChannelPixTop;
169 0 : maChannel1Rect.Right() = mnChannelPixBottom;
170 : }
171 : else
172 0 : maChannel1Rect.SetEmpty();
173 0 : if ( mnChannelPixOffset+mnChannelPixRange-1 > maThumbRect.Bottom() )
174 : {
175 0 : maChannel2Rect.Top() = maThumbRect.Bottom()+1;
176 0 : maChannel2Rect.Bottom() = mnChannelPixOffset+mnChannelPixRange-1;
177 0 : maChannel2Rect.Left() = mnChannelPixTop;
178 0 : maChannel2Rect.Right() = mnChannelPixBottom;
179 : }
180 : else
181 0 : maChannel2Rect.SetEmpty();
182 :
183 0 : const Rectangle aControlRegion( Rectangle( Point(0,0), Size( 10, SLIDER_THUMB_SIZE ) ) );
184 0 : Rectangle aThumbBounds, aThumbContent;
185 0 : if ( GetNativeControlRegion( CTRL_SLIDER, PART_THUMB_VERT,
186 : aControlRegion, ControlState::NONE, ImplControlValue(), OUString(),
187 0 : aThumbBounds, aThumbContent ) )
188 : {
189 0 : maThumbRect.Top() = mnThumbPixPos - aThumbBounds.GetHeight()/2;
190 0 : maThumbRect.Bottom() = maThumbRect.Top() + aThumbBounds.GetHeight() - 1;
191 0 : bInvalidateAll = true;
192 : }
193 : }
194 : }
195 : else
196 : {
197 0 : maChannel1Rect.SetEmpty();
198 0 : maChannel2Rect.SetEmpty();
199 0 : maThumbRect.SetEmpty();
200 : }
201 :
202 0 : if ( bUpdate )
203 : {
204 0 : if ( aOldThumbRect != maThumbRect )
205 : {
206 0 : mnDrawFlags = SLIDER_DRAW_ALL;
207 0 : if( bInvalidateAll )
208 0 : Invalidate();
209 : else
210 : {
211 0 : vcl::Region aInvalidRegion( aOldThumbRect );
212 0 : aInvalidRegion.Union( maThumbRect );
213 :
214 0 : if( !IsBackground() && GetParent() )
215 : {
216 0 : const Point aPos( GetPosPixel() );
217 0 : aInvalidRegion.Move( aPos.X(), aPos.Y() );
218 0 : GetParent()->Invalidate( aInvalidRegion, InvalidateFlags::Transparent | InvalidateFlags::Update );
219 : }
220 : else
221 0 : Invalidate( aInvalidRegion );
222 : }
223 : }
224 : }
225 0 : }
226 :
227 0 : void Slider::ImplSetFieldLink(const Link<>& rLink)
228 : {
229 0 : if (mpLinkedField != nullptr)
230 : {
231 0 : mpLinkedField->SetModifyHdl(rLink);
232 0 : mpLinkedField->SetUpHdl(rLink);
233 0 : mpLinkedField->SetDownHdl(rLink);
234 0 : mpLinkedField->SetFirstHdl(rLink);
235 0 : mpLinkedField->SetLastHdl(rLink);
236 0 : mpLinkedField->SetLoseFocusHdl(rLink);
237 : }
238 0 : }
239 :
240 0 : void Slider::ImplUpdateLinkedField()
241 : {
242 0 : if (mpLinkedField)
243 0 : mpLinkedField->SetValue(mnThumbPos);
244 0 : }
245 :
246 0 : IMPL_LINK(Slider, LinkedFieldModifyHdl, NumericField*, pField)
247 : {
248 0 : if (pField)
249 : {
250 0 : SetThumbPos(pField->GetValue());
251 : }
252 0 : return 0;
253 : }
254 :
255 0 : long Slider::ImplCalcThumbPos( long nPixPos )
256 : {
257 : // calculate position
258 : long nCalcThumbPos;
259 0 : nCalcThumbPos = ImplMulDiv( nPixPos-mnThumbPixOffset, mnMaxRange-mnMinRange, mnThumbPixRange-1 );
260 0 : nCalcThumbPos += mnMinRange;
261 0 : return nCalcThumbPos;
262 : }
263 :
264 0 : long Slider::ImplCalcThumbPosPix( long nPos )
265 : {
266 : // calculate position
267 : long nCalcThumbPos;
268 0 : nCalcThumbPos = ImplMulDiv( nPos-mnMinRange, mnThumbPixRange-1, mnMaxRange-mnMinRange );
269 : // at the beginning and end we try to display Slider correctly
270 0 : if ( !nCalcThumbPos && (mnThumbPos > mnMinRange) )
271 0 : nCalcThumbPos = 1;
272 0 : if ( nCalcThumbPos &&
273 0 : (nCalcThumbPos == mnThumbPixRange-1) &&
274 0 : (mnThumbPos < mnMaxRange) )
275 0 : nCalcThumbPos--;
276 0 : return nCalcThumbPos+mnThumbPixOffset;
277 : }
278 :
279 0 : void Slider::ImplCalc( bool bUpdate )
280 : {
281 0 : bool bInvalidateAll = false;
282 :
283 0 : if ( mbCalcSize )
284 : {
285 0 : long nOldChannelPixOffset = mnChannelPixOffset;
286 0 : long nOldChannelPixRange = mnChannelPixRange;
287 0 : long nOldChannelPixTop = mnChannelPixTop;
288 0 : long nOldChannelPixBottom = mnChannelPixBottom;
289 : long nCalcWidth;
290 : long nCalcHeight;
291 :
292 0 : maChannel1Rect.SetEmpty();
293 0 : maChannel2Rect.SetEmpty();
294 0 : maThumbRect.SetEmpty();
295 :
296 0 : Size aSize = GetOutputSizePixel();
297 0 : if ( GetStyle() & WB_HORZ )
298 : {
299 0 : nCalcWidth = aSize.Width();
300 0 : nCalcHeight = aSize.Height();
301 0 : maThumbRect.Top() = 0;
302 0 : maThumbRect.Bottom()= aSize.Height()-1;
303 : }
304 : else
305 : {
306 0 : nCalcWidth = aSize.Height();
307 0 : nCalcHeight = aSize.Width();
308 0 : maThumbRect.Left() = 0;
309 0 : maThumbRect.Right() = aSize.Width()-1;
310 : }
311 :
312 0 : if ( nCalcWidth >= SLIDER_THUMB_SIZE )
313 : {
314 0 : mnThumbPixOffset = SLIDER_THUMB_HALFSIZE;
315 0 : mnThumbPixRange = nCalcWidth-(SLIDER_THUMB_HALFSIZE*2);
316 0 : mnThumbPixPos = 0;
317 0 : mnChannelPixOffset = SLIDER_CHANNEL_OFFSET;
318 0 : mnChannelPixRange = nCalcWidth-(SLIDER_CHANNEL_OFFSET*2);
319 0 : mnChannelPixTop = (nCalcHeight/2)-SLIDER_CHANNEL_HALFSIZE;
320 0 : mnChannelPixBottom = mnChannelPixTop+SLIDER_CHANNEL_SIZE-1;
321 : }
322 : else
323 : {
324 0 : mnThumbPixRange = 0;
325 0 : mnChannelPixRange = 0;
326 : }
327 :
328 0 : if ( (nOldChannelPixOffset != mnChannelPixOffset) ||
329 0 : (nOldChannelPixRange != mnChannelPixRange) ||
330 0 : (nOldChannelPixTop != mnChannelPixTop) ||
331 0 : (nOldChannelPixBottom != mnChannelPixBottom) )
332 0 : bInvalidateAll = true;
333 :
334 0 : mbCalcSize = false;
335 : }
336 :
337 0 : if ( mnThumbPixRange )
338 0 : mnThumbPixPos = ImplCalcThumbPosPix( mnThumbPos );
339 :
340 0 : if ( bUpdate && bInvalidateAll )
341 : {
342 0 : mnDrawFlags = SLIDER_DRAW_ALL;
343 0 : Invalidate();
344 0 : bUpdate = false;
345 : }
346 0 : ImplUpdateRects( bUpdate );
347 0 : }
348 :
349 0 : void Slider::ImplDraw(vcl::RenderContext& rRenderContext, sal_uInt16 nDrawFlags)
350 : {
351 0 : DecorationView aDecoView(&rRenderContext);
352 : DrawButtonFlags nStyle;
353 0 : const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
354 0 : bool bEnabled = IsEnabled();
355 :
356 : // do missing calculations
357 0 : if (mbCalcSize)
358 0 : ImplCalc(false);
359 :
360 0 : ControlPart nPart = (GetStyle() & WB_HORZ) ? PART_TRACK_HORZ_AREA : PART_TRACK_VERT_AREA;
361 0 : ControlState nState = (IsEnabled() ? ControlState::ENABLED : ControlState::NONE);
362 0 : nState |= (HasFocus() ? ControlState::FOCUSED : ControlState::NONE);
363 0 : SliderValue sldValue;
364 :
365 0 : sldValue.mnMin = mnMinRange;
366 0 : sldValue.mnMax = mnMaxRange;
367 0 : sldValue.mnCur = mnThumbPos;
368 0 : sldValue.maThumbRect = maThumbRect;
369 :
370 0 : if (IsMouseOver())
371 : {
372 0 : if (maThumbRect.IsInside(GetPointerPosPixel()))
373 0 : sldValue.mnThumbState |= ControlState::ROLLOVER;
374 : }
375 :
376 0 : const Rectangle aCtrlRegion(Point(0,0), rRenderContext.GetOutputSizePixel());
377 0 : bool bNativeOK = rRenderContext.DrawNativeControl(CTRL_SLIDER, nPart, aCtrlRegion, nState, sldValue, OUString());
378 0 : if (bNativeOK)
379 0 : return;
380 :
381 0 : if ((nDrawFlags & SLIDER_DRAW_CHANNEL1) && !maChannel1Rect.IsEmpty())
382 : {
383 : long nRectSize;
384 0 : Rectangle aRect = maChannel1Rect;
385 0 : rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
386 0 : if (GetStyle() & WB_HORZ)
387 : {
388 0 : rRenderContext.DrawLine(aRect.TopLeft(), Point(aRect.Left(), aRect.Bottom() - 1));
389 0 : rRenderContext.DrawLine(aRect.TopLeft(), aRect.TopRight());
390 : }
391 : else
392 : {
393 0 : rRenderContext.DrawLine(aRect.TopLeft(), Point(aRect.Right() - 1, aRect.Top()));
394 0 : rRenderContext.DrawLine(aRect.TopLeft(), aRect.BottomLeft());
395 : }
396 0 : rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
397 0 : if (GetStyle() & WB_HORZ)
398 : {
399 0 : rRenderContext.DrawLine(aRect.BottomLeft(), aRect.BottomRight());
400 0 : nRectSize = aRect.GetWidth();
401 : }
402 : else
403 : {
404 0 : rRenderContext.DrawLine(aRect.TopRight(), aRect.BottomRight());
405 0 : nRectSize = aRect.GetHeight();
406 : }
407 :
408 0 : if (nRectSize > 1)
409 : {
410 0 : aRect.Left()++;
411 0 : aRect.Top()++;
412 0 : if (GetStyle() & WB_HORZ)
413 0 : aRect.Bottom()--;
414 : else
415 0 : aRect.Right()--;
416 0 : rRenderContext.SetLineColor();
417 0 : if (mnStateFlags & SLIDER_STATE_CHANNEL1_DOWN)
418 0 : rRenderContext.SetFillColor(rStyleSettings.GetShadowColor());
419 : else
420 0 : rRenderContext.SetFillColor(rStyleSettings.GetCheckedColor());
421 0 : rRenderContext.DrawRect(aRect);
422 : }
423 : }
424 :
425 0 : if ((nDrawFlags & SLIDER_DRAW_CHANNEL2) && !maChannel2Rect.IsEmpty())
426 : {
427 : long nRectSize;
428 0 : Rectangle aRect = maChannel2Rect;
429 0 : rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
430 0 : if (GetStyle() & WB_HORZ)
431 : {
432 0 : rRenderContext.DrawLine(aRect.TopRight(), aRect.BottomRight());
433 0 : rRenderContext.DrawLine(aRect.BottomLeft(), aRect.BottomRight());
434 0 : nRectSize = aRect.GetWidth();
435 : }
436 : else
437 : {
438 0 : rRenderContext.DrawLine(aRect.BottomLeft(), aRect.BottomRight());
439 0 : rRenderContext.DrawLine(aRect.TopRight(), aRect.BottomRight());
440 0 : nRectSize = aRect.GetHeight();
441 : }
442 :
443 0 : if (nRectSize > 1)
444 : {
445 0 : rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
446 0 : if (GetStyle() & WB_HORZ)
447 0 : rRenderContext.DrawLine(aRect.TopLeft(), Point(aRect.Right() - 1, aRect.Top()));
448 : else
449 0 : rRenderContext.DrawLine(aRect.TopLeft(), Point(aRect.Left(), aRect.Bottom() - 1));
450 :
451 0 : aRect.Right()--;
452 0 : aRect.Bottom()--;
453 0 : if (GetStyle() & WB_HORZ)
454 0 : aRect.Top()++;
455 : else
456 0 : aRect.Left()++;
457 0 : rRenderContext.SetLineColor();
458 0 : if (mnStateFlags & SLIDER_STATE_CHANNEL2_DOWN)
459 0 : rRenderContext.SetFillColor(rStyleSettings.GetShadowColor());
460 : else
461 0 : rRenderContext.SetFillColor(rStyleSettings.GetCheckedColor());
462 0 : rRenderContext.DrawRect(aRect);
463 : }
464 : }
465 :
466 0 : if (nDrawFlags & SLIDER_DRAW_THUMB)
467 : {
468 0 : if (!maThumbRect.IsEmpty())
469 : {
470 0 : if (bEnabled)
471 : {
472 0 : nStyle = DrawButtonFlags::NONE;
473 0 : if (mnStateFlags & SLIDER_STATE_THUMB_DOWN)
474 0 : nStyle |= DrawButtonFlags::Pressed;
475 0 : aDecoView.DrawButton(maThumbRect, nStyle);
476 : }
477 : else
478 : {
479 0 : rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
480 0 : rRenderContext.SetFillColor(rStyleSettings.GetCheckedColor());
481 0 : rRenderContext.DrawRect(maThumbRect);
482 : }
483 : }
484 0 : }
485 : }
486 :
487 0 : bool Slider::ImplIsPageUp( const Point& rPos )
488 : {
489 0 : Size aSize = GetOutputSizePixel();
490 0 : Rectangle aRect = maChannel1Rect;
491 0 : if ( GetStyle() & WB_HORZ )
492 : {
493 0 : aRect.Top() = 0;
494 0 : aRect.Bottom() = aSize.Height()-1;
495 : }
496 : else
497 : {
498 0 : aRect.Left() = 0;
499 0 : aRect.Right() = aSize.Width()-1;
500 : }
501 0 : return aRect.IsInside( rPos );
502 : }
503 :
504 0 : bool Slider::ImplIsPageDown( const Point& rPos )
505 : {
506 0 : Size aSize = GetOutputSizePixel();
507 0 : Rectangle aRect = maChannel2Rect;
508 0 : if ( GetStyle() & WB_HORZ )
509 : {
510 0 : aRect.Top() = 0;
511 0 : aRect.Bottom() = aSize.Height()-1;
512 : }
513 : else
514 : {
515 0 : aRect.Left() = 0;
516 0 : aRect.Right() = aSize.Width()-1;
517 : }
518 0 : return aRect.IsInside( rPos );
519 : }
520 :
521 0 : long Slider::ImplSlide( long nNewPos, bool bCallEndSlide )
522 : {
523 0 : long nOldPos = mnThumbPos;
524 0 : SetThumbPos( nNewPos );
525 0 : long nDelta = mnThumbPos-nOldPos;
526 0 : if ( nDelta )
527 : {
528 0 : mnDelta = nDelta;
529 0 : Slide();
530 0 : if ( bCallEndSlide )
531 0 : EndSlide();
532 0 : mnDelta = 0;
533 : }
534 0 : return nDelta;
535 : }
536 :
537 0 : long Slider::ImplDoAction( bool bCallEndSlide )
538 : {
539 0 : long nDelta = 0;
540 :
541 0 : switch ( meScrollType )
542 : {
543 : case SCROLL_LINEUP:
544 0 : nDelta = ImplSlide( mnThumbPos-mnLineSize, bCallEndSlide );
545 0 : break;
546 :
547 : case SCROLL_LINEDOWN:
548 0 : nDelta = ImplSlide( mnThumbPos+mnLineSize, bCallEndSlide );
549 0 : break;
550 :
551 : case SCROLL_PAGEUP:
552 0 : nDelta = ImplSlide( mnThumbPos-mnPageSize, bCallEndSlide );
553 0 : break;
554 :
555 : case SCROLL_PAGEDOWN:
556 0 : nDelta = ImplSlide( mnThumbPos+mnPageSize, bCallEndSlide );
557 0 : break;
558 :
559 : case SCROLL_SET:
560 0 : nDelta = ImplSlide( ImplCalcThumbPos( GetPointerPosPixel().X() ), bCallEndSlide );
561 0 : break;
562 : default:
563 0 : break;
564 : }
565 :
566 0 : return nDelta;
567 : }
568 :
569 0 : void Slider::ImplDoMouseAction( const Point& rMousePos, bool bCallAction )
570 : {
571 0 : sal_uInt16 nOldStateFlags = mnStateFlags;
572 0 : bool bAction = false;
573 :
574 0 : switch ( meScrollType )
575 : {
576 : case( SCROLL_SET ):
577 : {
578 0 : const bool bUp = ImplIsPageUp( rMousePos ), bDown = ImplIsPageDown( rMousePos );
579 :
580 0 : if ( bUp || bDown )
581 : {
582 0 : bAction = bCallAction;
583 0 : mnStateFlags |= ( bUp ? SLIDER_STATE_CHANNEL1_DOWN : SLIDER_STATE_CHANNEL2_DOWN );
584 : }
585 : else
586 0 : mnStateFlags &= ~( SLIDER_STATE_CHANNEL1_DOWN | SLIDER_STATE_CHANNEL2_DOWN );
587 0 : break;
588 : }
589 :
590 : case SCROLL_PAGEUP:
591 0 : if ( ImplIsPageUp( rMousePos ) )
592 : {
593 0 : bAction = bCallAction;
594 0 : mnStateFlags |= SLIDER_STATE_CHANNEL1_DOWN;
595 : }
596 : else
597 0 : mnStateFlags &= ~SLIDER_STATE_CHANNEL1_DOWN;
598 0 : break;
599 :
600 : case SCROLL_PAGEDOWN:
601 0 : if ( ImplIsPageDown( rMousePos ) )
602 : {
603 0 : bAction = bCallAction;
604 0 : mnStateFlags |= SLIDER_STATE_CHANNEL2_DOWN;
605 : }
606 : else
607 0 : mnStateFlags &= ~SLIDER_STATE_CHANNEL2_DOWN;
608 0 : break;
609 : default:
610 0 : break;
611 : }
612 :
613 0 : if ( bAction )
614 : {
615 0 : if ( ImplDoAction( false ) )
616 : {
617 : // Update the channel complete
618 0 : if ( mnDragDraw & SLIDER_DRAW_CHANNEL )
619 : {
620 0 : Update();
621 0 : mnDrawFlags = mnDragDraw;
622 0 : Invalidate();
623 : }
624 : }
625 : }
626 0 : else if ( nOldStateFlags != mnStateFlags )
627 : {
628 0 : mnDrawFlags = mnDragDraw;
629 0 : Invalidate();
630 : }
631 0 : }
632 :
633 0 : long Slider::ImplDoSlide( long nNewPos )
634 : {
635 0 : if ( meScrollType != SCROLL_DONTKNOW )
636 0 : return 0;
637 :
638 0 : meScrollType = SCROLL_DRAG;
639 0 : long nDelta = ImplSlide( nNewPos, true );
640 0 : meScrollType = SCROLL_DONTKNOW;
641 0 : return nDelta;
642 : }
643 :
644 0 : long Slider::ImplDoSlideAction( ScrollType eScrollType )
645 : {
646 0 : if ( (meScrollType != SCROLL_DONTKNOW) ||
647 0 : (eScrollType == SCROLL_DONTKNOW) ||
648 : (eScrollType == SCROLL_DRAG) )
649 0 : return 0;
650 :
651 0 : meScrollType = eScrollType;
652 0 : long nDelta = ImplDoAction( true );
653 0 : meScrollType = SCROLL_DONTKNOW;
654 0 : return nDelta;
655 : }
656 :
657 0 : void Slider::MouseButtonDown( const MouseEvent& rMEvt )
658 : {
659 0 : if ( rMEvt.IsLeft() )
660 : {
661 0 : const Point& rMousePos = rMEvt.GetPosPixel();
662 0 : StartTrackingFlags nTrackFlags = StartTrackingFlags::NONE;
663 :
664 0 : if ( maThumbRect.IsInside( rMousePos ) )
665 : {
666 0 : meScrollType = SCROLL_DRAG;
667 0 : mnDragDraw = SLIDER_DRAW_THUMB;
668 :
669 : // calculate additional values
670 0 : Point aCenterPos = maThumbRect.Center();
671 0 : if ( GetStyle() & WB_HORZ )
672 0 : mnMouseOff = rMousePos.X()-aCenterPos.X();
673 : else
674 0 : mnMouseOff = rMousePos.Y()-aCenterPos.Y();
675 : }
676 0 : else if ( ImplIsPageUp( rMousePos ) )
677 : {
678 0 : if( GetStyle() & WB_SLIDERSET )
679 0 : meScrollType = SCROLL_SET;
680 : else
681 : {
682 0 : nTrackFlags = StartTrackingFlags::ButtonRepeat;
683 0 : meScrollType = SCROLL_PAGEUP;
684 : }
685 :
686 0 : mnDragDraw = SLIDER_DRAW_CHANNEL;
687 : }
688 0 : else if ( ImplIsPageDown( rMousePos ) )
689 : {
690 0 : if( GetStyle() & WB_SLIDERSET )
691 0 : meScrollType = SCROLL_SET;
692 : else
693 : {
694 0 : nTrackFlags = StartTrackingFlags::ButtonRepeat;
695 0 : meScrollType = SCROLL_PAGEDOWN;
696 : }
697 :
698 0 : mnDragDraw = SLIDER_DRAW_CHANNEL;
699 : }
700 :
701 : // Shall we start Tracking?
702 0 : if( meScrollType != SCROLL_DONTKNOW )
703 : {
704 : // store Start position for cancel and EndScroll delta
705 0 : mnStartPos = mnThumbPos;
706 0 : ImplDoMouseAction( rMousePos, meScrollType != SCROLL_SET );
707 0 : Update();
708 :
709 0 : if( meScrollType != SCROLL_SET )
710 0 : StartTracking( nTrackFlags );
711 : }
712 : }
713 0 : }
714 :
715 0 : void Slider::MouseButtonUp( const MouseEvent& )
716 : {
717 0 : if( SCROLL_SET == meScrollType )
718 : {
719 : // reset Button and PageRect state
720 0 : const sal_uInt16 nOldStateFlags = mnStateFlags;
721 :
722 0 : mnStateFlags &= ~( SLIDER_STATE_CHANNEL1_DOWN | SLIDER_STATE_CHANNEL2_DOWN | SLIDER_STATE_THUMB_DOWN );
723 :
724 0 : if ( nOldStateFlags != mnStateFlags )
725 : {
726 0 : mnDrawFlags = mnDragDraw;
727 0 : Invalidate();
728 : }
729 0 : mnDragDraw = 0;
730 0 : ImplDoAction( true );
731 0 : meScrollType = SCROLL_DONTKNOW;
732 : }
733 0 : }
734 :
735 0 : void Slider::Tracking( const TrackingEvent& rTEvt )
736 : {
737 0 : if ( rTEvt.IsTrackingEnded() )
738 : {
739 : // reset Button and PageRect state
740 0 : sal_uInt16 nOldStateFlags = mnStateFlags;
741 : mnStateFlags &= ~(SLIDER_STATE_CHANNEL1_DOWN | SLIDER_STATE_CHANNEL2_DOWN |
742 0 : SLIDER_STATE_THUMB_DOWN);
743 0 : if ( nOldStateFlags != mnStateFlags )
744 : {
745 0 : mnDrawFlags = mnDragDraw;
746 0 : Invalidate();
747 : }
748 0 : mnDragDraw = 0;
749 :
750 : // on cancel, reset the previous Thumb position
751 0 : if ( rTEvt.IsTrackingCanceled() )
752 : {
753 0 : long nOldPos = mnThumbPos;
754 0 : SetThumbPos( mnStartPos );
755 0 : mnDelta = mnThumbPos-nOldPos;
756 0 : Slide();
757 : }
758 :
759 0 : if ( meScrollType == SCROLL_DRAG )
760 : {
761 : // after dragging, recalculate to a rounded Thumb position
762 0 : ImplCalc();
763 0 : Update();
764 :
765 0 : if ( !mbFullDrag && (mnStartPos != mnThumbPos) )
766 : {
767 0 : mnDelta = mnThumbPos-mnStartPos;
768 0 : Slide();
769 0 : mnDelta = 0;
770 : }
771 : }
772 :
773 0 : mnDelta = mnThumbPos-mnStartPos;
774 0 : EndSlide();
775 0 : mnDelta = 0;
776 0 : meScrollType = SCROLL_DONTKNOW;
777 : }
778 : else
779 : {
780 0 : const Point rMousePos = rTEvt.GetMouseEvent().GetPosPixel();
781 :
782 : // special handling for dragging
783 0 : if ( meScrollType == SCROLL_DRAG )
784 : {
785 : long nMovePix;
786 0 : Point aCenterPos = maThumbRect.Center();
787 0 : if ( GetStyle() & WB_HORZ )
788 0 : nMovePix = rMousePos.X()-(aCenterPos.X()+mnMouseOff);
789 : else
790 0 : nMovePix = rMousePos.Y()-(aCenterPos.Y()+mnMouseOff);
791 : // only if the mouse moves in Scroll direction we have to act
792 0 : if ( nMovePix )
793 : {
794 0 : mnThumbPixPos += nMovePix;
795 0 : if ( mnThumbPixPos < mnThumbPixOffset )
796 0 : mnThumbPixPos = mnThumbPixOffset;
797 0 : if ( mnThumbPixPos > (mnThumbPixOffset+mnThumbPixRange-1) )
798 0 : mnThumbPixPos = mnThumbPixOffset+mnThumbPixRange-1;
799 0 : long nOldPos = mnThumbPos;
800 0 : mnThumbPos = ImplCalcThumbPos( mnThumbPixPos );
801 0 : if ( nOldPos != mnThumbPos )
802 : {
803 0 : ImplUpdateRects();
804 0 : Update();
805 0 : ImplUpdateLinkedField();
806 0 : if ( mbFullDrag && (nOldPos != mnThumbPos) )
807 : {
808 0 : mnDelta = mnThumbPos-nOldPos;
809 0 : Slide();
810 0 : mnDelta = 0;
811 : }
812 : }
813 : }
814 : }
815 : else
816 0 : ImplDoMouseAction( rMousePos, rTEvt.IsTrackingRepeat() );
817 :
818 : // end tracking if ScrollBar values indicate we are done
819 0 : if ( !IsVisible() )
820 0 : EndTracking();
821 : }
822 0 : }
823 :
824 0 : void Slider::KeyInput( const KeyEvent& rKEvt )
825 : {
826 0 : if ( !rKEvt.GetKeyCode().GetModifier() )
827 : {
828 0 : switch ( rKEvt.GetKeyCode().GetCode() )
829 : {
830 : case KEY_HOME:
831 0 : ImplDoSlide( GetRangeMin() );
832 0 : break;
833 : case KEY_END:
834 0 : ImplDoSlide( GetRangeMax() );
835 0 : break;
836 :
837 : case KEY_LEFT:
838 : case KEY_UP:
839 0 : ImplDoSlideAction( SCROLL_LINEUP );
840 0 : break;
841 :
842 : case KEY_RIGHT:
843 : case KEY_DOWN:
844 0 : ImplDoSlideAction( SCROLL_LINEDOWN );
845 0 : break;
846 :
847 : case KEY_PAGEUP:
848 0 : ImplDoSlideAction( SCROLL_PAGEUP );
849 0 : break;
850 :
851 : case KEY_PAGEDOWN:
852 0 : ImplDoSlideAction( SCROLL_PAGEDOWN );
853 0 : break;
854 :
855 : default:
856 0 : Control::KeyInput( rKEvt );
857 0 : break;
858 : }
859 : }
860 : else
861 0 : Control::KeyInput( rKEvt );
862 0 : }
863 :
864 0 : void Slider::Paint(vcl::RenderContext& rRenderContext, const Rectangle& /*rRect*/)
865 : {
866 0 : if (mnDrawFlags)
867 : {
868 0 : ImplDraw(rRenderContext, mnDrawFlags);
869 0 : mnDrawFlags = 0;
870 : }
871 0 : }
872 :
873 0 : void Slider::Resize()
874 : {
875 0 : Control::Resize();
876 0 : mbCalcSize = true;
877 0 : if ( IsReallyVisible() )
878 0 : ImplCalc( false );
879 0 : mnDrawFlags = SLIDER_DRAW_ALL;
880 0 : Invalidate();
881 0 : }
882 :
883 0 : void Slider::SetLinkedField(VclPtr<NumericField> pField)
884 : {
885 0 : ImplSetFieldLink(Link<>());
886 0 : mpLinkedField = pField;
887 0 : ImplSetFieldLink(LINK(this, Slider, LinkedFieldModifyHdl));
888 0 : }
889 :
890 0 : void Slider::RequestHelp( const HelpEvent& rHEvt )
891 : {
892 0 : Control::RequestHelp( rHEvt );
893 0 : }
894 :
895 0 : void Slider::StateChanged( StateChangedType nType )
896 : {
897 0 : Control::StateChanged( nType );
898 :
899 0 : if ( nType == StateChangedType::InitShow )
900 0 : ImplCalc( false );
901 0 : else if ( nType == StateChangedType::Data )
902 : {
903 0 : if ( IsReallyVisible() && IsUpdateMode() )
904 0 : ImplCalc( true );
905 : }
906 0 : else if ( nType == StateChangedType::UpdateMode )
907 : {
908 0 : if ( IsReallyVisible() && IsUpdateMode() )
909 : {
910 0 : ImplCalc( false );
911 0 : mnDrawFlags = SLIDER_DRAW_ALL;
912 0 : Invalidate();
913 : }
914 : }
915 0 : else if ( nType == StateChangedType::Enable )
916 : {
917 0 : if ( IsReallyVisible() && IsUpdateMode() )
918 : {
919 0 : mnDrawFlags = SLIDER_DRAW_ALL;
920 0 : Invalidate();
921 : }
922 : }
923 0 : else if ( nType == StateChangedType::Style )
924 : {
925 0 : if ( IsReallyVisible() && IsUpdateMode() )
926 : {
927 0 : if ( (GetPrevStyle() & SLIDER_VIEW_STYLE) !=
928 0 : (GetStyle() & SLIDER_VIEW_STYLE) )
929 : {
930 0 : mbCalcSize = true;
931 0 : ImplCalc( false );
932 0 : mnDrawFlags = SLIDER_DRAW_ALL;
933 0 : Invalidate();
934 : }
935 : }
936 : }
937 0 : else if ( nType == StateChangedType::ControlBackground )
938 : {
939 0 : ImplInitSettings();
940 0 : mnDrawFlags = SLIDER_DRAW_ALL;
941 0 : Invalidate();
942 : }
943 0 : }
944 :
945 0 : void Slider::DataChanged( const DataChangedEvent& rDCEvt )
946 : {
947 0 : Control::DataChanged( rDCEvt );
948 :
949 0 : if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
950 0 : (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
951 : {
952 0 : ImplInitSettings();
953 0 : mnDrawFlags = SLIDER_DRAW_ALL;
954 0 : Invalidate();
955 : }
956 0 : }
957 :
958 0 : void Slider::Slide()
959 : {
960 0 : maSlideHdl.Call( this );
961 0 : }
962 :
963 0 : void Slider::EndSlide()
964 : {
965 0 : maEndSlideHdl.Call( this );
966 0 : }
967 :
968 0 : void Slider::SetRangeMin(long nNewRange)
969 : {
970 0 : SetRange(Range(nNewRange, GetRangeMax()));
971 0 : }
972 :
973 0 : void Slider::SetRangeMax(long nNewRange)
974 : {
975 0 : SetRange(Range(GetRangeMin(), nNewRange));
976 0 : }
977 :
978 0 : void Slider::SetRange( const Range& rRange )
979 : {
980 : // adjust Range
981 0 : Range aRange = rRange;
982 0 : aRange.Justify();
983 0 : long nNewMinRange = aRange.Min();
984 0 : long nNewMaxRange = aRange.Max();
985 :
986 : // reset Range if different
987 0 : if ( (mnMinRange != nNewMinRange) ||
988 0 : (mnMaxRange != nNewMaxRange) )
989 : {
990 0 : mnMinRange = nNewMinRange;
991 0 : mnMaxRange = nNewMaxRange;
992 :
993 : // adjust Thumb
994 0 : if ( mnThumbPos > mnMaxRange )
995 0 : mnThumbPos = mnMaxRange;
996 0 : if ( mnThumbPos < mnMinRange )
997 0 : mnThumbPos = mnMinRange;
998 0 : ImplUpdateLinkedField();
999 0 : CompatStateChanged( StateChangedType::Data );
1000 : }
1001 0 : }
1002 :
1003 0 : void Slider::SetThumbPos( long nNewThumbPos )
1004 : {
1005 0 : if ( nNewThumbPos < mnMinRange )
1006 0 : nNewThumbPos = mnMinRange;
1007 0 : if ( nNewThumbPos > mnMaxRange )
1008 0 : nNewThumbPos = mnMaxRange;
1009 :
1010 0 : if ( mnThumbPos != nNewThumbPos )
1011 : {
1012 0 : mnThumbPos = nNewThumbPos;
1013 0 : ImplUpdateLinkedField();
1014 0 : CompatStateChanged( StateChangedType::Data );
1015 : }
1016 0 : }
1017 :
1018 0 : Size Slider::CalcWindowSizePixel()
1019 : {
1020 0 : long nWidth = mnMaxRange-mnMinRange+(SLIDER_THUMB_HALFSIZE*2)+1;
1021 0 : long nHeight = SLIDER_HEIGHT;
1022 0 : Size aSize;
1023 0 : if ( GetStyle() & WB_HORZ )
1024 : {
1025 0 : aSize.Width() = nWidth;
1026 0 : aSize.Height() = nHeight;
1027 : }
1028 : else
1029 : {
1030 0 : aSize.Height() = nWidth;
1031 0 : aSize.Width() = nHeight;
1032 : }
1033 0 : return aSize;
1034 801 : }
1035 :
1036 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|