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