/src/libreoffice/vcl/source/control/spinfld.cxx
Line | Count | Source (jump to first uncovered line) |
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 <vcl/commandevent.hxx> |
21 | | #include <vcl/event.hxx> |
22 | | #include <vcl/decoview.hxx> |
23 | | #include <vcl/toolkit/spinfld.hxx> |
24 | | #include <vcl/settings.hxx> |
25 | | #include <vcl/uitest/uiobject.hxx> |
26 | | #include <sal/log.hxx> |
27 | | |
28 | | #include <spin.hxx> |
29 | | #include <svdata.hxx> |
30 | | |
31 | | namespace { |
32 | | |
33 | | void lcl_GetSpinbuttonValue(vcl::Window* pWin, |
34 | | const tools::Rectangle& rUpperRect, const tools::Rectangle& rLowerRect, |
35 | | bool bUpperIn, bool bLowerIn, bool bUpperEnabled, bool bLowerEnabled, |
36 | | bool bHorz, SpinbuttonValue& rValue ) |
37 | 0 | { |
38 | | // convert spinbutton data to a SpinbuttonValue structure for native painting |
39 | |
|
40 | 0 | rValue.maUpperRect = rUpperRect; |
41 | 0 | rValue.maLowerRect = rLowerRect; |
42 | |
|
43 | 0 | Point aPointerPos = pWin->GetPointerPosPixel(); |
44 | |
|
45 | 0 | ControlState nState = ControlState::ENABLED; |
46 | 0 | if (bUpperIn) |
47 | 0 | nState |= ControlState::PRESSED; |
48 | 0 | if (!pWin->IsEnabled() || !bUpperEnabled) |
49 | 0 | nState &= ~ControlState::ENABLED; |
50 | 0 | if (pWin->HasFocus()) |
51 | 0 | nState |= ControlState::FOCUSED; |
52 | 0 | if (pWin->IsMouseOver() && rUpperRect.Contains(aPointerPos)) |
53 | 0 | nState |= ControlState::ROLLOVER; |
54 | 0 | rValue.mnUpperState = nState; |
55 | |
|
56 | 0 | nState = ControlState::ENABLED; |
57 | 0 | if (bLowerIn) |
58 | 0 | nState |= ControlState::PRESSED; |
59 | 0 | if (!pWin->IsEnabled() || !bLowerEnabled) |
60 | 0 | nState &= ~ControlState::ENABLED; |
61 | 0 | if (pWin->HasFocus()) |
62 | 0 | nState |= ControlState::FOCUSED; |
63 | | // for overlapping spins: highlight only one |
64 | 0 | if (pWin->IsMouseOver() && rLowerRect.Contains(aPointerPos) && !rUpperRect.Contains(aPointerPos)) |
65 | 0 | nState |= ControlState::ROLLOVER; |
66 | 0 | rValue.mnLowerState = nState; |
67 | |
|
68 | 0 | rValue.mnUpperPart = bHorz ? ControlPart::ButtonLeft : ControlPart::ButtonUp; |
69 | 0 | rValue.mnLowerPart = bHorz ? ControlPart::ButtonRight : ControlPart::ButtonDown; |
70 | 0 | } |
71 | | |
72 | | bool lcl_DrawNativeSpinfield(vcl::RenderContext& rRenderContext, vcl::Window const * pWin, const SpinbuttonValue& rSpinbuttonValue) |
73 | 0 | { |
74 | 0 | bool bNativeOK = false; |
75 | |
|
76 | 0 | if (rRenderContext.IsNativeControlSupported(ControlType::Spinbox, ControlPart::Entire) && |
77 | | // there is just no useful native support for spinfields with dropdown |
78 | 0 | !(pWin->GetStyle() & WB_DROPDOWN)) |
79 | 0 | { |
80 | 0 | if (rRenderContext.IsNativeControlSupported(ControlType::Spinbox, rSpinbuttonValue.mnUpperPart) && |
81 | 0 | rRenderContext.IsNativeControlSupported(ControlType::Spinbox, rSpinbuttonValue.mnLowerPart)) |
82 | 0 | { |
83 | | // only paint the embedded spin buttons, all buttons are painted at once |
84 | 0 | tools::Rectangle aUpperAndLowerButtons( rSpinbuttonValue.maUpperRect.GetUnion( rSpinbuttonValue.maLowerRect ) ); |
85 | 0 | bNativeOK = rRenderContext.DrawNativeControl(ControlType::Spinbox, ControlPart::AllButtons, aUpperAndLowerButtons, |
86 | 0 | ControlState::ENABLED, rSpinbuttonValue, OUString()); |
87 | 0 | } |
88 | 0 | else |
89 | 0 | { |
90 | | // paint the spinbox as a whole, use borderwindow to have proper clipping |
91 | 0 | vcl::Window* pBorder = pWin->GetWindow(GetWindowType::Border); |
92 | | |
93 | | // to not overwrite everything, set the button region as clipregion to the border window |
94 | 0 | tools::Rectangle aClipRect(rSpinbuttonValue.maLowerRect); |
95 | 0 | aClipRect.Union(rSpinbuttonValue.maUpperRect); |
96 | |
|
97 | 0 | vcl::RenderContext* pContext = &rRenderContext; |
98 | 0 | vcl::Region oldRgn; |
99 | 0 | Point aPt; |
100 | 0 | Size aSize(pBorder->GetOutputSizePixel()); // the size of the border window, i.e., the whole control |
101 | 0 | tools::Rectangle aNatRgn(aPt, aSize); |
102 | |
|
103 | 0 | if (!pWin->SupportsDoubleBuffering()) |
104 | 0 | { |
105 | | // convert from screen space to borderwin space |
106 | 0 | aClipRect.SetPos(pBorder->ScreenToOutputPixel(pWin->OutputToScreenPixel(aClipRect.TopLeft()))); |
107 | |
|
108 | 0 | oldRgn = pBorder->GetOutDev()->GetClipRegion(); |
109 | 0 | pBorder->GetOutDev()->SetClipRegion(vcl::Region(aClipRect)); |
110 | |
|
111 | 0 | pContext = pBorder->GetOutDev(); |
112 | 0 | } |
113 | |
|
114 | 0 | tools::Rectangle aBound, aContent; |
115 | 0 | if (!ImplGetSVData()->maNWFData.mbCanDrawWidgetAnySize && |
116 | 0 | pContext->GetNativeControlRegion(ControlType::Spinbox, ControlPart::Entire, |
117 | 0 | aNatRgn, ControlState::NONE, rSpinbuttonValue, |
118 | 0 | aBound, aContent)) |
119 | 0 | { |
120 | 0 | aSize = aContent.GetSize(); |
121 | 0 | } |
122 | |
|
123 | 0 | tools::Rectangle aRgn(aPt, aSize); |
124 | 0 | if (pWin->SupportsDoubleBuffering()) |
125 | 0 | { |
126 | | // convert from borderwin space, to the pWin's space |
127 | 0 | aRgn.SetPos(pWin->ScreenToOutputPixel(pBorder->OutputToScreenPixel(aRgn.TopLeft()))); |
128 | 0 | } |
129 | |
|
130 | 0 | bNativeOK = pContext->DrawNativeControl(ControlType::Spinbox, ControlPart::Entire, aRgn, |
131 | 0 | ControlState::ENABLED, rSpinbuttonValue, OUString()); |
132 | |
|
133 | 0 | if (!pWin->SupportsDoubleBuffering()) |
134 | 0 | pBorder->GetOutDev()->SetClipRegion(oldRgn); |
135 | 0 | } |
136 | 0 | } |
137 | 0 | return bNativeOK; |
138 | 0 | } |
139 | | |
140 | | bool lcl_DrawNativeSpinbuttons(vcl::RenderContext& rRenderContext, const SpinbuttonValue& rSpinbuttonValue) |
141 | 0 | { |
142 | 0 | bool bNativeOK = false; |
143 | |
|
144 | 0 | if (rRenderContext.IsNativeControlSupported(ControlType::SpinButtons, ControlPart::Entire)) |
145 | 0 | { |
146 | 0 | tools::Rectangle aArea = rSpinbuttonValue.maUpperRect.GetUnion(rSpinbuttonValue.maLowerRect); |
147 | | // only paint the standalone spin buttons, all buttons are painted at once |
148 | 0 | bNativeOK = rRenderContext.DrawNativeControl(ControlType::SpinButtons, ControlPart::AllButtons, aArea, |
149 | 0 | ControlState::ENABLED, rSpinbuttonValue, OUString()); |
150 | 0 | } |
151 | 0 | return bNativeOK; |
152 | 0 | } |
153 | | |
154 | | } |
155 | | |
156 | | void ImplDrawSpinButton(vcl::RenderContext& rRenderContext, vcl::Window* pWindow, |
157 | | const tools::Rectangle& rUpperRect, const tools::Rectangle& rLowerRect, |
158 | | bool bUpperIn, bool bLowerIn, bool bUpperEnabled, bool bLowerEnabled, |
159 | | bool bHorz, bool bMirrorHorz) |
160 | 0 | { |
161 | 0 | bool bNativeOK = false; |
162 | |
|
163 | 0 | if (pWindow) |
164 | 0 | { |
165 | | // are we drawing standalone spin buttons or members of a spinfield ? |
166 | 0 | ControlType aControl = ControlType::SpinButtons; |
167 | 0 | switch (pWindow->GetType()) |
168 | 0 | { |
169 | 0 | case WindowType::EDIT: |
170 | 0 | case WindowType::MULTILINEEDIT: |
171 | 0 | case WindowType::PATTERNFIELD: |
172 | 0 | case WindowType::METRICFIELD: |
173 | 0 | case WindowType::CURRENCYFIELD: |
174 | 0 | case WindowType::DATEFIELD: |
175 | 0 | case WindowType::TIMEFIELD: |
176 | 0 | case WindowType::SPINFIELD: |
177 | 0 | case WindowType::FORMATTEDFIELD: |
178 | 0 | aControl = ControlType::Spinbox; |
179 | 0 | break; |
180 | 0 | default: |
181 | 0 | aControl = ControlType::SpinButtons; |
182 | 0 | break; |
183 | 0 | } |
184 | | |
185 | 0 | SpinbuttonValue aValue; |
186 | 0 | lcl_GetSpinbuttonValue(pWindow, rUpperRect, rLowerRect, |
187 | 0 | bUpperIn, bLowerIn, bUpperEnabled, bLowerEnabled, |
188 | 0 | bHorz, aValue); |
189 | |
|
190 | 0 | if( aControl == ControlType::Spinbox ) |
191 | 0 | bNativeOK = lcl_DrawNativeSpinfield(rRenderContext, pWindow, aValue); |
192 | 0 | else if( aControl == ControlType::SpinButtons ) |
193 | 0 | bNativeOK = lcl_DrawNativeSpinbuttons(rRenderContext, aValue); |
194 | 0 | } |
195 | | |
196 | 0 | if (bNativeOK) |
197 | 0 | return; |
198 | | |
199 | 0 | ImplDrawUpDownButtons(rRenderContext, |
200 | 0 | rUpperRect, rLowerRect, |
201 | 0 | bUpperIn, bLowerIn, bUpperEnabled, bLowerEnabled, |
202 | 0 | bHorz, bMirrorHorz); |
203 | 0 | } |
204 | | |
205 | | void ImplDrawUpDownButtons(vcl::RenderContext& rRenderContext, |
206 | | const tools::Rectangle& rUpperRect, const tools::Rectangle& rLowerRect, |
207 | | bool bUpperIn, bool bLowerIn, bool bUpperEnabled, bool bLowerEnabled, |
208 | | bool bHorz, bool bMirrorHorz) |
209 | 0 | { |
210 | 0 | DecorationView aDecoView(&rRenderContext); |
211 | |
|
212 | 0 | SymbolType eType1, eType2; |
213 | |
|
214 | 0 | if ( bHorz ) |
215 | 0 | { |
216 | 0 | eType1 = bMirrorHorz ? SymbolType::SPIN_RIGHT : SymbolType::SPIN_LEFT; |
217 | 0 | eType2 = bMirrorHorz ? SymbolType::SPIN_LEFT : SymbolType::SPIN_RIGHT; |
218 | 0 | } |
219 | 0 | else |
220 | 0 | { |
221 | 0 | eType1 = SymbolType::SPIN_UP; |
222 | 0 | eType2 = SymbolType::SPIN_DOWN; |
223 | 0 | } |
224 | |
|
225 | 0 | DrawButtonFlags nStyle = DrawButtonFlags::NoLeftLightBorder; |
226 | | // draw upper/left Button |
227 | 0 | if (bUpperIn) |
228 | 0 | nStyle |= DrawButtonFlags::Pressed; |
229 | |
|
230 | 0 | tools::Rectangle aUpRect = aDecoView.DrawButton(rUpperRect, nStyle); |
231 | |
|
232 | 0 | nStyle = DrawButtonFlags::NoLeftLightBorder; |
233 | | // draw lower/right Button |
234 | 0 | if (bLowerIn) |
235 | 0 | nStyle |= DrawButtonFlags::Pressed; |
236 | |
|
237 | 0 | tools::Rectangle aLowRect = aDecoView.DrawButton(rLowerRect, nStyle); |
238 | | |
239 | | // make use of additional default edge |
240 | 0 | aUpRect.AdjustLeft( -1 ); |
241 | 0 | aUpRect.AdjustTop( -1 ); |
242 | 0 | aUpRect.AdjustRight( 1 ); |
243 | 0 | aUpRect.AdjustBottom( 1 ); |
244 | 0 | aLowRect.AdjustLeft( -1 ); |
245 | 0 | aLowRect.AdjustTop( -1 ); |
246 | 0 | aLowRect.AdjustRight( 1 ); |
247 | 0 | aLowRect.AdjustBottom( 1 ); |
248 | | |
249 | | // draw into the edge, so that something is visible if the rectangle is too small |
250 | 0 | if (aUpRect.GetHeight() < 4) |
251 | 0 | { |
252 | 0 | aUpRect.AdjustRight( 1 ); |
253 | 0 | aUpRect.AdjustBottom( 1 ); |
254 | 0 | aLowRect.AdjustRight( 1 ); |
255 | 0 | aLowRect.AdjustBottom( 1 ); |
256 | 0 | } |
257 | | |
258 | | // calculate Symbol size |
259 | 0 | tools::Long nTempSize1 = aUpRect.GetWidth(); |
260 | 0 | tools::Long nTempSize2 = aLowRect.GetWidth(); |
261 | 0 | if (std::abs( nTempSize1-nTempSize2 ) == 1) |
262 | 0 | { |
263 | 0 | if (nTempSize1 > nTempSize2) |
264 | 0 | aUpRect.AdjustLeft( 1 ); |
265 | 0 | else |
266 | 0 | aLowRect.AdjustLeft( 1 ); |
267 | 0 | } |
268 | 0 | nTempSize1 = aUpRect.GetHeight(); |
269 | 0 | nTempSize2 = aLowRect.GetHeight(); |
270 | 0 | if (std::abs(nTempSize1 - nTempSize2) == 1) |
271 | 0 | { |
272 | 0 | if (nTempSize1 > nTempSize2) |
273 | 0 | aUpRect.AdjustTop( 1 ); |
274 | 0 | else |
275 | 0 | aLowRect.AdjustTop( 1 ); |
276 | 0 | } |
277 | |
|
278 | 0 | const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings(); |
279 | |
|
280 | 0 | DrawSymbolFlags nSymStyle = DrawSymbolFlags::NONE; |
281 | 0 | if (!bUpperEnabled) |
282 | 0 | nSymStyle |= DrawSymbolFlags::Disable; |
283 | 0 | aDecoView.DrawSymbol(aUpRect, eType1, rStyleSettings.GetButtonTextColor(), nSymStyle); |
284 | |
|
285 | 0 | nSymStyle = DrawSymbolFlags::NONE; |
286 | 0 | if (!bLowerEnabled) |
287 | 0 | nSymStyle |= DrawSymbolFlags::Disable; |
288 | 0 | aDecoView.DrawSymbol(aLowRect, eType2, rStyleSettings.GetButtonTextColor(), nSymStyle); |
289 | 0 | } |
290 | | |
291 | | void SpinField::ImplInitSpinFieldData() |
292 | 0 | { |
293 | 0 | mpEdit.disposeAndClear(); |
294 | 0 | mbSpin = false; |
295 | 0 | mbRepeat = false; |
296 | 0 | mbUpperIn = false; |
297 | 0 | mbLowerIn = false; |
298 | 0 | mbInitialUp = false; |
299 | 0 | mbInitialDown = false; |
300 | 0 | mbInDropDown = false; |
301 | 0 | mbUpperEnabled = true; |
302 | 0 | mbLowerEnabled = true; |
303 | 0 | } |
304 | | |
305 | | void SpinField::ImplInit(vcl::Window* pParent, WinBits nWinStyle) |
306 | 0 | { |
307 | 0 | Edit::ImplInit( pParent, nWinStyle ); |
308 | |
|
309 | 0 | if (!(nWinStyle & (WB_SPIN | WB_DROPDOWN))) |
310 | 0 | return; |
311 | | |
312 | 0 | mbSpin = true; |
313 | | |
314 | | // Some themes want external spin buttons, therefore the main |
315 | | // spinfield should not overdraw the border between its encapsulated |
316 | | // edit field and the spin buttons |
317 | 0 | if ((nWinStyle & WB_SPIN) && ImplUseNativeBorder(*GetOutDev(), nWinStyle)) |
318 | 0 | { |
319 | 0 | SetBackground(); |
320 | 0 | mpEdit.reset(VclPtr<Edit>::Create(this, WB_NOBORDER)); |
321 | 0 | mpEdit->SetBackground(); |
322 | 0 | } |
323 | 0 | else |
324 | 0 | mpEdit.reset(VclPtr<Edit>::Create(this, WB_NOBORDER)); |
325 | |
|
326 | 0 | mpEdit->EnableRTL(false); |
327 | 0 | mpEdit->SetPosPixel(Point()); |
328 | 0 | mpEdit->Show(); |
329 | |
|
330 | 0 | SetSubEdit(mpEdit); |
331 | |
|
332 | 0 | maRepeatTimer.SetInvokeHandler(LINK( this, SpinField, ImplTimeout)); |
333 | 0 | maRepeatTimer.SetTimeout(MouseSettings::GetButtonStartRepeat()); |
334 | 0 | if (nWinStyle & WB_REPEAT) |
335 | 0 | mbRepeat = true; |
336 | |
|
337 | 0 | SetCompoundControl(true); |
338 | 0 | } |
339 | | |
340 | | SpinField::SpinField(vcl::Window* pParent, WinBits nWinStyle, WindowType eType) : |
341 | 0 | Edit(eType), maRepeatTimer("SpinField maRepeatTimer") |
342 | 0 | { |
343 | 0 | ImplInitSpinFieldData(); |
344 | 0 | ImplInit(pParent, nWinStyle); |
345 | 0 | } Unexecuted instantiation: SpinField::SpinField(vcl::Window*, long, WindowType) Unexecuted instantiation: SpinField::SpinField(vcl::Window*, long, WindowType) |
346 | | |
347 | | SpinField::~SpinField() |
348 | 0 | { |
349 | 0 | disposeOnce(); |
350 | 0 | } |
351 | | |
352 | | void SpinField::dispose() |
353 | 0 | { |
354 | 0 | mpEdit.disposeAndClear(); |
355 | |
|
356 | 0 | Edit::dispose(); |
357 | 0 | } |
358 | | |
359 | | void SpinField::Up() |
360 | 0 | { |
361 | 0 | ImplCallEventListenersAndHandler( VclEventId::SpinfieldUp, [this] () { maUpHdlLink.Call(*this); } ); |
362 | 0 | } |
363 | | |
364 | | void SpinField::Down() |
365 | 0 | { |
366 | 0 | ImplCallEventListenersAndHandler( VclEventId::SpinfieldDown, [this] () { maDownHdlLink.Call(*this); } ); |
367 | 0 | } |
368 | | |
369 | | void SpinField::First() |
370 | 0 | { |
371 | 0 | ImplCallEventListenersAndHandler(VclEventId::SpinfieldFirst, nullptr); |
372 | 0 | } |
373 | | |
374 | | void SpinField::Last() |
375 | 0 | { |
376 | 0 | ImplCallEventListenersAndHandler(VclEventId::SpinfieldLast, nullptr); |
377 | 0 | } |
378 | | |
379 | | void SpinField::MouseButtonDown( const MouseEvent& rMEvt ) |
380 | 0 | { |
381 | 0 | if (!HasFocus() && (!mpEdit || !mpEdit->HasFocus())) |
382 | 0 | { |
383 | 0 | GrabFocus(); |
384 | 0 | } |
385 | |
|
386 | 0 | if (!IsReadOnly()) |
387 | 0 | { |
388 | 0 | if (maUpperRect.Contains(rMEvt.GetPosPixel())) |
389 | 0 | { |
390 | 0 | mbUpperIn = true; |
391 | 0 | mbInitialUp = true; |
392 | 0 | Invalidate(maUpperRect); |
393 | 0 | } |
394 | 0 | else if (maLowerRect.Contains(rMEvt.GetPosPixel())) |
395 | 0 | { |
396 | 0 | mbLowerIn = true; |
397 | 0 | mbInitialDown = true; |
398 | 0 | Invalidate(maLowerRect); |
399 | 0 | } |
400 | 0 | else if (maDropDownRect.Contains(rMEvt.GetPosPixel())) |
401 | 0 | { |
402 | | // put DropDownButton to the right |
403 | 0 | mbInDropDown = ShowDropDown( !mbInDropDown ); |
404 | 0 | Invalidate(tools::Rectangle(Point(), GetOutputSizePixel())); |
405 | 0 | } |
406 | |
|
407 | 0 | if (mbUpperIn || mbLowerIn) |
408 | 0 | { |
409 | 0 | CaptureMouse(); |
410 | 0 | if (mbRepeat) |
411 | 0 | maRepeatTimer.Start(); |
412 | 0 | return; |
413 | 0 | } |
414 | 0 | } |
415 | | |
416 | 0 | Edit::MouseButtonDown(rMEvt); |
417 | 0 | } |
418 | | |
419 | | void SpinField::MouseButtonUp(const MouseEvent& rMEvt) |
420 | 0 | { |
421 | 0 | ReleaseMouse(); |
422 | 0 | mbInitialUp = mbInitialDown = false; |
423 | 0 | maRepeatTimer.Stop(); |
424 | 0 | maRepeatTimer.SetTimeout(MouseSettings::GetButtonStartRepeat()); |
425 | |
|
426 | 0 | if (mbUpperIn) |
427 | 0 | { |
428 | 0 | mbUpperIn = false; |
429 | 0 | Invalidate(maUpperRect); |
430 | 0 | Up(); |
431 | 0 | } |
432 | 0 | else if (mbLowerIn) |
433 | 0 | { |
434 | 0 | mbLowerIn = false; |
435 | 0 | Invalidate(maLowerRect); |
436 | 0 | Down(); |
437 | 0 | } |
438 | |
|
439 | 0 | Edit::MouseButtonUp(rMEvt); |
440 | 0 | } |
441 | | |
442 | | void SpinField::MouseMove(const MouseEvent& rMEvt) |
443 | 0 | { |
444 | 0 | if (rMEvt.IsLeft()) |
445 | 0 | { |
446 | 0 | if (mbInitialUp) |
447 | 0 | { |
448 | 0 | bool bNewUpperIn = maUpperRect.Contains(rMEvt.GetPosPixel()); |
449 | 0 | if (bNewUpperIn != mbUpperIn) |
450 | 0 | { |
451 | 0 | if (bNewUpperIn) |
452 | 0 | { |
453 | 0 | if (mbRepeat) |
454 | 0 | maRepeatTimer.Start(); |
455 | 0 | } |
456 | 0 | else |
457 | 0 | maRepeatTimer.Stop(); |
458 | |
|
459 | 0 | mbUpperIn = bNewUpperIn; |
460 | 0 | Invalidate(maUpperRect); |
461 | 0 | } |
462 | 0 | } |
463 | 0 | else if (mbInitialDown) |
464 | 0 | { |
465 | 0 | bool bNewLowerIn = maLowerRect.Contains(rMEvt.GetPosPixel()); |
466 | 0 | if (bNewLowerIn != mbLowerIn) |
467 | 0 | { |
468 | 0 | if (bNewLowerIn) |
469 | 0 | { |
470 | 0 | if (mbRepeat) |
471 | 0 | maRepeatTimer.Start(); |
472 | 0 | } |
473 | 0 | else |
474 | 0 | maRepeatTimer.Stop(); |
475 | |
|
476 | 0 | mbLowerIn = bNewLowerIn; |
477 | 0 | Invalidate(maLowerRect); |
478 | 0 | } |
479 | 0 | } |
480 | 0 | } |
481 | |
|
482 | 0 | Edit::MouseMove(rMEvt); |
483 | 0 | } |
484 | | |
485 | | bool SpinField::EventNotify(NotifyEvent& rNEvt) |
486 | 0 | { |
487 | 0 | bool bDone = false; |
488 | 0 | if (rNEvt.GetType() == NotifyEventType::KEYINPUT) |
489 | 0 | { |
490 | 0 | const KeyEvent& rKEvt = *rNEvt.GetKeyEvent(); |
491 | 0 | if (!IsReadOnly()) |
492 | 0 | { |
493 | 0 | sal_uInt16 nMod = rKEvt.GetKeyCode().GetModifier(); |
494 | 0 | switch (rKEvt.GetKeyCode().GetCode()) |
495 | 0 | { |
496 | 0 | case KEY_UP: |
497 | 0 | { |
498 | 0 | if (!nMod) |
499 | 0 | { |
500 | 0 | Up(); |
501 | 0 | bDone = true; |
502 | 0 | } |
503 | 0 | } |
504 | 0 | break; |
505 | 0 | case KEY_DOWN: |
506 | 0 | { |
507 | 0 | if (!nMod) |
508 | 0 | { |
509 | 0 | Down(); |
510 | 0 | bDone = true; |
511 | 0 | } |
512 | 0 | else if ((nMod == KEY_MOD2) && !mbInDropDown && (GetStyle() & WB_DROPDOWN)) |
513 | 0 | { |
514 | 0 | mbInDropDown = ShowDropDown(true); |
515 | 0 | Invalidate(tools::Rectangle(Point(), GetOutputSizePixel())); |
516 | 0 | bDone = true; |
517 | 0 | } |
518 | 0 | } |
519 | 0 | break; |
520 | 0 | case KEY_PAGEUP: |
521 | 0 | { |
522 | 0 | if (!nMod) |
523 | 0 | { |
524 | 0 | Last(); |
525 | 0 | bDone = true; |
526 | 0 | } |
527 | 0 | } |
528 | 0 | break; |
529 | 0 | case KEY_PAGEDOWN: |
530 | 0 | { |
531 | 0 | if (!nMod) |
532 | 0 | { |
533 | 0 | First(); |
534 | 0 | bDone = true; |
535 | 0 | } |
536 | 0 | } |
537 | 0 | break; |
538 | 0 | } |
539 | 0 | } |
540 | 0 | } |
541 | | |
542 | 0 | if (rNEvt.GetType() == NotifyEventType::COMMAND) |
543 | 0 | { |
544 | 0 | if ((rNEvt.GetCommandEvent()->GetCommand() == CommandEventId::Wheel) && !IsReadOnly()) |
545 | 0 | { |
546 | 0 | const tools::Rectangle aRect(Point(0, 0), GetSizePixel()); |
547 | 0 | const Point& rMousePos = rNEvt.GetCommandEvent()->GetMousePosPixel(); |
548 | 0 | const bool bMouseHovered = aRect.Contains(rMousePos); |
549 | |
|
550 | 0 | MouseWheelBehaviour nWheelBehavior(GetSettings().GetMouseSettings().GetWheelBehavior()); |
551 | 0 | if (bMouseHovered |
552 | 0 | && (nWheelBehavior == MouseWheelBehaviour::ALWAYS |
553 | 0 | || (nWheelBehavior == MouseWheelBehaviour::FocusOnly && HasChildPathFocus()))) |
554 | 0 | { |
555 | 0 | const CommandWheelData* pData = rNEvt.GetCommandEvent()->GetWheelData(); |
556 | 0 | if (pData->GetMode() == CommandWheelMode::SCROLL) |
557 | 0 | { |
558 | 0 | if (pData->GetDelta() < 0) |
559 | 0 | Down(); |
560 | 0 | else |
561 | 0 | Up(); |
562 | 0 | bDone = true; |
563 | |
|
564 | 0 | if (!HasChildPathFocus()) |
565 | 0 | GrabFocus(); |
566 | 0 | } |
567 | 0 | } |
568 | 0 | else |
569 | 0 | bDone = false; // don't eat this event, let the default handling happen (i.e. scroll the context) |
570 | 0 | } |
571 | 0 | } |
572 | |
|
573 | 0 | return bDone || Edit::EventNotify(rNEvt); |
574 | 0 | } |
575 | | |
576 | | void SpinField::FillLayoutData() const |
577 | 0 | { |
578 | 0 | if (mbSpin) |
579 | 0 | { |
580 | 0 | mxLayoutData.emplace(); |
581 | 0 | AppendLayoutData(*GetSubEdit()); |
582 | 0 | GetSubEdit()->SetLayoutDataParent(this); |
583 | 0 | } |
584 | 0 | else |
585 | 0 | Edit::FillLayoutData(); |
586 | 0 | } |
587 | | |
588 | | void SpinField::SetUpperEnabled(bool bEnabled) |
589 | 0 | { |
590 | 0 | if (mbUpperEnabled == bEnabled) |
591 | 0 | return; |
592 | | |
593 | 0 | mbUpperEnabled = bEnabled; |
594 | |
|
595 | 0 | if (mbSpin) |
596 | 0 | Invalidate(maUpperRect); |
597 | 0 | } |
598 | | |
599 | | void SpinField::SetLowerEnabled(bool bEnabled) |
600 | 0 | { |
601 | 0 | if (mbLowerEnabled == bEnabled) |
602 | 0 | return; |
603 | | |
604 | 0 | mbLowerEnabled = bEnabled; |
605 | |
|
606 | 0 | if (mbSpin) |
607 | 0 | Invalidate(maLowerRect); |
608 | 0 | } |
609 | | |
610 | | void SpinField::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) |
611 | 0 | { |
612 | 0 | if (mbSpin) |
613 | 0 | { |
614 | 0 | bool bEnabled = IsEnabled(); |
615 | 0 | bool bUpperEnabled = bEnabled && IsUpperEnabled(); |
616 | 0 | bool bLowerEnabled = bEnabled && IsLowerEnabled(); |
617 | 0 | ImplDrawSpinButton(rRenderContext, this, maUpperRect, maLowerRect, |
618 | 0 | mbUpperIn && bUpperEnabled, mbLowerIn && bLowerEnabled, |
619 | 0 | bUpperEnabled, bLowerEnabled); |
620 | 0 | } |
621 | |
|
622 | 0 | if (GetStyle() & WB_DROPDOWN) |
623 | 0 | { |
624 | 0 | DecorationView aView(&rRenderContext); |
625 | |
|
626 | 0 | DrawButtonFlags nStyle = DrawButtonFlags::NoLightBorder; |
627 | 0 | if (mbInDropDown) |
628 | 0 | nStyle |= DrawButtonFlags::Pressed; |
629 | 0 | tools::Rectangle aInnerRect = aView.DrawButton(maDropDownRect, nStyle); |
630 | |
|
631 | 0 | DrawSymbolFlags nSymbolStyle = IsEnabled() ? DrawSymbolFlags::NONE : DrawSymbolFlags::Disable; |
632 | 0 | aView.DrawSymbol(aInnerRect, SymbolType::SPIN_DOWN, rRenderContext.GetSettings().GetStyleSettings().GetButtonTextColor(), nSymbolStyle); |
633 | 0 | } |
634 | |
|
635 | 0 | Edit::Paint(rRenderContext, rRect); |
636 | 0 | } |
637 | | |
638 | | void SpinField::ImplCalcButtonAreas(const OutputDevice* pDev, const Size& rOutSz, tools::Rectangle& rDDArea, |
639 | | tools::Rectangle& rSpinUpArea, tools::Rectangle& rSpinDownArea) |
640 | 0 | { |
641 | 0 | const StyleSettings& rStyleSettings = pDev->GetSettings().GetStyleSettings(); |
642 | |
|
643 | 0 | Size aSize = rOutSz; |
644 | 0 | Size aDropDownSize; |
645 | |
|
646 | 0 | if (GetStyle() & WB_DROPDOWN) |
647 | 0 | { |
648 | 0 | tools::Long nW = rStyleSettings.GetScrollBarSize(); |
649 | 0 | nW = GetDrawPixel( pDev, nW ); |
650 | 0 | aDropDownSize = Size( CalcZoom( nW ), aSize.Height() ); |
651 | 0 | aSize.AdjustWidth( -(aDropDownSize.Width()) ); |
652 | 0 | rDDArea = tools::Rectangle( Point( aSize.Width(), 0 ), aDropDownSize ); |
653 | 0 | rDDArea.AdjustTop( -1 ); |
654 | 0 | } |
655 | 0 | else |
656 | 0 | rDDArea.SetEmpty(); |
657 | | |
658 | | // calculate sizes according to the height |
659 | 0 | if (GetStyle() & WB_SPIN) |
660 | 0 | { |
661 | 0 | tools::Long nBottom1 = aSize.Height()/2; |
662 | 0 | tools::Long nBottom2 = aSize.Height()-1; |
663 | 0 | tools::Long nTop2 = nBottom1; |
664 | 0 | if ( !(aSize.Height() & 0x01) ) |
665 | 0 | nBottom1--; |
666 | |
|
667 | 0 | bool bNativeRegionOK = false; |
668 | 0 | tools::Rectangle aContentUp, aContentDown; |
669 | |
|
670 | 0 | if ((pDev->GetOutDevType() == OUTDEV_WINDOW) && |
671 | | // there is just no useful native support for spinfields with dropdown |
672 | 0 | ! (GetStyle() & WB_DROPDOWN) && |
673 | 0 | IsNativeControlSupported(ControlType::Spinbox, ControlPart::Entire)) |
674 | 0 | { |
675 | 0 | vcl::Window *pWin = pDev->GetOwnerWindow(); |
676 | 0 | vcl::Window *pBorder = pWin->GetWindow( GetWindowType::Border ); |
677 | | |
678 | | // get the system's spin button size |
679 | 0 | ImplControlValue aControlValue; |
680 | 0 | tools::Rectangle aBound; |
681 | 0 | Point aPoint; |
682 | | |
683 | | // use the full extent of the control |
684 | 0 | tools::Rectangle aArea( aPoint, pBorder->GetOutputSizePixel() ); |
685 | |
|
686 | 0 | bNativeRegionOK = |
687 | 0 | pWin->GetNativeControlRegion(ControlType::Spinbox, ControlPart::ButtonUp, |
688 | 0 | aArea, ControlState::NONE, aControlValue, aBound, aContentUp) && |
689 | 0 | pWin->GetNativeControlRegion(ControlType::Spinbox, ControlPart::ButtonDown, |
690 | 0 | aArea, ControlState::NONE, aControlValue, aBound, aContentDown); |
691 | |
|
692 | 0 | if (bNativeRegionOK) |
693 | 0 | { |
694 | | // convert back from border space to local coordinates |
695 | 0 | aPoint = pBorder->ScreenToOutputPixel( pWin->OutputToScreenPixel( aPoint ) ); |
696 | 0 | aContentUp.Move(-aPoint.X(), -aPoint.Y()); |
697 | 0 | aContentDown.Move(-aPoint.X(), -aPoint.Y()); |
698 | 0 | } |
699 | 0 | } |
700 | |
|
701 | 0 | if (bNativeRegionOK) |
702 | 0 | { |
703 | 0 | rSpinUpArea = aContentUp; |
704 | 0 | rSpinDownArea = aContentDown; |
705 | 0 | } |
706 | 0 | else |
707 | 0 | { |
708 | 0 | aSize.AdjustWidth( -(CalcZoom( GetDrawPixel( pDev, rStyleSettings.GetSpinSize() ) )) ); |
709 | |
|
710 | 0 | rSpinUpArea = tools::Rectangle( aSize.Width(), 0, rOutSz.Width()-aDropDownSize.Width()-1, nBottom1 ); |
711 | 0 | rSpinDownArea = tools::Rectangle( rSpinUpArea.Left(), nTop2, rSpinUpArea.Right(), nBottom2 ); |
712 | 0 | } |
713 | 0 | } |
714 | 0 | else |
715 | 0 | { |
716 | 0 | rSpinUpArea.SetEmpty(); |
717 | 0 | rSpinDownArea.SetEmpty(); |
718 | 0 | } |
719 | 0 | } |
720 | | |
721 | | void SpinField::Resize() |
722 | 0 | { |
723 | 0 | if (!mbSpin) |
724 | 0 | return; |
725 | | |
726 | 0 | Control::Resize(); |
727 | 0 | Size aSize = GetOutputSizePixel(); |
728 | 0 | bool bSubEditPositioned = false; |
729 | |
|
730 | 0 | if (GetStyle() & (WB_SPIN | WB_DROPDOWN)) |
731 | 0 | { |
732 | 0 | ImplCalcButtonAreas( GetOutDev(), aSize, maDropDownRect, maUpperRect, maLowerRect ); |
733 | |
|
734 | 0 | ImplControlValue aControlValue; |
735 | 0 | Point aPoint; |
736 | 0 | tools::Rectangle aContent, aBound; |
737 | | |
738 | | // use the full extent of the control |
739 | 0 | vcl::Window *pBorder = GetWindow( GetWindowType::Border ); |
740 | 0 | tools::Rectangle aArea( aPoint, pBorder->GetOutputSizePixel() ); |
741 | | |
742 | | // adjust position and size of the edit field |
743 | 0 | if (GetNativeControlRegion(ControlType::Spinbox, ControlPart::SubEdit, aArea, ControlState::NONE, |
744 | 0 | aControlValue, aBound, aContent) && |
745 | | // there is just no useful native support for spinfields with dropdown |
746 | 0 | !(GetStyle() & WB_DROPDOWN)) |
747 | 0 | { |
748 | | // convert back from border space to local coordinates |
749 | 0 | aPoint = pBorder->ScreenToOutputPixel(OutputToScreenPixel(aPoint)); |
750 | 0 | aContent.Move(-aPoint.X(), -aPoint.Y()); |
751 | | |
752 | | // use the themes drop down size |
753 | 0 | mpEdit->SetPosPixel( aContent.TopLeft() ); |
754 | 0 | bSubEditPositioned = true; |
755 | 0 | aSize = aContent.GetSize(); |
756 | 0 | } |
757 | 0 | else |
758 | 0 | { |
759 | 0 | if (maUpperRect.IsEmpty()) |
760 | 0 | { |
761 | 0 | SAL_WARN_IF( maDropDownRect.IsEmpty(), "vcl", "SpinField::Resize: SPIN && DROPDOWN, but all empty rects?" ); |
762 | 0 | aSize.setWidth( maDropDownRect.Left() ); |
763 | 0 | } |
764 | 0 | else |
765 | 0 | aSize.setWidth( maUpperRect.Left() ); |
766 | 0 | } |
767 | 0 | } |
768 | | |
769 | 0 | if (!bSubEditPositioned) |
770 | 0 | { |
771 | | // this moves our sub edit if RTL gets switched |
772 | 0 | mpEdit->SetPosPixel(Point()); |
773 | 0 | } |
774 | 0 | mpEdit->SetSizePixel(aSize); |
775 | |
|
776 | 0 | if (GetStyle() & WB_SPIN) |
777 | 0 | Invalidate(tools::Rectangle(maUpperRect.TopLeft(), maLowerRect.BottomRight())); |
778 | 0 | if (GetStyle() & WB_DROPDOWN) |
779 | 0 | Invalidate(maDropDownRect); |
780 | 0 | } |
781 | | |
782 | | void SpinField::StateChanged(StateChangedType nType) |
783 | 0 | { |
784 | 0 | Edit::StateChanged(nType); |
785 | |
|
786 | 0 | if (nType == StateChangedType::Enable) |
787 | 0 | { |
788 | 0 | if (mbSpin || (GetStyle() & WB_DROPDOWN)) |
789 | 0 | { |
790 | 0 | mpEdit->Enable(IsEnabled()); |
791 | |
|
792 | 0 | if (mbSpin) |
793 | 0 | { |
794 | 0 | Invalidate(maLowerRect); |
795 | 0 | Invalidate(maUpperRect); |
796 | 0 | } |
797 | 0 | if (GetStyle() & WB_DROPDOWN) |
798 | 0 | Invalidate(maDropDownRect); |
799 | 0 | } |
800 | 0 | } |
801 | 0 | else if (nType == StateChangedType::Style) |
802 | 0 | { |
803 | 0 | if (GetStyle() & WB_REPEAT) |
804 | 0 | mbRepeat = true; |
805 | 0 | else |
806 | 0 | mbRepeat = false; |
807 | 0 | } |
808 | 0 | else if (nType == StateChangedType::Zoom) |
809 | 0 | { |
810 | 0 | Resize(); |
811 | 0 | if (mpEdit) |
812 | 0 | mpEdit->SetZoom(GetZoom()); |
813 | 0 | Invalidate(); |
814 | 0 | } |
815 | 0 | else if (nType == StateChangedType::ControlFont) |
816 | 0 | { |
817 | 0 | if (mpEdit) |
818 | 0 | mpEdit->SetControlFont(GetControlFont()); |
819 | 0 | Invalidate(); |
820 | 0 | } |
821 | 0 | else if (nType == StateChangedType::ControlForeground) |
822 | 0 | { |
823 | 0 | if (mpEdit) |
824 | 0 | mpEdit->SetControlForeground(GetControlForeground()); |
825 | 0 | Invalidate(); |
826 | 0 | } |
827 | 0 | else if (nType == StateChangedType::ControlBackground) |
828 | 0 | { |
829 | 0 | if (mpEdit) |
830 | 0 | mpEdit->SetControlBackground(GetControlBackground()); |
831 | 0 | Invalidate(); |
832 | 0 | } |
833 | 0 | else if( nType == StateChangedType::Mirroring ) |
834 | 0 | { |
835 | 0 | if (mpEdit) |
836 | 0 | mpEdit->CompatStateChanged(StateChangedType::Mirroring); |
837 | 0 | Resize(); |
838 | 0 | } |
839 | 0 | } |
840 | | |
841 | | void SpinField::DataChanged( const DataChangedEvent& rDCEvt ) |
842 | 0 | { |
843 | 0 | Edit::DataChanged(rDCEvt); |
844 | |
|
845 | 0 | if ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) && |
846 | 0 | (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) |
847 | 0 | { |
848 | 0 | Resize(); |
849 | 0 | Invalidate(); |
850 | 0 | } |
851 | 0 | } |
852 | | |
853 | | tools::Rectangle* SpinField::ImplFindPartRect(const Point& rPt) |
854 | 0 | { |
855 | 0 | if (maUpperRect.Contains(rPt)) |
856 | 0 | return &maUpperRect; |
857 | 0 | else if (maLowerRect.Contains(rPt)) |
858 | 0 | return &maLowerRect; |
859 | 0 | else |
860 | 0 | return nullptr; |
861 | 0 | } |
862 | | |
863 | | bool SpinField::PreNotify(NotifyEvent& rNEvt) |
864 | 0 | { |
865 | 0 | if (rNEvt.GetType() == NotifyEventType::MOUSEMOVE) |
866 | 0 | { |
867 | 0 | const MouseEvent* pMouseEvt = rNEvt.GetMouseEvent(); |
868 | 0 | if (pMouseEvt && !pMouseEvt->GetButtons() && !pMouseEvt->IsSynthetic() && !pMouseEvt->IsModifierChanged()) |
869 | 0 | { |
870 | | // trigger redraw if mouse over state has changed |
871 | 0 | if( IsNativeControlSupported(ControlType::Spinbox, ControlPart::Entire) || |
872 | 0 | IsNativeControlSupported(ControlType::Spinbox, ControlPart::AllButtons) ) |
873 | 0 | { |
874 | 0 | tools::Rectangle* pRect = ImplFindPartRect( GetPointerPosPixel() ); |
875 | 0 | tools::Rectangle* pLastRect = ImplFindPartRect( GetLastPointerPosPixel() ); |
876 | 0 | if( pRect != pLastRect || (pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow()) ) |
877 | 0 | { |
878 | 0 | if (!IsNativeWidgetEnabled() || |
879 | 0 | !IsNativeControlSupported(ControlType::Editbox, ControlPart::Entire)) |
880 | 0 | { |
881 | | // paint directly |
882 | 0 | vcl::Region aRgn( GetOutDev()->GetActiveClipRegion() ); |
883 | 0 | if (pLastRect) |
884 | 0 | { |
885 | 0 | GetOutDev()->SetClipRegion(vcl::Region(*pLastRect)); |
886 | 0 | Invalidate(*pLastRect); |
887 | 0 | GetOutDev()->SetClipRegion( aRgn ); |
888 | 0 | } |
889 | 0 | if (pRect) |
890 | 0 | { |
891 | 0 | GetOutDev()->SetClipRegion(vcl::Region(*pRect)); |
892 | 0 | Invalidate(*pRect); |
893 | 0 | GetOutDev()->SetClipRegion( aRgn ); |
894 | 0 | } |
895 | 0 | } |
896 | 0 | } |
897 | 0 | } |
898 | 0 | } |
899 | 0 | } |
900 | |
|
901 | 0 | return Edit::PreNotify(rNEvt); |
902 | 0 | } |
903 | | |
904 | | void SpinField::EndDropDown() |
905 | 0 | { |
906 | 0 | mbInDropDown = false; |
907 | 0 | Invalidate(tools::Rectangle(Point(), GetOutputSizePixel())); |
908 | 0 | } |
909 | | |
910 | | bool SpinField::ShowDropDown( bool ) |
911 | 0 | { |
912 | 0 | return false; |
913 | 0 | } |
914 | | |
915 | | Size SpinField::CalcMinimumSizeForText(const OUString &rString) const |
916 | 0 | { |
917 | 0 | Size aSz = Edit::CalcMinimumSizeForText(rString); |
918 | |
|
919 | 0 | if ( GetStyle() & WB_DROPDOWN ) |
920 | 0 | aSz.AdjustWidth(GetSettings().GetStyleSettings().GetScrollBarSize() ); |
921 | 0 | if ( GetStyle() & WB_SPIN ) |
922 | 0 | { |
923 | 0 | ImplControlValue aControlValue; |
924 | 0 | tools::Rectangle aArea( Point(), Size(100, aSz.Height())); |
925 | 0 | tools::Rectangle aEntireBound, aEntireContent, aEditBound, aEditContent; |
926 | 0 | if ( |
927 | 0 | GetNativeControlRegion(ControlType::Spinbox, ControlPart::Entire, |
928 | 0 | aArea, ControlState::NONE, aControlValue, aEntireBound, aEntireContent) && |
929 | 0 | GetNativeControlRegion(ControlType::Spinbox, ControlPart::SubEdit, |
930 | 0 | aArea, ControlState::NONE, aControlValue, aEditBound, aEditContent) |
931 | 0 | ) |
932 | 0 | { |
933 | 0 | aSz.AdjustWidth(aEntireContent.GetWidth() - aEditContent.GetWidth()); |
934 | 0 | } |
935 | 0 | else |
936 | 0 | { |
937 | 0 | aSz.AdjustWidth(maUpperRect.GetWidth() ); |
938 | 0 | } |
939 | 0 | } |
940 | |
|
941 | 0 | return aSz; |
942 | 0 | } |
943 | | |
944 | | Size SpinField::CalcMinimumSize() const |
945 | 0 | { |
946 | 0 | return CalcMinimumSizeForText(GetText()); |
947 | 0 | } |
948 | | |
949 | | Size SpinField::GetOptimalSize() const |
950 | 0 | { |
951 | 0 | return CalcMinimumSize(); |
952 | 0 | } |
953 | | |
954 | | Size SpinField::CalcSize(sal_Int32 nChars) const |
955 | 0 | { |
956 | 0 | Size aSz = Edit::CalcSize( nChars ); |
957 | |
|
958 | 0 | if ( GetStyle() & WB_DROPDOWN ) |
959 | 0 | aSz.AdjustWidth(GetSettings().GetStyleSettings().GetScrollBarSize() ); |
960 | 0 | if ( GetStyle() & WB_SPIN ) |
961 | 0 | aSz.AdjustWidth(GetSettings().GetStyleSettings().GetSpinSize() ); |
962 | |
|
963 | 0 | return aSz; |
964 | 0 | } |
965 | | |
966 | | IMPL_LINK( SpinField, ImplTimeout, Timer*, pTimer, void ) |
967 | 0 | { |
968 | 0 | if ( pTimer->GetTimeout() == static_cast<sal_uInt64>(MouseSettings::GetButtonStartRepeat()) ) |
969 | 0 | { |
970 | 0 | pTimer->SetTimeout( GetSettings().GetMouseSettings().GetButtonRepeat() ); |
971 | 0 | pTimer->Start(); |
972 | 0 | } |
973 | 0 | else |
974 | 0 | { |
975 | 0 | if ( mbInitialUp ) |
976 | 0 | Up(); |
977 | 0 | else |
978 | 0 | Down(); |
979 | 0 | } |
980 | 0 | } |
981 | | |
982 | | void SpinField::Draw(OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags) |
983 | 0 | { |
984 | 0 | Edit::Draw(pDev, rPos, nFlags); |
985 | |
|
986 | 0 | WinBits nFieldStyle = GetStyle(); |
987 | 0 | if ( (nFlags & SystemTextColorFlags::NoControls ) || !( nFieldStyle & (WB_SPIN|WB_DROPDOWN) ) ) |
988 | 0 | return; |
989 | | |
990 | 0 | Point aPos = pDev->LogicToPixel( rPos ); |
991 | 0 | Size aSize = GetSizePixel(); |
992 | 0 | AllSettings aOldSettings = pDev->GetSettings(); |
993 | |
|
994 | 0 | pDev->Push(); |
995 | 0 | pDev->SetMapMode(); |
996 | |
|
997 | 0 | tools::Rectangle aDD, aUp, aDown; |
998 | 0 | ImplCalcButtonAreas(pDev, aSize, aDD, aUp, aDown); |
999 | 0 | aDD.Move(aPos.X(), aPos.Y()); |
1000 | 0 | aUp.Move(aPos.X(), aPos.Y()); |
1001 | 0 | aUp.AdjustTop( 1 ); |
1002 | 0 | aDown.Move(aPos.X(), aPos.Y()); |
1003 | |
|
1004 | 0 | Color aButtonTextColor; |
1005 | 0 | if (nFlags & SystemTextColorFlags::Mono) |
1006 | 0 | aButtonTextColor = COL_BLACK; |
1007 | 0 | else |
1008 | 0 | aButtonTextColor = GetSettings().GetStyleSettings().GetButtonTextColor(); |
1009 | |
|
1010 | 0 | if (GetStyle() & WB_DROPDOWN) |
1011 | 0 | { |
1012 | 0 | DecorationView aView( pDev ); |
1013 | 0 | tools::Rectangle aInnerRect = aView.DrawButton( aDD, DrawButtonFlags::NoLightBorder ); |
1014 | 0 | DrawSymbolFlags nSymbolStyle = IsEnabled() ? DrawSymbolFlags::NONE : DrawSymbolFlags::Disable; |
1015 | 0 | aView.DrawSymbol(aInnerRect, SymbolType::SPIN_DOWN, aButtonTextColor, nSymbolStyle); |
1016 | 0 | } |
1017 | |
|
1018 | 0 | if (GetStyle() & WB_SPIN) |
1019 | 0 | { |
1020 | 0 | ImplDrawSpinButton(*pDev, this, aUp, aDown, false, false); |
1021 | 0 | } |
1022 | |
|
1023 | 0 | pDev->Pop(); |
1024 | 0 | pDev->SetSettings(aOldSettings); |
1025 | |
|
1026 | 0 | } |
1027 | | |
1028 | | FactoryFunction SpinField::GetUITestFactory() const |
1029 | 0 | { |
1030 | 0 | return SpinFieldUIObject::create; |
1031 | 0 | } |
1032 | | |
1033 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |