LibreOffice Module vcl (master) 1
field.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 <sal/config.h>
21
22#include <cmath>
23#include <string_view>
24
25#include <sal/log.hxx>
26#include <o3tl/string_view.hxx>
27#include <osl/diagnose.h>
28
29#include <comphelper/string.hxx>
31
32#include <vcl/builder.hxx>
33#include <vcl/fieldvalues.hxx>
34#include <vcl/toolkit/field.hxx>
35#include <vcl/event.hxx>
36#include <vcl/svapp.hxx>
37#include <vcl/settings.hxx>
40
41#include <svdata.hxx>
42
43#include <i18nutil/unicode.hxx>
44
45#include <rtl/math.hxx>
46
48#include <boost/property_tree/ptree.hpp>
49#include <tools/json_writer.hxx>
50
51using namespace ::com::sun::star;
52using namespace ::comphelper;
53
54namespace
55{
56
57std::string FieldUnitToString(FieldUnit unit)
58{
59 switch(unit)
60 {
61 case FieldUnit::NONE:
62 return "";
63
64 case FieldUnit::MM:
65 return "mm";
66
67 case FieldUnit::CM:
68 return "cm";
69
70 case FieldUnit::M:
71 return "m";
72
73 case FieldUnit::KM:
74 return "km";
75
76 case FieldUnit::TWIP:
77 return "twip";
78
79 case FieldUnit::POINT:
80 return "point";
81
82 case FieldUnit::PICA:
83 return "pica";
84
85 case FieldUnit::INCH:
86 return "inch";
87
88 case FieldUnit::FOOT:
89 return "foot";
90
91 case FieldUnit::MILE:
92 return "mile";
93
94 case FieldUnit::CHAR:
95 return "char";
96
97 case FieldUnit::LINE:
98 return "line";
99
100 case FieldUnit::CUSTOM:
101 return "custom";
103 case FieldUnit::PERCENT:
104 return "percent";
105
106 case FieldUnit::MM_100TH:
107 return "mm100th";
108
109 case FieldUnit::PIXEL:
110 return "pixel";
111
112 case FieldUnit::DEGREE:
113 return "degree";
114
115 case FieldUnit::SECOND:
116 return "second";
117
118 case FieldUnit::MILLISECOND:
119 return "millisecond";
121
122 return "";
123}
124
125sal_Int64 ImplPower10( sal_uInt16 n )
126{
127 sal_uInt16 i;
128 sal_Int64 nValue = 1;
129
130 for ( i=0; i < n; i++ )
131 nValue *= 10;
132
133 return nValue;
134}
135
136bool ImplNumericProcessKeyInput( const KeyEvent& rKEvt,
137 bool bStrictFormat, bool bThousandSep,
138 const LocaleDataWrapper& rLocaleDataWrapper )
139{
140 if ( !bStrictFormat )
141 return false;
142 else
143 {
144 sal_Unicode cChar = rKEvt.GetCharCode();
145 sal_uInt16 nGroup = rKEvt.GetKeyCode().GetGroup();
146
147 return !((nGroup == KEYGROUP_FKEYS) ||
148 (nGroup == KEYGROUP_CURSOR) ||
149 (nGroup == KEYGROUP_MISC) ||
150 ((cChar >= '0') && (cChar <= '9')) ||
151 rLocaleDataWrapper.getNumDecimalSep() == OUStringChar(cChar) ||
152 (bThousandSep && rLocaleDataWrapper.getNumThousandSep() == OUStringChar(cChar)) ||
153 rLocaleDataWrapper.getNumDecimalSepAlt() == OUStringChar(cChar) ||
154 (cChar == '-'));
155 }
156}
157
158bool ImplNumericGetValue( const OUString& rStr, sal_Int64& rValue,
159 sal_uInt16 nDecDigits, const LocaleDataWrapper& rLocaleDataWrapper,
160 bool bCurrency = false )
161{
162 OUString aStr = rStr;
163 OUStringBuffer aStr1, aStr2, aStrNum, aStrDenom;
164 bool bNegative = false;
165 bool bFrac = false;
166 sal_Int32 nDecPos, nFracDivPos;
167 sal_Int64 nValue;
168
169 // react on empty string
170 if ( rStr.isEmpty() )
171 return false;
172
173 // remove leading and trailing spaces
174 aStr = aStr.trim();
175
176
177 // find position of decimal point
178 nDecPos = aStr.indexOf( rLocaleDataWrapper.getNumDecimalSep() );
179 if (nDecPos < 0 && !rLocaleDataWrapper.getNumDecimalSepAlt().isEmpty())
180 nDecPos = aStr.indexOf( rLocaleDataWrapper.getNumDecimalSepAlt() );
181 // find position of fraction
182 nFracDivPos = aStr.indexOf( '/' );
183
184 // parse fractional strings
185 if (nFracDivPos > 0)
186 {
187 bFrac = true;
188 sal_Int32 nFracNumPos = aStr.lastIndexOf(' ', nFracDivPos);
190 // If in "a b/c" format.
191 if(nFracNumPos != -1 )
192 {
193 aStr1.append(aStr.subView(0, nFracNumPos));
194 aStrNum.append(aStr.subView(nFracNumPos+1, nFracDivPos-nFracNumPos-1));
195 aStrDenom.append(aStr.subView(nFracDivPos+1));
196 }
197 // "a/b" format, or not a fraction at all
198 else
199 {
200 aStrNum.append(aStr.subView(0, nFracDivPos));
201 aStrDenom.append(aStr.subView(nFracDivPos+1));
202 }
203
204 }
205 // parse decimal strings
206 else if ( nDecPos >= 0)
207 {
208 aStr1.append(aStr.subView(0, nDecPos));
209 aStr2.append(aStr.subView(nDecPos+1));
210 }
211 else
212 aStr1 = aStr;
213
214 // negative?
215 if ( bCurrency )
216 {
217 if ( aStr.startsWith("(") && aStr.endsWith(")") )
218 bNegative = true;
219 if ( !bNegative )
220 {
221 for (sal_Int32 i=0; i < aStr.getLength(); i++ )
222 {
223 if ( (aStr[i] >= '0') && (aStr[i] <= '9') )
224 break;
225 else if ( aStr[i] == '-' )
226 {
227 bNegative = true;
228 break;
229 }
230 }
231 }
232 if (!bNegative && !aStr.isEmpty())
233 {
234 sal_uInt16 nFormat = rLocaleDataWrapper.getCurrNegativeFormat();
235 if ( (nFormat == 3) || (nFormat == 6) || // $1- || 1-$
236 (nFormat == 7) || (nFormat == 10) ) // 1$- || 1 $-
237 {
238 for (sal_Int32 i = aStr.getLength()-1; i > 0; --i )
239 {
240 if ( (aStr[i] >= '0') && (aStr[i] <= '9') )
241 break;
242 else if ( aStr[i] == '-' )
243 {
244 bNegative = true;
245 break;
246 }
247 }
248 }
249 }
250 }
251 else
252 {
253 if ( !aStr1.isEmpty() && aStr1[0] == '-')
254 bNegative = true;
255 if ( !aStrNum.isEmpty() && aStrNum[0] == '-') // For non-mixed fractions
256 bNegative = true;
257 }
258
259 // remove all unwanted characters
260 // For whole number
261 for (sal_Int32 i=0; i < aStr1.getLength(); )
262 {
263 if ( (aStr1[i] >= '0') && (aStr1[i] <= '9') )
264 i++;
265 else
266 aStr1.remove( i, 1 );
267 }
268 // For decimal
269 if (!bFrac) {
270 for (sal_Int32 i=0; i < aStr2.getLength(); )
271 {
272 if ((aStr2[i] >= '0') && (aStr2[i] <= '9'))
273 ++i;
274 else
275 aStr2.remove(i, 1);
276 }
277 }
278 else {
279 // for numerator
280 for (sal_Int32 i=0; i < aStrNum.getLength(); )
281 {
282 if ((aStrNum[i] >= '0') && (aStrNum[i] <= '9'))
283 ++i;
284 else
285 aStrNum.remove(i, 1);
286 }
287 // for denominator
288 for (sal_Int32 i=0; i < aStrDenom.getLength(); )
289 {
290 if ((aStrDenom[i] >= '0') && (aStrDenom[i] <= '9'))
291 ++i;
292 else
293 aStrDenom.remove(i, 1);
294 }
295 }
296
297
298 if ( !bFrac && aStr1.isEmpty() && aStr2.isEmpty() )
299 return false;
300 else if ( bFrac && aStr1.isEmpty() && (aStrNum.isEmpty() || aStrDenom.isEmpty()) )
301 return false;
302
303 if ( aStr1.isEmpty() )
304 aStr1 = "0";
305 if ( bNegative )
306 aStr1.insert(0, "-");
307
308 // Convert fractional strings
309 if (bFrac) {
310 // Convert to fraction
311 sal_Int64 nWholeNum = o3tl::toInt64(aStr1);
312 aStr1.setLength(0);
313 sal_Int64 nNum = o3tl::toInt64(aStrNum);
314 sal_Int64 nDenom = o3tl::toInt64(aStrDenom);
315 if (nDenom == 0) return false; // Division by zero
316 double nFrac2Dec = nWholeNum + static_cast<double>(nNum)/nDenom; // Convert to double for floating point precision
317 OUStringBuffer aStrFrac;
318 aStrFrac.append(nFrac2Dec);
319 // Reconvert division result to string and parse
320 nDecPos = aStrFrac.indexOf('.');
321 if ( nDecPos >= 0)
322 {
323 aStr1.append(aStrFrac.getStr(), nDecPos);
324 aStr2.append(aStrFrac.getStr()+nDecPos+1);
325 }
326 else
327 aStr1 = aStrFrac;
328 }
329
330 // prune and round fraction
331 bool bRound = false;
332 if (aStr2.getLength() > nDecDigits)
333 {
334 if (aStr2[nDecDigits] >= '5')
335 bRound = true;
336 string::truncateToLength(aStr2, nDecDigits);
337 }
338 if (aStr2.getLength() < nDecDigits)
339 string::padToLength(aStr2, nDecDigits, '0');
340
341 aStr = aStr1 + aStr2;
342
343 // check range
344 nValue = aStr.toInt64();
345 if( nValue == 0 )
346 {
347 // check if string is equivalent to zero
348 sal_Int32 nIndex = bNegative ? 1 : 0;
349 while (nIndex < aStr.getLength() && aStr[nIndex] == '0')
350 ++nIndex;
351 if( nIndex < aStr.getLength() )
352 {
353 rValue = bNegative ? SAL_MIN_INT64 : SAL_MAX_INT64;
354 return true;
355 }
356 }
357 if (bRound)
358 {
359 if ( !bNegative )
360 nValue++;
361 else
362 nValue--;
363 }
364
365 rValue = nValue;
366
367 return true;
368}
369
370void ImplUpdateSeparatorString( OUString& io_rText,
371 std::u16string_view rOldDecSep, std::u16string_view rNewDecSep,
372 std::u16string_view rOldThSep, std::u16string_view rNewThSep )
373{
374 OUStringBuffer aBuf( io_rText.getLength() );
375 sal_Int32 nIndexDec = 0, nIndexTh = 0, nIndex = 0;
376
377 const sal_Unicode* pBuffer = io_rText.getStr();
378 while( nIndex != -1 )
379 {
380 nIndexDec = io_rText.indexOf( rOldDecSep, nIndex );
381 nIndexTh = io_rText.indexOf( rOldThSep, nIndex );
382 if( (nIndexTh != -1 && nIndexDec != -1 && nIndexTh < nIndexDec )
383 || (nIndexTh != -1 && nIndexDec == -1)
384 )
385 {
386 aBuf.append( pBuffer + nIndex, nIndexTh - nIndex );
387 aBuf.append( rNewThSep );
388 nIndex = nIndexTh + rOldThSep.size();
389 }
390 else if( nIndexDec != -1 )
391 {
392 aBuf.append( pBuffer + nIndex, nIndexDec - nIndex );
393 aBuf.append( rNewDecSep );
394 nIndex = nIndexDec + rOldDecSep.size();
395 }
396 else
397 {
398 aBuf.append( pBuffer + nIndex );
399 nIndex = -1;
400 }
401 }
402
403 io_rText = aBuf.makeStringAndClear();
404}
405
406void ImplUpdateSeparators( std::u16string_view rOldDecSep, std::u16string_view rNewDecSep,
407 std::u16string_view rOldThSep, std::u16string_view rNewThSep,
408 Edit* pEdit )
409{
410 bool bChangeDec = (rOldDecSep != rNewDecSep);
411 bool bChangeTh = (rOldThSep != rNewThSep );
412
413 if( !(bChangeDec || bChangeTh) )
414 return;
415
416 bool bUpdateMode = pEdit->IsUpdateMode();
417 pEdit->SetUpdateMode( false );
418 OUString aText = pEdit->GetText();
419 ImplUpdateSeparatorString( aText, rOldDecSep, rNewDecSep, rOldThSep, rNewThSep );
420 pEdit->SetText( aText );
421
422 ComboBox* pCombo = dynamic_cast<ComboBox*>(pEdit);
423 if( pCombo )
424 {
425 // update box entries
426 sal_Int32 nEntryCount = pCombo->GetEntryCount();
427 for ( sal_Int32 i=0; i < nEntryCount; i++ )
428 {
429 aText = pCombo->GetEntry( i );
430 void* pEntryData = pCombo->GetEntryData( i );
431 ImplUpdateSeparatorString( aText, rOldDecSep, rNewDecSep, rOldThSep, rNewThSep );
432 pCombo->RemoveEntryAt(i);
433 pCombo->InsertEntry( aText, i );
434 pCombo->SetEntryData( i, pEntryData );
435 }
436 }
437 if( bUpdateMode )
438 pEdit->SetUpdateMode( bUpdateMode );
439}
440
441} // namespace
442
444{
445 mpField = pField;
446 mpLocaleDataWrapper = nullptr;
447 mbReformat = false;
448 mbStrictFormat = false;
449 mbEmptyFieldValue = false;
451}
452
454{
455}
456
458{
459 if ( !mpLocaleDataWrapper )
460 {
462 }
463 return *mpLocaleDataWrapper;
464}
465
468{
469 // just get rid of, the next time it is requested, it will get loaded with the right
470 // language tag
471 mpLocaleDataWrapper.reset();
472}
473
475{
477}
478
480{
481}
482
484{
485 Reformat();
486};
487
489{
490 if ( bStrict != mbStrictFormat )
491 {
492 mbStrictFormat = bStrict;
493 if ( mbStrictFormat )
494 ReformatAll();
495 }
496}
497
498const lang::Locale& FormatterBase::GetLocale() const
499{
500 if ( mpField )
502 else
504}
505
507{
508 if ( mpField )
510 else
512}
513
514void FormatterBase::ImplSetText( const OUString& rText, Selection const * pNewSelection )
515{
516 if ( mpField )
517 {
518 if (pNewSelection)
519 mpField->SetText(rText, *pNewSelection);
520 else
521 {
523 aSel.Min() = aSel.Max();
524 mpField->SetText(rText, aSel);
525 }
526 MarkToBeReformatted( false );
527 }
528}
529
531{
532 if ( mpField )
533 mpField->SetText( OUString() );
534 mbEmptyFieldValue = true;
535}
536
538{
539 return (!mpField || mpField->GetText().isEmpty());
540}
541
542void NumericFormatter::FormatValue(Selection const * pNewSelection)
543{
544 mbFormatting = true;
545 ImplSetText(CreateFieldText(mnLastValue), pNewSelection);
546 mbFormatting = false;
547}
548
550{
552 FormatValue();
553}
554
556 : FormatterBase(pEdit)
557 , mnLastValue(0)
558 , mnMin(0)
559 // a "large" value substantially smaller than SAL_MAX_INT64, to avoid
560 // overflow in computations using this "dummy" value
561 , mnMax(SAL_MAX_INT32)
562 , mbFormatting(false)
563 , mnSpinSize(1)
564 // for fields
565 , mnFirst(mnMin)
566 , mnLast(mnMax)
567 , mnDecimalDigits(0)
568 , mbThousandSep(true)
569{
570 ReformatAll();
571}
572
574{
575}
576
577void NumericFormatter::SetMin( sal_Int64 nNewMin )
578{
579 mnMin = nNewMin;
580 if ( !IsEmptyFieldValue() )
581 ReformatAll();
582}
583
584void NumericFormatter::SetMax( sal_Int64 nNewMax )
585{
586 mnMax = nNewMax;
587 if ( !IsEmptyFieldValue() )
588 ReformatAll();
589}
590
592{
593 mbThousandSep = bValue;
594 ReformatAll();
595}
596
597void NumericFormatter::SetDecimalDigits( sal_uInt16 nDigits )
598{
599 mnDecimalDigits = nDigits;
600 ReformatAll();
601}
602
603void NumericFormatter::SetValue( sal_Int64 nNewValue )
604{
605 SetUserValue( nNewValue );
606 SetEmptyFieldValueData( false );
607}
608
609OUString NumericFormatter::CreateFieldText( sal_Int64 nValue ) const
610{
611 return ImplGetLocaleDataWrapper().getNum( nValue, GetDecimalDigits(), IsUseThousandSep(), /*ShowTrailingZeros*/true );
612}
613
614void NumericFormatter::ImplSetUserValue( sal_Int64 nNewValue, Selection const * pNewSelection )
615{
616 nNewValue = ClipAgainstMinMax(nNewValue);
617 mnLastValue = nNewValue;
618
619 if ( GetField() )
620 FormatValue(pNewSelection);
621}
622
623void NumericFormatter::SetUserValue( sal_Int64 nNewValue )
624{
625 ImplSetUserValue( nNewValue );
626}
627
628sal_Int64 NumericFormatter::GetValueFromString(const OUString& rStr) const
629{
630 sal_Int64 nTempValue;
631
632 if (ImplNumericGetValue(rStr, nTempValue,
634 {
635 return ClipAgainstMinMax(nTempValue);
636 }
637 else
638 return mnLastValue;
639}
640
642{
644 getNum(GetValue(), GetDecimalDigits(), false, false);
645}
646
647// currently used by online
648void NumericFormatter::SetValueFromString(const OUString& rStr)
649{
650 sal_Int64 nValue;
651
652 if (ImplNumericGetValue(rStr, nValue, GetDecimalDigits(),
653 Application::GetSettings().GetNeutralLocaleDataWrapper()))
654 {
656 }
657 else
658 {
659 SAL_WARN("vcl", "fail to convert the value: " << rStr );
660 }
661}
662
664{
665 if (mbFormatting) //don't parse the entry if we're currently formatting what to put in it
666 return mnLastValue;
667
668 return GetField() ? GetValueFromString(GetField()->GetText()) : 0;
669}
670
671sal_Int64 NumericFormatter::Normalize( sal_Int64 nValue ) const
672{
673 return (nValue * ImplPower10( GetDecimalDigits() ) );
674}
675
676sal_Int64 NumericFormatter::Denormalize( sal_Int64 nValue ) const
677{
678 sal_Int64 nFactor = ImplPower10( GetDecimalDigits() );
679
680 if ((nValue < ( SAL_MIN_INT64 + nFactor )) ||
681 (nValue > ( SAL_MAX_INT64 - nFactor )))
682 {
683 return ( nValue / nFactor );
684 }
685
686 if( nValue < 0 )
687 {
688 sal_Int64 nHalf = nFactor / 2;
689 return ((nValue - nHalf) / nFactor );
690 }
691 else
692 {
693 sal_Int64 nHalf = nFactor / 2;
694 return ((nValue + nHalf) / nFactor );
695 }
696}
697
699{
700 if ( !GetField() )
701 return;
702
703 if ( GetField()->GetText().isEmpty() && ImplGetEmptyFieldValue() )
704 return;
705
707}
708
710{
711 sal_Int64 nValue = GetValue();
712 sal_Int64 nRemainder = nValue % mnSpinSize;
713 if (nValue >= 0)
714 nValue = (nRemainder == 0) ? nValue + mnSpinSize : nValue + mnSpinSize - nRemainder;
715 else
716 nValue = (nRemainder == 0) ? nValue + mnSpinSize : nValue - nRemainder;
717
719
721}
722
724{
725 sal_Int64 nValue = GetValue();
726 sal_Int64 nRemainder = nValue % mnSpinSize;
727 if (nValue >= 0)
728 nValue = (nRemainder == 0) ? nValue - mnSpinSize : nValue - nRemainder;
729 else
730 nValue = (nRemainder == 0) ? nValue - mnSpinSize : nValue - mnSpinSize - nRemainder;
731
733
735}
736
738{
740}
741
743{
745}
746
747void NumericFormatter::ImplNewFieldValue( sal_Int64 nNewValue )
748{
749 if ( !GetField() )
750 return;
751
752 // !!! We should check why we do not validate in ImplSetUserValue() if the value was
753 // changed. This should be done there as well since otherwise the call to Modify would not
754 // be allowed. Anyway, the paths from ImplNewFieldValue, ImplSetUserValue, and ImplSetText
755 // should be checked and clearly traced (with comment) in order to find out what happens.
756
757 Selection aSelection = GetField()->GetSelection();
758 aSelection.Normalize();
759 OUString aText = GetField()->GetText();
760 // leave it as is if selected until end
761 if ( static_cast<sal_Int32>(aSelection.Max()) == aText.getLength() )
762 {
763 if ( !aSelection.Len() )
764 aSelection.Min() = SELECTION_MAX;
765 aSelection.Max() = SELECTION_MAX;
766 }
767
768 sal_Int64 nOldLastValue = mnLastValue;
769 ImplSetUserValue( nNewValue, &aSelection );
770 mnLastValue = nOldLastValue;
771
772 // Modify during Edit is only set during KeyInput
773 if ( GetField()->GetText() != aText )
774 {
776 GetField()->Modify();
777 }
778}
779
780sal_Int64 NumericFormatter::ClipAgainstMinMax(sal_Int64 nValue) const
781{
782 if (nValue > mnMax)
783 nValue = mnMax;
784 else if (nValue < mnMin)
785 nValue = mnMin;
786 return nValue;
787}
788
789namespace
790{
791 Size calcMinimumSize(const Edit &rSpinField, const NumericFormatter &rFormatter)
792 {
793 OUStringBuffer aBuf;
794 sal_Int32 nTextLen;
795
796 nTextLen = OUString(OUString::number(rFormatter.GetMin())).getLength();
797 string::padToLength(aBuf, nTextLen, '9');
798 Size aMinTextSize = rSpinField.CalcMinimumSizeForText(
799 rFormatter.CreateFieldText(OUString::unacquired(aBuf).toInt64()));
800 aBuf.setLength(0);
801
802 nTextLen = OUString(OUString::number(rFormatter.GetMax())).getLength();
803 string::padToLength(aBuf, nTextLen, '9');
804 Size aMaxTextSize = rSpinField.CalcMinimumSizeForText(
805 rFormatter.CreateFieldText(OUString::unacquired(aBuf).toInt64()));
806 aBuf.setLength(0);
807
808 Size aRet(std::max(aMinTextSize.Width(), aMaxTextSize.Width()),
809 std::max(aMinTextSize.Height(), aMaxTextSize.Height()));
810
811 OUStringBuffer sBuf("999999999");
812 sal_uInt16 nDigits = rFormatter.GetDecimalDigits();
813 if (nDigits)
814 {
815 sBuf.append('.');
816 string::padToLength(aBuf, aBuf.getLength() + nDigits, '9');
817 }
818 aMaxTextSize = rSpinField.CalcMinimumSizeForText(sBuf.makeStringAndClear());
819 aRet.setWidth( std::min(aRet.Width(), aMaxTextSize.Width()) );
820
821 return aRet;
822 }
823}
824
825NumericBox::NumericBox(vcl::Window* pParent, WinBits nWinStyle)
826 : ComboBox(pParent, nWinStyle)
827 , NumericFormatter(this)
828{
829 Reformat();
830 if ( !(nWinStyle & WB_HIDE ) )
831 Show();
832}
833
834void NumericBox::dispose()
835{
836 ClearField();
838}
839
840Size NumericBox::CalcMinimumSize() const
841{
842 Size aRet(calcMinimumSize(*this, *this));
843
844 if (IsDropDownBox())
845 {
846 Size aComboSugg(ComboBox::CalcMinimumSize());
847 aRet.setWidth( std::max(aRet.Width(), aComboSugg.Width()) );
848 aRet.setHeight( std::max(aRet.Height(), aComboSugg.Height()) );
849 }
850
851 return aRet;
852}
853
854bool NumericBox::PreNotify( NotifyEvent& rNEvt )
855{
856 if ( (rNEvt.GetType() == NotifyEventType::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
857 {
858 if ( ImplNumericProcessKeyInput( *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
859 return true;
860 }
861
862 return ComboBox::PreNotify( rNEvt );
863}
864
865bool NumericBox::EventNotify( NotifyEvent& rNEvt )
866{
867 if ( rNEvt.GetType() == NotifyEventType::GETFOCUS )
868 MarkToBeReformatted( false );
869 else if ( rNEvt.GetType() == NotifyEventType::LOSEFOCUS )
870 {
871 if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
872 Reformat();
873 }
874
875 return ComboBox::EventNotify( rNEvt );
876}
877
878void NumericBox::DataChanged( const DataChangedEvent& rDCEvt )
879{
880 ComboBox::DataChanged( rDCEvt );
881
883 {
884 OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
885 OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
886 ImplResetLocaleDataWrapper();
887 OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
888 OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
889 ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
890 ReformatAll();
891 }
892}
893
894void NumericBox::Modify()
895{
896 MarkToBeReformatted( true );
898}
899
900void NumericBox::ImplNumericReformat( const OUString& rStr, sal_Int64& rValue,
901 OUString& rOutStr )
902{
903 if (ImplNumericGetValue(rStr, rValue, GetDecimalDigits(), ImplGetLocaleDataWrapper()))
904 {
905 sal_Int64 nTempVal = ClipAgainstMinMax(rValue);
906 rOutStr = CreateFieldText( nTempVal );
907 }
908}
909
910void NumericBox::ReformatAll()
911{
912 sal_Int64 nValue;
913 OUString aStr;
914 SetUpdateMode( false );
915 sal_Int32 nEntryCount = GetEntryCount();
916 for ( sal_Int32 i=0; i < nEntryCount; i++ )
917 {
918 ImplNumericReformat( GetEntry( i ), nValue, aStr );
919 RemoveEntryAt(i);
920 InsertEntry( aStr, i );
921 }
923 SetUpdateMode( true );
924}
925
926static bool ImplMetricProcessKeyInput( const KeyEvent& rKEvt,
927 bool bUseThousandSep, const LocaleDataWrapper& rWrapper )
928{
929 // no meaningful strict format; therefore allow all characters
930 return ImplNumericProcessKeyInput( rKEvt, false, bUseThousandSep, rWrapper );
931}
932
933static OUString ImplMetricGetUnitText(std::u16string_view rStr)
934{
935 // fetch unit text
936 OUStringBuffer aStr;
937 for (sal_Int32 i = static_cast<sal_Int32>(rStr.size())-1; i >= 0; --i)
938 {
939 sal_Unicode c = rStr[i];
940 if ( (c == '\'') || (c == '\"') || (c == '%') || (c == 0x2032) || (c == 0x2033) || unicode::isAlpha(c) || unicode::isControl(c) )
941 aStr.insert(0, c);
942 else
943 {
944 if (!aStr.isEmpty())
945 break;
946 }
947 }
948 return aStr.makeStringAndClear();
949}
950
951// #104355# support localized measurements
952
953static OUString ImplMetricToString( FieldUnit rUnit )
954{
955 // return unit's default string (ie, the first one )
956 for (auto const& elem : ImplGetFieldUnits())
957 {
958 if (elem.second == rUnit)
959 return elem.first;
960 }
961
962 return OUString();
963}
964
965namespace
966{
967 FieldUnit StringToMetric(const OUString &rMetricString)
968 {
969 // return FieldUnit
970 OUString aStr = rMetricString.toAsciiLowerCase().replaceAll(" ", "");
971 for (auto const& elem : ImplGetCleanedFieldUnits())
972 {
973 if ( elem.first == aStr )
974 return elem.second;
975 }
976
977 return FieldUnit::NONE;
978 }
979}
980
981static FieldUnit ImplMetricGetUnit(std::u16string_view rStr)
982{
983 OUString aStr = ImplMetricGetUnitText(rStr);
984 return StringToMetric(aStr);
985}
986
987static FieldUnit ImplMap2FieldUnit( MapUnit meUnit, tools::Long& nDecDigits )
988{
989 switch( meUnit )
990 {
991 case MapUnit::Map100thMM :
992 nDecDigits -= 2;
993 return FieldUnit::MM;
994 case MapUnit::Map10thMM :
995 nDecDigits -= 1;
996 return FieldUnit::MM;
997 case MapUnit::MapMM :
998 return FieldUnit::MM;
999 case MapUnit::MapCM :
1000 return FieldUnit::CM;
1001 case MapUnit::Map1000thInch :
1002 nDecDigits -= 3;
1003 return FieldUnit::INCH;
1004 case MapUnit::Map100thInch :
1005 nDecDigits -= 2;
1006 return FieldUnit::INCH;
1007 case MapUnit::Map10thInch :
1008 nDecDigits -= 1;
1009 return FieldUnit::INCH;
1010 case MapUnit::MapInch :
1011 return FieldUnit::INCH;
1012 case MapUnit::MapPoint :
1013 return FieldUnit::POINT;
1014 case MapUnit::MapTwip :
1015 return FieldUnit::TWIP;
1016 default:
1017 OSL_FAIL( "default eInUnit" );
1018 break;
1019 }
1020 return FieldUnit::NONE;
1021}
1022
1023static double nonValueDoubleToValueDouble( double nValue )
1024{
1025 return std::isfinite( nValue ) ? nValue : 0.0;
1026}
1027
1028namespace vcl
1029{
1030 sal_Int64 ConvertValue(sal_Int64 nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits,
1031 FieldUnit eInUnit, FieldUnit eOutUnit)
1032 {
1034 static_cast<double>(nValue), mnBaseValue, nDecDigits, eInUnit, eOutUnit));
1035 sal_Int64 nLong ;
1036
1037 // caution: precision loss in double cast
1038 if ( nDouble <= double(SAL_MIN_INT64) )
1039 nLong = SAL_MIN_INT64;
1040 else if ( nDouble >= double(SAL_MAX_INT64) )
1041 nLong = SAL_MAX_INT64;
1042 else
1043 nLong = static_cast<sal_Int64>( std::round(nDouble) );
1044
1045 return nLong;
1046 }
1047}
1048
1049namespace {
1050
1051bool checkConversionUnits(MapUnit eInUnit, FieldUnit eOutUnit)
1052{
1053 return eOutUnit != FieldUnit::PERCENT
1054 && eOutUnit != FieldUnit::CUSTOM
1055 && eOutUnit != FieldUnit::NONE
1056 && eInUnit != MapUnit::MapPixel
1057 && eInUnit != MapUnit::MapSysFont
1058 && eInUnit != MapUnit::MapAppFont
1059 && eInUnit != MapUnit::MapRelative;
1060}
1061
1062double convertValue( double nValue, tools::Long nDigits, FieldUnit eInUnit, FieldUnit eOutUnit )
1063{
1064 if ( nDigits < 0 )
1065 {
1066 while ( nDigits )
1067 {
1068 nValue += 5;
1069 nValue /= 10;
1070 nDigits++;
1071 }
1072 }
1073 else
1074 {
1075 nValue *= ImplPower10(nDigits);
1076 }
1077
1078 if ( eInUnit != eOutUnit )
1079 {
1080 const o3tl::Length eFrom = FieldToO3tlLength(eInUnit), eTo = FieldToO3tlLength(eOutUnit);
1081 if (eFrom != o3tl::Length::invalid && eTo != o3tl::Length::invalid)
1082 nValue = o3tl::convert(nValue, eFrom, eTo);
1083 }
1084
1085 return nValue;
1086}
1087
1088}
1089
1090namespace vcl
1091{
1092 sal_Int64 ConvertValue( sal_Int64 nValue, sal_uInt16 nDigits,
1093 MapUnit eInUnit, FieldUnit eOutUnit )
1094 {
1095 if ( !checkConversionUnits(eInUnit, eOutUnit) )
1096 {
1097 OSL_FAIL( "invalid parameters" );
1098 return nValue;
1099 }
1100
1101 tools::Long nDecDigits = nDigits;
1102 FieldUnit eFieldUnit = ImplMap2FieldUnit( eInUnit, nDecDigits );
1103
1104 // Avoid sal_Int64 <-> double conversion issues if possible:
1105 if (eFieldUnit == eOutUnit && nDigits == 0)
1106 {
1107 return nValue;
1108 }
1109
1110 return static_cast<sal_Int64>(
1112 convertValue( nValue, nDecDigits, eFieldUnit, eOutUnit ) ) );
1113 }
1114
1115 double ConvertDoubleValue(double nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits,
1116 FieldUnit eInUnit, FieldUnit eOutUnit)
1117 {
1118 if ( eInUnit != eOutUnit )
1119 {
1120 if (eInUnit == FieldUnit::PERCENT && mnBaseValue > 0 && nValue > 0)
1121 {
1122 sal_Int64 nDiv = 100 * ImplPower10(nDecDigits);
1123
1124 if (mnBaseValue != 1)
1125 nValue *= mnBaseValue;
1126
1127 nValue += nDiv / 2;
1128 nValue /= nDiv;
1129 }
1130 else
1131 {
1134 if (eFrom != o3tl::Length::invalid && eTo != o3tl::Length::invalid)
1135 nValue = o3tl::convert(nValue, eFrom, eTo);
1136 }
1137 }
1138
1139 return nValue;
1140 }
1141
1142 double ConvertDoubleValue(double nValue, sal_uInt16 nDigits,
1143 MapUnit eInUnit, FieldUnit eOutUnit)
1144 {
1145 if ( !checkConversionUnits(eInUnit, eOutUnit) )
1146 {
1147 OSL_FAIL( "invalid parameters" );
1148 return nValue;
1149 }
1150
1151 tools::Long nDecDigits = nDigits;
1152 FieldUnit eFieldUnit = ImplMap2FieldUnit( eInUnit, nDecDigits );
1153
1154 return convertValue(nValue, nDecDigits, eFieldUnit, eOutUnit);
1155 }
1156
1157 double ConvertDoubleValue(double nValue, sal_uInt16 nDigits,
1158 FieldUnit eInUnit, MapUnit eOutUnit)
1159 {
1160 if ( eInUnit == FieldUnit::PERCENT ||
1161 eInUnit == FieldUnit::CUSTOM ||
1162 eInUnit == FieldUnit::NONE ||
1163 eInUnit == FieldUnit::DEGREE ||
1164 eInUnit == FieldUnit::SECOND ||
1165 eInUnit == FieldUnit::MILLISECOND ||
1166 eInUnit == FieldUnit::PIXEL ||
1167 eOutUnit == MapUnit::MapPixel ||
1168 eOutUnit == MapUnit::MapSysFont ||
1169 eOutUnit == MapUnit::MapAppFont ||
1170 eOutUnit == MapUnit::MapRelative )
1171 {
1172 OSL_FAIL( "invalid parameters" );
1173 return nValue;
1174 }
1175
1176 tools::Long nDecDigits = nDigits;
1177 FieldUnit eFieldUnit = ImplMap2FieldUnit( eOutUnit, nDecDigits );
1178
1179 if ( nDecDigits < 0 )
1180 {
1181 nValue *= ImplPower10(-nDecDigits);
1182 }
1183 else
1184 {
1185 nValue /= ImplPower10(nDecDigits);
1186 }
1187
1188 if ( eFieldUnit != eInUnit )
1189 {
1191 const o3tl::Length eTo = FieldToO3tlLength(eFieldUnit, o3tl::Length::invalid);
1192 if (eFrom != o3tl::Length::invalid && eTo != o3tl::Length::invalid)
1193 nValue = o3tl::convert(nValue, eFrom, eTo);
1194 }
1195 return nValue;
1196 }
1197}
1198
1199namespace vcl
1200{
1201 bool TextToValue(const OUString& rStr, double& rValue, sal_Int64 nBaseValue,
1202 sal_uInt16 nDecDigits, const LocaleDataWrapper& rLocaleDataWrapper, FieldUnit eUnit)
1203 {
1204 // Get value
1205 sal_Int64 nValue;
1206 if ( !ImplNumericGetValue( rStr, nValue, nDecDigits, rLocaleDataWrapper ) )
1207 return false;
1208
1209 // Determine unit
1210 FieldUnit eEntryUnit = ImplMetricGetUnit( rStr );
1211
1212 // Recalculate unit
1213 // caution: conversion to double loses precision
1214 rValue = vcl::ConvertDoubleValue(static_cast<double>(nValue), nBaseValue, nDecDigits, eEntryUnit, eUnit);
1215
1216 return true;
1217 }
1218}
1219
1220void MetricFormatter::ImplMetricReformat( const OUString& rStr, double& rValue, OUString& rOutStr )
1221{
1223 return;
1224
1225 double nTempVal = rValue;
1226 // caution: precision loss in double cast
1227 if ( nTempVal > GetMax() )
1228 nTempVal = static_cast<double>(GetMax());
1229 else if ( nTempVal < GetMin())
1230 nTempVal = static_cast<double>(GetMin());
1231 rOutStr = CreateFieldText( static_cast<sal_Int64>(nTempVal) );
1232}
1233
1235 : NumericFormatter(pEdit)
1236 , meUnit(FieldUnit::NONE)
1237{
1238}
1239
1241{
1242}
1243
1245{
1246 if (eNewUnit == FieldUnit::MM_100TH)
1247 {
1249 meUnit = FieldUnit::MM;
1250 }
1251 else
1252 meUnit = eNewUnit;
1253 ReformatAll();
1254}
1255
1256void MetricFormatter::SetCustomUnitText( const OUString& rStr )
1257{
1258 maCustomUnitText = rStr;
1259 ReformatAll();
1260}
1261
1262void MetricFormatter::SetValue( sal_Int64 nNewValue, FieldUnit eInUnit )
1263{
1264 SetUserValue( nNewValue, eInUnit );
1265}
1266
1267OUString MetricFormatter::CreateFieldText( sal_Int64 nValue ) const
1268{
1269 //whether percent is separated from its number is locale
1270 //specific, pawn it off to icu to decide
1271 if (meUnit == FieldUnit::PERCENT)
1272 {
1273 double dValue = nValue;
1274 dValue /= ImplPower10(GetDecimalDigits());
1275 return unicode::formatPercent(dValue, GetLanguageTag());
1276 }
1277
1279
1280 if( meUnit == FieldUnit::CUSTOM )
1282 else
1283 {
1284 OUString aSuffix = ImplMetricToString( meUnit );
1285 if (meUnit != FieldUnit::NONE && meUnit != FieldUnit::DEGREE && meUnit != FieldUnit::INCH && meUnit != FieldUnit::FOOT)
1286 aStr += " ";
1287 if (meUnit == FieldUnit::INCH)
1288 {
1289 OUString sDoublePrime = u"\u2033";
1290 if (aSuffix != "\"" && aSuffix != sDoublePrime)
1291 aStr += " ";
1292 else
1293 aSuffix = sDoublePrime;
1294 }
1295 else if (meUnit == FieldUnit::FOOT)
1296 {
1297 OUString sPrime = u"\u2032";
1298 if (aSuffix != "'" && aSuffix != sPrime)
1299 aStr += " ";
1300 else
1301 aSuffix = sPrime;
1302 }
1303
1304 assert(meUnit != FieldUnit::PERCENT);
1305 aStr += aSuffix;
1306 }
1307 return aStr;
1308}
1309
1310void MetricFormatter::SetUserValue( sal_Int64 nNewValue, FieldUnit eInUnit )
1311{
1312 // convert to previously configured units
1313 nNewValue = vcl::ConvertValue( nNewValue, 0, GetDecimalDigits(), eInUnit, meUnit );
1314 NumericFormatter::SetUserValue( nNewValue );
1315}
1316
1317sal_Int64 MetricFormatter::GetValueFromStringUnit(const OUString& rStr, FieldUnit eOutUnit) const
1318{
1319 double nTempValue;
1320 // caution: precision loss in double cast
1321 if (!vcl::TextToValue(rStr, nTempValue, 0, GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit))
1322 nTempValue = static_cast<double>(mnLastValue);
1323
1324 // caution: precision loss in double cast
1325 if (nTempValue > mnMax)
1326 nTempValue = static_cast<double>(mnMax);
1327 else if (nTempValue < mnMin)
1328 nTempValue = static_cast<double>(mnMin);
1329
1330 // convert to requested units
1331 return vcl::ConvertValue(static_cast<sal_Int64>(nTempValue), 0, GetDecimalDigits(), meUnit, eOutUnit);
1332}
1333
1334sal_Int64 MetricFormatter::GetValueFromString(const OUString& rStr) const
1335{
1336 return GetValueFromStringUnit(rStr, FieldUnit::NONE);
1337}
1338
1339sal_Int64 MetricFormatter::GetValue( FieldUnit eOutUnit ) const
1340{
1341 return GetField() ? GetValueFromStringUnit(GetField()->GetText(), eOutUnit) : 0;
1342}
1343
1344void MetricFormatter::SetValue( sal_Int64 nValue )
1345{
1346 // Implementation not inline, because it is a virtual Function
1347 SetValue( nValue, FieldUnit::NONE );
1348}
1349
1350void MetricFormatter::SetMin( sal_Int64 nNewMin, FieldUnit eInUnit )
1351{
1352 // convert to requested units
1354}
1355
1356sal_Int64 MetricFormatter::GetMin( FieldUnit eOutUnit ) const
1357{
1358 // convert to requested units
1360}
1361
1362void MetricFormatter::SetMax( sal_Int64 nNewMax, FieldUnit eInUnit )
1363{
1364 // convert to requested units
1366}
1367
1368sal_Int64 MetricFormatter::GetMax( FieldUnit eOutUnit ) const
1369{
1370 // convert to requested units
1372}
1373
1375{
1376 if ( !GetField() )
1377 return;
1378
1379 OUString aText = GetField()->GetText();
1380
1381 OUString aStr;
1382 // caution: precision loss in double cast
1383 double nTemp = static_cast<double>(mnLastValue);
1384 ImplMetricReformat( aText, nTemp, aStr );
1385 mnLastValue = static_cast<sal_Int64>(nTemp);
1386
1387 if ( !aStr.isEmpty() )
1388 {
1389 ImplSetText( aStr );
1390 }
1391 else
1393}
1394
1396{
1397 // convert to requested units
1398 return vcl::ConvertValue(0/*nCorrectedValue*/, 0, GetDecimalDigits(),
1399 meUnit, eOutUnit);
1400}
1401
1403 : SpinField(pParent, nWinStyle, WindowType::METRICFIELD)
1404 , MetricFormatter(this)
1405{
1406 Reformat();
1407}
1408
1410{
1411 ClearField();
1413}
1414
1416{
1417 return calcMinimumSize(*this, *this);
1418}
1419
1420bool MetricField::set_property(const OString &rKey, const OUString &rValue)
1421{
1422 if (rKey == "digits")
1423 SetDecimalDigits(rValue.toInt32());
1424 else if (rKey == "spin-size")
1425 SetSpinSize(rValue.toInt32());
1426 else
1427 return SpinField::set_property(rKey, rValue);
1428 return true;
1429}
1430
1432{
1433 sal_Int64 nRawMax = GetMax( nNewUnit );
1434 sal_Int64 nMax = Denormalize( nRawMax );
1435 sal_Int64 nMin = Denormalize( GetMin( nNewUnit ) );
1436 sal_Int64 nFirst = Denormalize( GetFirst( nNewUnit ) );
1437 sal_Int64 nLast = Denormalize( GetLast( nNewUnit ) );
1438
1439 MetricFormatter::SetUnit( nNewUnit );
1440
1441 SetMax( Normalize( nMax ), nNewUnit );
1442 SetMin( Normalize( nMin ), nNewUnit );
1443 SetFirst( Normalize( nFirst ), nNewUnit );
1444 SetLast( Normalize( nLast ), nNewUnit );
1445}
1446
1447void MetricField::SetFirst( sal_Int64 nNewFirst, FieldUnit eInUnit )
1448{
1449 // convert
1450 nNewFirst = vcl::ConvertValue(nNewFirst, 0, GetDecimalDigits(), eInUnit, meUnit);
1451 mnFirst = nNewFirst;
1452}
1453
1454sal_Int64 MetricField::GetFirst( FieldUnit eOutUnit ) const
1455{
1456 // convert
1457 return vcl::ConvertValue(mnFirst, 0, GetDecimalDigits(), meUnit, eOutUnit);
1458}
1459
1460void MetricField::SetLast( sal_Int64 nNewLast, FieldUnit eInUnit )
1461{
1462 // convert
1463 nNewLast = vcl::ConvertValue(nNewLast, 0, GetDecimalDigits(), eInUnit, meUnit);
1464 mnLast = nNewLast;
1465}
1466
1467sal_Int64 MetricField::GetLast( FieldUnit eOutUnit ) const
1468{
1469 // convert
1470 return vcl::ConvertValue(mnLast, 0, GetDecimalDigits(), meUnit, eOutUnit);
1471}
1472
1474{
1475 if ( (rNEvt.GetType() == NotifyEventType::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
1476 {
1478 return true;
1479 }
1480
1481 return SpinField::PreNotify( rNEvt );
1482}
1483
1485{
1486 if ( rNEvt.GetType() == NotifyEventType::GETFOCUS )
1487 MarkToBeReformatted( false );
1488 else if ( rNEvt.GetType() == NotifyEventType::LOSEFOCUS )
1489 {
1490 if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
1491 Reformat();
1492 }
1493
1494 return SpinField::EventNotify( rNEvt );
1495}
1496
1498{
1499 SpinField::DataChanged( rDCEvt );
1500
1501 if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
1502 {
1503 OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1504 OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1506 OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1507 OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1508 ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
1509 ReformatAll();
1510 }
1511}
1512
1514{
1515 MarkToBeReformatted( true );
1517}
1518
1520{
1521 FieldUp();
1522 SpinField::Up();
1523}
1524
1526{
1527 FieldDown();
1529}
1530
1532{
1533 FieldFirst();
1535}
1536
1538{
1539 FieldLast();
1541}
1542
1544{
1545 SpinField::DumpAsPropertyTree(rJsonWriter);
1546 rJsonWriter.put("min", GetMin());
1547 rJsonWriter.put("max", GetMax());
1548 rJsonWriter.put("unit", FieldUnitToString(GetUnit()));
1550 getNum(GetValue(), GetDecimalDigits(), false, false);
1551 rJsonWriter.put("value", sValue);
1552}
1553
1555{
1557}
1558
1560 : ComboBox(pParent, nWinStyle)
1561 , MetricFormatter(this)
1562{
1563 Reformat();
1564}
1565
1567{
1568 ClearField();
1570}
1571
1573{
1574 Size aRet(calcMinimumSize(*this, *this));
1575
1576 if (IsDropDownBox())
1577 {
1578 Size aComboSugg(ComboBox::CalcMinimumSize());
1579 aRet.setWidth( std::max(aRet.Width(), aComboSugg.Width()) );
1580 aRet.setHeight( std::max(aRet.Height(), aComboSugg.Height()) );
1581 }
1582
1583 return aRet;
1584}
1585
1587{
1588 if ( (rNEvt.GetType() == NotifyEventType::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
1589 {
1591 return true;
1592 }
1593
1594 return ComboBox::PreNotify( rNEvt );
1595}
1596
1598{
1599 if ( rNEvt.GetType() == NotifyEventType::GETFOCUS )
1600 MarkToBeReformatted( false );
1601 else if ( rNEvt.GetType() == NotifyEventType::LOSEFOCUS )
1602 {
1603 if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
1604 Reformat();
1605 }
1606
1607 return ComboBox::EventNotify( rNEvt );
1608}
1609
1611{
1612 ComboBox::DataChanged( rDCEvt );
1613
1614 if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
1615 {
1616 OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1617 OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1619 OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1620 OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1621 ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
1622 ReformatAll();
1623 }
1624}
1625
1627{
1628 MarkToBeReformatted( true );
1630}
1631
1633{
1634 double nValue;
1635 OUString aStr;
1636 SetUpdateMode( false );
1637 sal_Int32 nEntryCount = GetEntryCount();
1638 for ( sal_Int32 i=0; i < nEntryCount; i++ )
1639 {
1642 InsertEntry( aStr, i );
1643 }
1645 SetUpdateMode( true );
1646}
1647
1648static bool ImplCurrencyProcessKeyInput( const KeyEvent& rKEvt,
1649 bool bUseThousandSep, const LocaleDataWrapper& rWrapper )
1650{
1651 // no strict format set; therefore allow all characters
1652 return ImplNumericProcessKeyInput( rKEvt, false, bUseThousandSep, rWrapper );
1653}
1654
1655static bool ImplCurrencyGetValue( const OUString& rStr, sal_Int64& rValue,
1656 sal_uInt16 nDecDigits, const LocaleDataWrapper& rWrapper )
1657{
1658 // fetch number
1659 return ImplNumericGetValue( rStr, rValue, nDecDigits, rWrapper, true );
1660}
1661
1662void CurrencyFormatter::ImplCurrencyReformat( const OUString& rStr, OUString& rOutStr )
1663{
1664 sal_Int64 nValue;
1665 if ( !ImplNumericGetValue( rStr, nValue, GetDecimalDigits(), ImplGetLocaleDataWrapper(), true ) )
1666 return;
1667
1668 sal_Int64 nTempVal = nValue;
1669 if ( nTempVal > GetMax() )
1670 nTempVal = GetMax();
1671 else if ( nTempVal < GetMin())
1672 nTempVal = GetMin();
1673 rOutStr = CreateFieldText( nTempVal );
1674}
1675
1676CurrencyFormatter::CurrencyFormatter(Edit* pField)
1677 : NumericFormatter(pField)
1678{
1679}
1680
1681CurrencyFormatter::~CurrencyFormatter()
1682{
1683}
1684
1685void CurrencyFormatter::SetValue( sal_Int64 nNewValue )
1686{
1687 SetUserValue( nNewValue );
1688 SetEmptyFieldValueData( false );
1689}
1690
1691OUString CurrencyFormatter::CreateFieldText( sal_Int64 nValue ) const
1692{
1693 return ImplGetLocaleDataWrapper().getCurr( nValue, GetDecimalDigits(),
1694 ImplGetLocaleDataWrapper().getCurrSymbol(),
1695 IsUseThousandSep() );
1696}
1697
1698sal_Int64 CurrencyFormatter::GetValueFromString(const OUString& rStr) const
1699{
1700 sal_Int64 nTempValue;
1701 if ( ImplCurrencyGetValue( rStr, nTempValue, GetDecimalDigits(), ImplGetLocaleDataWrapper() ) )
1702 {
1703 return ClipAgainstMinMax(nTempValue);
1704 }
1705 else
1706 return mnLastValue;
1707}
1708
1709void CurrencyFormatter::Reformat()
1710{
1711 if ( !GetField() )
1712 return;
1713
1714 OUString aStr;
1715 ImplCurrencyReformat( GetField()->GetText(), aStr );
1716
1717 if ( !aStr.isEmpty() )
1718 {
1719 ImplSetText( aStr );
1720 sal_Int64 nTemp = mnLastValue;
1721 ImplCurrencyGetValue( aStr, nTemp, GetDecimalDigits(), ImplGetLocaleDataWrapper() );
1722 mnLastValue = nTemp;
1723 }
1724 else
1725 SetValue( mnLastValue );
1726}
1727
1728CurrencyField::CurrencyField(vcl::Window* pParent, WinBits nWinStyle)
1729 : SpinField(pParent, nWinStyle)
1730 , CurrencyFormatter(this)
1731{
1732 Reformat();
1733}
1734
1735void CurrencyField::dispose()
1736{
1737 ClearField();
1739}
1740
1741bool CurrencyField::PreNotify( NotifyEvent& rNEvt )
1742{
1743 if ( (rNEvt.GetType() == NotifyEventType::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
1744 {
1745 if ( ImplCurrencyProcessKeyInput( *rNEvt.GetKeyEvent(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
1746 return true;
1747 }
1748
1749 return SpinField::PreNotify( rNEvt );
1750}
1751
1752bool CurrencyField::EventNotify( NotifyEvent& rNEvt )
1753{
1754 if ( rNEvt.GetType() == NotifyEventType::GETFOCUS )
1755 MarkToBeReformatted( false );
1756 else if ( rNEvt.GetType() == NotifyEventType::LOSEFOCUS )
1757 {
1758 if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
1759 Reformat();
1760 }
1761
1762 return SpinField::EventNotify( rNEvt );
1763}
1764
1765void CurrencyField::DataChanged( const DataChangedEvent& rDCEvt )
1766{
1767 SpinField::DataChanged( rDCEvt );
1768
1769 if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
1770 {
1771 OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1772 OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1773 ImplResetLocaleDataWrapper();
1774 OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1775 OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1776 ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
1777 ReformatAll();
1778 }
1779}
1780
1781void CurrencyField::Modify()
1782{
1783 MarkToBeReformatted( true );
1785}
1786
1787void CurrencyField::Up()
1788{
1789 FieldUp();
1790 SpinField::Up();
1791}
1792
1793void CurrencyField::Down()
1794{
1795 FieldDown();
1797}
1798
1799void CurrencyField::First()
1800{
1801 FieldFirst();
1803}
1804
1805void CurrencyField::Last()
1806{
1807 FieldLast();
1809}
1810
1811CurrencyBox::CurrencyBox(vcl::Window* pParent, WinBits nWinStyle)
1812 : ComboBox(pParent, nWinStyle)
1813 , CurrencyFormatter(this)
1814{
1815 Reformat();
1816}
1817
1818void CurrencyBox::dispose()
1819{
1820 ClearField();
1822}
1823
1824bool CurrencyBox::PreNotify( NotifyEvent& rNEvt )
1825{
1826 if ( (rNEvt.GetType() == NotifyEventType::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
1827 {
1828 if ( ImplCurrencyProcessKeyInput( *rNEvt.GetKeyEvent(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
1829 return true;
1830 }
1831
1832 return ComboBox::PreNotify( rNEvt );
1833}
1834
1835bool CurrencyBox::EventNotify( NotifyEvent& rNEvt )
1836{
1837 if ( rNEvt.GetType() == NotifyEventType::GETFOCUS )
1838 MarkToBeReformatted( false );
1839 else if ( rNEvt.GetType() == NotifyEventType::LOSEFOCUS )
1840 {
1841 if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
1842 Reformat();
1843 }
1844
1845 return ComboBox::EventNotify( rNEvt );
1846}
1847
1848void CurrencyBox::DataChanged( const DataChangedEvent& rDCEvt )
1849{
1850 ComboBox::DataChanged( rDCEvt );
1851
1852 if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
1853 {
1854 OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1855 OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1856 ImplResetLocaleDataWrapper();
1857 OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1858 OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1859 ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
1860 ReformatAll();
1861 }
1862}
1863
1864void CurrencyBox::Modify()
1865{
1866 MarkToBeReformatted( true );
1868}
1869
1870void CurrencyBox::ReformatAll()
1871{
1872 OUString aStr;
1873 SetUpdateMode( false );
1874 sal_Int32 nEntryCount = GetEntryCount();
1875 for ( sal_Int32 i=0; i < nEntryCount; i++ )
1876 {
1877 ImplCurrencyReformat( GetEntry( i ), aStr );
1878 RemoveEntryAt(i);
1879 InsertEntry( aStr, i );
1880 }
1881 CurrencyFormatter::Reformat();
1882 SetUpdateMode( true );
1883}
1884
1885/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
constexpr o3tl::Length FieldToO3tlLength(FieldUnit eU, o3tl::Length ePixelValue=o3tl::Length::px)
const LanguageTag & GetLanguageTag() const
const LocaleDataWrapper & GetNeutralLocaleDataWrapper() const
static const AllSettings & GetSettings()
Gets the application's settings.
Definition: svapp.cxx:761
A widget used to choose from a list of items and which has an entry.
Definition: combobox.hxx:39
void RemoveEntryAt(sal_Int32 nPos)
Definition: combobox.cxx:923
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
Definition: combobox.cxx:694
void SetEntryData(sal_Int32 nPos, void *pNewData)
Definition: combobox.cxx:1314
virtual void Modify() override
Definition: combobox.cxx:821
sal_Int32 GetEntryCount() const
Definition: combobox.cxx:963
bool IsDropDownBox() const
Definition: combobox.cxx:606
Size CalcMinimumSize() const override
Definition: combobox.cxx:1023
OUString GetEntry(sal_Int32 nPos) const
Definition: combobox.cxx:954
sal_Int32 InsertEntry(const OUString &rStr, sal_Int32 nPos=COMBOBOX_APPEND)
Definition: combobox.cxx:882
void * GetEntryData(sal_Int32 nPos) const
Definition: combobox.cxx:1319
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects.
Definition: combobox.cxx:125
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: combobox.cxx:716
DataChangedEventType GetType() const
Definition: event.hxx:362
AllSettingsFlags GetFlags() const
Definition: event.hxx:363
Definition: edit.hxx:56
virtual void Modify()
Definition: edit.cxx:2316
virtual bool set_property(const OString &rKey, const OUString &rValue) override
Definition: edit.cxx:183
virtual void SetText(const OUString &rStr) override
Definition: edit.cxx:2547
virtual const Selection & GetSelection() const
Definition: edit.cxx:2470
virtual void DumpAsPropertyTree(tools::JsonWriter &rJsonWriter) override
Dumps itself and potentially its children to a property tree, to be written easily to JSON.
Definition: edit.cxx:2920
virtual Size CalcMinimumSizeForText(const OUString &rString) const
Definition: edit.cxx:2609
virtual void SetModifyFlag()
Definition: edit.cxx:2590
virtual OUString GetText() const override
Definition: edit.cxx:2566
SAL_DLLPRIVATE bool ImplGetEmptyFieldValue() const
Definition: field.hxx:57
SAL_DLLPRIVATE void ImplSetText(const OUString &rText, Selection const *pNewSel=nullptr)
Definition: field.cxx:514
SAL_DLLPRIVATE LocaleDataWrapper & ImplGetLocaleDataWrapper() const
Definition: field.cxx:457
void SetEmptyFieldValueData(bool bValue)
Definition: field.hxx:59
bool mbEmptyFieldValue
Definition: field.hxx:52
const LocaleDataWrapper & GetLocaleDataWrapper() const
Definition: field.cxx:474
bool mbReformat
Definition: field.hxx:50
SAL_DLLPRIVATE void ImplResetLocaleDataWrapper() const
reset the LocaleDataWrapper when the language tag changes
Definition: field.cxx:467
std::unique_ptr< LocaleDataWrapper > mpLocaleDataWrapper
Definition: field.hxx:49
virtual void Reformat()
Definition: field.cxx:479
bool MustBeReformatted() const
Definition: field.hxx:74
void SetEmptyFieldValue()
Definition: field.cxx:530
virtual void ReformatAll()
Definition: field.cxx:483
virtual ~FormatterBase()
Definition: field.cxx:453
bool mbEmptyFieldValueEnabled
Definition: field.hxx:53
const css::lang::Locale & GetLocale() const
Definition: field.cxx:498
const LanguageTag & GetLanguageTag() const
Definition: field.cxx:506
VclPtr< Edit > mpField
Definition: field.hxx:47
bool IsEmptyFieldValueEnabled() const
Definition: field.hxx:90
bool IsEmptyFieldValue() const
Definition: field.cxx:537
FormatterBase(Edit *pField)
Definition: field.cxx:443
void MarkToBeReformatted(bool b)
Definition: field.hxx:75
void SetStrictFormat(bool bStrict)
Definition: field.cxx:488
void ClearField()
Definition: field.hxx:66
bool mbStrictFormat
Definition: field.hxx:51
Edit * GetField() const
Definition: field.hxx:65
sal_Unicode GetCharCode() const
Definition: event.hxx:56
const vcl::KeyCode & GetKeyCode() const
Definition: event.hxx:57
const css::lang::Locale & getLocale(bool bResolveSystem=true) const
sal_uInt16 getCurrNegativeFormat() const
OUString getNum(sal_Int64 nNumber, sal_uInt16 nDecimals, bool bUseThousandSep=true, bool bTrailingZeros=true) const
const OUString & getNumThousandSep() const
const OUString & getNumDecimalSepAlt() const
const OUString & getNumDecimalSep() const
MetricBox(vcl::Window *pParent, WinBits nWinStyle)
Definition: field.cxx:1559
virtual Size CalcMinimumSize() const override
Definition: field.cxx:1572
virtual void Modify() override
Definition: field.cxx:1626
virtual bool PreNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:1586
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
Definition: field.cxx:1610
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects.
Definition: field.cxx:1566
virtual void ReformatAll() override
Definition: field.cxx:1632
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:1597
static std::unique_ptr< UIObject > create(vcl::Window *pWindow)
virtual bool PreNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:1473
virtual void DumpAsPropertyTree(tools::JsonWriter &) override
Dumps itself and potentially its children to a property tree, to be written easily to JSON.
Definition: field.cxx:1543
virtual void Down() override
Definition: field.cxx:1525
virtual void First() override
Definition: field.cxx:1531
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects.
Definition: field.cxx:1409
virtual void Last() override
Definition: field.cxx:1537
MetricField(vcl::Window *pParent, WinBits nWinStyle)
Definition: field.cxx:1402
virtual FactoryFunction GetUITestFactory() const override
Definition: field.cxx:1554
virtual void SetUnit(FieldUnit meUnit) override
Definition: field.cxx:1431
virtual bool set_property(const OString &rKey, const OUString &rValue) override
Definition: field.cxx:1420
virtual Size CalcMinimumSize() const override
Definition: field.cxx:1415
void SetLast(sal_Int64 nNewLast, FieldUnit eInUnit)
Definition: field.cxx:1460
void SetFirst(sal_Int64 nNewFirst, FieldUnit eInUnit)
Definition: field.cxx:1447
virtual void Modify() override
Definition: field.cxx:1513
virtual void Up() override
Definition: field.cxx:1519
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
Definition: field.cxx:1497
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: field.cxx:1484
sal_Int64 GetValueFromStringUnit(const OUString &rStr, FieldUnit eOutUnit) const
Definition: field.cxx:1317
FieldUnit meUnit
Definition: field.hxx:194
void SetMax(sal_Int64 nNewMax, FieldUnit eInUnit)
Definition: field.cxx:1362
virtual sal_Int64 GetValueFromString(const OUString &rStr) const override
Definition: field.cxx:1334
sal_Int64 GetMin() const
Definition: field.hxx:101
virtual OUString CreateFieldText(sal_Int64 nValue) const override
Definition: field.cxx:1267
virtual ~MetricFormatter() override
Definition: field.cxx:1240
SAL_DLLPRIVATE void ImplMetricReformat(const OUString &rStr, double &rValue, OUString &rOutStr)
Definition: field.cxx:1220
sal_Int64 GetValue() const
Definition: field.cxx:663
MetricFormatter(Edit *pEdit)
Definition: field.cxx:1234
FieldUnit GetUnit() const
Definition: field.hxx:171
virtual void Reformat() override
Definition: field.cxx:1374
OUString maCustomUnitText
Definition: field.hxx:204
sal_Int64 GetCorrectedValue(FieldUnit eOutUnit) const
Definition: field.cxx:1395
sal_Int64 GetMax() const
Definition: field.hxx:103
void SetCustomUnitText(const OUString &rStr)
Definition: field.cxx:1256
virtual void SetUnit(FieldUnit meUnit)
Definition: field.cxx:1244
void SetMin(sal_Int64 nNewMin, FieldUnit eInUnit)
Definition: field.cxx:1350
void SetValue(sal_Int64 nNewValue, FieldUnit eInUnit)
Definition: field.cxx:1262
void SetUserValue(sal_Int64 nNewValue, FieldUnit eInUnit)
Definition: field.cxx:1310
const KeyEvent * GetKeyEvent() const
Definition: event.hxx:316
NotifyEventType GetType() const
Definition: event.hxx:308
void FormatValue(Selection const *pNewSelection=nullptr)
Definition: field.cxx:542
void SetMax(sal_Int64 nNewMax)
Definition: field.cxx:584
sal_Int64 GetLast() const
Definition: field.hxx:110
SAL_DLLPRIVATE void ImplSetUserValue(sal_Int64 nNewValue, Selection const *pNewSelection=nullptr)
Definition: field.cxx:614
sal_Int64 GetFirst() const
Definition: field.hxx:108
bool IsUseThousandSep() const
Definition: field.hxx:118
void FieldDown()
Definition: field.cxx:723
sal_Int64 mnLastValue
Definition: field.hxx:132
sal_Int64 GetMin() const
Definition: field.hxx:101
void FieldLast()
Definition: field.cxx:742
bool mbFormatting
Definition: field.hxx:135
sal_Int64 GetValue() const
Definition: field.cxx:663
bool mbThousandSep
Definition: field.hxx:159
sal_Int64 mnMax
Definition: field.hxx:134
NumericFormatter(Edit *pEdit)
Definition: field.cxx:555
void SetUseThousandSep(bool b)
Definition: field.cxx:591
virtual sal_Int64 GetValueFromString(const OUString &rStr) const
Definition: field.cxx:628
sal_Int64 ClipAgainstMinMax(sal_Int64 nValue) const
Definition: field.cxx:780
sal_Int64 mnFirst
Definition: field.hxx:140
virtual OUString CreateFieldText(sal_Int64 nValue) const
Definition: field.cxx:609
sal_uInt16 GetDecimalDigits() const
Definition: field.hxx:115
SAL_DLLPRIVATE void ImplNewFieldValue(sal_Int64 nNewValue)
Definition: field.cxx:747
OUString GetValueString() const
Definition: field.cxx:641
sal_Int64 Normalize(sal_Int64 nValue) const
Definition: field.cxx:671
sal_Int64 GetMax() const
Definition: field.hxx:103
sal_uInt16 mnDecimalDigits
Definition: field.hxx:158
virtual void SetValue(sal_Int64 nNewValue)
Definition: field.cxx:603
virtual ~NumericFormatter() override
Definition: field.cxx:573
void SetDecimalDigits(sal_uInt16 nDigits)
Definition: field.cxx:597
void SetUserValue(sal_Int64 nNewValue)
Definition: field.cxx:623
void SetValueFromString(const OUString &rStr)
Definition: field.cxx:648
virtual void Reformat() override
Definition: field.cxx:698
void SetSpinSize(sal_Int64 nNewSize)
Definition: field.hxx:111
void FieldFirst()
Definition: field.cxx:737
SAL_DLLPRIVATE void ImplNumericReformat()
Definition: field.cxx:549
sal_Int64 Denormalize(sal_Int64 nValue) const
Definition: field.cxx:676
void FieldUp()
Definition: field.cxx:709
sal_Int64 mnMin
Definition: field.hxx:133
void SetMin(sal_Int64 nNewMin)
Definition: field.cxx:577
sal_Int64 mnSpinSize
Definition: field.hxx:139
sal_Int64 mnLast
Definition: field.hxx:141
tools::Long Min() const
tools::Long Len() const
void Normalize()
tools::Long Max() const
constexpr tools::Long Height() const
void setWidth(tools::Long nWidth)
void setHeight(tools::Long nHeight)
constexpr tools::Long Width() const
virtual void Last()
Definition: spinfld.cxx:374
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: spinfld.cxx:485
virtual void First()
Definition: spinfld.cxx:369
virtual void DataChanged(const DataChangedEvent &rDCEvt) override
Definition: spinfld.cxx:836
virtual bool PreNotify(NotifyEvent &rNEvt) override
Definition: spinfld.cxx:858
virtual void Down()
Definition: spinfld.cxx:364
virtual void Up()
Definition: spinfld.cxx:359
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
void put(const char *pPropName, const OUString &rPropValue)
static bool isAlpha(const sal_Unicode ch)
static OUString formatPercent(double dNumber, const LanguageTag &rLangTag)
static bool isControl(const sal_Unicode ch)
sal_uInt16 GetGroup() const
Definition: keycod.hxx:62
bool IsMod2() const
Definition: keycod.hxx:58
void SetUpdateMode(bool bUpdate)
Definition: window.cxx:2972
bool IsUpdateMode() const
Definition: window2.cxx:1197
const AllSettings & GetSettings() const
Definition: window3.cxx:129
virtual bool PreNotify(NotifyEvent &rNEvt)
Definition: event.cxx:52
virtual void SetValue(tools::Long nNew) override
float u
static OUString ImplMetricToString(FieldUnit rUnit)
Definition: field.cxx:953
static OUString ImplMetricGetUnitText(std::u16string_view rStr)
Definition: field.cxx:933
static bool ImplCurrencyProcessKeyInput(const KeyEvent &rKEvt, bool bUseThousandSep, const LocaleDataWrapper &rWrapper)
Definition: field.cxx:1648
static bool ImplCurrencyGetValue(const OUString &rStr, sal_Int64 &rValue, sal_uInt16 nDecDigits, const LocaleDataWrapper &rWrapper)
Definition: field.cxx:1655
static bool ImplMetricProcessKeyInput(const KeyEvent &rKEvt, bool bUseThousandSep, const LocaleDataWrapper &rWrapper)
Definition: field.cxx:926
static double nonValueDoubleToValueDouble(double nValue)
Definition: field.cxx:1023
static FieldUnit ImplMap2FieldUnit(MapUnit meUnit, tools::Long &nDecDigits)
Definition: field.cxx:987
static FieldUnit ImplMetricGetUnit(std::u16string_view rStr)
Definition: field.cxx:981
FieldUnit
sal_Int16 nValue
#define SELECTION_MAX
std::function< std::unique_ptr< UIObject >(vcl::Window *)> FactoryFunction
sal_Int32 nIndex
sal_Int64 n
constexpr sal_uInt16 KEYGROUP_MISC
Definition: keycodes.hxx:41
constexpr sal_uInt16 KEYGROUP_FKEYS
Definition: keycodes.hxx:39
constexpr sal_uInt16 KEYGROUP_CURSOR
Definition: keycodes.hxx:40
#define SAL_WARN(area, stream)
MapUnit
aStr
aBuf
NONE
int i
sal_Int64 toInt64(std::u16string_view str, sal_Int16 radix=10)
constexpr Point convert(const Point &rPoint, o3tl::Length eFrom, o3tl::Length eTo)
long Long
bool TextToValue(const OUString &rStr, double &rValue, sal_Int64 nBaseValue, sal_uInt16 nDecDigits, const LocaleDataWrapper &rLocaleDataWrapper, FieldUnit eUnit)
Definition: field.cxx:1201
double ConvertDoubleValue(double nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits, FieldUnit eInUnit, FieldUnit eOutUnit)
Definition: field.cxx:1115
sal_Int64 ConvertValue(sal_Int64 nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits, FieldUnit eInUnit, FieldUnit eOutUnit)
Definition: field.cxx:1030
const FieldUnitStringList & ImplGetFieldUnits()
Definition: svdata.cxx:265
const FieldUnitStringList & ImplGetCleanedFieldUnits()
Definition: svdata.cxx:295
#define SAL_MAX_INT64
#define SAL_MAX_INT32
#define SAL_MIN_INT64
sal_uInt16 sal_Unicode
sal_Int64 WinBits
Definition: wintypes.hxx:109
WindowType
Definition: wintypes.hxx:27
WinBits const WB_HIDE
Definition: wintypes.hxx:160