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