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