Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "sal/config.h"
21 :
22 : #include <comphelper/processfactory.hxx>
23 : #include <comphelper/string.hxx>
24 :
25 : #include "tools/debug.hxx"
26 :
27 : #include "tools/rc.h"
28 :
29 : #include "vcl/dialog.hxx"
30 : #include "vcl/field.hxx"
31 : #include "vcl/event.hxx"
32 : #include "vcl/svapp.hxx"
33 : #include "vcl/settings.hxx"
34 :
35 : #include "svids.hrc"
36 : #include "svdata.hxx"
37 :
38 : #include "i18nutil/unicode.hxx"
39 :
40 : #include "rtl/math.hxx"
41 :
42 : #include <unotools/localedatawrapper.hxx>
43 :
44 : using namespace ::com::sun::star;
45 : using namespace ::comphelper;
46 :
47 : namespace
48 : {
49 :
50 : #define FORMAT_NUMERIC 1
51 : #define FORMAT_METRIC 2
52 : #define FORMAT_CURRENCY 3
53 :
54 43807 : static sal_Int64 ImplPower10( sal_uInt16 n )
55 : {
56 : sal_uInt16 i;
57 43807 : sal_Int64 nValue = 1;
58 :
59 101713 : for ( i=0; i < n; i++ )
60 57906 : nValue *= 10;
61 :
62 43807 : return nValue;
63 : }
64 :
65 0 : static bool ImplNumericProcessKeyInput( Edit*, const KeyEvent& rKEvt,
66 : bool bStrictFormat, bool bThousandSep,
67 : const LocaleDataWrapper& rLocaleDataWrappper )
68 : {
69 0 : if ( !bStrictFormat )
70 0 : return false;
71 : else
72 : {
73 0 : sal_Unicode cChar = rKEvt.GetCharCode();
74 0 : sal_uInt16 nGroup = rKEvt.GetKeyCode().GetGroup();
75 :
76 0 : if ( (nGroup == KEYGROUP_FKEYS) || (nGroup == KEYGROUP_CURSOR) ||
77 0 : (nGroup == KEYGROUP_MISC) ||
78 0 : ((cChar >= '0') && (cChar <= '9')) ||
79 0 : string::equals(rLocaleDataWrappper.getNumDecimalSep(), cChar) ||
80 0 : (bThousandSep && string::equals(rLocaleDataWrappper.getNumThousandSep(), cChar)) ||
81 : (cChar == '-') )
82 0 : return false;
83 : else
84 0 : return true;
85 : }
86 : }
87 :
88 34937 : static bool ImplNumericGetValue( const OUString& rStr, sal_Int64& rValue,
89 : sal_uInt16 nDecDigits, const LocaleDataWrapper& rLocaleDataWrappper,
90 : bool bCurrency = false )
91 : {
92 34937 : OUString aStr = rStr;
93 69874 : OUStringBuffer aStr1, aStr2, aStrFrac, aStrNum, aStrDenom;
94 34937 : bool bNegative = false;
95 34937 : bool bFrac = false;
96 : sal_Int32 nDecPos, nFracDivPos, nFracNumPos;
97 : sal_Int64 nValue;
98 :
99 : // react on empty string
100 34937 : if ( rStr.isEmpty() )
101 4320 : return false;
102 :
103 : // remove leading and trailing spaces
104 30617 : aStr = aStr.trim();
105 :
106 :
107 :
108 : // find position of decimal point
109 30617 : nDecPos = aStr.indexOf( rLocaleDataWrappper.getNumDecimalSep() );
110 : // find position of fraction
111 30617 : nFracDivPos = aStr.indexOf( '/' );
112 :
113 : // parse fractional strings
114 30617 : if (nFracDivPos > 0)
115 : {
116 0 : bFrac = true;
117 0 : nFracNumPos = aStr.lastIndexOf(' ', nFracDivPos);
118 :
119 : // If in "a b/c" format.
120 0 : if(nFracNumPos != -1 )
121 : {
122 0 : aStr1.append(aStr.getStr(), nFracNumPos);
123 0 : aStrNum.append(aStr.getStr()+nFracNumPos+1, nFracDivPos-nFracNumPos-1);
124 0 : aStrDenom.append(aStr.getStr()+nFracDivPos+1);
125 : }
126 : // "a/b" format, or not a fraction at all
127 : else
128 : {
129 0 : aStrNum.append(aStr.getStr(), nFracDivPos);
130 0 : aStrDenom.append(aStr.getStr()+nFracDivPos+1);
131 : }
132 :
133 : }
134 : // parse decimal strings
135 30617 : else if ( nDecPos >= 0)
136 : {
137 13964 : aStr1.append(aStr.getStr(), nDecPos);
138 13964 : aStr2.append(aStr.getStr()+nDecPos+1);
139 : }
140 : else
141 16653 : aStr1 = aStr;
142 :
143 : // negative?
144 30617 : if ( bCurrency )
145 : {
146 0 : if ( aStr.startsWith("(") && aStr.endsWith(")") )
147 0 : bNegative = true;
148 0 : if ( !bNegative )
149 : {
150 0 : for (sal_Int32 i=0; i < aStr.getLength(); i++ )
151 : {
152 0 : if ( (aStr[i] >= '0') && (aStr[i] <= '9') )
153 0 : break;
154 0 : else if ( aStr[i] == '-' )
155 : {
156 0 : bNegative = true;
157 0 : break;
158 : }
159 : }
160 : }
161 0 : if ( !bNegative && bCurrency && !aStr.isEmpty() )
162 : {
163 0 : sal_uInt16 nFormat = rLocaleDataWrappper.getCurrNegativeFormat();
164 0 : if ( (nFormat == 3) || (nFormat == 6) || // $1- || 1-$
165 0 : (nFormat == 7) || (nFormat == 10) ) // 1$- || 1 $-
166 : {
167 0 : for (sal_Int32 i = aStr.getLength()-1; i > 0; --i )
168 : {
169 0 : if ( (aStr[i] >= '0') && (aStr[i] <= '9') )
170 0 : break;
171 0 : else if ( aStr[i] == '-' )
172 : {
173 0 : bNegative = true;
174 0 : break;
175 : }
176 : }
177 : }
178 : }
179 : }
180 : else
181 : {
182 30617 : if ( !aStr1.isEmpty() && aStr1[0] == '-')
183 0 : bNegative = true;
184 30617 : if ( !aStrNum.isEmpty() && aStrNum[0] == '-') // For non-mixed fractions
185 0 : bNegative = true;
186 : }
187 :
188 : // remove all unwanted charaters
189 : // For whole number
190 95335 : for (sal_Int32 i=0; i < aStr1.getLength(); )
191 : {
192 34101 : if ( (aStr1[i] >= '0') && (aStr1[i] <= '9') )
193 32988 : i++;
194 : else
195 1113 : aStr1.remove( i, 1 );
196 : }
197 : // For decimal
198 30617 : if (!bFrac) {
199 110322 : for (sal_Int32 i=0; i < aStr2.getLength(); )
200 : {
201 49088 : if ((aStr2[i] >= '0') && (aStr2[i] <= '9'))
202 27926 : ++i;
203 : else
204 21162 : aStr2.remove(i, 1);
205 : }
206 : }
207 : else {
208 : // for numerator
209 0 : for (sal_Int32 i=0; i < aStrNum.getLength(); )
210 : {
211 0 : if ((aStrNum[i] >= '0') && (aStrNum[i] <= '9'))
212 0 : ++i;
213 : else
214 0 : aStrNum.remove(i, 1);
215 : }
216 : // for denominator
217 0 : for (sal_Int32 i=0; i < aStrDenom.getLength(); )
218 : {
219 0 : if ((aStrDenom[i] >= '0') && (aStrDenom[i] <= '9'))
220 0 : ++i;
221 : else
222 0 : aStrDenom.remove(i, 1);
223 : }
224 : }
225 :
226 :
227 30617 : if ( !bFrac && aStr1.isEmpty() && aStr2.isEmpty() )
228 0 : return false;
229 30617 : else if ( bFrac && aStr1.isEmpty() && (aStrNum.isEmpty() || aStrDenom.isEmpty()) )
230 0 : return false;
231 :
232 30617 : if ( aStr1.isEmpty() )
233 0 : aStr1 = "0";
234 30617 : if ( bNegative )
235 0 : aStr1.insert(0, "-");
236 :
237 : // Convert fractional strings
238 30617 : if (bFrac) {
239 : // Convert to fraction
240 0 : sal_Int64 nWholeNum = aStr1.makeStringAndClear().toInt64();
241 0 : sal_Int64 nNum = aStrNum.makeStringAndClear().toInt64();
242 0 : sal_Int64 nDenom = aStrDenom.makeStringAndClear().toInt64();
243 0 : if (nDenom == 0) return false; // Division by zero
244 0 : double nFrac2Dec = nWholeNum + (double)nNum/nDenom; // Convert to double for floating point precision
245 0 : aStrFrac.append(nFrac2Dec);
246 : // Reconvert division result to string and parse
247 0 : nDecPos = aStrFrac.indexOf( rLocaleDataWrappper.getNumDecimalSep() );
248 0 : if ( nDecPos >= 0)
249 : {
250 0 : aStr1.append(aStrFrac.getStr(), nDecPos);
251 0 : aStr2.append(aStrFrac.getStr()+nDecPos+1);
252 : }
253 : else
254 0 : aStr1 = aStrFrac;
255 : }
256 :
257 : // prune and round fraction
258 30617 : bool bRound = false;
259 30617 : if (aStr2.getLength() > nDecDigits)
260 : {
261 0 : if (aStr2[nDecDigits] >= '5')
262 0 : bRound = true;
263 0 : string::truncateToLength(aStr2, nDecDigits);
264 : }
265 30617 : if (aStr2.getLength() < nDecDigits)
266 9693 : string::padToLength(aStr2, nDecDigits, '0');
267 :
268 30617 : aStr = aStr1.makeStringAndClear() + aStr2.makeStringAndClear();
269 :
270 : // check range
271 30617 : nValue = aStr.toInt64();
272 30617 : if( nValue == 0 )
273 : {
274 : // check if string is equivalent to zero
275 26181 : sal_Int16 nIndex = bNegative ? 1 : 0;
276 115167 : while (nIndex < aStr.getLength() && aStr[nIndex] == '0')
277 62805 : ++nIndex;
278 26181 : if( nIndex < aStr.getLength() )
279 : {
280 0 : rValue = bNegative ? SAL_MIN_INT64 : SAL_MAX_INT64;
281 0 : return true;
282 : }
283 : }
284 30617 : if (bRound)
285 : {
286 0 : if ( !bNegative )
287 0 : nValue++;
288 : else
289 0 : nValue--;
290 : }
291 :
292 30617 : rValue = nValue;
293 :
294 65554 : return true;
295 : }
296 :
297 0 : static void ImplUpdateSeparatorString( OUString& io_rText,
298 : const OUString& rOldDecSep, const OUString& rNewDecSep,
299 : const OUString& rOldThSep, const OUString& rNewThSep )
300 : {
301 0 : OUStringBuffer aBuf( io_rText.getLength() );
302 0 : sal_Int32 nIndexDec = 0, nIndexTh = 0, nIndex = 0;
303 :
304 0 : const sal_Unicode* pBuffer = io_rText.getStr();
305 0 : while( nIndex != -1 )
306 : {
307 0 : nIndexDec = io_rText.indexOf( rOldDecSep, nIndex );
308 0 : nIndexTh = io_rText.indexOf( rOldThSep, nIndex );
309 0 : if( (nIndexTh != -1 && nIndexDec != -1 && nIndexTh < nIndexDec )
310 0 : || (nIndexTh != -1 && nIndexDec == -1)
311 : )
312 : {
313 0 : aBuf.append( pBuffer + nIndex, nIndexTh - nIndex );
314 0 : aBuf.append( rNewThSep );
315 0 : nIndex = nIndexTh + rOldThSep.getLength();
316 : }
317 0 : else if( nIndexDec != -1 )
318 : {
319 0 : aBuf.append( pBuffer + nIndex, nIndexDec - nIndex );
320 0 : aBuf.append( rNewDecSep );
321 0 : nIndex = nIndexDec + rOldDecSep.getLength();
322 : }
323 : else
324 : {
325 0 : aBuf.append( pBuffer + nIndex );
326 0 : nIndex = -1;
327 : }
328 : }
329 :
330 0 : io_rText = aBuf.makeStringAndClear();
331 0 : }
332 :
333 0 : static void ImplUpdateSeparators( const OUString& rOldDecSep, const OUString& rNewDecSep,
334 : const OUString& rOldThSep, const OUString& rNewThSep,
335 : Edit* pEdit )
336 : {
337 0 : bool bChangeDec = (rOldDecSep != rNewDecSep);
338 0 : bool bChangeTh = (rOldThSep != rNewThSep );
339 :
340 0 : if( bChangeDec || bChangeTh )
341 : {
342 0 : bool bUpdateMode = pEdit->IsUpdateMode();
343 0 : pEdit->SetUpdateMode( false );
344 0 : OUString aText = pEdit->GetText();
345 0 : ImplUpdateSeparatorString( aText, rOldDecSep, rNewDecSep, rOldThSep, rNewThSep );
346 0 : pEdit->SetText( aText );
347 :
348 0 : ComboBox* pCombo = dynamic_cast<ComboBox*>(pEdit);
349 0 : if( pCombo )
350 : {
351 : // update box entries
352 0 : sal_Int32 nEntryCount = pCombo->GetEntryCount();
353 0 : for ( sal_Int32 i=0; i < nEntryCount; i++ )
354 : {
355 0 : aText = pCombo->GetEntry( i );
356 0 : void* pEntryData = pCombo->GetEntryData( i );
357 0 : ImplUpdateSeparatorString( aText, rOldDecSep, rNewDecSep, rOldThSep, rNewThSep );
358 0 : pCombo->RemoveEntryAt(i);
359 0 : pCombo->InsertEntry( aText, i );
360 0 : pCombo->SetEntryData( i, pEntryData );
361 : }
362 : }
363 0 : if( bUpdateMode )
364 0 : pEdit->SetUpdateMode( bUpdateMode );
365 : }
366 0 : }
367 :
368 : } // namespace
369 :
370 3394 : FormatterBase::FormatterBase( Edit* pField )
371 : {
372 3394 : mpField = pField;
373 3394 : mpLocaleDataWrapper = NULL;
374 3394 : mbReformat = false;
375 3394 : mbStrictFormat = false;
376 3394 : mbEmptyFieldValue = false;
377 3394 : mbEmptyFieldValueEnabled = false;
378 3394 : mbDefaultLocale = true;
379 3394 : }
380 :
381 0 : FormatterBase::~FormatterBase()
382 : {
383 0 : delete mpLocaleDataWrapper;
384 0 : }
385 :
386 114350 : LocaleDataWrapper& FormatterBase::ImplGetLocaleDataWrapper() const
387 : {
388 114350 : if ( !mpLocaleDataWrapper )
389 : {
390 3386 : const_cast<FormatterBase*>(this)->mpLocaleDataWrapper = new LocaleDataWrapper( GetLanguageTag() );
391 : }
392 114350 : return *mpLocaleDataWrapper;
393 : }
394 :
395 0 : const LocaleDataWrapper& FormatterBase::GetLocaleDataWrapper() const
396 : {
397 0 : return ImplGetLocaleDataWrapper();
398 : }
399 :
400 0 : void FormatterBase::Reformat()
401 : {
402 0 : }
403 :
404 26437 : void FormatterBase::ReformatAll()
405 : {
406 26437 : Reformat();
407 26437 : };
408 :
409 129 : void FormatterBase::SetStrictFormat( bool bStrict )
410 : {
411 129 : if ( bStrict != mbStrictFormat )
412 : {
413 80 : mbStrictFormat = bStrict;
414 80 : if ( mbStrictFormat )
415 69 : ReformatAll();
416 : }
417 129 : }
418 :
419 0 : void FormatterBase::SetLocale( const lang::Locale& rLocale )
420 : {
421 0 : ImplGetLocaleDataWrapper().setLanguageTag( LanguageTag( rLocale) );
422 0 : mbDefaultLocale = false;
423 0 : ReformatAll();
424 0 : }
425 :
426 34 : const lang::Locale& FormatterBase::GetLocale() const
427 : {
428 34 : if ( !mpLocaleDataWrapper || mbDefaultLocale )
429 : {
430 34 : if ( mpField )
431 34 : return mpField->GetSettings().GetLanguageTag().getLocale();
432 : else
433 0 : return Application::GetSettings().GetLanguageTag().getLocale();
434 : }
435 :
436 0 : return mpLocaleDataWrapper->getLanguageTag().getLocale();
437 : }
438 :
439 3386 : const LanguageTag& FormatterBase::GetLanguageTag() const
440 : {
441 3386 : if ( !mpLocaleDataWrapper || mbDefaultLocale )
442 : {
443 3386 : if ( mpField )
444 3386 : return mpField->GetSettings().GetLanguageTag();
445 : else
446 0 : return Application::GetSettings().GetLanguageTag();
447 : }
448 :
449 0 : return mpLocaleDataWrapper->getLanguageTag();
450 : }
451 :
452 666 : const AllSettings& FormatterBase::GetFieldSettings() const
453 : {
454 666 : if ( mpField )
455 666 : return mpField->GetSettings();
456 : else
457 0 : return Application::GetSettings();
458 : }
459 :
460 37312 : void FormatterBase::ImplSetText( const OUString& rText, Selection* pNewSelection )
461 : {
462 37312 : if ( mpField )
463 : {
464 37312 : if ( pNewSelection )
465 20 : mpField->SetText( rText, *pNewSelection );
466 : else
467 : {
468 37292 : Selection aSel = mpField->GetSelection();
469 37292 : aSel.Min() = aSel.Max();
470 37292 : mpField->SetText( rText, aSel );
471 : }
472 :
473 37312 : MarkToBeReformatted( false );
474 : }
475 37312 : }
476 :
477 42 : void FormatterBase::SetEmptyFieldValue()
478 : {
479 42 : if ( mpField )
480 42 : mpField->SetText( OUString() );
481 42 : mbEmptyFieldValue = true;
482 42 : }
483 :
484 18175 : bool FormatterBase::IsEmptyFieldValue() const
485 : {
486 18175 : return (!mpField || mpField->GetText().isEmpty());
487 : }
488 :
489 463 : bool NumericFormatter::ImplNumericReformat( const OUString& rStr, sal_Int64& rValue,
490 : OUString& rOutStr )
491 : {
492 463 : if ( !ImplNumericGetValue( rStr, rValue, GetDecimalDigits(), ImplGetLocaleDataWrapper() ) )
493 348 : return true;
494 : else
495 : {
496 115 : sal_Int64 nTempVal = ClipAgainstMinMax(rValue);
497 :
498 115 : if ( GetErrorHdl().IsSet() && (rValue != nTempVal) )
499 : {
500 0 : mnCorrectedValue = nTempVal;
501 0 : if ( !GetErrorHdl().Call( this ) )
502 : {
503 0 : mnCorrectedValue = 0;
504 0 : return false;
505 : }
506 : else
507 0 : mnCorrectedValue = 0;
508 : }
509 :
510 115 : rOutStr = CreateFieldText( nTempVal );
511 115 : return true;
512 : }
513 : }
514 :
515 3334 : void NumericFormatter::ImplInit()
516 : {
517 3334 : mnFieldValue = 0;
518 3334 : mnLastValue = 0;
519 3334 : mnMin = 0;
520 3334 : mnMax = SAL_MAX_INT64;
521 3334 : mnCorrectedValue = 0;
522 3334 : mnDecimalDigits = 2;
523 3334 : mnType = FORMAT_NUMERIC;
524 3334 : mbThousandSep = true;
525 3334 : mbShowTrailingZeros = true;
526 3334 : mbWrapOnLimits = false;
527 :
528 : // for fields
529 3334 : mnSpinSize = 1;
530 3334 : mnFirst = mnMin;
531 3334 : mnLast = mnMax;
532 :
533 3334 : SetDecimalDigits( 0 );
534 3334 : }
535 :
536 3334 : NumericFormatter::NumericFormatter()
537 : {
538 3334 : ImplInit();
539 3334 : }
540 :
541 8 : void NumericFormatter::ImplLoadRes( const ResId& rResId )
542 : {
543 8 : ResMgr* pMgr = rResId.GetResMgr();
544 :
545 8 : if( pMgr )
546 : {
547 8 : sal_uLong nMask = pMgr->ReadLong();
548 :
549 8 : if ( NUMERICFORMATTER_MIN & nMask )
550 8 : mnMin = pMgr->ReadLong();
551 :
552 8 : if ( NUMERICFORMATTER_MAX & nMask )
553 8 : mnMax = pMgr->ReadLong();
554 :
555 8 : if ( NUMERICFORMATTER_STRICTFORMAT & nMask )
556 0 : SetStrictFormat( pMgr->ReadShort() != 0 );
557 :
558 8 : if ( NUMERICFORMATTER_DECIMALDIGITS & nMask )
559 0 : SetDecimalDigits( pMgr->ReadShort() );
560 :
561 8 : if ( NUMERICFORMATTER_VALUE & nMask )
562 : {
563 8 : mnFieldValue = ClipAgainstMinMax(pMgr->ReadLong());
564 8 : mnLastValue = mnFieldValue;
565 : }
566 :
567 8 : if ( NUMERICFORMATTER_NOTHOUSANDSEP & nMask )
568 0 : SetUseThousandSep( pMgr->ReadShort() == 0 );
569 : }
570 8 : }
571 :
572 0 : NumericFormatter::~NumericFormatter()
573 : {
574 0 : }
575 :
576 8744 : void NumericFormatter::SetMin( sal_Int64 nNewMin )
577 : {
578 8744 : mnMin = nNewMin;
579 8744 : if ( !IsEmptyFieldValue() )
580 8744 : ReformatAll();
581 8744 : }
582 :
583 9233 : void NumericFormatter::SetMax( sal_Int64 nNewMax )
584 : {
585 9233 : mnMax = nNewMax;
586 9233 : if ( !IsEmptyFieldValue() )
587 9232 : ReformatAll();
588 9233 : }
589 :
590 0 : void NumericFormatter::SetUseThousandSep( bool bValue )
591 : {
592 0 : mbThousandSep = bValue;
593 0 : ReformatAll();
594 0 : }
595 :
596 7900 : void NumericFormatter::SetDecimalDigits( sal_uInt16 nDigits )
597 : {
598 7900 : mnDecimalDigits = nDigits;
599 7900 : ReformatAll();
600 7900 : }
601 :
602 986 : void NumericFormatter::SetShowTrailingZeros( bool bShowTrailingZeros )
603 : {
604 986 : if ( mbShowTrailingZeros != bShowTrailingZeros )
605 : {
606 986 : mbShowTrailingZeros = bShowTrailingZeros;
607 986 : ReformatAll();
608 : }
609 986 : }
610 :
611 :
612 430 : void NumericFormatter::SetValue( sal_Int64 nNewValue )
613 : {
614 430 : SetUserValue( nNewValue );
615 430 : mnFieldValue = mnLastValue;
616 430 : SetEmptyFieldValueData( false );
617 430 : }
618 :
619 77599 : OUString NumericFormatter::CreateFieldText( sal_Int64 nValue ) const
620 : {
621 77599 : return OUString(ImplGetLocaleDataWrapper().getNum( nValue, GetDecimalDigits(), IsUseThousandSep(), IsShowTrailingZeros() ));
622 : }
623 :
624 9542 : void NumericFormatter::ImplSetUserValue( sal_Int64 nNewValue, Selection* pNewSelection )
625 : {
626 9542 : nNewValue = ClipAgainstMinMax(nNewValue);
627 9542 : mnLastValue = nNewValue;
628 :
629 9542 : if ( GetField() )
630 9542 : ImplSetText( CreateFieldText( nNewValue ), pNewSelection );
631 9542 : }
632 :
633 9542 : void NumericFormatter::SetUserValue( sal_Int64 nNewValue )
634 : {
635 9542 : ImplSetUserValue( nNewValue );
636 9542 : }
637 :
638 0 : sal_Int64 NumericFormatter::GetValue() const
639 : {
640 0 : if ( !GetField() )
641 0 : return 0;
642 :
643 : sal_Int64 nTempValue;
644 :
645 0 : if ( ImplNumericGetValue( GetField()->GetText(), nTempValue,
646 0 : GetDecimalDigits(), ImplGetLocaleDataWrapper() ) )
647 : {
648 0 : return ClipAgainstMinMax(nTempValue);
649 : }
650 : else
651 0 : return mnLastValue;
652 : }
653 :
654 0 : bool NumericFormatter::IsValueModified() const
655 : {
656 0 : if ( ImplGetEmptyFieldValue() )
657 0 : return !IsEmptyFieldValue();
658 0 : else if ( GetValue() != mnFieldValue )
659 0 : return true;
660 : else
661 0 : return false;
662 : }
663 :
664 22789 : sal_Int64 NumericFormatter::Normalize( sal_Int64 nValue ) const
665 : {
666 22789 : return (nValue * ImplPower10( GetDecimalDigits() ) );
667 : }
668 :
669 20988 : sal_Int64 NumericFormatter::Denormalize( sal_Int64 nValue ) const
670 : {
671 20988 : sal_Int64 nFactor = ImplPower10( GetDecimalDigits() );
672 :
673 41976 : if ((nValue < ( SAL_MIN_INT64 + nFactor )) ||
674 20988 : (nValue > ( SAL_MAX_INT64 - nFactor )))
675 : {
676 7106 : return ( nValue / nFactor );
677 : }
678 :
679 13882 : if( nValue < 0 )
680 : {
681 8 : sal_Int64 nHalf = nFactor / 2;
682 8 : return ((nValue - nHalf) / nFactor );
683 : }
684 : else
685 : {
686 13874 : sal_Int64 nHalf = nFactor / 2;
687 13874 : return ((nValue + nHalf) / nFactor );
688 : }
689 : }
690 :
691 3797 : void NumericFormatter::Reformat()
692 : {
693 3797 : if ( !GetField() )
694 6668 : return;
695 :
696 463 : if ( GetField()->GetText().isEmpty() && ImplGetEmptyFieldValue() )
697 0 : return;
698 :
699 463 : OUString aStr;
700 463 : sal_Int64 nTemp = mnLastValue;
701 463 : bool bOK = ImplNumericReformat( GetField()->GetText(), nTemp, aStr );
702 463 : mnLastValue = nTemp;
703 463 : if ( !bOK )
704 0 : return;
705 :
706 463 : if ( !aStr.isEmpty() )
707 115 : ImplSetText( aStr );
708 : else
709 348 : SetValue( mnLastValue );
710 : }
711 :
712 0 : void NumericFormatter::FieldUp()
713 : {
714 0 : sal_Int64 nValue = GetValue();
715 0 : sal_Int64 nRemainder = nValue % mnSpinSize;
716 0 : if (nValue >= 0)
717 0 : nValue = (nRemainder == 0) ? nValue + mnSpinSize : nValue + mnSpinSize - nRemainder;
718 : else
719 0 : nValue = (nRemainder == 0) ? nValue + mnSpinSize : nValue - nRemainder;
720 :
721 0 : nValue = ClipAgainstMinMax(nValue);
722 :
723 0 : ImplNewFieldValue( nValue );
724 0 : }
725 :
726 0 : void NumericFormatter::FieldDown()
727 : {
728 0 : sal_Int64 nValue = GetValue();
729 0 : sal_Int64 nRemainder = nValue % mnSpinSize;
730 0 : if (nValue >= 0)
731 0 : nValue = (nRemainder == 0) ? nValue - mnSpinSize : nValue - nRemainder;
732 : else
733 0 : nValue = (nRemainder == 0) ? nValue - mnSpinSize : nValue - mnSpinSize - nRemainder;
734 :
735 0 : nValue = ClipAgainstMinMax(nValue);
736 :
737 0 : ImplNewFieldValue( nValue );
738 0 : }
739 :
740 0 : void NumericFormatter::FieldFirst()
741 : {
742 0 : ImplNewFieldValue( mnFirst );
743 0 : }
744 :
745 0 : void NumericFormatter::FieldLast()
746 : {
747 0 : ImplNewFieldValue( mnLast );
748 0 : }
749 :
750 0 : void NumericFormatter::ImplNewFieldValue( sal_Int64 nNewValue )
751 : {
752 0 : if ( GetField() )
753 : {
754 : // !!! We should check why we do not validate in ImplSetUserValue() if the value was
755 : // changed. This should be done there as well since otherwise the call to Modify would not
756 : // be allowed. Anyway, the paths from ImplNewFieldValue, ImplSetUserValue, and ImplSetText
757 : // should be checked and clearly traced (with comment) in order to find out what happens.
758 :
759 0 : Selection aSelection = GetField()->GetSelection();
760 0 : aSelection.Justify();
761 0 : OUString aText = GetField()->GetText();
762 : // leave it as is if selected until end
763 0 : if ( (sal_Int32)aSelection.Max() == aText.getLength() )
764 : {
765 0 : if ( !aSelection.Len() )
766 0 : aSelection.Min() = SELECTION_MAX;
767 0 : aSelection.Max() = SELECTION_MAX;
768 : }
769 :
770 0 : sal_Int64 nOldLastValue = mnLastValue;
771 0 : ImplSetUserValue( nNewValue, &aSelection );
772 0 : mnLastValue = nOldLastValue;
773 :
774 : // Modify during Edit is only set during KeyInput
775 0 : if ( GetField()->GetText() != aText )
776 : {
777 0 : GetField()->SetModifyFlag();
778 0 : GetField()->Modify();
779 0 : }
780 : }
781 0 : }
782 :
783 9665 : sal_Int64 NumericFormatter::ClipAgainstMinMax(sal_Int64 nValue) const
784 : {
785 9665 : if (nValue > mnMax)
786 0 : nValue = mbWrapOnLimits ? ((nValue - mnMin) % (mnMax + 1)) + mnMin
787 0 : : mnMax;
788 9665 : else if (nValue < mnMin)
789 0 : nValue = mbWrapOnLimits ? ((nValue + mnMax + 1 - mnMin) % (mnMax + 1)) + mnMin
790 1028 : : mnMin;
791 9665 : return nValue;
792 : }
793 :
794 340 : NumericField::NumericField( vcl::Window* pParent, WinBits nWinStyle ) :
795 340 : SpinField( pParent, nWinStyle )
796 : {
797 340 : SetField( this );
798 340 : Reformat();
799 340 : }
800 :
801 8 : NumericField::NumericField( vcl::Window* pParent, const ResId& rResId ) :
802 8 : SpinField( WINDOW_NUMERICFIELD )
803 : {
804 8 : rResId.SetRT( RSC_NUMERICFIELD );
805 8 : WinBits nStyle = ImplInitRes( rResId ) ;
806 8 : SpinField::ImplInit( pParent, nStyle );
807 8 : SetField( this );
808 8 : ImplLoadRes( rResId );
809 8 : Reformat();
810 :
811 8 : if ( !(nStyle & WB_HIDE ) )
812 8 : Show();
813 8 : }
814 :
815 1812 : bool NumericField::set_property(const OString &rKey, const OString &rValue)
816 : {
817 1812 : if (rKey == "digits")
818 0 : SetDecimalDigits(rValue.toInt32());
819 1812 : else if (rKey == "spin-size")
820 0 : SetSpinSize(rValue.toInt32());
821 1812 : else if (rKey == "wrap")
822 0 : mbWrapOnLimits = toBool(rValue);
823 : else
824 1812 : return SpinField::set_property(rKey, rValue);
825 0 : return true;
826 : }
827 :
828 8 : void NumericField::ImplLoadRes( const ResId& rResId )
829 : {
830 8 : SpinField::ImplLoadRes( rResId );
831 8 : NumericFormatter::ImplLoadRes( ResId( static_cast<RSHEADER_TYPE *>(GetClassRes()), *rResId.GetResMgr() ) );
832 :
833 8 : sal_uLong nMask = ReadLongRes();
834 :
835 8 : if ( NUMERICFIELD_FIRST & nMask )
836 8 : mnFirst = ReadLongRes();
837 :
838 8 : if ( NUMERICFIELD_LAST & nMask )
839 8 : mnLast = ReadLongRes();
840 :
841 8 : if ( NUMERICFIELD_SPINSIZE & nMask )
842 0 : mnSpinSize = ReadLongRes();
843 8 : }
844 :
845 0 : bool NumericField::PreNotify( NotifyEvent& rNEvt )
846 : {
847 0 : if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
848 : {
849 0 : if ( ImplNumericProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
850 0 : return true;
851 : }
852 :
853 0 : return SpinField::PreNotify( rNEvt );
854 : }
855 :
856 340 : bool NumericField::Notify( NotifyEvent& rNEvt )
857 : {
858 340 : if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
859 0 : MarkToBeReformatted( false );
860 340 : else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
861 : {
862 0 : if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
863 0 : Reformat();
864 : }
865 :
866 340 : return SpinField::Notify( rNEvt );
867 : }
868 :
869 314 : void NumericField::DataChanged( const DataChangedEvent& rDCEvt )
870 : {
871 314 : SpinField::DataChanged( rDCEvt );
872 :
873 314 : if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
874 : {
875 0 : OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
876 0 : OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
877 0 : if ( IsDefaultLocale() )
878 0 : ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
879 0 : OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
880 0 : OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
881 0 : ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
882 0 : ReformatAll();
883 : }
884 314 : }
885 :
886 0 : void NumericField::Modify()
887 : {
888 0 : MarkToBeReformatted( true );
889 0 : SpinField::Modify();
890 0 : }
891 :
892 0 : void NumericField::Up()
893 : {
894 0 : FieldUp();
895 0 : SpinField::Up();
896 0 : }
897 :
898 0 : void NumericField::Down()
899 : {
900 0 : FieldDown();
901 0 : SpinField::Down();
902 0 : }
903 :
904 0 : void NumericField::First()
905 : {
906 0 : FieldFirst();
907 0 : SpinField::First();
908 0 : }
909 :
910 0 : void NumericField::Last()
911 : {
912 0 : FieldLast();
913 0 : SpinField::Last();
914 0 : }
915 :
916 : namespace
917 : {
918 4975 : Size calcMinimumSize(const Edit &rSpinField, const NumericFormatter &rFormatter)
919 : {
920 4975 : OUStringBuffer aBuf;
921 : sal_Int32 nTextLen;
922 :
923 4975 : nTextLen = OUString::number(rFormatter.GetMin()).getLength();
924 4975 : string::padToLength(aBuf, nTextLen, '9');
925 : Size aMinTextSize = rSpinField.CalcMinimumSizeForText(
926 4975 : rFormatter.CreateFieldText(aBuf.makeStringAndClear().toInt64()));
927 :
928 4975 : nTextLen = OUString::number(rFormatter.GetMax()).getLength();
929 4975 : string::padToLength(aBuf, nTextLen, '9');
930 : Size aMaxTextSize = rSpinField.CalcMinimumSizeForText(
931 4975 : rFormatter.CreateFieldText(aBuf.makeStringAndClear().toInt64()));
932 :
933 4975 : Size aRet(std::max(aMinTextSize.Width(), aMaxTextSize.Width()),
934 9950 : std::max(aMinTextSize.Height(), aMaxTextSize.Height()));
935 :
936 9950 : OUStringBuffer sBuf("999999999");
937 4975 : sal_uInt16 nDigits = rFormatter.GetDecimalDigits();
938 4975 : if (nDigits)
939 : {
940 4371 : sBuf.append('.');
941 4371 : string::padToLength(aBuf, aBuf.getLength() + nDigits, '9');
942 : }
943 4975 : aMaxTextSize = rSpinField.CalcMinimumSizeForText(sBuf.makeStringAndClear());
944 4975 : aRet.Width() = std::min(aRet.Width(), aMaxTextSize.Width());
945 :
946 9950 : return aRet;
947 : }
948 : }
949 :
950 302 : Size NumericField::CalcMinimumSize() const
951 : {
952 302 : return calcMinimumSize(*this, *this);
953 : }
954 :
955 0 : NumericBox::NumericBox( vcl::Window* pParent, WinBits nWinStyle ) :
956 0 : ComboBox( pParent, nWinStyle )
957 : {
958 0 : SetField( this );
959 0 : Reformat();
960 0 : if ( !(nWinStyle & WB_HIDE ) )
961 0 : Show();
962 0 : }
963 :
964 0 : Size NumericBox::CalcMinimumSize() const
965 : {
966 0 : Size aRet(calcMinimumSize(*this, *this));
967 :
968 0 : if (IsDropDownBox())
969 : {
970 0 : Size aComboSugg(ComboBox::CalcMinimumSize());
971 0 : aRet.Width() = std::max(aRet.Width(), aComboSugg.Width());
972 0 : aRet.Height() = std::max(aRet.Height(), aComboSugg.Height());
973 : }
974 :
975 0 : return aRet;
976 : }
977 :
978 0 : bool NumericBox::PreNotify( NotifyEvent& rNEvt )
979 : {
980 0 : if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
981 : {
982 0 : if ( ImplNumericProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
983 0 : return true;
984 : }
985 :
986 0 : return ComboBox::PreNotify( rNEvt );
987 : }
988 :
989 0 : bool NumericBox::Notify( NotifyEvent& rNEvt )
990 : {
991 0 : if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
992 0 : MarkToBeReformatted( false );
993 0 : else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
994 : {
995 0 : if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
996 0 : Reformat();
997 : }
998 :
999 0 : return ComboBox::Notify( rNEvt );
1000 : }
1001 :
1002 0 : void NumericBox::DataChanged( const DataChangedEvent& rDCEvt )
1003 : {
1004 0 : ComboBox::DataChanged( rDCEvt );
1005 :
1006 0 : if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
1007 : {
1008 0 : OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1009 0 : OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1010 0 : if ( IsDefaultLocale() )
1011 0 : ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
1012 0 : OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1013 0 : OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1014 0 : ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
1015 0 : ReformatAll();
1016 : }
1017 0 : }
1018 :
1019 0 : void NumericBox::Modify()
1020 : {
1021 0 : MarkToBeReformatted( true );
1022 0 : ComboBox::Modify();
1023 0 : }
1024 :
1025 0 : void NumericBox::ReformatAll()
1026 : {
1027 : sal_Int64 nValue;
1028 0 : OUString aStr;
1029 0 : SetUpdateMode( false );
1030 0 : sal_Int32 nEntryCount = GetEntryCount();
1031 0 : for ( sal_Int32 i=0; i < nEntryCount; i++ )
1032 : {
1033 0 : ImplNumericReformat( GetEntry( i ), nValue, aStr );
1034 0 : RemoveEntryAt(i);
1035 0 : InsertEntry( aStr, i );
1036 : }
1037 0 : NumericFormatter::Reformat();
1038 0 : SetUpdateMode( true );
1039 0 : }
1040 :
1041 0 : void NumericBox::InsertValue( sal_Int64 nValue, sal_Int32 nPos )
1042 : {
1043 0 : ComboBox::InsertEntry( CreateFieldText( nValue ), nPos );
1044 0 : }
1045 :
1046 0 : static bool ImplMetricProcessKeyInput( Edit* pEdit, const KeyEvent& rKEvt,
1047 : bool, bool bUseThousandSep, const LocaleDataWrapper& rWrapper )
1048 : {
1049 : // no meaningfull strict format; therefore allow all characters
1050 0 : return ImplNumericProcessKeyInput( pEdit, rKEvt, false, bUseThousandSep, rWrapper );
1051 : }
1052 :
1053 40642 : static OUString ImplMetricGetUnitText(const OUString& rStr)
1054 : {
1055 : // fetch unit text
1056 40642 : OUStringBuffer aStr;
1057 104401 : for (sal_Int32 i = rStr.getLength()-1; i >= 0; --i)
1058 : {
1059 74672 : sal_Unicode c = rStr[i];
1060 74672 : if ( (c == '\'') || (c == '\"') || (c == '%' ) || unicode::isAlpha(c) || unicode::isControl(c) )
1061 11215 : aStr.insert(0, c);
1062 : else
1063 : {
1064 63457 : if (!aStr.isEmpty())
1065 10913 : break;
1066 : }
1067 : }
1068 40642 : return aStr.makeStringAndClear();
1069 : }
1070 :
1071 : // #104355# support localized mesaurements
1072 :
1073 62870 : static const OUString ImplMetricToString( FieldUnit rUnit )
1074 : {
1075 62870 : FieldUnitStringList* pList = ImplGetFieldUnits();
1076 62870 : if( pList )
1077 : {
1078 : // return unit's default string (ie, the first one )
1079 1278862 : for( FieldUnitStringList::const_iterator it = pList->begin(); it != pList->end(); ++it )
1080 : {
1081 1235744 : if ( it->second == rUnit )
1082 19752 : return it->first;
1083 : }
1084 : }
1085 :
1086 43118 : return OUString();
1087 : }
1088 :
1089 30502 : static FieldUnit ImplStringToMetric(const OUString &rMetricString)
1090 : {
1091 30502 : FieldUnitStringList* pList = ImplGetCleanedFieldUnits();
1092 30502 : if( pList )
1093 : {
1094 : // return FieldUnit
1095 30502 : OUString aStr(rMetricString.toAsciiLowerCase());
1096 30502 : aStr = string::remove(aStr, ' ');
1097 587450 : for( FieldUnitStringList::const_iterator it = pList->begin(); it != pList->end(); ++it )
1098 : {
1099 567854 : if ( it->first == aStr )
1100 10906 : return it->second;
1101 19596 : }
1102 : }
1103 :
1104 19596 : return FUNIT_NONE;
1105 : }
1106 :
1107 30502 : static FieldUnit ImplMetricGetUnit(const OUString& rStr)
1108 : {
1109 30502 : OUString aStr = ImplMetricGetUnitText( rStr );
1110 30502 : return ImplStringToMetric( aStr );
1111 : }
1112 :
1113 : #define K *1000L
1114 : #define M *1000000LL
1115 : #define X *5280L
1116 :
1117 : // twip in km = 254 / 14 400 000 000
1118 : // expressions too big for default size 32 bit need LL to avoid overflow
1119 :
1120 : static const sal_Int64 aImplFactor[FUNIT_LINE+1][FUNIT_LINE+1] =
1121 : { /*
1122 : mm/100 mm cm m km twip point pica inch foot mile char line */
1123 : { 1, 100, 1 K, 100 K, 100 M, 2540, 2540, 2540, 2540,2540*12,2540*12 X , 53340, 396240},
1124 : { 1, 1, 10, 1 K, 1 M, 2540, 2540, 2540, 2540,2540*12,2540*12 X , 5334, 396240},
1125 : { 1, 1, 1, 100, 100 K, 254, 254, 254, 254, 254*12, 254*12 X , 5334, 39624},
1126 : { 1, 1, 1, 1, 1 K, 254, 254, 254, 254, 254*12, 254*12 X , 533400, 39624},
1127 : { 1, 1, 1, 1, 1, 254, 254, 254, 254, 254*12, 254*12 X ,533400 K, 39624},
1128 : { 1440,144 K,144 K,14400 K,14400LL M, 1, 20, 240, 1440,1440*12,1440*12 X , 210, 3120},
1129 : { 72, 7200, 7200, 720 K, 720 M, 1, 1, 12, 72, 72*12, 72*12 X , 210, 156},
1130 : { 6, 600, 600, 60 K, 60 M, 1, 1, 1, 6, 6*12, 6*12 X , 210, 10},
1131 : { 1, 100, 100, 10 K, 10 M, 1, 1, 1, 1, 12, 12 X , 210, 45},
1132 : { 1, 100, 100, 10 K, 10 M, 1, 1, 1, 1, 1, 1 X , 210, 45},
1133 : { 1, 100, 100, 10 K, 10 M, 1, 1, 1, 1, 1, 1 , 210, 45},
1134 : { 144, 1440,14400, 14400, 14400, 1, 20, 240, 1440,1440*12, 1440*12 X, 1, 156 },
1135 : { 720,72000,72000, 7200 K,7200LL M, 20, 10, 13, 11, 11*12, 11*12 X, 105, 1 }
1136 : };
1137 : #undef X
1138 : #undef M
1139 : #undef K
1140 :
1141 : static FieldUnit eDefaultUnit = FUNIT_NONE;
1142 :
1143 2986 : FieldUnit MetricField::GetDefaultUnit() { return eDefaultUnit; }
1144 0 : void MetricField::SetDefaultUnit( FieldUnit meUnit ) { eDefaultUnit = meUnit; }
1145 :
1146 18 : static FieldUnit ImplMap2FieldUnit( MapUnit meUnit, long& nDecDigits )
1147 : {
1148 18 : switch( meUnit )
1149 : {
1150 : case MAP_100TH_MM :
1151 18 : nDecDigits -= 2;
1152 18 : return FUNIT_MM;
1153 : case MAP_10TH_MM :
1154 0 : nDecDigits -= 1;
1155 0 : return FUNIT_MM;
1156 : case MAP_MM :
1157 0 : return FUNIT_MM;
1158 : case MAP_CM :
1159 0 : return FUNIT_CM;
1160 : case MAP_1000TH_INCH :
1161 0 : nDecDigits -= 3;
1162 0 : return FUNIT_INCH;
1163 : case MAP_100TH_INCH :
1164 0 : nDecDigits -= 2;
1165 0 : return FUNIT_INCH;
1166 : case MAP_10TH_INCH :
1167 0 : nDecDigits -= 1;
1168 0 : return FUNIT_INCH;
1169 : case MAP_INCH :
1170 0 : return FUNIT_INCH;
1171 : case MAP_POINT :
1172 0 : return FUNIT_POINT;
1173 : case MAP_TWIP :
1174 0 : return FUNIT_TWIP;
1175 : default:
1176 : OSL_FAIL( "default eInUnit" );
1177 0 : break;
1178 : }
1179 0 : return FUNIT_NONE;
1180 : }
1181 :
1182 98546 : static double nonValueDoubleToValueDouble( double nValue )
1183 : {
1184 98546 : return rtl::math::isFinite( nValue ) ? nValue : 0.0;
1185 : }
1186 :
1187 98528 : sal_Int64 MetricField::ConvertValue( sal_Int64 nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits,
1188 : FieldUnit eInUnit, FieldUnit eOutUnit )
1189 : {
1190 : double nDouble = nonValueDoubleToValueDouble( ConvertDoubleValue(
1191 98528 : (double)nValue, mnBaseValue, nDecDigits, eInUnit, eOutUnit ) );
1192 : sal_Int64 nLong ;
1193 :
1194 : // caution: precision loss in double cast
1195 98528 : if ( nDouble <= (double)SAL_MIN_INT64 )
1196 0 : nLong = SAL_MIN_INT64;
1197 98528 : else if ( nDouble >= (double)SAL_MAX_INT64 )
1198 12506 : nLong = SAL_MAX_INT64;
1199 : else
1200 86022 : nLong = static_cast<sal_Int64>( nDouble );
1201 :
1202 98528 : return nLong;
1203 : }
1204 :
1205 18 : sal_Int64 MetricField::ConvertValue( sal_Int64 nValue, sal_uInt16 nDigits,
1206 : MapUnit eInUnit, FieldUnit eOutUnit )
1207 : {
1208 : return static_cast<sal_Int64>(
1209 : nonValueDoubleToValueDouble(
1210 18 : ConvertDoubleValue( nValue, nDigits, eInUnit, eOutUnit ) ) );
1211 : }
1212 :
1213 137992 : double MetricField::ConvertDoubleValue( double nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits,
1214 : FieldUnit eInUnit, FieldUnit eOutUnit )
1215 : {
1216 137992 : if ( eInUnit != eOutUnit )
1217 : {
1218 54750 : sal_Int64 nMult = 1, nDiv = 1;
1219 :
1220 54750 : if ( eInUnit == FUNIT_PERCENT )
1221 : {
1222 0 : if ( (mnBaseValue <= 0) || (nValue <= 0) )
1223 0 : return nValue;
1224 0 : nDiv = 100 * ImplPower10(nDecDigits);
1225 :
1226 0 : nMult = mnBaseValue;
1227 : }
1228 54750 : else if ( eOutUnit == FUNIT_PERCENT ||
1229 37832 : eOutUnit == FUNIT_CUSTOM ||
1230 37832 : eOutUnit == FUNIT_NONE ||
1231 36224 : eOutUnit == FUNIT_DEGREE ||
1232 36224 : eOutUnit == FUNIT_SECOND ||
1233 36224 : eOutUnit == FUNIT_MILLISECOND ||
1234 36224 : eOutUnit == FUNIT_PIXEL ||
1235 22704 : eInUnit == FUNIT_CUSTOM ||
1236 20141 : eInUnit == FUNIT_NONE ||
1237 20141 : eInUnit == FUNIT_DEGREE ||
1238 20141 : eInUnit == FUNIT_MILLISECOND ||
1239 : eInUnit == FUNIT_PIXEL )
1240 34609 : return nValue;
1241 : else
1242 : {
1243 20141 : if ( eOutUnit == FUNIT_100TH_MM )
1244 1742 : eOutUnit = FUNIT_NONE;
1245 20141 : if ( eInUnit == FUNIT_100TH_MM )
1246 11071 : eInUnit = FUNIT_NONE;
1247 :
1248 20141 : nDiv = aImplFactor[eInUnit][eOutUnit];
1249 20141 : nMult = aImplFactor[eOutUnit][eInUnit];
1250 :
1251 : DBG_ASSERT( nMult > 0, "illegal *" );
1252 : DBG_ASSERT( nDiv > 0, "illegal /" );
1253 : }
1254 :
1255 20141 : if ( nMult != 1 && nMult > 0 )
1256 9002 : nValue *= nMult;
1257 20141 : if ( nDiv != 1 && nDiv > 0 )
1258 : {
1259 20101 : nValue += ( nValue < 0 ) ? (-nDiv/2) : (nDiv/2);
1260 20101 : nValue /= nDiv;
1261 : }
1262 : }
1263 :
1264 103383 : return nValue;
1265 : }
1266 :
1267 18 : double MetricField::ConvertDoubleValue( double nValue, sal_uInt16 nDigits,
1268 : MapUnit eInUnit, FieldUnit eOutUnit )
1269 : {
1270 18 : if ( eOutUnit == FUNIT_PERCENT ||
1271 18 : eOutUnit == FUNIT_CUSTOM ||
1272 18 : eOutUnit == FUNIT_NONE ||
1273 18 : eInUnit == MAP_PIXEL ||
1274 18 : eInUnit == MAP_SYSFONT ||
1275 18 : eInUnit == MAP_APPFONT ||
1276 : eInUnit == MAP_RELATIVE )
1277 : {
1278 : OSL_FAIL( "invalid parameters" );
1279 0 : return nValue;
1280 : }
1281 :
1282 18 : long nDecDigits = nDigits;
1283 18 : FieldUnit eFieldUnit = ImplMap2FieldUnit( eInUnit, nDecDigits );
1284 :
1285 18 : if ( nDecDigits < 0 )
1286 : {
1287 8 : while ( nDecDigits )
1288 : {
1289 4 : nValue += 5;
1290 4 : nValue /= 10;
1291 4 : nDecDigits++;
1292 : }
1293 : }
1294 : else
1295 : {
1296 16 : nValue *= ImplPower10(nDecDigits);
1297 : }
1298 :
1299 18 : if ( eFieldUnit != eOutUnit )
1300 : {
1301 18 : sal_Int64 nDiv = aImplFactor[eFieldUnit][eOutUnit];
1302 18 : sal_Int64 nMult = aImplFactor[eOutUnit][eFieldUnit];
1303 :
1304 : DBG_ASSERT( nMult > 0, "illegal *" );
1305 : DBG_ASSERT( nDiv > 0, "illegal /" );
1306 :
1307 18 : if ( nMult != 1 && nMult > 0)
1308 18 : nValue *= nMult;
1309 18 : if ( nDiv != 1 && nDiv > 0 )
1310 : {
1311 18 : nValue += (nValue < 0) ? (-nDiv/2) : (nDiv/2);
1312 18 : nValue /= nDiv;
1313 : }
1314 : }
1315 18 : return nValue;
1316 : }
1317 :
1318 0 : double MetricField::ConvertDoubleValue( double nValue, sal_uInt16 nDigits,
1319 : FieldUnit eInUnit, MapUnit eOutUnit )
1320 : {
1321 0 : if ( eInUnit == FUNIT_PERCENT ||
1322 0 : eInUnit == FUNIT_CUSTOM ||
1323 0 : eInUnit == FUNIT_NONE ||
1324 0 : eInUnit == FUNIT_DEGREE ||
1325 0 : eInUnit == FUNIT_SECOND ||
1326 0 : eInUnit == FUNIT_MILLISECOND ||
1327 0 : eInUnit == FUNIT_PIXEL ||
1328 0 : eOutUnit == MAP_PIXEL ||
1329 0 : eOutUnit == MAP_SYSFONT ||
1330 0 : eOutUnit == MAP_APPFONT ||
1331 : eOutUnit == MAP_RELATIVE )
1332 : {
1333 : OSL_FAIL( "invalid parameters" );
1334 0 : return nValue;
1335 : }
1336 :
1337 0 : long nDecDigits = nDigits;
1338 0 : FieldUnit eFieldUnit = ImplMap2FieldUnit( eOutUnit, nDecDigits );
1339 :
1340 0 : if ( nDecDigits < 0 )
1341 : {
1342 0 : nValue *= ImplPower10(-nDecDigits);
1343 : }
1344 : else
1345 : {
1346 0 : nValue /= ImplPower10(nDecDigits);
1347 : }
1348 :
1349 0 : if ( eFieldUnit != eInUnit )
1350 : {
1351 0 : sal_Int64 nDiv = aImplFactor[eInUnit][eFieldUnit];
1352 0 : sal_Int64 nMult = aImplFactor[eFieldUnit][eInUnit];
1353 :
1354 : DBG_ASSERT( nMult > 0, "illegal *" );
1355 : DBG_ASSERT( nDiv > 0, "illegal /" );
1356 :
1357 0 : if( nMult != 1 && nMult > 0 )
1358 0 : nValue *= nMult;
1359 0 : if( nDiv != 1 && nDiv > 0 )
1360 : {
1361 0 : nValue += (nValue < 0) ? (-nDiv/2) : (nDiv/2);
1362 0 : nValue /= nDiv;
1363 : }
1364 : }
1365 0 : return nValue;
1366 : }
1367 :
1368 34474 : static bool ImplMetricGetValue( const OUString& rStr, double& rValue, sal_Int64 nBaseValue,
1369 : sal_uInt16 nDecDigits, const LocaleDataWrapper& rLocaleDataWrapper, FieldUnit eUnit )
1370 : {
1371 : // Get value
1372 : sal_Int64 nValue;
1373 34474 : if ( !ImplNumericGetValue( rStr, nValue, nDecDigits, rLocaleDataWrapper ) )
1374 3972 : return false;
1375 :
1376 : // Determine unit
1377 30502 : FieldUnit eEntryUnit = ImplMetricGetUnit( rStr );
1378 :
1379 : // Recalculate unit
1380 : // caution: conversion to double loses precision
1381 30502 : rValue = MetricField::ConvertDoubleValue( (double)nValue, nBaseValue, nDecDigits, eEntryUnit, eUnit );
1382 :
1383 30502 : return true;
1384 : }
1385 :
1386 30136 : bool MetricFormatter::ImplMetricReformat( const OUString& rStr, double& rValue, OUString& rOutStr )
1387 : {
1388 30136 : if ( !ImplMetricGetValue( rStr, rValue, mnBaseValue, GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit ) )
1389 2986 : return true;
1390 : else
1391 : {
1392 27150 : double nTempVal = rValue;
1393 : // caution: precision loss in double cast
1394 27150 : if ( nTempVal > GetMax() )
1395 0 : nTempVal = (double)GetMax();
1396 27150 : else if ( nTempVal < GetMin())
1397 986 : nTempVal = (double)GetMin();
1398 :
1399 27150 : if ( GetErrorHdl().IsSet() && (rValue != nTempVal) )
1400 : {
1401 0 : mnCorrectedValue = (sal_Int64)nTempVal;
1402 0 : if ( !GetErrorHdl().Call( this ) )
1403 : {
1404 0 : mnCorrectedValue = 0;
1405 0 : return false;
1406 : }
1407 : else
1408 0 : mnCorrectedValue = 0;
1409 : }
1410 :
1411 27150 : rOutStr = CreateFieldText( (sal_Int64)nTempVal );
1412 27150 : return true;
1413 : }
1414 : }
1415 :
1416 2986 : inline void MetricFormatter::ImplInit()
1417 : {
1418 2986 : mnBaseValue = 0;
1419 2986 : meUnit = MetricField::GetDefaultUnit();
1420 2986 : mnType = FORMAT_METRIC;
1421 2986 : }
1422 :
1423 2986 : MetricFormatter::MetricFormatter()
1424 : {
1425 2986 : ImplInit();
1426 2986 : }
1427 :
1428 0 : void MetricFormatter::ImplLoadRes( const ResId& rResId )
1429 : {
1430 0 : NumericFormatter::ImplLoadRes( rResId );
1431 :
1432 0 : ResMgr* pMgr = rResId.GetResMgr();
1433 0 : if( pMgr )
1434 : {
1435 0 : sal_uLong nMask = pMgr->ReadLong();
1436 :
1437 0 : if ( METRICFORMATTER_UNIT & nMask )
1438 : {
1439 0 : sal_uLong nUnit = pMgr->ReadLong();
1440 : assert(nUnit <= FUNIT_MILLISECOND && "out of FieldUnit bounds");
1441 0 : if (nUnit <= FUNIT_MILLISECOND)
1442 0 : meUnit = (FieldUnit)nUnit;
1443 : }
1444 :
1445 0 : if ( METRICFORMATTER_CUSTOMUNITTEXT & nMask )
1446 0 : maCustomUnitText = pMgr->ReadString();
1447 : }
1448 0 : }
1449 :
1450 0 : MetricFormatter::~MetricFormatter()
1451 : {
1452 0 : }
1453 :
1454 3699 : void MetricFormatter::SetUnit( FieldUnit eNewUnit )
1455 : {
1456 3699 : if ( eNewUnit == FUNIT_100TH_MM )
1457 : {
1458 0 : SetDecimalDigits( GetDecimalDigits() + 2 );
1459 0 : meUnit = FUNIT_MM;
1460 : }
1461 : else
1462 3699 : meUnit = eNewUnit;
1463 3699 : ReformatAll();
1464 3699 : }
1465 :
1466 0 : void MetricFormatter::SetCustomUnitText( const OUString& rStr )
1467 : {
1468 0 : maCustomUnitText = rStr;
1469 0 : ReformatAll();
1470 0 : }
1471 :
1472 9112 : void MetricFormatter::SetValue( sal_Int64 nNewValue, FieldUnit eInUnit )
1473 : {
1474 9112 : SetUserValue( nNewValue, eInUnit );
1475 9112 : mnFieldValue = mnLastValue;
1476 9112 : }
1477 :
1478 76404 : OUString MetricFormatter::CreateFieldText( sal_Int64 nValue ) const
1479 : {
1480 : //whether percent is separated from its number is locale
1481 : //specific, pawn it off to icu to decide
1482 76404 : if (meUnit == FUNIT_PERCENT)
1483 : {
1484 14 : double dValue = nValue;
1485 14 : dValue /= ImplPower10(GetDecimalDigits());
1486 14 : return unicode::formatPercent(dValue, Application::GetSettings().GetUILanguageTag());
1487 : }
1488 :
1489 76390 : OUString aStr = NumericFormatter::CreateFieldText( nValue );
1490 :
1491 76390 : if( meUnit == FUNIT_CUSTOM )
1492 13520 : aStr += maCustomUnitText;
1493 : else
1494 : {
1495 62870 : if (meUnit != FUNIT_NONE && meUnit != FUNIT_DEGREE)
1496 17842 : aStr += " ";
1497 : assert(meUnit != FUNIT_PERCENT);
1498 62870 : aStr += ImplMetricToString( meUnit );
1499 : }
1500 76390 : return aStr;
1501 : }
1502 :
1503 9112 : void MetricFormatter::SetUserValue( sal_Int64 nNewValue, FieldUnit eInUnit )
1504 : {
1505 : // convert to previously configured units
1506 9112 : nNewValue = MetricField::ConvertValue( nNewValue, mnBaseValue, GetDecimalDigits(), eInUnit, meUnit );
1507 9112 : NumericFormatter::SetUserValue( nNewValue );
1508 9112 : }
1509 :
1510 4338 : sal_Int64 MetricFormatter::GetValue( FieldUnit eOutUnit ) const
1511 : {
1512 4338 : if ( !GetField() )
1513 0 : return 0;
1514 :
1515 : double nTempValue;
1516 : // caution: precision loss in double cast
1517 4338 : if ( !ImplMetricGetValue( GetField()->GetText(), nTempValue, mnBaseValue, GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit ) )
1518 986 : nTempValue = (double)mnLastValue;
1519 :
1520 : // caution: precision loss in double cast
1521 4338 : if ( nTempValue > mnMax )
1522 0 : nTempValue = (double)mnMax;
1523 4338 : else if ( nTempValue < mnMin )
1524 0 : nTempValue = (double)mnMin;
1525 :
1526 : // convert to requested units
1527 4338 : return MetricField::ConvertValue( (sal_Int64)nTempValue, mnBaseValue, GetDecimalDigits(), meUnit, eOutUnit );
1528 : }
1529 :
1530 3163 : void MetricFormatter::SetValue( sal_Int64 nValue )
1531 : {
1532 : // Implementation not inline, because it is a virtual Function
1533 3163 : SetValue( nValue, FUNIT_NONE );
1534 3163 : }
1535 :
1536 0 : sal_Int64 MetricFormatter::GetValue() const
1537 : {
1538 : // Implementation not inline, because it is a virtual Function
1539 0 : return GetValue( FUNIT_NONE );
1540 : }
1541 :
1542 6020 : void MetricFormatter::SetMin( sal_Int64 nNewMin, FieldUnit eInUnit )
1543 : {
1544 : // convert to requested units
1545 6020 : NumericFormatter::SetMin( MetricField::ConvertValue( nNewMin, mnBaseValue, GetDecimalDigits(),
1546 12040 : eInUnit, meUnit ) );
1547 6020 : }
1548 :
1549 5247 : sal_Int64 MetricFormatter::GetMin( FieldUnit eOutUnit ) const
1550 : {
1551 : // convert to requested units
1552 : return MetricField::ConvertValue( NumericFormatter::GetMin(), mnBaseValue,
1553 5247 : GetDecimalDigits(), meUnit, eOutUnit );
1554 : }
1555 :
1556 6548 : void MetricFormatter::SetMax( sal_Int64 nNewMax, FieldUnit eInUnit )
1557 : {
1558 : // convert to requested units
1559 6548 : NumericFormatter::SetMax( MetricField::ConvertValue( nNewMax, mnBaseValue, GetDecimalDigits(),
1560 13096 : eInUnit, meUnit ) );
1561 6548 : }
1562 :
1563 5247 : sal_Int64 MetricFormatter::GetMax( FieldUnit eOutUnit ) const
1564 : {
1565 : // convert to requested units
1566 : return MetricField::ConvertValue( NumericFormatter::GetMax(), mnBaseValue,
1567 5247 : GetDecimalDigits(), meUnit, eOutUnit );
1568 : }
1569 :
1570 0 : void MetricFormatter::SetBaseValue( sal_Int64 nNewBase, FieldUnit eInUnit )
1571 : {
1572 0 : mnBaseValue = MetricField::ConvertValue( nNewBase, mnBaseValue, GetDecimalDigits(),
1573 0 : eInUnit, meUnit );
1574 0 : }
1575 :
1576 4636 : sal_Int64 MetricFormatter::GetBaseValue( FieldUnit eOutUnit ) const
1577 : {
1578 : // convert to requested units
1579 4636 : return MetricField::ConvertValue( mnBaseValue, mnBaseValue, GetDecimalDigits(),
1580 9272 : meUnit, eOutUnit );
1581 : }
1582 :
1583 30136 : void MetricFormatter::Reformat()
1584 : {
1585 30136 : if ( !GetField() )
1586 0 : return;
1587 :
1588 30136 : OUString aText = GetField()->GetText();
1589 30136 : if ( meUnit == FUNIT_CUSTOM )
1590 10140 : maCurUnitText = ImplMetricGetUnitText( aText );
1591 :
1592 60272 : OUString aStr;
1593 : // caution: precision loss in double cast
1594 30136 : double nTemp = (double)mnLastValue;
1595 30136 : bool bOK = ImplMetricReformat( aText, nTemp, aStr );
1596 30136 : mnLastValue = (sal_Int64)nTemp;
1597 :
1598 30136 : if ( !bOK )
1599 0 : return;
1600 :
1601 30136 : if ( !aStr.isEmpty() )
1602 : {
1603 27150 : ImplSetText( aStr );
1604 27150 : if ( meUnit == FUNIT_CUSTOM )
1605 10140 : CustomConvert();
1606 : }
1607 : else
1608 2986 : SetValue( mnLastValue );
1609 60272 : maCurUnitText.clear();
1610 : }
1611 :
1612 0 : sal_Int64 MetricFormatter::GetCorrectedValue( FieldUnit eOutUnit ) const
1613 : {
1614 : // convert to requested units
1615 0 : return MetricField::ConvertValue( mnCorrectedValue, mnBaseValue, GetDecimalDigits(),
1616 0 : meUnit, eOutUnit );
1617 : }
1618 :
1619 1848 : MetricField::MetricField( vcl::Window* pParent, WinBits nWinStyle ) :
1620 1848 : SpinField( pParent, nWinStyle )
1621 : {
1622 1848 : SetField( this );
1623 1848 : Reformat();
1624 1848 : }
1625 :
1626 0 : MetricField::MetricField( vcl::Window* pParent, const ResId& rResId ) :
1627 0 : SpinField( WINDOW_METRICFIELD )
1628 : {
1629 0 : rResId.SetRT( RSC_METRICFIELD );
1630 0 : WinBits nStyle = ImplInitRes( rResId ) ;
1631 0 : SpinField::ImplInit( pParent, nStyle );
1632 0 : SetField( this );
1633 0 : ImplLoadRes( rResId );
1634 :
1635 0 : if ( !(nStyle & WB_HIDE ) )
1636 0 : Show();
1637 0 : }
1638 :
1639 3536 : Size MetricField::CalcMinimumSize() const
1640 : {
1641 3536 : return calcMinimumSize(*this, *this);
1642 : }
1643 :
1644 13466 : bool MetricField::set_property(const OString &rKey, const OString &rValue)
1645 : {
1646 13466 : if (rKey == "digits")
1647 0 : SetDecimalDigits(rValue.toInt32());
1648 13466 : else if (rKey == "spin-size")
1649 0 : SetSpinSize(rValue.toInt32());
1650 : else
1651 13466 : return SpinField::set_property(rKey, rValue);
1652 0 : return true;
1653 : }
1654 :
1655 0 : void MetricField::ImplLoadRes( const ResId& rResId )
1656 : {
1657 0 : SpinField::ImplLoadRes( rResId );
1658 0 : MetricFormatter::ImplLoadRes( ResId( static_cast<RSHEADER_TYPE *>(GetClassRes()), *rResId.GetResMgr() ) );
1659 :
1660 0 : sal_uLong nMask = ReadLongRes();
1661 :
1662 0 : if ( METRICFIELD_FIRST & nMask )
1663 0 : mnFirst = ReadLongRes();
1664 :
1665 0 : if ( METRICFIELD_LAST & nMask )
1666 0 : mnLast = ReadLongRes();
1667 :
1668 0 : if ( METRICFIELD_SPINSIZE & nMask )
1669 0 : mnSpinSize = ReadLongRes();
1670 :
1671 0 : Reformat();
1672 0 : }
1673 :
1674 3547 : void MetricField::SetUnit( FieldUnit nNewUnit )
1675 : {
1676 3547 : sal_Int64 nRawMax = GetMax( nNewUnit );
1677 3547 : sal_Int64 nMax = Denormalize( nRawMax );
1678 3547 : sal_Int64 nMin = Denormalize( GetMin( nNewUnit ) );
1679 3547 : sal_Int64 nFirst = Denormalize( GetFirst( nNewUnit ) );
1680 3547 : sal_Int64 nLast = Denormalize( GetLast( nNewUnit ) );
1681 :
1682 3547 : MetricFormatter::SetUnit( nNewUnit );
1683 :
1684 3547 : SetMax( Normalize( nMax ), nNewUnit );
1685 3547 : SetMin( Normalize( nMin ), nNewUnit );
1686 3547 : SetFirst( Normalize( nFirst ), nNewUnit );
1687 3547 : SetLast( Normalize( nLast ), nNewUnit );
1688 3547 : }
1689 :
1690 5241 : void MetricField::SetFirst( sal_Int64 nNewFirst, FieldUnit eInUnit )
1691 : {
1692 : // convert
1693 5241 : nNewFirst = MetricField::ConvertValue( nNewFirst, mnBaseValue, GetDecimalDigits(),
1694 10482 : eInUnit, meUnit );
1695 5241 : mnFirst = nNewFirst;
1696 5241 : }
1697 :
1698 5247 : sal_Int64 MetricField::GetFirst( FieldUnit eOutUnit ) const
1699 : {
1700 : // convert
1701 5247 : return MetricField::ConvertValue( mnFirst, mnBaseValue, GetDecimalDigits(),
1702 10494 : meUnit, eOutUnit );
1703 : }
1704 :
1705 5241 : void MetricField::SetLast( sal_Int64 nNewLast, FieldUnit eInUnit )
1706 : {
1707 : // convert
1708 5241 : nNewLast = MetricField::ConvertValue( nNewLast, mnBaseValue, GetDecimalDigits(),
1709 10482 : eInUnit, meUnit );
1710 5241 : mnLast = nNewLast;
1711 5241 : }
1712 :
1713 5247 : sal_Int64 MetricField::GetLast( FieldUnit eOutUnit ) const
1714 : {
1715 : // conver
1716 5247 : return MetricField::ConvertValue( mnLast, mnBaseValue, GetDecimalDigits(),
1717 10494 : meUnit, eOutUnit );
1718 : }
1719 :
1720 0 : bool MetricField::PreNotify( NotifyEvent& rNEvt )
1721 : {
1722 0 : if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
1723 : {
1724 0 : if ( ImplMetricProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
1725 0 : return true;
1726 : }
1727 :
1728 0 : return SpinField::PreNotify( rNEvt );
1729 : }
1730 :
1731 1847 : bool MetricField::Notify( NotifyEvent& rNEvt )
1732 : {
1733 1847 : if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
1734 0 : MarkToBeReformatted( false );
1735 1847 : else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
1736 : {
1737 0 : if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
1738 0 : Reformat();
1739 : }
1740 :
1741 1847 : return SpinField::Notify( rNEvt );
1742 : }
1743 :
1744 0 : void MetricField::DataChanged( const DataChangedEvent& rDCEvt )
1745 : {
1746 0 : SpinField::DataChanged( rDCEvt );
1747 :
1748 0 : if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
1749 : {
1750 0 : OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1751 0 : OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1752 0 : if ( IsDefaultLocale() )
1753 0 : ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
1754 0 : OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1755 0 : OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1756 0 : ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
1757 0 : ReformatAll();
1758 : }
1759 0 : }
1760 :
1761 0 : void MetricField::Modify()
1762 : {
1763 0 : MarkToBeReformatted( true );
1764 0 : SpinField::Modify();
1765 0 : }
1766 :
1767 0 : void MetricField::Up()
1768 : {
1769 0 : FieldUp();
1770 0 : SpinField::Up();
1771 0 : }
1772 :
1773 0 : void MetricField::Down()
1774 : {
1775 0 : FieldDown();
1776 0 : SpinField::Down();
1777 0 : }
1778 :
1779 0 : void MetricField::First()
1780 : {
1781 0 : FieldFirst();
1782 0 : SpinField::First();
1783 0 : }
1784 :
1785 0 : void MetricField::Last()
1786 : {
1787 0 : FieldLast();
1788 0 : SpinField::Last();
1789 0 : }
1790 :
1791 10140 : void MetricField::CustomConvert()
1792 : {
1793 10140 : maCustomConvertLink.Call( this );
1794 10140 : }
1795 :
1796 1138 : MetricBox::MetricBox( vcl::Window* pParent, WinBits nWinStyle ) :
1797 1138 : ComboBox( pParent, nWinStyle )
1798 : {
1799 1138 : SetField( this );
1800 1138 : Reformat();
1801 1138 : }
1802 :
1803 1137 : Size MetricBox::CalcMinimumSize() const
1804 : {
1805 1137 : Size aRet(calcMinimumSize(*this, *this));
1806 :
1807 1137 : if (IsDropDownBox())
1808 : {
1809 1137 : Size aComboSugg(ComboBox::CalcMinimumSize());
1810 1137 : aRet.Width() = std::max(aRet.Width(), aComboSugg.Width());
1811 1137 : aRet.Height() = std::max(aRet.Height(), aComboSugg.Height());
1812 : }
1813 :
1814 1137 : return aRet;
1815 : }
1816 :
1817 0 : bool MetricBox::PreNotify( NotifyEvent& rNEvt )
1818 : {
1819 0 : if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
1820 : {
1821 0 : if ( ImplMetricProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
1822 0 : return true;
1823 : }
1824 :
1825 0 : return ComboBox::PreNotify( rNEvt );
1826 : }
1827 :
1828 2276 : bool MetricBox::Notify( NotifyEvent& rNEvt )
1829 : {
1830 2276 : if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
1831 0 : MarkToBeReformatted( false );
1832 2276 : else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
1833 : {
1834 0 : if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
1835 0 : Reformat();
1836 : }
1837 :
1838 2276 : return ComboBox::Notify( rNEvt );
1839 : }
1840 :
1841 0 : void MetricBox::DataChanged( const DataChangedEvent& rDCEvt )
1842 : {
1843 0 : ComboBox::DataChanged( rDCEvt );
1844 :
1845 0 : if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
1846 : {
1847 0 : OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1848 0 : OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1849 0 : if ( IsDefaultLocale() )
1850 0 : ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
1851 0 : OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
1852 0 : OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
1853 0 : ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
1854 0 : ReformatAll();
1855 : }
1856 0 : }
1857 :
1858 0 : void MetricBox::Modify()
1859 : {
1860 0 : MarkToBeReformatted( true );
1861 0 : ComboBox::Modify();
1862 0 : }
1863 :
1864 4250 : void MetricBox::ReformatAll()
1865 : {
1866 : double nValue;
1867 4250 : OUString aStr;
1868 4250 : SetUpdateMode( false );
1869 4250 : sal_Int32 nEntryCount = GetEntryCount();
1870 4250 : for ( sal_Int32 i=0; i < nEntryCount; i++ )
1871 : {
1872 0 : ImplMetricReformat( GetEntry( i ), nValue, aStr );
1873 0 : RemoveEntryAt(i);
1874 0 : InsertEntry( aStr, i );
1875 : }
1876 4250 : MetricFormatter::Reformat();
1877 4250 : SetUpdateMode( true );
1878 4250 : }
1879 :
1880 0 : void MetricBox::CustomConvert()
1881 : {
1882 0 : maCustomConvertLink.Call( this );
1883 0 : }
1884 :
1885 30796 : void MetricBox::InsertValue( sal_Int64 nValue, FieldUnit eInUnit, sal_Int32 nPos )
1886 : {
1887 : // convert to previously configured units
1888 30796 : nValue = MetricField::ConvertValue( nValue, mnBaseValue, GetDecimalDigits(),
1889 61592 : eInUnit, meUnit );
1890 30796 : ComboBox::InsertEntry( CreateFieldText( nValue ), nPos );
1891 30796 : }
1892 :
1893 0 : sal_Int64 MetricBox::GetValue( sal_Int32 nPos, FieldUnit eOutUnit ) const
1894 : {
1895 0 : double nValue = 0;
1896 : ImplMetricGetValue( ComboBox::GetEntry( nPos ), nValue, mnBaseValue,
1897 0 : GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit );
1898 :
1899 : // convert to previously configured units
1900 0 : sal_Int64 nRetValue = MetricField::ConvertValue( (sal_Int64)nValue, mnBaseValue, GetDecimalDigits(),
1901 0 : meUnit, eOutUnit );
1902 :
1903 0 : return nRetValue;
1904 : }
1905 :
1906 0 : sal_Int32 MetricBox::GetValuePos( sal_Int64 nValue, FieldUnit eInUnit ) const
1907 : {
1908 : // convert to previously configured units
1909 0 : nValue = MetricField::ConvertValue( nValue, mnBaseValue, GetDecimalDigits(),
1910 0 : eInUnit, meUnit );
1911 0 : return ComboBox::GetEntryPos( CreateFieldText( nValue ) );
1912 : }
1913 :
1914 4338 : sal_Int64 MetricBox::GetValue( FieldUnit eOutUnit ) const
1915 : {
1916 : // Implementation not inline, because it is a virtual Function
1917 4338 : return MetricFormatter::GetValue( eOutUnit );
1918 : }
1919 :
1920 0 : sal_Int64 MetricBox::GetValue() const
1921 : {
1922 : // Implementation not inline, because it is a virtual Function
1923 0 : return GetValue( FUNIT_NONE );
1924 : }
1925 :
1926 0 : static bool ImplCurrencyProcessKeyInput( Edit* pEdit, const KeyEvent& rKEvt,
1927 : bool, bool bUseThousandSep, const LocaleDataWrapper& rWrapper )
1928 : {
1929 : // no strict format set; therefore allow all characters
1930 0 : return ImplNumericProcessKeyInput( pEdit, rKEvt, false, bUseThousandSep, rWrapper );
1931 : }
1932 :
1933 0 : inline bool ImplCurrencyGetValue( const OUString& rStr, sal_Int64& rValue,
1934 : sal_uInt16 nDecDigits, const LocaleDataWrapper& rWrapper )
1935 : {
1936 : // fetch number
1937 0 : return ImplNumericGetValue( rStr, rValue, nDecDigits, rWrapper, true );
1938 : }
1939 :
1940 0 : bool CurrencyFormatter::ImplCurrencyReformat( const OUString& rStr, OUString& rOutStr )
1941 : {
1942 : sal_Int64 nValue;
1943 0 : if ( !ImplNumericGetValue( rStr, nValue, GetDecimalDigits(), ImplGetLocaleDataWrapper(), true ) )
1944 0 : return true;
1945 : else
1946 : {
1947 0 : sal_Int64 nTempVal = nValue;
1948 0 : if ( nTempVal > GetMax() )
1949 0 : nTempVal = GetMax();
1950 0 : else if ( nTempVal < GetMin())
1951 0 : nTempVal = GetMin();
1952 :
1953 0 : if ( GetErrorHdl().IsSet() && (nValue != nTempVal) )
1954 : {
1955 0 : mnCorrectedValue = nTempVal;
1956 0 : if ( !GetErrorHdl().Call( this ) )
1957 : {
1958 0 : mnCorrectedValue = 0;
1959 0 : return false;
1960 : }
1961 : else
1962 0 : mnCorrectedValue = 0;
1963 : }
1964 :
1965 0 : rOutStr = CreateFieldText( nTempVal );
1966 0 : return true;
1967 : }
1968 : }
1969 :
1970 0 : inline void CurrencyFormatter::ImplInit()
1971 : {
1972 0 : mnType = FORMAT_CURRENCY;
1973 0 : }
1974 :
1975 0 : CurrencyFormatter::CurrencyFormatter()
1976 : {
1977 0 : ImplInit();
1978 0 : }
1979 :
1980 0 : CurrencyFormatter::~CurrencyFormatter()
1981 : {
1982 0 : }
1983 :
1984 0 : OUString CurrencyFormatter::GetCurrencySymbol() const
1985 : {
1986 0 : return ImplGetLocaleDataWrapper().getCurrSymbol();
1987 : }
1988 :
1989 0 : void CurrencyFormatter::SetValue( sal_Int64 nNewValue )
1990 : {
1991 0 : SetUserValue( nNewValue );
1992 0 : mnFieldValue = mnLastValue;
1993 0 : SetEmptyFieldValueData( false );
1994 0 : }
1995 :
1996 0 : OUString CurrencyFormatter::CreateFieldText( sal_Int64 nValue ) const
1997 : {
1998 0 : return ImplGetLocaleDataWrapper().getCurr( nValue, GetDecimalDigits(), GetCurrencySymbol(), IsUseThousandSep() );
1999 : }
2000 :
2001 0 : sal_Int64 CurrencyFormatter::GetValue() const
2002 : {
2003 0 : if ( !GetField() )
2004 0 : return 0;
2005 :
2006 : sal_Int64 nTempValue;
2007 0 : if ( ImplCurrencyGetValue( GetField()->GetText(), nTempValue, GetDecimalDigits(), ImplGetLocaleDataWrapper() ) )
2008 : {
2009 0 : return ClipAgainstMinMax(nTempValue);
2010 : }
2011 : else
2012 0 : return mnLastValue;
2013 : }
2014 :
2015 0 : void CurrencyFormatter::Reformat()
2016 : {
2017 0 : if ( !GetField() )
2018 0 : return;
2019 :
2020 0 : OUString aStr;
2021 0 : bool bOK = ImplCurrencyReformat( GetField()->GetText(), aStr );
2022 0 : if ( !bOK )
2023 0 : return;
2024 :
2025 0 : if ( !aStr.isEmpty() )
2026 : {
2027 0 : ImplSetText( aStr );
2028 0 : sal_Int64 nTemp = mnLastValue;
2029 0 : ImplCurrencyGetValue( aStr, nTemp, GetDecimalDigits(), ImplGetLocaleDataWrapper() );
2030 0 : mnLastValue = nTemp;
2031 : }
2032 : else
2033 0 : SetValue( mnLastValue );
2034 : }
2035 :
2036 0 : CurrencyField::CurrencyField( vcl::Window* pParent, WinBits nWinStyle ) :
2037 0 : SpinField( pParent, nWinStyle )
2038 : {
2039 0 : SetField( this );
2040 0 : Reformat();
2041 0 : }
2042 :
2043 0 : bool CurrencyField::PreNotify( NotifyEvent& rNEvt )
2044 : {
2045 0 : if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
2046 : {
2047 0 : if ( ImplCurrencyProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
2048 0 : return true;
2049 : }
2050 :
2051 0 : return SpinField::PreNotify( rNEvt );
2052 : }
2053 :
2054 0 : bool CurrencyField::Notify( NotifyEvent& rNEvt )
2055 : {
2056 0 : if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
2057 0 : MarkToBeReformatted( false );
2058 0 : else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
2059 : {
2060 0 : if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
2061 0 : Reformat();
2062 : }
2063 :
2064 0 : return SpinField::Notify( rNEvt );
2065 : }
2066 :
2067 0 : void CurrencyField::DataChanged( const DataChangedEvent& rDCEvt )
2068 : {
2069 0 : SpinField::DataChanged( rDCEvt );
2070 :
2071 0 : if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
2072 : {
2073 0 : OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
2074 0 : OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
2075 0 : if ( IsDefaultLocale() )
2076 0 : ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
2077 0 : OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
2078 0 : OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
2079 0 : ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
2080 0 : ReformatAll();
2081 : }
2082 0 : }
2083 :
2084 0 : void CurrencyField::Modify()
2085 : {
2086 0 : MarkToBeReformatted( true );
2087 0 : SpinField::Modify();
2088 0 : }
2089 :
2090 0 : void CurrencyField::Up()
2091 : {
2092 0 : FieldUp();
2093 0 : SpinField::Up();
2094 0 : }
2095 :
2096 0 : void CurrencyField::Down()
2097 : {
2098 0 : FieldDown();
2099 0 : SpinField::Down();
2100 0 : }
2101 :
2102 0 : void CurrencyField::First()
2103 : {
2104 0 : FieldFirst();
2105 0 : SpinField::First();
2106 0 : }
2107 :
2108 0 : void CurrencyField::Last()
2109 : {
2110 0 : FieldLast();
2111 0 : SpinField::Last();
2112 0 : }
2113 :
2114 0 : CurrencyBox::CurrencyBox( vcl::Window* pParent, WinBits nWinStyle ) :
2115 0 : ComboBox( pParent, nWinStyle )
2116 : {
2117 0 : SetField( this );
2118 0 : Reformat();
2119 0 : }
2120 :
2121 0 : bool CurrencyBox::PreNotify( NotifyEvent& rNEvt )
2122 : {
2123 0 : if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() )
2124 : {
2125 0 : if ( ImplCurrencyProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
2126 0 : return true;
2127 : }
2128 :
2129 0 : return ComboBox::PreNotify( rNEvt );
2130 : }
2131 :
2132 0 : bool CurrencyBox::Notify( NotifyEvent& rNEvt )
2133 : {
2134 0 : if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
2135 0 : MarkToBeReformatted( false );
2136 0 : else if ( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
2137 : {
2138 0 : if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
2139 0 : Reformat();
2140 : }
2141 :
2142 0 : return ComboBox::Notify( rNEvt );
2143 : }
2144 :
2145 0 : void CurrencyBox::DataChanged( const DataChangedEvent& rDCEvt )
2146 : {
2147 0 : ComboBox::DataChanged( rDCEvt );
2148 :
2149 0 : if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::LOCALE) )
2150 : {
2151 0 : OUString sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
2152 0 : OUString sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
2153 0 : if ( IsDefaultLocale() )
2154 0 : ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
2155 0 : OUString sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep();
2156 0 : OUString sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep();
2157 0 : ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this );
2158 0 : ReformatAll();
2159 : }
2160 0 : }
2161 :
2162 0 : void CurrencyBox::Modify()
2163 : {
2164 0 : MarkToBeReformatted( true );
2165 0 : ComboBox::Modify();
2166 0 : }
2167 :
2168 0 : void CurrencyBox::ReformatAll()
2169 : {
2170 0 : OUString aStr;
2171 0 : SetUpdateMode( false );
2172 0 : sal_Int32 nEntryCount = GetEntryCount();
2173 0 : for ( sal_Int32 i=0; i < nEntryCount; i++ )
2174 : {
2175 0 : ImplCurrencyReformat( GetEntry( i ), aStr );
2176 0 : RemoveEntryAt(i);
2177 0 : InsertEntry( aStr, i );
2178 : }
2179 0 : CurrencyFormatter::Reformat();
2180 0 : SetUpdateMode( true );
2181 0 : }
2182 :
2183 0 : sal_Int64 CurrencyBox::GetValue() const
2184 : {
2185 : // Implementation not inline, because it is a virtual Function
2186 0 : return CurrencyFormatter::GetValue();
2187 801 : }
2188 :
2189 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|