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/rcid.h>
21 : #include <vcl/spin.h>
22 : #include <vcl/event.hxx>
23 : #include <vcl/spin.hxx>
24 :
25 : // =======================================================================
26 :
27 0 : void SpinButton::ImplInit( Window* pParent, WinBits nStyle )
28 : {
29 0 : mbUpperIn = sal_False;
30 0 : mbLowerIn = sal_False;
31 0 : mbInitialUp = sal_False;
32 0 : mbInitialDown = sal_False;
33 :
34 0 : mnMinRange = 0;
35 0 : mnMaxRange = 100;
36 0 : mnValue = 0;
37 0 : mnValueStep = 1;
38 :
39 0 : maRepeatTimer.SetTimeout( GetSettings().GetMouseSettings().GetButtonStartRepeat() );
40 0 : maRepeatTimer.SetTimeoutHdl( LINK( this, SpinButton, ImplTimeout ) );
41 :
42 0 : mbRepeat = 0 != ( nStyle & WB_REPEAT );
43 :
44 0 : if ( nStyle & WB_HSCROLL )
45 0 : mbHorz = sal_True;
46 : else
47 0 : mbHorz = sal_False;
48 :
49 0 : Control::ImplInit( pParent, nStyle, NULL );
50 0 : }
51 :
52 : // -----------------------------------------------------------------------
53 :
54 0 : SpinButton::SpinButton( Window* pParent, WinBits nStyle )
55 : :Control( WINDOW_SPINBUTTON )
56 0 : ,mbUpperIsFocused( sal_False )
57 : {
58 0 : ImplInit( pParent, nStyle );
59 0 : }
60 :
61 : // -----------------------------------------------------------------------
62 :
63 0 : SpinButton::~SpinButton()
64 : {
65 0 : }
66 :
67 : // -----------------------------------------------------------------------
68 :
69 0 : IMPL_LINK( SpinButton, ImplTimeout, Timer*, pTimer )
70 : {
71 0 : if ( pTimer->GetTimeout() == GetSettings().GetMouseSettings().GetButtonStartRepeat() )
72 : {
73 0 : pTimer->SetTimeout( GetSettings().GetMouseSettings().GetButtonRepeat() );
74 0 : pTimer->Start();
75 : }
76 : else
77 : {
78 0 : if ( mbInitialUp )
79 0 : Up();
80 : else
81 0 : Down();
82 : }
83 :
84 0 : return 0;
85 : }
86 :
87 : // -----------------------------------------------------------------------
88 :
89 0 : void SpinButton::Up()
90 : {
91 0 : if ( ImplIsUpperEnabled() )
92 : {
93 0 : mnValue += mnValueStep;
94 0 : StateChanged( STATE_CHANGE_DATA );
95 :
96 0 : ImplMoveFocus( sal_True );
97 : }
98 :
99 0 : ImplCallEventListenersAndHandler( VCLEVENT_SPINBUTTON_UP, maUpHdlLink, this );
100 0 : }
101 :
102 : // -----------------------------------------------------------------------
103 :
104 0 : void SpinButton::Down()
105 : {
106 0 : if ( ImplIsLowerEnabled() )
107 : {
108 0 : mnValue -= mnValueStep;
109 0 : StateChanged( STATE_CHANGE_DATA );
110 :
111 0 : ImplMoveFocus( sal_False );
112 : }
113 :
114 0 : ImplCallEventListenersAndHandler( VCLEVENT_SPINBUTTON_DOWN, maDownHdlLink, this );
115 0 : }
116 :
117 : // -----------------------------------------------------------------------
118 :
119 0 : void SpinButton::Resize()
120 : {
121 0 : Control::Resize();
122 :
123 0 : Size aSize( GetOutputSizePixel() );
124 0 : Point aTmpPoint;
125 0 : Rectangle aRect( aTmpPoint, aSize );
126 0 : if ( mbHorz )
127 : {
128 0 : maLowerRect = Rectangle( 0, 0, aSize.Width()/2, aSize.Height()-1 );
129 0 : maUpperRect = Rectangle( maLowerRect.TopRight(), aRect.BottomRight() );
130 : }
131 : else
132 : {
133 0 : maUpperRect = Rectangle( 0, 0, aSize.Width()-1, aSize.Height()/2 );
134 0 : maLowerRect = Rectangle( maUpperRect.BottomLeft(), aRect.BottomRight() );
135 : }
136 :
137 0 : ImplCalcFocusRect( ImplIsUpperEnabled() || !ImplIsLowerEnabled() );
138 :
139 0 : Invalidate();
140 0 : }
141 :
142 : // -----------------------------------------------------------------------
143 :
144 0 : void SpinButton::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, sal_uLong nFlags )
145 : {
146 0 : Point aPos = pDev->LogicToPixel( rPos );
147 0 : Size aSize = pDev->LogicToPixel( rSize );
148 :
149 0 : pDev->Push();
150 0 : pDev->SetMapMode();
151 0 : if ( !(nFlags & WINDOW_DRAW_MONO) )
152 : {
153 : // DecoView uses the FaceColor...
154 0 : AllSettings aSettings = pDev->GetSettings();
155 0 : StyleSettings aStyleSettings = aSettings.GetStyleSettings();
156 0 : if ( IsControlBackground() )
157 0 : aStyleSettings.SetFaceColor( GetControlBackground() );
158 : else
159 0 : aStyleSettings.SetFaceColor( GetSettings().GetStyleSettings().GetFaceColor() );
160 :
161 0 : aSettings.SetStyleSettings( aStyleSettings );
162 0 : pDev->SetSettings( aSettings );
163 : }
164 :
165 0 : Rectangle aRect( Point( 0, 0 ), aSize );
166 0 : Rectangle aLowerRect, aUpperRect;
167 0 : if ( mbHorz )
168 : {
169 0 : aLowerRect = Rectangle( 0, 0, aSize.Width()/2, aSize.Height()-1 );
170 0 : aUpperRect = Rectangle( aLowerRect.TopRight(), aRect.BottomRight() );
171 : }
172 : else
173 : {
174 0 : aUpperRect = Rectangle( 0, 0, aSize.Width()-1, aSize.Height()/2 );
175 0 : aLowerRect = Rectangle( aUpperRect.BottomLeft(), aRect.BottomRight() );
176 : }
177 :
178 0 : aUpperRect += aPos;
179 0 : aLowerRect += aPos;
180 :
181 : ImplDrawSpinButton( pDev, aUpperRect, aLowerRect, sal_False, sal_False,
182 0 : IsEnabled() && ImplIsUpperEnabled(),
183 0 : IsEnabled() && ImplIsLowerEnabled(), mbHorz, sal_True );
184 0 : pDev->Pop();
185 0 : }
186 :
187 :
188 0 : void SpinButton::Paint( const Rectangle& )
189 : {
190 0 : HideFocus();
191 :
192 0 : sal_Bool bEnable = IsEnabled();
193 : ImplDrawSpinButton( this, maUpperRect, maLowerRect, mbUpperIn, mbLowerIn,
194 0 : bEnable && ImplIsUpperEnabled(),
195 0 : bEnable && ImplIsLowerEnabled(), mbHorz, sal_True );
196 :
197 0 : if ( HasFocus() )
198 0 : ShowFocus( maFocusRect );
199 0 : }
200 :
201 : // -----------------------------------------------------------------------
202 :
203 0 : void SpinButton::MouseButtonDown( const MouseEvent& rMEvt )
204 : {
205 0 : if ( maUpperRect.IsInside( rMEvt.GetPosPixel() ) && ( ImplIsUpperEnabled() ) )
206 : {
207 0 : mbUpperIn = sal_True;
208 0 : mbInitialUp = sal_True;
209 0 : Invalidate( maUpperRect );
210 : }
211 0 : else if ( maLowerRect.IsInside( rMEvt.GetPosPixel() ) && ( ImplIsLowerEnabled() ) )
212 : {
213 0 : mbLowerIn = sal_True;
214 0 : mbInitialDown = sal_True;
215 0 : Invalidate( maLowerRect );
216 : }
217 :
218 0 : if ( mbUpperIn || mbLowerIn )
219 : {
220 0 : Update();
221 0 : CaptureMouse();
222 0 : if ( mbRepeat )
223 0 : maRepeatTimer.Start();
224 : }
225 0 : }
226 :
227 : // -----------------------------------------------------------------------
228 :
229 0 : void SpinButton::MouseButtonUp( const MouseEvent& )
230 : {
231 0 : ReleaseMouse();
232 0 : if ( mbRepeat )
233 : {
234 0 : maRepeatTimer.Stop();
235 0 : maRepeatTimer.SetTimeout(GetSettings().GetMouseSettings().GetButtonStartRepeat() );
236 : }
237 :
238 0 : if ( mbUpperIn )
239 : {
240 0 : mbUpperIn = sal_False;
241 0 : Invalidate( maUpperRect );
242 0 : Update();
243 0 : Up();
244 : }
245 0 : else if ( mbLowerIn )
246 : {
247 0 : mbLowerIn = sal_False;
248 0 : Invalidate( maLowerRect );
249 0 : Update();
250 0 : Down();
251 : }
252 :
253 0 : mbInitialUp = mbInitialDown = sal_False;
254 0 : }
255 :
256 : // -----------------------------------------------------------------------
257 :
258 0 : void SpinButton::MouseMove( const MouseEvent& rMEvt )
259 : {
260 0 : if ( !rMEvt.IsLeft() || (!mbInitialUp && !mbInitialDown) )
261 0 : return;
262 :
263 0 : if ( !maUpperRect.IsInside( rMEvt.GetPosPixel() ) &&
264 : mbUpperIn && mbInitialUp )
265 : {
266 0 : mbUpperIn = sal_False;
267 0 : maRepeatTimer.Stop();
268 0 : Invalidate( maUpperRect );
269 0 : Update();
270 : }
271 0 : else if ( !maLowerRect.IsInside( rMEvt.GetPosPixel() ) &&
272 : mbLowerIn & mbInitialDown )
273 : {
274 0 : mbLowerIn = sal_False;
275 0 : maRepeatTimer.Stop();
276 0 : Invalidate( maLowerRect );
277 0 : Update();
278 : }
279 0 : else if ( maUpperRect.IsInside( rMEvt.GetPosPixel() ) &&
280 0 : !mbUpperIn && mbInitialUp )
281 : {
282 0 : mbUpperIn = sal_True;
283 0 : if ( mbRepeat )
284 0 : maRepeatTimer.Start();
285 0 : Invalidate( maUpperRect );
286 0 : Update();
287 : }
288 0 : else if ( maLowerRect.IsInside( rMEvt.GetPosPixel() ) &&
289 0 : !mbLowerIn && mbInitialDown )
290 : {
291 0 : mbLowerIn = sal_True;
292 0 : if ( mbRepeat )
293 0 : maRepeatTimer.Start();
294 0 : Invalidate( maLowerRect );
295 0 : Update();
296 : }
297 : }
298 :
299 : // -----------------------------------------------------------------------
300 :
301 0 : void SpinButton::KeyInput( const KeyEvent& rKEvt )
302 : {
303 0 : if ( !rKEvt.GetKeyCode().GetModifier() )
304 : {
305 0 : switch ( rKEvt.GetKeyCode().GetCode() )
306 : {
307 : case KEY_LEFT:
308 : case KEY_RIGHT:
309 : {
310 0 : sal_Bool bUp = KEY_RIGHT == rKEvt.GetKeyCode().GetCode();
311 0 : if ( mbHorz && !ImplMoveFocus( bUp ) )
312 0 : bUp ? Up() : Down();
313 : }
314 0 : break;
315 :
316 : case KEY_UP:
317 : case KEY_DOWN:
318 : {
319 0 : sal_Bool bUp = KEY_UP == rKEvt.GetKeyCode().GetCode();
320 0 : if ( !mbHorz && !ImplMoveFocus( KEY_UP == rKEvt.GetKeyCode().GetCode() ) )
321 0 : bUp ? Up() : Down();
322 : }
323 0 : break;
324 :
325 : case KEY_SPACE:
326 0 : mbUpperIsFocused ? Up() : Down();
327 0 : break;
328 :
329 : default:
330 0 : Control::KeyInput( rKEvt );
331 0 : break;
332 : }
333 : }
334 : else
335 0 : Control::KeyInput( rKEvt );
336 0 : }
337 :
338 : // -----------------------------------------------------------------------
339 :
340 0 : void SpinButton::StateChanged( StateChangedType nType )
341 : {
342 0 : switch ( nType )
343 : {
344 : case STATE_CHANGE_DATA:
345 : case STATE_CHANGE_ENABLE:
346 0 : Invalidate();
347 0 : break;
348 :
349 : case STATE_CHANGE_STYLE:
350 : {
351 0 : sal_Bool bNewRepeat = 0 != ( GetStyle() & WB_REPEAT );
352 0 : if ( bNewRepeat != mbRepeat )
353 : {
354 0 : if ( maRepeatTimer.IsActive() )
355 : {
356 0 : maRepeatTimer.Stop();
357 0 : maRepeatTimer.SetTimeout( GetSettings().GetMouseSettings().GetButtonStartRepeat() );
358 : }
359 0 : mbRepeat = bNewRepeat;
360 : }
361 :
362 0 : sal_Bool bNewHorz = 0 != ( GetStyle() & WB_HSCROLL );
363 0 : if ( bNewHorz != mbHorz )
364 : {
365 0 : mbHorz = bNewHorz;
366 0 : Resize();
367 : }
368 : }
369 0 : break;
370 : }
371 :
372 0 : Control::StateChanged( nType );
373 0 : }
374 :
375 : // -----------------------------------------------------------------------
376 :
377 0 : void SpinButton::SetRangeMin( long nNewRange )
378 : {
379 0 : SetRange( Range( nNewRange, GetRangeMax() ) );
380 0 : }
381 :
382 : // -----------------------------------------------------------------------
383 :
384 0 : void SpinButton::SetRangeMax( long nNewRange )
385 : {
386 0 : SetRange( Range( GetRangeMin(), nNewRange ) );
387 0 : }
388 :
389 : // -----------------------------------------------------------------------
390 :
391 0 : void SpinButton::SetRange( const Range& rRange )
392 : {
393 : // adjust rage
394 0 : Range aRange = rRange;
395 0 : aRange.Justify();
396 0 : long nNewMinRange = aRange.Min();
397 0 : long nNewMaxRange = aRange.Max();
398 :
399 : // do something only if old and new range differ
400 0 : if ( (mnMinRange != nNewMinRange) ||
401 : (mnMaxRange != nNewMaxRange) )
402 : {
403 0 : mnMinRange = nNewMinRange;
404 0 : mnMaxRange = nNewMaxRange;
405 :
406 : // adjust value to new range, if necessary
407 0 : if ( mnValue > mnMaxRange )
408 0 : mnValue = mnMaxRange;
409 0 : if ( mnValue < mnMinRange )
410 0 : mnValue = mnMinRange;
411 :
412 0 : StateChanged( STATE_CHANGE_DATA );
413 : }
414 0 : }
415 :
416 : // -----------------------------------------------------------------------
417 :
418 0 : void SpinButton::SetValue( long nValue )
419 : {
420 : // adjust, if necessary
421 0 : if ( nValue > mnMaxRange )
422 0 : nValue = mnMaxRange;
423 0 : if ( nValue < mnMinRange )
424 0 : nValue = mnMinRange;
425 :
426 0 : if ( mnValue != nValue )
427 : {
428 0 : mnValue = nValue;
429 0 : StateChanged( STATE_CHANGE_DATA );
430 : }
431 0 : }
432 :
433 : // -----------------------------------------------------------------------
434 :
435 0 : void SpinButton::GetFocus()
436 : {
437 0 : ShowFocus( maFocusRect );
438 0 : Control::GetFocus();
439 0 : }
440 :
441 : // -----------------------------------------------------------------------
442 :
443 0 : void SpinButton::LoseFocus()
444 : {
445 0 : HideFocus();
446 0 : Control::LoseFocus();
447 0 : }
448 :
449 : // -----------------------------------------------------------------------
450 :
451 0 : sal_Bool SpinButton::ImplMoveFocus( sal_Bool _bUpper )
452 : {
453 0 : if ( _bUpper == mbUpperIsFocused )
454 0 : return sal_False;
455 :
456 0 : HideFocus();
457 0 : ImplCalcFocusRect( _bUpper );
458 0 : if ( HasFocus() )
459 0 : ShowFocus( maFocusRect );
460 0 : return sal_True;
461 : }
462 :
463 : // -----------------------------------------------------------------------
464 :
465 0 : void SpinButton::ImplCalcFocusRect( sal_Bool _bUpper )
466 : {
467 0 : maFocusRect = _bUpper ? maUpperRect : maLowerRect;
468 : // inflate by some pixels
469 0 : maFocusRect.Left() += 2;
470 0 : maFocusRect.Top() += 2;
471 0 : maFocusRect.Right() -= 2;
472 0 : maFocusRect.Bottom() -= 2;
473 0 : mbUpperIsFocused = _bUpper;
474 0 : }
475 :
476 : // -----------------------------------------------------------------------
477 :
478 0 : Rectangle* SpinButton::ImplFindPartRect( const Point& rPt )
479 : {
480 0 : if( maUpperRect.IsInside( rPt ) )
481 0 : return &maUpperRect;
482 0 : else if( maLowerRect.IsInside( rPt ) )
483 0 : return &maLowerRect;
484 : else
485 0 : return NULL;
486 : }
487 :
488 0 : long SpinButton::PreNotify( NotifyEvent& rNEvt )
489 : {
490 0 : long nDone = 0;
491 0 : const MouseEvent* pMouseEvt = NULL;
492 :
493 0 : if( (rNEvt.GetType() == EVENT_MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != NULL )
494 : {
495 0 : if( !pMouseEvt->GetButtons() && !pMouseEvt->IsSynthetic() && !pMouseEvt->IsModifierChanged() )
496 : {
497 : // trigger redraw if mouse over state has changed
498 0 : if( IsNativeControlSupported(CTRL_SPINBOX, PART_ENTIRE_CONTROL) ||
499 0 : IsNativeControlSupported(CTRL_SPINBOX, PART_ALL_BUTTONS) )
500 : {
501 0 : Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() );
502 0 : Rectangle* pLastRect = ImplFindPartRect( GetLastPointerPosPixel() );
503 0 : if( pRect != pLastRect || (pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow()) )
504 : {
505 0 : Region aRgn( GetActiveClipRegion() );
506 0 : if( pLastRect )
507 : {
508 0 : SetClipRegion( *pLastRect );
509 0 : Paint( *pLastRect );
510 0 : SetClipRegion( aRgn );
511 : }
512 0 : if( pRect )
513 : {
514 0 : SetClipRegion( *pRect );
515 0 : Paint( *pRect );
516 0 : SetClipRegion( aRgn );
517 0 : }
518 : }
519 : }
520 : }
521 : }
522 :
523 0 : return nDone ? nDone : Control::PreNotify(rNEvt);
524 : }
525 :
526 : // -----------------------------------------------------------------------
527 :
528 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|