LibreOffice Module vcl (master) 1
spinfld.cxx
Go to the documentation of this file.
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>
24#include <vcl/settings.hxx>
26#include <sal/log.hxx>
27
28#include <spin.hxx>
29#include <svdata.hxx>
30
31namespace {
32
33void ImplGetSpinbuttonValue(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{
38 // convert spinbutton data to a SpinbuttonValue structure for native painting
39
40 rValue.maUpperRect = rUpperRect;
41 rValue.maLowerRect = rLowerRect;
42
43 Point aPointerPos = pWin->GetPointerPosPixel();
44
46 if (bUpperIn)
48 if (!pWin->IsEnabled() || !bUpperEnabled)
49 nState &= ~ControlState::ENABLED;
50 if (pWin->HasFocus())
52 if (pWin->IsMouseOver() && rUpperRect.Contains(aPointerPos))
54 rValue.mnUpperState = nState;
55
57 if (bLowerIn)
59 if (!pWin->IsEnabled() || !bLowerEnabled)
60 nState &= ~ControlState::ENABLED;
61 if (pWin->HasFocus())
63 // for overlapping spins: highlight only one
64 if (pWin->IsMouseOver() && rLowerRect.Contains(aPointerPos) && !rUpperRect.Contains(aPointerPos))
66 rValue.mnLowerState = nState;
67
70}
71
72bool ImplDrawNativeSpinfield(vcl::RenderContext& rRenderContext, vcl::Window const * pWin, const SpinbuttonValue& rSpinbuttonValue)
73{
74 bool bNativeOK = false;
75
77 // there is just no useful native support for spinfields with dropdown
78 !(pWin->GetStyle() & WB_DROPDOWN))
79 {
80 if (rRenderContext.IsNativeControlSupported(ControlType::Spinbox, rSpinbuttonValue.mnUpperPart) &&
81 rRenderContext.IsNativeControlSupported(ControlType::Spinbox, rSpinbuttonValue.mnLowerPart))
82 {
83 // only paint the embedded spin buttons, all buttons are painted at once
84 tools::Rectangle aUpperAndLowerButtons( rSpinbuttonValue.maUpperRect.GetUnion( rSpinbuttonValue.maLowerRect ) );
85 bNativeOK = rRenderContext.DrawNativeControl(ControlType::Spinbox, ControlPart::AllButtons, aUpperAndLowerButtons,
86 ControlState::ENABLED, rSpinbuttonValue, OUString());
87 }
88 else
89 {
90 // paint the spinbox as a whole, use borderwindow to have proper clipping
92
93 // to not overwrite everything, set the button region as clipregion to the border window
94 tools::Rectangle aClipRect(rSpinbuttonValue.maLowerRect);
95 aClipRect.Union(rSpinbuttonValue.maUpperRect);
96
97 vcl::RenderContext* pContext = &rRenderContext;
98 vcl::Region oldRgn;
99 Point aPt;
100 Size aSize(pBorder->GetOutputSizePixel()); // the size of the border window, i.e., the whole control
101 tools::Rectangle aNatRgn(aPt, aSize);
102
103 if (!pWin->SupportsDoubleBuffering())
104 {
105 // convert from screen space to borderwin space
106 aClipRect.SetPos(pBorder->ScreenToOutputPixel(pWin->OutputToScreenPixel(aClipRect.TopLeft())));
107
108 oldRgn = pBorder->GetOutDev()->GetClipRegion();
109 pBorder->GetOutDev()->SetClipRegion(vcl::Region(aClipRect));
110
111 pContext = pBorder->GetOutDev();
112 }
113
114 tools::Rectangle aBound, aContent;
115 if (!ImplGetSVData()->maNWFData.mbCanDrawWidgetAnySize &&
117 aNatRgn, ControlState::NONE, rSpinbuttonValue,
118 aBound, aContent))
119 {
120 aSize = aContent.GetSize();
121 }
122
123 tools::Rectangle aRgn(aPt, aSize);
124 if (pWin->SupportsDoubleBuffering())
125 {
126 // convert from borderwin space, to the pWin's space
127 aRgn.SetPos(pWin->ScreenToOutputPixel(pBorder->OutputToScreenPixel(aRgn.TopLeft())));
128 }
129
131 ControlState::ENABLED, rSpinbuttonValue, OUString());
132
133 if (!pWin->SupportsDoubleBuffering())
134 pBorder->GetOutDev()->SetClipRegion(oldRgn);
135 }
136 }
137 return bNativeOK;
138}
139
140bool ImplDrawNativeSpinbuttons(vcl::RenderContext& rRenderContext, const SpinbuttonValue& rSpinbuttonValue)
141{
142 bool bNativeOK = false;
143
145 {
146 tools::Rectangle aArea = rSpinbuttonValue.maUpperRect.GetUnion(rSpinbuttonValue.maLowerRect);
147 // only paint the standalone spin buttons, all buttons are painted at once
148 bNativeOK = rRenderContext.DrawNativeControl(ControlType::SpinButtons, ControlPart::AllButtons, aArea,
149 ControlState::ENABLED, rSpinbuttonValue, OUString());
150 }
151 return bNativeOK;
152}
153
154}
155
156void 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{
161 bool bNativeOK = false;
162
163 if (pWindow)
164 {
165 // are we drawing standalone spin buttons or members of a spinfield ?
167 switch (pWindow->GetType())
168 {
169 case WindowType::EDIT:
178 aControl = ControlType::Spinbox;
179 break;
180 default:
181 aControl = ControlType::SpinButtons;
182 break;
183 }
184
185 SpinbuttonValue aValue;
186 ImplGetSpinbuttonValue(pWindow, rUpperRect, rLowerRect,
187 bUpperIn, bLowerIn, bUpperEnabled, bLowerEnabled,
188 bHorz, aValue);
189
190 if( aControl == ControlType::Spinbox )
191 bNativeOK = ImplDrawNativeSpinfield(rRenderContext, pWindow, aValue);
192 else if( aControl == ControlType::SpinButtons )
193 bNativeOK = ImplDrawNativeSpinbuttons(rRenderContext, aValue);
194 }
195
196 if (bNativeOK)
197 return;
198
199 ImplDrawUpDownButtons(rRenderContext,
200 rUpperRect, rLowerRect,
201 bUpperIn, bLowerIn, bUpperEnabled, bLowerEnabled,
202 bHorz, bMirrorHorz);
203}
204
206 const tools::Rectangle& rUpperRect, const tools::Rectangle& rLowerRect,
207 bool bUpperIn, bool bLowerIn, bool bUpperEnabled, bool bLowerEnabled,
208 bool bHorz, bool bMirrorHorz)
209{
210 DecorationView aDecoView(&rRenderContext);
211
212 SymbolType eType1, eType2;
213
214 if ( bHorz )
215 {
216 eType1 = bMirrorHorz ? SymbolType::SPIN_RIGHT : SymbolType::SPIN_LEFT;
217 eType2 = bMirrorHorz ? SymbolType::SPIN_LEFT : SymbolType::SPIN_RIGHT;
218 }
219 else
220 {
221 eType1 = SymbolType::SPIN_UP;
222 eType2 = SymbolType::SPIN_DOWN;
223 }
224
226 // draw upper/left Button
227 if (bUpperIn)
228 nStyle |= DrawButtonFlags::Pressed;
229
230 tools::Rectangle aUpRect = aDecoView.DrawButton(rUpperRect, nStyle);
231
233 // draw lower/right Button
234 if (bLowerIn)
235 nStyle |= DrawButtonFlags::Pressed;
236
237 tools::Rectangle aLowRect = aDecoView.DrawButton(rLowerRect, nStyle);
238
239 // make use of additional default edge
240 aUpRect.AdjustLeft( -1 );
241 aUpRect.AdjustTop( -1 );
242 aUpRect.AdjustRight( 1 );
243 aUpRect.AdjustBottom( 1 );
244 aLowRect.AdjustLeft( -1 );
245 aLowRect.AdjustTop( -1 );
246 aLowRect.AdjustRight( 1 );
247 aLowRect.AdjustBottom( 1 );
248
249 // draw into the edge, so that something is visible if the rectangle is too small
250 if (aUpRect.GetHeight() < 4)
251 {
252 aUpRect.AdjustRight( 1 );
253 aUpRect.AdjustBottom( 1 );
254 aLowRect.AdjustRight( 1 );
255 aLowRect.AdjustBottom( 1 );
256 }
257
258 // calculate Symbol size
259 tools::Long nTempSize1 = aUpRect.GetWidth();
260 tools::Long nTempSize2 = aLowRect.GetWidth();
261 if (std::abs( nTempSize1-nTempSize2 ) == 1)
262 {
263 if (nTempSize1 > nTempSize2)
264 aUpRect.AdjustLeft( 1 );
265 else
266 aLowRect.AdjustLeft( 1 );
267 }
268 nTempSize1 = aUpRect.GetHeight();
269 nTempSize2 = aLowRect.GetHeight();
270 if (std::abs(nTempSize1 - nTempSize2) == 1)
271 {
272 if (nTempSize1 > nTempSize2)
273 aUpRect.AdjustTop( 1 );
274 else
275 aLowRect.AdjustTop( 1 );
276 }
277
278 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
279
281 if (!bUpperEnabled)
282 nSymStyle |= DrawSymbolFlags::Disable;
283 aDecoView.DrawSymbol(aUpRect, eType1, rStyleSettings.GetButtonTextColor(), nSymStyle);
284
285 nSymStyle = DrawSymbolFlags::NONE;
286 if (!bLowerEnabled)
287 nSymStyle |= DrawSymbolFlags::Disable;
288 aDecoView.DrawSymbol(aLowRect, eType2, rStyleSettings.GetButtonTextColor(), nSymStyle);
289}
290
292{
294 mbSpin = false;
295 mbRepeat = false;
296 mbUpperIn = false;
297 mbLowerIn = false;
298 mbInitialUp = false;
299 mbInitialDown = false;
300 mbInDropDown = false;
301 mbUpperEnabled = true;
302 mbLowerEnabled = true;
303}
304
305void SpinField::ImplInit(vcl::Window* pParent, WinBits nWinStyle)
306{
307 Edit::ImplInit( pParent, nWinStyle );
308
309 if (!(nWinStyle & (WB_SPIN | WB_DROPDOWN)))
310 return;
311
312 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 if ((nWinStyle & WB_SPIN) && ImplUseNativeBorder(*GetOutDev(), nWinStyle))
318 {
322 }
323 else
325
326 mpEdit->EnableRTL(false);
328 mpEdit->Show();
329
331
332 maRepeatTimer.SetInvokeHandler(LINK( this, SpinField, ImplTimeout));
334 if (nWinStyle & WB_REPEAT)
335 mbRepeat = true;
336
337 SetCompoundControl(true);
338}
339
341 Edit(nType), maRepeatTimer("SpinField maRepeatTimer")
342{
344 ImplInit(pParent, nWinStyle);
345}
346
348{
349 disposeOnce();
350}
351
353{
355
357}
358
360{
362}
363
365{
367}
368
370{
372}
373
375{
377}
378
380{
381 if (!HasFocus() && (!mpEdit || !mpEdit->HasFocus()))
382 {
383 GrabFocus();
384 }
385
386 if (!IsReadOnly())
387 {
388 if (maUpperRect.Contains(rMEvt.GetPosPixel()))
389 {
390 mbUpperIn = true;
391 mbInitialUp = true;
393 }
394 else if (maLowerRect.Contains(rMEvt.GetPosPixel()))
395 {
396 mbLowerIn = true;
397 mbInitialDown = true;
399 }
400 else if (maDropDownRect.Contains(rMEvt.GetPosPixel()))
401 {
402 // put DropDownButton to the right
405 }
406
407 if (mbUpperIn || mbLowerIn)
408 {
409 CaptureMouse();
410 if (mbRepeat)
412 return;
413 }
414 }
415
417}
418
420{
421 ReleaseMouse();
422 mbInitialUp = mbInitialDown = false;
425
426 if (mbUpperIn)
427 {
428 mbUpperIn = false;
430 Up();
431 }
432 else if (mbLowerIn)
433 {
434 mbLowerIn = false;
436 Down();
437 }
438
439 Edit::MouseButtonUp(rMEvt);
440}
441
443{
444 if (rMEvt.IsLeft())
445 {
446 if (mbInitialUp)
447 {
448 bool bNewUpperIn = maUpperRect.Contains(rMEvt.GetPosPixel());
449 if (bNewUpperIn != mbUpperIn)
450 {
451 if (bNewUpperIn)
452 {
453 if (mbRepeat)
455 }
456 else
458
459 mbUpperIn = bNewUpperIn;
461 }
462 }
463 else if (mbInitialDown)
464 {
465 bool bNewLowerIn = maLowerRect.Contains(rMEvt.GetPosPixel());
466 if (bNewLowerIn != mbLowerIn)
467 {
468 if (bNewLowerIn)
469 {
470 if (mbRepeat)
472 }
473 else
475
476 mbLowerIn = bNewLowerIn;
478 }
479 }
480 }
481
482 Edit::MouseMove(rMEvt);
483}
484
486{
487 bool bDone = false;
488 if (rNEvt.GetType() == NotifyEventType::KEYINPUT)
489 {
490 const KeyEvent& rKEvt = *rNEvt.GetKeyEvent();
491 if (!IsReadOnly())
492 {
493 sal_uInt16 nMod = rKEvt.GetKeyCode().GetModifier();
494 switch (rKEvt.GetKeyCode().GetCode())
495 {
496 case KEY_UP:
497 {
498 if (!nMod)
499 {
500 Up();
501 bDone = true;
502 }
503 }
504 break;
505 case KEY_DOWN:
506 {
507 if (!nMod)
508 {
509 Down();
510 bDone = true;
511 }
512 else if ((nMod == KEY_MOD2) && !mbInDropDown && (GetStyle() & WB_DROPDOWN))
513 {
516 bDone = true;
517 }
518 }
519 break;
520 case KEY_PAGEUP:
521 {
522 if (!nMod)
523 {
524 Last();
525 bDone = true;
526 }
527 }
528 break;
529 case KEY_PAGEDOWN:
530 {
531 if (!nMod)
532 {
533 First();
534 bDone = true;
535 }
536 }
537 break;
538 }
539 }
540 }
541
542 if (rNEvt.GetType() == NotifyEventType::COMMAND)
543 {
545 {
546 MouseWheelBehaviour nWheelBehavior(GetSettings().GetMouseSettings().GetWheelBehavior());
547 if (nWheelBehavior == MouseWheelBehaviour::ALWAYS
548 || (nWheelBehavior == MouseWheelBehaviour::FocusOnly && HasChildPathFocus()))
549 {
551 if (pData->GetMode() == CommandWheelMode::SCROLL)
552 {
553 if (pData->GetDelta() < 0)
554 Down();
555 else
556 Up();
557 bDone = true;
558
559 if (!HasChildPathFocus())
560 GrabFocus();
561 }
562 }
563 else
564 bDone = false; // don't eat this event, let the default handling happen (i.e. scroll the context)
565 }
566 }
567
568 return bDone || Edit::EventNotify(rNEvt);
569}
570
572{
573 if (mbSpin)
574 {
575 mxLayoutData.emplace();
578 }
579 else
581}
582
583void SpinField::SetUpperEnabled(bool bEnabled)
584{
585 if (mbUpperEnabled == bEnabled)
586 return;
587
588 mbUpperEnabled = bEnabled;
589
590 if (mbSpin)
592}
593
594void SpinField::SetLowerEnabled(bool bEnabled)
595{
596 if (mbLowerEnabled == bEnabled)
597 return;
598
599 mbLowerEnabled = bEnabled;
600
601 if (mbSpin)
603}
604
605void SpinField::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
606{
607 if (mbSpin)
608 {
609 bool bEnabled = IsEnabled();
610 bool bUpperEnabled = bEnabled && IsUpperEnabled();
611 bool bLowerEnabled = bEnabled && IsLowerEnabled();
612 ImplDrawSpinButton(rRenderContext, this, maUpperRect, maLowerRect,
613 mbUpperIn && bUpperEnabled, mbLowerIn && bLowerEnabled,
614 bUpperEnabled, bLowerEnabled);
615 }
616
617 if (GetStyle() & WB_DROPDOWN)
618 {
619 DecorationView aView(&rRenderContext);
620
622 if (mbInDropDown)
623 nStyle |= DrawButtonFlags::Pressed;
624 tools::Rectangle aInnerRect = aView.DrawButton(maDropDownRect, nStyle);
625
627 aView.DrawSymbol(aInnerRect, SymbolType::SPIN_DOWN, rRenderContext.GetSettings().GetStyleSettings().GetButtonTextColor(), nSymbolStyle);
628 }
629
630 Edit::Paint(rRenderContext, rRect);
631}
632
633void SpinField::ImplCalcButtonAreas(const OutputDevice* pDev, const Size& rOutSz, tools::Rectangle& rDDArea,
634 tools::Rectangle& rSpinUpArea, tools::Rectangle& rSpinDownArea)
635{
636 const StyleSettings& rStyleSettings = pDev->GetSettings().GetStyleSettings();
637
638 Size aSize = rOutSz;
639 Size aDropDownSize;
640
641 if (GetStyle() & WB_DROPDOWN)
642 {
643 tools::Long nW = rStyleSettings.GetScrollBarSize();
644 nW = GetDrawPixel( pDev, nW );
645 aDropDownSize = Size( CalcZoom( nW ), aSize.Height() );
646 aSize.AdjustWidth( -(aDropDownSize.Width()) );
647 rDDArea = tools::Rectangle( Point( aSize.Width(), 0 ), aDropDownSize );
648 rDDArea.AdjustTop( -1 );
649 }
650 else
651 rDDArea.SetEmpty();
652
653 // calculate sizes according to the height
654 if (GetStyle() & WB_SPIN)
655 {
656 tools::Long nBottom1 = aSize.Height()/2;
657 tools::Long nBottom2 = aSize.Height()-1;
658 tools::Long nTop2 = nBottom1;
659 if ( !(aSize.Height() & 0x01) )
660 nBottom1--;
661
662 bool bNativeRegionOK = false;
663 tools::Rectangle aContentUp, aContentDown;
664
665 if ((pDev->GetOutDevType() == OUTDEV_WINDOW) &&
666 // there is just no useful native support for spinfields with dropdown
667 ! (GetStyle() & WB_DROPDOWN) &&
669 {
670 vcl::Window *pWin = pDev->GetOwnerWindow();
671 vcl::Window *pBorder = pWin->GetWindow( GetWindowType::Border );
672
673 // get the system's spin button size
674 ImplControlValue aControlValue;
675 tools::Rectangle aBound;
676 Point aPoint;
677
678 // use the full extent of the control
679 tools::Rectangle aArea( aPoint, pBorder->GetOutputSizePixel() );
680
681 bNativeRegionOK =
683 aArea, ControlState::NONE, aControlValue, aBound, aContentUp) &&
685 aArea, ControlState::NONE, aControlValue, aBound, aContentDown);
686
687 if (bNativeRegionOK)
688 {
689 // convert back from border space to local coordinates
690 aPoint = pBorder->ScreenToOutputPixel( pWin->OutputToScreenPixel( aPoint ) );
691 aContentUp.Move(-aPoint.X(), -aPoint.Y());
692 aContentDown.Move(-aPoint.X(), -aPoint.Y());
693 }
694 }
695
696 if (bNativeRegionOK)
697 {
698 rSpinUpArea = aContentUp;
699 rSpinDownArea = aContentDown;
700 }
701 else
702 {
703 aSize.AdjustWidth( -(CalcZoom( GetDrawPixel( pDev, rStyleSettings.GetSpinSize() ) )) );
704
705 rSpinUpArea = tools::Rectangle( aSize.Width(), 0, rOutSz.Width()-aDropDownSize.Width()-1, nBottom1 );
706 rSpinDownArea = tools::Rectangle( rSpinUpArea.Left(), nTop2, rSpinUpArea.Right(), nBottom2 );
707 }
708 }
709 else
710 {
711 rSpinUpArea.SetEmpty();
712 rSpinDownArea.SetEmpty();
713 }
714}
715
717{
718 if (!mbSpin)
719 return;
720
722 Size aSize = GetOutputSizePixel();
723 bool bSubEditPositioned = false;
724
725 if (GetStyle() & (WB_SPIN | WB_DROPDOWN))
726 {
728
729 ImplControlValue aControlValue;
730 Point aPoint;
731 tools::Rectangle aContent, aBound;
732
733 // use the full extent of the control
735 tools::Rectangle aArea( aPoint, pBorder->GetOutputSizePixel() );
736
737 // adjust position and size of the edit field
739 aControlValue, aBound, aContent) &&
740 // there is just no useful native support for spinfields with dropdown
741 !(GetStyle() & WB_DROPDOWN))
742 {
743 // convert back from border space to local coordinates
744 aPoint = pBorder->ScreenToOutputPixel(OutputToScreenPixel(aPoint));
745 aContent.Move(-aPoint.X(), -aPoint.Y());
746
747 // use the themes drop down size
748 mpEdit->SetPosPixel( aContent.TopLeft() );
749 bSubEditPositioned = true;
750 aSize = aContent.GetSize();
751 }
752 else
753 {
754 if (maUpperRect.IsEmpty())
755 {
756 SAL_WARN_IF( maDropDownRect.IsEmpty(), "vcl", "SpinField::Resize: SPIN && DROPDOWN, but all empty rects?" );
757 aSize.setWidth( maDropDownRect.Left() );
758 }
759 else
760 aSize.setWidth( maUpperRect.Left() );
761 }
762 }
763
764 if (!bSubEditPositioned)
765 {
766 // this moves our sub edit if RTL gets switched
768 }
769 mpEdit->SetSizePixel(aSize);
770
771 if (GetStyle() & WB_SPIN)
773 if (GetStyle() & WB_DROPDOWN)
775}
776
778{
780
782 {
783 if (mbSpin || (GetStyle() & WB_DROPDOWN))
784 {
786
787 if (mbSpin)
788 {
791 }
792 if (GetStyle() & WB_DROPDOWN)
794 }
795 }
796 else if (nType == StateChangedType::Style)
797 {
798 if (GetStyle() & WB_REPEAT)
799 mbRepeat = true;
800 else
801 mbRepeat = false;
802 }
803 else if (nType == StateChangedType::Zoom)
804 {
805 Resize();
806 if (mpEdit)
808 Invalidate();
809 }
811 {
812 if (mpEdit)
814 Invalidate();
815 }
817 {
818 if (mpEdit)
820 Invalidate();
821 }
823 {
824 if (mpEdit)
826 Invalidate();
827 }
829 {
830 if (mpEdit)
832 Resize();
833 }
834}
835
837{
838 Edit::DataChanged(rDCEvt);
839
840 if ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
842 {
843 Resize();
844 Invalidate();
845 }
846}
847
849{
850 if (maUpperRect.Contains(rPt))
851 return &maUpperRect;
852 else if (maLowerRect.Contains(rPt))
853 return &maLowerRect;
854 else
855 return nullptr;
856}
857
859{
860 if (rNEvt.GetType() == NotifyEventType::MOUSEMOVE)
861 {
862 const MouseEvent* pMouseEvt = rNEvt.GetMouseEvent();
863 if (pMouseEvt && !pMouseEvt->GetButtons() && !pMouseEvt->IsSynthetic() && !pMouseEvt->IsModifierChanged())
864 {
865 // trigger redraw if mouse over state has changed
868 {
871 if( pRect != pLastRect || (pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow()) )
872 {
873 if (!IsNativeWidgetEnabled() ||
875 {
876 // paint directly
877 vcl::Region aRgn( GetOutDev()->GetActiveClipRegion() );
878 if (pLastRect)
879 {
880 GetOutDev()->SetClipRegion(vcl::Region(*pLastRect));
881 Invalidate(*pLastRect);
882 GetOutDev()->SetClipRegion( aRgn );
883 }
884 if (pRect)
885 {
887 Invalidate(*pRect);
888 GetOutDev()->SetClipRegion( aRgn );
889 }
890 }
891 }
892 }
893 }
894 }
895
896 return Edit::PreNotify(rNEvt);
897}
898
900{
901 mbInDropDown = false;
903}
904
906{
907 return false;
908}
909
910Size SpinField::CalcMinimumSizeForText(const OUString &rString) const
911{
912 Size aSz = Edit::CalcMinimumSizeForText(rString);
913
914 if ( GetStyle() & WB_DROPDOWN )
915 aSz.AdjustWidth(GetSettings().GetStyleSettings().GetScrollBarSize() );
916 if ( GetStyle() & WB_SPIN )
917 {
918 ImplControlValue aControlValue;
919 tools::Rectangle aArea( Point(), Size(100, aSz.Height()));
920 tools::Rectangle aEntireBound, aEntireContent, aEditBound, aEditContent;
921 if (
923 aArea, ControlState::NONE, aControlValue, aEntireBound, aEntireContent) &&
925 aArea, ControlState::NONE, aControlValue, aEditBound, aEditContent)
926 )
927 {
928 aSz.AdjustWidth(aEntireContent.GetWidth() - aEditContent.GetWidth());
929 }
930 else
931 {
933 }
934 }
935
936 return aSz;
937}
938
940{
942}
943
945{
946 return CalcMinimumSize();
947}
948
949Size SpinField::CalcSize(sal_Int32 nChars) const
950{
951 Size aSz = Edit::CalcSize( nChars );
952
953 if ( GetStyle() & WB_DROPDOWN )
954 aSz.AdjustWidth(GetSettings().GetStyleSettings().GetScrollBarSize() );
955 if ( GetStyle() & WB_SPIN )
956 aSz.AdjustWidth(GetSettings().GetStyleSettings().GetSpinSize() );
957
958 return aSz;
959}
960
961IMPL_LINK( SpinField, ImplTimeout, Timer*, pTimer, void )
962{
963 if ( pTimer->GetTimeout() == static_cast<sal_uInt64>(MouseSettings::GetButtonStartRepeat()) )
964 {
965 pTimer->SetTimeout( GetSettings().GetMouseSettings().GetButtonRepeat() );
966 pTimer->Start();
967 }
968 else
969 {
970 if ( mbInitialUp )
971 Up();
972 else
973 Down();
974 }
975}
976
977void SpinField::Draw(OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags)
978{
979 Edit::Draw(pDev, rPos, nFlags);
980
981 WinBits nFieldStyle = GetStyle();
982 if ( (nFlags & SystemTextColorFlags::NoControls ) || !( nFieldStyle & (WB_SPIN|WB_DROPDOWN) ) )
983 return;
984
985 Point aPos = pDev->LogicToPixel( rPos );
986 Size aSize = GetSizePixel();
987 AllSettings aOldSettings = pDev->GetSettings();
988
989 pDev->Push();
990 pDev->SetMapMode();
991
992 tools::Rectangle aDD, aUp, aDown;
993 ImplCalcButtonAreas(pDev, aSize, aDD, aUp, aDown);
994 aDD.Move(aPos.X(), aPos.Y());
995 aUp.Move(aPos.X(), aPos.Y());
996 aUp.AdjustTop( 1 );
997 aDown.Move(aPos.X(), aPos.Y());
998
999 Color aButtonTextColor;
1000 if (nFlags & SystemTextColorFlags::Mono)
1001 aButtonTextColor = COL_BLACK;
1002 else
1003 aButtonTextColor = GetSettings().GetStyleSettings().GetButtonTextColor();
1004
1005 if (GetStyle() & WB_DROPDOWN)
1006 {
1007 DecorationView aView( pDev );
1010 aView.DrawSymbol(aInnerRect, SymbolType::SPIN_DOWN, aButtonTextColor, nSymbolStyle);
1011 }
1012
1013 if (GetStyle() & WB_SPIN)
1014 {
1015 ImplDrawSpinButton(*pDev, this, aUp, aDown, false, false);
1016 }
1017
1018 pDev->Pop();
1019 pDev->SetSettings(aOldSettings);
1020
1021}
1022
1024{
1026}
1027
1028/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SystemTextColorFlags
@ SubEdit
The edit field part of a control, e.g.
ControlType
These types are all based on the supported variants vcl/salnativewidgets.hxx and must be kept in-sync...
const StyleSettings & GetStyleSettings() const
CommandEventId GetCommand() const
const CommandWheelData * GetWheelData() const
std::optional< vcl::ControlLayoutData > mxLayoutData
Definition: ctrl.hxx:84
bool ImplCallEventListenersAndHandler(VclEventId nEvent, std::function< void()> const &callHandler)
this calls both our event listeners, and a specified handler
Definition: ctrl.cxx:302
void SetLayoutDataParent(const Control *pParent) const
Definition: ctrl.cxx:321
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: ctrl.cxx:226
virtual void Resize() override
Definition: ctrl.cxx:75
virtual void EnableRTL(bool bEnable=true) override
Definition: ctrl.cxx:66
void AppendLayoutData(const Control &rSubControl) const
Definition: ctrl.cxx:270
DataChangedEventType GetType() const
Definition: event.hxx:362
AllSettingsFlags GetFlags() const
Definition: event.hxx:363
tools::Rectangle DrawButton(const tools::Rectangle &rRect, DrawButtonFlags nStyle)
Definition: decoview.cxx:901
void DrawSymbol(const tools::Rectangle &rRect, SymbolType eType, const Color &rColor, DrawSymbolFlags nStyle=DrawSymbolFlags::NONE)
Definition: decoview.cxx:768
Definition: edit.hxx:56
virtual void Paint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect) override
Definition: edit.cxx:1726
SAL_DLLPRIVATE void ImplInit(vcl::Window *pParent, WinBits nStyle)
Definition: edit.cxx:306
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects.
Definition: edit.cxx:225
virtual Size CalcSize(sal_Int32 nChars) const
Definition: edit.cxx:2687
virtual bool PreNotify(NotifyEvent &rNEvt) override
Definition: edit.cxx:1918
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
Definition: edit.cxx:2255
Edit * GetSubEdit() const
Definition: edit.hxx:218
virtual void MouseButtonDown(const MouseEvent &rMEvt) override
Definition: edit.cxx:1322
SAL_DLLPRIVATE bool ImplUseNativeBorder(vcl::RenderContext const &rRenderContext, WinBits nStyle) const
Definition: edit.cxx:290
virtual void MouseButtonUp(const MouseEvent &rMEvt) override
Definition: edit.cxx:1363
void SetSubEdit(Edit *pEdit)
Definition: edit.cxx:2612
virtual Size CalcMinimumSizeForText(const OUString &rString) const
Definition: edit.cxx:2627
virtual bool IsReadOnly() const
Definition: edit.hxx:176
virtual void FillLayoutData() const override
Definition: edit.cxx:1720
virtual void Draw(OutputDevice *pDev, const Point &rPos, SystemTextColorFlags nFlags) override
Definition: edit.cxx:1745
virtual void StateChanged(StateChangedType nType) override
Definition: edit.cxx:2174
virtual OUString GetText() const override
Definition: edit.cxx:2584
const vcl::KeyCode & GetKeyCode() const
Definition: event.hxx:57
bool IsEnterWindow() const
Definition: event.hxx:138
bool IsSynthetic() const
Definition: event.hxx:142
bool IsLeaveWindow() const
Definition: event.hxx:140
sal_uInt16 GetButtons() const
Definition: event.hxx:147
const Point & GetPosPixel() const
Definition: event.hxx:123
bool IsModifierChanged() const
Definition: event.hxx:144
bool IsLeft() const
Definition: event.hxx:149
static sal_Int32 GetButtonStartRepeat()
const KeyEvent * GetKeyEvent() const
Definition: event.hxx:316
const CommandEvent * GetCommandEvent() const
Definition: event.hxx:332
const MouseEvent * GetMouseEvent() const
Definition: event.hxx:324
NotifyEventType GetType() const
Definition: event.hxx:308
Some things multiple-inherit from VclAbstractDialog and OutputDevice, so we need to use virtual inher...
Definition: outdev.hxx:171
virtual void SetSettings(const AllSettings &rSettings)
Definition: outdev.cxx:216
vcl::Region GetClipRegion() const
void SetMapMode()
Definition: map.cxx:620
SAL_WARN_UNUSED_RESULT Point LogicToPixel(const Point &rLogicPt) const
Definition: map.cxx:904
void Push(vcl::PushFlags nFlags=vcl::PushFlags::ALL)
Definition: stack.cxx:33
void Pop()
Definition: stack.cxx:92
bool GetNativeControlRegion(ControlType nType, ControlPart nPart, const tools::Rectangle &rControlRegion, ControlState nState, const ImplControlValue &aValue, tools::Rectangle &rNativeBoundingRegion, tools::Rectangle &rNativeContentRegion) const
Query the native control's actual drawing region (including adornment)
bool DrawNativeControl(ControlType nType, ControlPart nPart, const tools::Rectangle &rControlRegion, ControlState nState, const ImplControlValue &aValue, const OUString &aCaption, const Color &rBackgroundColor=COL_AUTO)
Request rendering of a particular control and/or part.
OutDevType GetOutDevType() const
Definition: outdev.hxx:407
const AllSettings & GetSettings() const
Definition: outdev.hxx:289
bool IsNativeControlSupported(ControlType nType, ControlPart nPart) const
Query the platform layer for control support.
virtual vcl::Window * GetOwnerWindow() const
Get the vcl::Window that this OutputDevice belongs to, if any.
Definition: outdev.hxx:1900
constexpr tools::Long Height() const
void setWidth(tools::Long nWidth)
tools::Long AdjustWidth(tools::Long n)
constexpr tools::Long Width() const
static std::unique_ptr< UIObject > create(vcl::Window *pWindow)
bool mbLowerIn
Definition: spinfld.hxx:98
virtual void MouseButtonDown(const MouseEvent &rMEvt) override
Definition: spinfld.cxx:379
SAL_DLLPRIVATE void ImplInitSpinFieldData()
Definition: spinfld.cxx:291
virtual void StateChanged(StateChangedType nType) override
Definition: spinfld.cxx:777
virtual void Last()
Definition: spinfld.cxx:374
Link< SpinField &, void > maUpHdlLink
Definition: spinfld.hxx:91
Link< SpinField &, void > maDownHdlLink
Definition: spinfld.hxx:92
virtual FactoryFunction GetUITestFactory() const override
Definition: spinfld.cxx:1023
virtual void MouseButtonUp(const MouseEvent &rMEvt) override
Definition: spinfld.cxx:419
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: spinfld.cxx:485
virtual void First()
Definition: spinfld.cxx:369
bool mbRepeat
Definition: spinfld.hxx:93
virtual void FillLayoutData() const override
Definition: spinfld.cxx:571
virtual Size GetOptimalSize() const override
Definition: spinfld.cxx:944
bool mbSpin
Definition: spinfld.hxx:94
bool mbUpperIn
Definition: spinfld.hxx:97
virtual Size CalcMinimumSizeForText(const OUString &rString) const override
Definition: spinfld.cxx:910
bool mbLowerEnabled
Definition: spinfld.hxx:101
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
Definition: spinfld.cxx:836
virtual bool ShowDropDown(bool bShow)
Definition: spinfld.cxx:905
VclPtr< Edit > mpEdit
Definition: spinfld.hxx:89
SAL_DLLPRIVATE void SetLowerEnabled(bool bEnabled)
Definition: spinfld.cxx:594
SAL_DLLPRIVATE bool IsLowerEnabled() const
Definition: spinfld.hxx:67
virtual ~SpinField() override
Definition: spinfld.cxx:347
virtual bool PreNotify(NotifyEvent &rNEvt) override
Definition: spinfld.cxx:858
SpinField(vcl::Window *pParent, WinBits nWinStyle, WindowType nType=WindowType::SPINFIELD)
Definition: spinfld.cxx:340
virtual void Down()
Definition: spinfld.cxx:364
virtual void Draw(OutputDevice *pDev, const Point &rPos, SystemTextColorFlags nFlags) override
Definition: spinfld.cxx:977
virtual void MouseMove(const MouseEvent &rMEvt) override
Definition: spinfld.cxx:442
SAL_DLLPRIVATE void ImplCalcButtonAreas(const OutputDevice *pDev, const Size &rOutSz, tools::Rectangle &rDDArea, tools::Rectangle &rSpinUpArea, tools::Rectangle &rSpinDownArea)
Definition: spinfld.cxx:633
virtual Size CalcSize(sal_Int32 nChars) const override
Definition: spinfld.cxx:949
bool mbInitialDown
Definition: spinfld.hxx:96
virtual Size CalcMinimumSize() const override
Definition: spinfld.cxx:939
SAL_DLLPRIVATE bool IsUpperEnabled() const
Definition: spinfld.hxx:66
tools::Rectangle maUpperRect
Definition: spinfld.hxx:70
virtual void Up()
Definition: spinfld.cxx:359
tools::Rectangle * ImplFindPartRect(const Point &rPt)
Definition: spinfld.cxx:848
SAL_DLLPRIVATE void ImplInit(vcl::Window *pParent, WinBits nStyle)
Definition: spinfld.cxx:305
void EndDropDown()
Definition: spinfld.cxx:899
tools::Rectangle maLowerRect
Definition: spinfld.hxx:71
virtual void Paint(vcl::RenderContext &rRenderContext, const tools::Rectangle &rRect) override
Definition: spinfld.cxx:605
tools::Rectangle maDropDownRect
Definition: spinfld.hxx:72
bool mbInitialUp
Definition: spinfld.hxx:95
bool mbInDropDown
Definition: spinfld.hxx:99
AutoTimer maRepeatTimer
Definition: spinfld.hxx:90
SAL_DLLPRIVATE void SetUpperEnabled(bool bEnabled)
Definition: spinfld.cxx:583
bool mbUpperEnabled
Definition: spinfld.hxx:100
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects.
Definition: spinfld.cxx:352
virtual void Resize() override
Definition: spinfld.cxx:716
tools::Rectangle maLowerRect
ControlPart mnLowerPart
tools::Rectangle maUpperRect
ControlState mnUpperState
ControlState mnLowerState
ControlPart mnUpperPart
sal_Int32 GetScrollBarSize() const
const Color & GetButtonTextColor() const
sal_Int32 GetSpinSize() const
void Stop()
Definition: scheduler.cxx:590
Definition: timer.hxx:27
void SetTimeout(sal_uInt64 nTimeoutMs)
Definition: timer.cxx:90
void SetInvokeHandler(const Link< Timer *, void > &rLink)
Definition: timer.hxx:56
virtual void Start(bool bStartTimer=true) override
Schedules the task for execution.
Definition: timer.cxx:83
A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for refer...
Definition: vclptr.hxx:58
void disposeAndClear()
Definition: vclptr.hxx:200
void set(reference_type *pBody)
Definition: vclptr.hxx:148
constexpr tools::Long GetWidth() const
bool Contains(const Point &rPOINT) const
tools::Rectangle GetUnion(const tools::Rectangle &rRect) const
constexpr Point TopLeft() const
constexpr Size GetSize() const
void Move(tools::Long nHorzMoveDelta, tools::Long nVertMoveDelta)
constexpr tools::Long Right() const
tools::Long AdjustTop(tools::Long nVertMoveDelta)
tools::Long AdjustRight(tools::Long nHorzMoveDelta)
constexpr Point BottomRight() const
constexpr tools::Long GetHeight() const
tools::Long AdjustBottom(tools::Long nVertMoveDelta)
tools::Long AdjustLeft(tools::Long nHorzMoveDelta)
constexpr tools::Long Left() const
constexpr bool IsEmpty() const
sal_uInt16 GetCode() const
Definition: keycod.hxx:49
sal_uInt16 GetModifier() const
Definition: keycod.hxx:52
Point OutputToScreenPixel(const Point &rPos) const
Definition: window.cxx:2810
bool IsNativeWidgetEnabled() const
Definition: window.cxx:3711
void SetControlForeground()
Definition: window2.cxx:481
bool HasChildPathFocus(bool bSystemWindow=false) const
Definition: window.cxx:3011
void SetControlFont()
Definition: window2.cxx:433
bool IsMouseOver() const
Definition: mouse.cxx:620
WindowType GetType() const
Definition: window2.cxx:1005
bool SupportsDoubleBuffering() const
Can the widget derived from this Window do the double-buffering via RenderContext properly?
Definition: window.cxx:3861
virtual void SetSizePixel(const Size &rNewSize)
Definition: window2.cxx:1293
tools::Long CalcZoom(tools::Long n) const
Definition: window2.cxx:421
vcl::Window * GetWindow(GetWindowType nType) const
Definition: stacking.cxx:1035
const Color & GetControlForeground() const
Definition: window2.cxx:1103
void GrabFocus()
Definition: window.cxx:2983
void SetControlBackground()
Definition: window2.cxx:521
bool HasFocus() const
Definition: window.cxx:2988
bool GetNativeControlRegion(ControlType nType, ControlPart nPart, const tools::Rectangle &rControlRegion, ControlState nState, const ImplControlValue &aValue, tools::Rectangle &rNativeBoundingRegion, tools::Rectangle &rNativeContentRegion) const
Query the native control's actual drawing region (including adornment)
Definition: window3.cxx:79
Point GetLastPointerPosPixel()
Definition: mouse.cxx:576
void Enable(bool bEnable=true, bool bChild=true)
Definition: window.cxx:2437
WinBits GetStyle() const
Definition: window2.cxx:984
const Fraction & GetZoom() const
Definition: window2.cxx:1241
const AllSettings & GetSettings() const
Definition: window3.cxx:129
void Show(bool bVisible=true, ShowFlags nFlags=ShowFlags::NONE)
Definition: window.cxx:2191
bool IsNativeControlSupported(ControlType nType, ControlPart nPart) const
Query the platform layer for control support.
Definition: window3.cxx:74
vcl::Font GetControlFont() const
Definition: window2.cxx:462
::OutputDevice const * GetOutDev() const
Definition: window.cxx:567
void SetZoom(const Fraction &rZoom)
Definition: window2.cxx:394
virtual void MouseMove(const MouseEvent &rMEvt)
Definition: mouse.cxx:414
tools::Long GetDrawPixel(::OutputDevice const *pDev, tools::Long nPixels) const
Definition: window2.cxx:587
void ReleaseMouse()
Definition: mouse.cxx:469
virtual Size GetSizePixel() const
Definition: window.cxx:2406
Size GetOutputSizePixel() const
Definition: window3.cxx:89
Point GetPointerPosPixel()
Definition: mouse.cxx:564
const Color & GetControlBackground() const
Definition: window2.cxx:1113
void CaptureMouse()
Definition: mouse.cxx:451
virtual void Invalidate(InvalidateFlags nFlags=InvalidateFlags::NONE)
Definition: paint.cxx:1143
virtual void SetPosPixel(const Point &rNewPos)
Definition: window2.cxx:1288
Point ScreenToOutputPixel(const Point &rPos) const
Definition: window.cxx:2816
bool IsEnabled() const
Definition: window2.cxx:1153
void SetCompoundControl(bool bCompound)
Definition: window2.cxx:978
void SetBackground()
Definition: window3.cxx:100
SAL_DLLPRIVATE void CompatStateChanged(StateChangedType nStateChange)
Definition: window.cxx:3899
constexpr ::Color COL_BLACK(0x00, 0x00, 0x00)
DrawButtonFlags
Definition: decoview.hxx:54
DrawSymbolFlags
Definition: decoview.hxx:35
sal_Int32 nState
std::function< std::unique_ptr< UIObject >(vcl::Window *)> FactoryFunction
constexpr sal_uInt16 KEY_MOD2
Definition: keycodes.hxx:32
constexpr sal_uInt16 KEY_PAGEDOWN
Definition: keycodes.hxx:117
constexpr sal_uInt16 KEY_UP
Definition: keycodes.hxx:111
constexpr sal_uInt16 KEY_DOWN
Definition: keycodes.hxx:110
constexpr sal_uInt16 KEY_PAGEUP
Definition: keycodes.hxx:116
#define SAL_WARN_IF(condition, area, stream)
std::unique_ptr< sal_Int32[]> pData
long Long
@ OUTDEV_WINDOW
Definition: outdev.hxx:144
QPRO_FUNC_TYPE nType
MouseWheelBehaviour
Definition: settings.hxx:78
void ImplDrawSpinButton(vcl::RenderContext &rRenderContext, vcl::Window *pWindow, const tools::Rectangle &rUpperRect, const tools::Rectangle &rLowerRect, bool bUpperIn, bool bLowerIn, bool bUpperEnabled, bool bLowerEnabled, bool bHorz, bool bMirrorHorz)
Definition: spinfld.cxx:156
void ImplDrawUpDownButtons(vcl::RenderContext &rRenderContext, const tools::Rectangle &rUpperRect, const tools::Rectangle &rLowerRect, bool bUpperIn, bool bLowerIn, bool bUpperEnabled, bool bLowerEnabled, bool bHorz, bool bMirrorHorz)
Definition: spinfld.cxx:205
IMPL_LINK(SpinField, ImplTimeout, Timer *, pTimer, void)
Definition: spinfld.cxx:961
ImplSVData * ImplGetSVData()
Definition: svdata.cxx:76
SymbolType
Definition: vclenum.hxx:74
StateChangedType
Definition: window.hxx:291
sal_Int64 WinBits
Definition: wintypes.hxx:109
WinBits const WB_DROPDOWN
Definition: wintypes.hxx:159
WindowType
Definition: wintypes.hxx:27
WinBits const WB_REPEAT
Definition: wintypes.hxx:154
WinBits const WB_SPIN
Definition: wintypes.hxx:153
WinBits const WB_NOBORDER
Definition: wintypes.hxx:116