1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_vcl.hxx" 26 27 #ifndef _BIGINT_HXX 28 #define _TOOLS_BIGINT 29 #include "tools/bigint.hxx" 30 #endif 31 32 #include "tools/debug.hxx" 33 34 #include "tools/rc.h" 35 #include "tools/resary.hxx" 36 37 #include "vcl/field.hxx" 38 #include "vcl/event.hxx" 39 #include "vcl/svapp.hxx" 40 #include "vcl/unohelp.hxx" 41 42 #include "svids.hrc" 43 #include "svdata.hxx" 44 45 #include "i18nutil/unicode.hxx" 46 47 #include "rtl/math.hxx" 48 49 50 #include <unotools/localedatawrapper.hxx> 51 52 using namespace ::com::sun::star; 53 54 // ----------------------------------------------------------------------- 55 56 #define FORMAT_NUMERIC 1 57 #define FORMAT_METRIC 2 58 #define FORMAT_CURRENCY 3 59 60 // ----------------------------------------------------------------------- 61 62 static sal_Int64 ImplPower10( sal_uInt16 n ) 63 { 64 sal_uInt16 i; 65 sal_Int64 nValue = 1; 66 67 for ( i=0; i < n; i++ ) 68 nValue *= 10; 69 70 return nValue; 71 } 72 73 // ----------------------------------------------------------------------- 74 75 static sal_Bool ImplNumericProcessKeyInput( Edit*, const KeyEvent& rKEvt, 76 sal_Bool bStrictFormat, sal_Bool bThousandSep, 77 const LocaleDataWrapper& rLocaleDataWrappper ) 78 { 79 if ( !bStrictFormat ) 80 return sal_False; 81 else 82 { 83 xub_Unicode cChar = rKEvt.GetCharCode(); 84 sal_uInt16 nGroup = rKEvt.GetKeyCode().GetGroup(); 85 86 if ( (nGroup == KEYGROUP_FKEYS) || (nGroup == KEYGROUP_CURSOR) || 87 (nGroup == KEYGROUP_MISC) || 88 ((cChar >= '0') && (cChar <= '9')) || 89 (cChar == rLocaleDataWrappper.getNumDecimalSep() ) || 90 (bThousandSep && (cChar == rLocaleDataWrappper.getNumThousandSep())) || 91 (cChar == '-') ) 92 return sal_False; 93 else 94 return sal_True; 95 } 96 } 97 98 // ----------------------------------------------------------------------- 99 100 static sal_Bool ImplNumericGetValue( const XubString& rStr, double& rValue, 101 sal_uInt16 nDecDigits, const LocaleDataWrapper& rLocaleDataWrappper, 102 sal_Bool bCurrency = sal_False ) 103 { 104 XubString aStr = rStr; 105 XubString aStr1; 106 XubString aStr2; 107 sal_Bool bNegative = sal_False; 108 xub_StrLen nDecPos; 109 xub_StrLen i; 110 111 // Reaktion auf leeren String 112 if ( !rStr.Len() ) 113 return sal_False; 114 115 // Fuehrende und nachfolgende Leerzeichen entfernen 116 aStr.EraseLeadingAndTrailingChars( ' ' ); 117 118 // Position des Dezimalpunktes suchen 119 nDecPos = aStr.Search( rLocaleDataWrappper.getNumDecimalSep() ); 120 if ( nDecPos != STRING_NOTFOUND ) 121 { 122 aStr1 = aStr.Copy( 0, nDecPos ); 123 aStr2 = aStr.Copy( nDecPos+1 ); 124 } 125 else 126 aStr1 = aStr; 127 128 // Negativ ? 129 if ( bCurrency ) 130 { 131 if ( (aStr.GetChar( 0 ) == '(') && (aStr.GetChar( aStr.Len()-1 ) == ')') ) 132 bNegative = sal_True; 133 if ( !bNegative ) 134 { 135 for ( i=0; i < aStr.Len(); i++ ) 136 { 137 if ( (aStr.GetChar( i ) >= '0') && (aStr.GetChar( i ) <= '9') ) 138 break; 139 else if ( aStr.GetChar( i ) == '-' ) 140 { 141 bNegative = sal_True; 142 break; 143 } 144 } 145 } 146 if ( !bNegative && bCurrency && aStr.Len() ) 147 { 148 sal_uInt16 nFormat = rLocaleDataWrappper.getCurrNegativeFormat(); 149 if ( (nFormat == 3) || (nFormat == 6) || 150 (nFormat == 7) || (nFormat == 10) ) 151 { 152 for ( i = (xub_StrLen)(aStr.Len()-1); i > 0; i++ ) 153 { 154 if ( (aStr.GetChar( i ) >= '0') && (aStr.GetChar( i ) <= '9') ) 155 break; 156 else if ( aStr.GetChar( i ) == '-' ) 157 { 158 bNegative = sal_True; 159 break; 160 } 161 } 162 } 163 } 164 } 165 else 166 { 167 if ( aStr1.GetChar( 0 ) == '-' ) 168 bNegative = sal_True; 169 } 170 171 // Alle unerwuenschten Zeichen rauswerfen 172 for ( i=0; i < aStr1.Len(); ) 173 { 174 if ( (aStr1.GetChar( i ) >= '0') && (aStr1.GetChar( i ) <= '9') ) 175 i++; 176 else 177 aStr1.Erase( i, 1 ); 178 } 179 for ( i=0; i < aStr2.Len(); ) 180 { 181 if ( (aStr2.GetChar( i ) >= '0') && (aStr2.GetChar( i ) <= '9') ) 182 i++; 183 else 184 aStr2.Erase( i, 1 ); 185 } 186 187 if ( !aStr1.Len() && !aStr2.Len() ) 188 return sal_False; 189 190 if ( !aStr1.Len() ) 191 aStr1.Insert( '0' ); 192 if ( bNegative ) 193 aStr1.Insert( '-', 0 ); 194 195 // Nachkommateil zurechtstutzen und dabei runden 196 sal_Bool bRound = sal_False; 197 if ( aStr2.Len() > nDecDigits ) 198 { 199 if ( aStr2.GetChar( nDecDigits ) >= '5' ) 200 bRound = sal_True; 201 aStr2.Erase( nDecDigits ); 202 } 203 if ( aStr2.Len() < nDecDigits ) 204 aStr2.Expand( nDecDigits, '0' ); 205 206 aStr = aStr1; 207 aStr += aStr2; 208 209 // Bereichsueberpruefung 210 double nValue = aStr.ToDouble(); 211 if ( bRound ) 212 { 213 if ( !bNegative ) 214 nValue++; 215 else 216 nValue--; 217 } 218 219 rValue = nValue; 220 221 return sal_True; 222 } 223 224 static void ImplUpdateSeparatorString( String& io_rText, 225 const String& rOldDecSep, const String& rNewDecSep, 226 const String& rOldThSep, const String& rNewThSep ) 227 { 228 rtl::OUStringBuffer aBuf( io_rText.Len() ); 229 xub_StrLen nIndexDec = 0, nIndexTh = 0, nIndex = 0; 230 231 const sal_Unicode* pBuffer = io_rText.GetBuffer(); 232 while( nIndex != STRING_NOTFOUND ) 233 { 234 nIndexDec = io_rText.Search( rOldDecSep, nIndex ); 235 nIndexTh = io_rText.Search( rOldThSep, nIndex ); 236 if( (nIndexTh != STRING_NOTFOUND && nIndexDec != STRING_NOTFOUND && nIndexTh < nIndexDec ) 237 || (nIndexTh != STRING_NOTFOUND && nIndexDec == STRING_NOTFOUND) 238 ) 239 { 240 aBuf.append( pBuffer + nIndex, nIndexTh - nIndex ); 241 aBuf.append( rNewThSep ); 242 nIndex = nIndexTh + rOldThSep.Len(); 243 } 244 else if( nIndexDec != STRING_NOTFOUND ) 245 { 246 aBuf.append( pBuffer + nIndex, nIndexDec - nIndex ); 247 aBuf.append( rNewDecSep ); 248 nIndex = nIndexDec + rOldDecSep.Len(); 249 } 250 else 251 { 252 aBuf.append( pBuffer + nIndex ); 253 nIndex = STRING_NOTFOUND; 254 } 255 } 256 257 io_rText = aBuf.makeStringAndClear(); 258 } 259 260 static void ImplUpdateSeparators( const String& rOldDecSep, const String& rNewDecSep, 261 const String& rOldThSep, const String& rNewThSep, 262 Edit* pEdit ) 263 { 264 bool bChangeDec = (rOldDecSep != rNewDecSep); 265 bool bChangeTh = (rOldThSep != rNewThSep ); 266 267 if( bChangeDec || bChangeTh ) 268 { 269 sal_Bool bUpdateMode = pEdit->IsUpdateMode(); 270 pEdit->SetUpdateMode( sal_False ); 271 String aText = pEdit->GetText(); 272 ImplUpdateSeparatorString( aText, rOldDecSep, rNewDecSep, rOldThSep, rNewThSep ); 273 pEdit->SetText( aText ); 274 275 ComboBox* pCombo = dynamic_cast<ComboBox*>(pEdit); 276 if( pCombo ) 277 { 278 // update box entries 279 sal_uInt16 nEntryCount = pCombo->GetEntryCount(); 280 for ( sal_uInt16 i=0; i < nEntryCount; i++ ) 281 { 282 aText = pCombo->GetEntry( i ); 283 void* pEntryData = pCombo->GetEntryData( i ); 284 ImplUpdateSeparatorString( aText, rOldDecSep, rNewDecSep, rOldThSep, rNewThSep ); 285 pCombo->RemoveEntry( i ); 286 pCombo->InsertEntry( aText, i ); 287 pCombo->SetEntryData( i, pEntryData ); 288 } 289 } 290 if( bUpdateMode ) 291 pEdit->SetUpdateMode( bUpdateMode ); 292 } 293 } 294 295 // ----------------------------------------------------------------------- 296 297 FormatterBase::FormatterBase( Edit* pField ) 298 { 299 mpField = pField; 300 mpLocaleDataWrapper = NULL; 301 mbReformat = sal_False; 302 mbStrictFormat = sal_False; 303 mbEmptyFieldValue = sal_False; 304 mbEmptyFieldValueEnabled = sal_False; 305 mbDefaultLocale = sal_True; 306 } 307 308 // ----------------------------------------------------------------------- 309 310 FormatterBase::~FormatterBase() 311 { 312 delete mpLocaleDataWrapper; 313 } 314 315 // ----------------------------------------------------------------------- 316 317 LocaleDataWrapper& FormatterBase::ImplGetLocaleDataWrapper() const 318 { 319 if ( !mpLocaleDataWrapper ) 320 { 321 ((FormatterBase*)this)->mpLocaleDataWrapper = new LocaleDataWrapper( vcl::unohelper::GetMultiServiceFactory(), GetLocale() ); 322 } 323 return *mpLocaleDataWrapper; 324 } 325 326 const LocaleDataWrapper& FormatterBase::GetLocaleDataWrapper() const 327 { 328 return ImplGetLocaleDataWrapper(); 329 } 330 331 // ----------------------------------------------------------------------- 332 333 void FormatterBase::Reformat() 334 { 335 } 336 337 // ----------------------------------------------------------------------- 338 339 void FormatterBase::ReformatAll() 340 { 341 Reformat(); 342 }; 343 344 // ----------------------------------------------------------------------- 345 346 void FormatterBase::SetStrictFormat( sal_Bool bStrict ) 347 { 348 if ( bStrict != mbStrictFormat ) 349 { 350 mbStrictFormat = bStrict; 351 if ( mbStrictFormat ) 352 ReformatAll(); 353 } 354 } 355 356 // ----------------------------------------------------------------------- 357 358 void FormatterBase::SetLocale( const lang::Locale& rLocale ) 359 { 360 ImplGetLocaleDataWrapper().setLocale( rLocale ); 361 mbDefaultLocale = sal_False; 362 ReformatAll(); 363 } 364 365 // ----------------------------------------------------------------------- 366 367 const lang::Locale& FormatterBase::GetLocale() const 368 { 369 if ( !mpLocaleDataWrapper || mbDefaultLocale ) 370 { 371 if ( mpField ) 372 return mpField->GetSettings().GetLocale(); 373 else 374 return Application::GetSettings().GetLocale(); 375 } 376 377 return mpLocaleDataWrapper->getLocale(); 378 } 379 380 // ----------------------------------------------------------------------- 381 382 const AllSettings& FormatterBase::GetFieldSettings() const 383 { 384 if ( mpField ) 385 return mpField->GetSettings(); 386 else 387 return Application::GetSettings(); 388 } 389 390 // ----------------------------------------------------------------------- 391 392 void FormatterBase::SetFieldText( const XubString& rText, sal_Bool bKeepSelection ) 393 { 394 if ( mpField ) 395 { 396 Selection aNewSelection( 0xFFFF, 0xFFFF ); 397 if ( bKeepSelection ) 398 aNewSelection = mpField->GetSelection(); 399 400 ImplSetText( rText, &aNewSelection ); 401 } 402 } 403 404 // ----------------------------------------------------------------------- 405 406 void FormatterBase::ImplSetText( const XubString& rText, Selection* pNewSelection ) 407 { 408 if ( mpField ) 409 { 410 if ( pNewSelection ) 411 mpField->SetText( rText, *pNewSelection ); 412 else 413 { 414 Selection aSel = mpField->GetSelection(); 415 aSel.Min() = aSel.Max(); 416 mpField->SetText( rText, aSel ); 417 } 418 419 MarkToBeReformatted( sal_False ); 420 } 421 } 422 423 // ----------------------------------------------------------------------- 424 425 void FormatterBase::SetEmptyFieldValue() 426 { 427 if ( mpField ) 428 mpField->SetText( ImplGetSVEmptyStr() ); 429 mbEmptyFieldValue = sal_True; 430 } 431 432 // ----------------------------------------------------------------------- 433 434 sal_Bool FormatterBase::IsEmptyFieldValue() const 435 { 436 return (!mpField || !mpField->GetText().Len()); 437 } 438 439 // ----------------------------------------------------------------------- 440 441 sal_Bool NumericFormatter::ImplNumericReformat( const XubString& rStr, double& rValue, 442 XubString& rOutStr ) 443 { 444 if ( !ImplNumericGetValue( rStr, rValue, GetDecimalDigits(), ImplGetLocaleDataWrapper() ) ) 445 return sal_True; 446 else 447 { 448 double nTempVal = rValue; 449 // caution: precision loss in double cast 450 if ( nTempVal > mnMax ) 451 nTempVal = (double)mnMax; 452 else if ( nTempVal < mnMin ) 453 nTempVal = (double)mnMin; 454 455 if ( GetErrorHdl().IsSet() && (rValue != nTempVal) ) 456 { 457 mnCorrectedValue = (sal_Int64)nTempVal; 458 if ( !GetErrorHdl().Call( this ) ) 459 { 460 mnCorrectedValue = 0; 461 return sal_False; 462 } 463 else 464 mnCorrectedValue = 0; 465 } 466 467 rOutStr = CreateFieldText( (sal_Int64)nTempVal ); 468 return sal_True; 469 } 470 } 471 472 // ----------------------------------------------------------------------- 473 474 void NumericFormatter::ImplInit() 475 { 476 mnFieldValue = 0; 477 mnLastValue = 0; 478 mnMin = 0; 479 mnMax = 0x7FFFFFFFFFFFFFFFLL; 480 #ifdef OS2 // see i120312 for details. 481 mnMax = 0x00000000FFFFFFFFLL; 482 #endif 483 mnCorrectedValue = 0; 484 mnDecimalDigits = 2; 485 mnType = FORMAT_NUMERIC; 486 mbThousandSep = sal_True; 487 mbShowTrailingZeros = sal_True; 488 489 // for fields 490 mnSpinSize = 1; 491 mnFirst = mnMin; 492 mnLast = mnMax; 493 494 SetDecimalDigits( 0 ); 495 } 496 497 // ----------------------------------------------------------------------- 498 499 NumericFormatter::NumericFormatter() 500 { 501 ImplInit(); 502 } 503 504 // ----------------------------------------------------------------------- 505 506 void NumericFormatter::ImplLoadRes( const ResId& rResId ) 507 { 508 ResMgr* pMgr = rResId.GetResMgr(); 509 510 if( pMgr ) 511 { 512 sal_uLong nMask = pMgr->ReadLong(); 513 514 if ( NUMERICFORMATTER_MIN & nMask ) 515 mnMin = pMgr->ReadLong(); 516 517 if ( NUMERICFORMATTER_MAX & nMask ) 518 mnMax = pMgr->ReadLong(); 519 520 if ( NUMERICFORMATTER_STRICTFORMAT & nMask ) 521 SetStrictFormat( (sal_Bool)pMgr->ReadShort() ); 522 523 if ( NUMERICFORMATTER_DECIMALDIGITS & nMask ) 524 SetDecimalDigits( pMgr->ReadShort() ); 525 526 if ( NUMERICFORMATTER_VALUE & nMask ) 527 { 528 mnFieldValue = pMgr->ReadLong(); 529 if ( mnFieldValue > mnMax ) 530 mnFieldValue = mnMax; 531 else if ( mnFieldValue < mnMin ) 532 mnFieldValue = mnMin; 533 mnLastValue = mnFieldValue; 534 } 535 536 if ( NUMERICFORMATTER_NOTHOUSANDSEP & nMask ) 537 SetUseThousandSep( !(sal_Bool)pMgr->ReadShort() ); 538 } 539 } 540 541 // ----------------------------------------------------------------------- 542 543 NumericFormatter::~NumericFormatter() 544 { 545 } 546 547 // ----------------------------------------------------------------------- 548 549 void NumericFormatter::SetMin( sal_Int64 nNewMin ) 550 { 551 mnMin = nNewMin; 552 if ( !IsEmptyFieldValue() ) 553 ReformatAll(); 554 } 555 556 // ----------------------------------------------------------------------- 557 558 void NumericFormatter::SetMax( sal_Int64 nNewMax ) 559 { 560 mnMax = nNewMax; 561 if ( !IsEmptyFieldValue() ) 562 ReformatAll(); 563 } 564 565 // ----------------------------------------------------------------------- 566 567 void NumericFormatter::SetUseThousandSep( sal_Bool b ) 568 { 569 mbThousandSep = b; 570 ReformatAll(); 571 } 572 573 // ----------------------------------------------------------------------- 574 575 void NumericFormatter::SetDecimalDigits( sal_uInt16 nDigits ) 576 { 577 mnDecimalDigits = nDigits; 578 ReformatAll(); 579 } 580 581 // ----------------------------------------------------------------------- 582 583 void NumericFormatter::SetShowTrailingZeros( sal_Bool bShowTrailingZeros ) 584 { 585 if ( mbShowTrailingZeros != bShowTrailingZeros ) 586 { 587 mbShowTrailingZeros = bShowTrailingZeros; 588 ReformatAll(); 589 } 590 } 591 592 // ----------------------------------------------------------------------- 593 594 sal_uInt16 NumericFormatter::GetDecimalDigits() const 595 { 596 return mnDecimalDigits; 597 } 598 599 // ----------------------------------------------------------------------- 600 601 void NumericFormatter::SetValue( sal_Int64 nNewValue ) 602 { 603 SetUserValue( nNewValue ); 604 mnFieldValue = mnLastValue; 605 SetEmptyFieldValueData( sal_False ); 606 } 607 608 // ----------------------------------------------------------------------- 609 610 XubString NumericFormatter::CreateFieldText( sal_Int64 nValue ) const 611 { 612 return ImplGetLocaleDataWrapper().getNum( nValue, GetDecimalDigits(), IsUseThousandSep(), IsShowTrailingZeros() ); 613 } 614 615 // ----------------------------------------------------------------------- 616 617 void NumericFormatter::ImplSetUserValue( sal_Int64 nNewValue, Selection* pNewSelection ) 618 { 619 if ( nNewValue > mnMax ) 620 nNewValue = mnMax; 621 else if ( nNewValue < mnMin ) 622 nNewValue = mnMin; 623 mnLastValue = nNewValue; 624 625 if ( GetField() ) 626 ImplSetText( CreateFieldText( nNewValue ), pNewSelection ); 627 } 628 629 // ----------------------------------------------------------------------- 630 631 void NumericFormatter::SetUserValue( sal_Int64 nNewValue ) 632 { 633 ImplSetUserValue( nNewValue ); 634 } 635 636 // ----------------------------------------------------------------------- 637 638 sal_Int64 NumericFormatter::GetValue() const 639 { 640 if ( !GetField() ) 641 return 0; 642 643 double nTempValue; 644 645 if ( ImplNumericGetValue( GetField()->GetText(), nTempValue, 646 GetDecimalDigits(), ImplGetLocaleDataWrapper() ) ) 647 { 648 // caution: precision loss in double cast 649 if ( nTempValue > mnMax ) 650 nTempValue = (double)mnMax; 651 else if ( nTempValue < mnMin ) 652 nTempValue = (double)mnMin; 653 return (sal_Int64)nTempValue; 654 } 655 else 656 return mnLastValue; 657 } 658 659 // ----------------------------------------------------------------------- 660 661 sal_Bool NumericFormatter::IsValueModified() const 662 { 663 if ( ImplGetEmptyFieldValue() ) 664 return !IsEmptyFieldValue(); 665 else if ( GetValue() != mnFieldValue ) 666 return sal_True; 667 else 668 return sal_False; 669 } 670 671 // ----------------------------------------------------------------------- 672 673 Fraction NumericFormatter::ConvertToFraction( sal_Int64 nValue ) 674 { 675 // caution: precision loss in double cast (and in fraction anyhow) 676 return Fraction( (double)nValue/(double)ImplPower10( GetDecimalDigits() ) ); 677 } 678 679 // ----------------------------------------------------------------------- 680 681 sal_Int64 NumericFormatter::ConvertToLong( const Fraction& rValue ) 682 { 683 Fraction aFract = rValue; 684 aFract *= Fraction( (long)ImplPower10( GetDecimalDigits() ), 1 ); 685 return (sal_Int64)(double)aFract; 686 } 687 688 // ----------------------------------------------------------------------- 689 690 sal_Int64 NumericFormatter::Normalize( sal_Int64 nValue ) const 691 { 692 return (nValue * ImplPower10( GetDecimalDigits() ) ); 693 } 694 695 // ----------------------------------------------------------------------- 696 697 sal_Int64 NumericFormatter::Denormalize( sal_Int64 nValue ) const 698 { 699 sal_Int64 nFactor = ImplPower10( GetDecimalDigits() ); 700 701 if((nValue < ( SAL_MIN_INT64 + nFactor )) || 702 (nValue > ( SAL_MAX_INT64 - nFactor ))) 703 return ( nValue / nFactor ); 704 if( nValue < 0 ) 705 return ((nValue-(nFactor/2)) / nFactor ); 706 else 707 return ((nValue+(nFactor/2)) / nFactor ); 708 } 709 710 // ----------------------------------------------------------------------- 711 712 void NumericFormatter::Reformat() 713 { 714 if ( !GetField() ) 715 return; 716 717 if ( !GetField()->GetText().Len() && ImplGetEmptyFieldValue() ) 718 return; 719 720 XubString aStr; 721 // caution: precision loss in double cast 722 double nTemp = (double)mnLastValue; 723 sal_Bool bOK = ImplNumericReformat( GetField()->GetText(), nTemp, aStr ); 724 mnLastValue = (sal_Int64)nTemp; 725 if ( !bOK ) 726 return; 727 728 if ( aStr.Len() ) 729 ImplSetText( aStr ); 730 else 731 SetValue( mnLastValue ); 732 } 733 734 // ----------------------------------------------------------------------- 735 736 void NumericFormatter::FieldUp() 737 { 738 sal_Int64 nValue = GetValue(); 739 nValue += mnSpinSize; 740 if ( nValue > mnMax ) 741 nValue = mnMax; 742 743 ImplNewFieldValue( nValue ); 744 } 745 746 // ----------------------------------------------------------------------- 747 748 void NumericFormatter::FieldDown() 749 { 750 sal_Int64 nValue = GetValue(); 751 nValue -= mnSpinSize; 752 if ( nValue < mnMin ) 753 nValue = mnMin; 754 755 ImplNewFieldValue( nValue ); 756 } 757 758 // ----------------------------------------------------------------------- 759 760 void NumericFormatter::FieldFirst() 761 { 762 ImplNewFieldValue( mnFirst ); 763 } 764 765 // ----------------------------------------------------------------------- 766 767 void NumericFormatter::FieldLast() 768 { 769 ImplNewFieldValue( mnLast ); 770 } 771 772 // ----------------------------------------------------------------------- 773 774 void NumericFormatter::ImplNewFieldValue( sal_Int64 nNewValue ) 775 { 776 if ( GetField() ) 777 { 778 // !!! TH-18.2.99: Wenn wir Zeit haben sollte mal geklaert werden, 779 // !!! warum nicht bei ImplSetUserValue() geprueft wird, ob 780 // !!! sich der Wert aendert. Denn auch hier muesste dieses 781 // !!! gemacht werden, da ansonsten der Modify-Aufruf 782 // !!! nicht gemacht werden duerfte. Jedenfalls sollten die 783 // !!! Wege von ImplNewFieldValue, ImplSetUserValue und 784 // !!! ImplSetText ueberprueft und klarer gestalltet (mit Kommentar) 785 // !!! werden, damit wir mal wissen, was dort ablaeuft!!! 786 787 Selection aSelection = GetField()->GetSelection(); 788 aSelection.Justify(); 789 XubString aText = GetField()->GetText(); 790 // Wenn bis ans Ende selektiert war, soll das auch so bleiben... 791 if ( (xub_StrLen)aSelection.Max() == aText.Len() ) 792 { 793 if ( !aSelection.Len() ) 794 aSelection.Min() = SELECTION_MAX; 795 aSelection.Max() = SELECTION_MAX; 796 } 797 798 sal_Int64 nOldLastValue = mnLastValue; 799 ImplSetUserValue( nNewValue, &aSelection ); 800 mnLastValue = nOldLastValue; 801 802 // Modify am Edit wird nur bei KeyInput gesetzt... 803 if ( GetField()->GetText() != aText ) 804 { 805 GetField()->SetModifyFlag(); 806 GetField()->Modify(); 807 } 808 } 809 } 810 811 // ----------------------------------------------------------------------- 812 813 NumericField::NumericField( Window* pParent, WinBits nWinStyle ) : 814 SpinField( pParent, nWinStyle ) 815 { 816 SetField( this ); 817 Reformat(); 818 } 819 820 // ----------------------------------------------------------------------- 821 822 NumericField::NumericField( Window* pParent, const ResId& rResId ) : 823 SpinField( WINDOW_NUMERICFIELD ) 824 { 825 rResId.SetRT( RSC_NUMERICFIELD ); 826 WinBits nStyle = ImplInitRes( rResId ) ; 827 SpinField::ImplInit( pParent, nStyle ); 828 SetField( this ); 829 ImplLoadRes( rResId ); 830 Reformat(); 831 832 if ( !(nStyle & WB_HIDE ) ) 833 Show(); 834 } 835 836 // ----------------------------------------------------------------------- 837 838 void NumericField::ImplLoadRes( const ResId& rResId ) 839 { 840 SpinField::ImplLoadRes( rResId ); 841 NumericFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) ); 842 843 sal_uLong nMask = ReadLongRes(); 844 845 if ( NUMERICFIELD_FIRST & nMask ) 846 mnFirst = ReadLongRes(); 847 848 if ( NUMERICFIELD_LAST & nMask ) 849 mnLast = ReadLongRes(); 850 851 if ( NUMERICFIELD_SPINSIZE & nMask ) 852 mnSpinSize = ReadLongRes(); 853 } 854 855 // ----------------------------------------------------------------------- 856 857 NumericField::~NumericField() 858 { 859 } 860 861 // ----------------------------------------------------------------------- 862 863 long NumericField::PreNotify( NotifyEvent& rNEvt ) 864 { 865 if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() ) 866 { 867 if ( ImplNumericProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) ) 868 return 1; 869 } 870 871 return SpinField::PreNotify( rNEvt ); 872 } 873 874 // ----------------------------------------------------------------------- 875 876 long NumericField::Notify( NotifyEvent& rNEvt ) 877 { 878 if ( rNEvt.GetType() == EVENT_GETFOCUS ) 879 MarkToBeReformatted( sal_False ); 880 else if ( rNEvt.GetType() == EVENT_LOSEFOCUS ) 881 { 882 if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) ) 883 Reformat(); 884 } 885 886 return SpinField::Notify( rNEvt ); 887 } 888 889 // ----------------------------------------------------------------------- 890 891 void NumericField::DataChanged( const DataChangedEvent& rDCEvt ) 892 { 893 SpinField::DataChanged( rDCEvt ); 894 895 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) ) 896 { 897 String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep(); 898 String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep(); 899 if ( IsDefaultLocale() ) 900 ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() ); 901 String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep(); 902 String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep(); 903 ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this ); 904 ReformatAll(); 905 } 906 } 907 908 // ----------------------------------------------------------------------- 909 910 void NumericField::Modify() 911 { 912 MarkToBeReformatted( sal_True ); 913 SpinField::Modify(); 914 } 915 916 // ----------------------------------------------------------------------- 917 918 void NumericField::Up() 919 { 920 FieldUp(); 921 SpinField::Up(); 922 } 923 924 // ----------------------------------------------------------------------- 925 926 void NumericField::Down() 927 { 928 FieldDown(); 929 SpinField::Down(); 930 } 931 932 // ----------------------------------------------------------------------- 933 934 void NumericField::First() 935 { 936 FieldFirst(); 937 SpinField::First(); 938 } 939 940 // ----------------------------------------------------------------------- 941 942 void NumericField::Last() 943 { 944 FieldLast(); 945 SpinField::Last(); 946 } 947 948 // ----------------------------------------------------------------------- 949 950 NumericBox::NumericBox( Window* pParent, WinBits nWinStyle ) : 951 ComboBox( pParent, nWinStyle ) 952 { 953 SetField( this ); 954 Reformat(); 955 } 956 957 // ----------------------------------------------------------------------- 958 959 NumericBox::NumericBox( Window* pParent, const ResId& rResId ) : 960 ComboBox( WINDOW_NUMERICBOX ) 961 { 962 rResId.SetRT( RSC_NUMERICBOX ); 963 WinBits nStyle = ImplInitRes( rResId ); 964 ComboBox::ImplInit( pParent, nStyle ); 965 SetField( this ); 966 ComboBox::ImplLoadRes( rResId ); 967 NumericFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) ); 968 Reformat(); 969 970 if ( !(nStyle & WB_HIDE ) ) 971 Show(); 972 } 973 974 // ----------------------------------------------------------------------- 975 976 NumericBox::~NumericBox() 977 { 978 } 979 980 // ----------------------------------------------------------------------- 981 982 long NumericBox::PreNotify( NotifyEvent& rNEvt ) 983 { 984 if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() ) 985 { 986 if ( ImplNumericProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) ) 987 return 1; 988 } 989 990 return ComboBox::PreNotify( rNEvt ); 991 } 992 993 // ----------------------------------------------------------------------- 994 995 long NumericBox::Notify( NotifyEvent& rNEvt ) 996 { 997 if ( rNEvt.GetType() == EVENT_GETFOCUS ) 998 MarkToBeReformatted( sal_False ); 999 else if ( rNEvt.GetType() == EVENT_LOSEFOCUS ) 1000 { 1001 if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) ) 1002 Reformat(); 1003 } 1004 1005 return ComboBox::Notify( rNEvt ); 1006 } 1007 1008 // ----------------------------------------------------------------------- 1009 1010 void NumericBox::DataChanged( const DataChangedEvent& rDCEvt ) 1011 { 1012 ComboBox::DataChanged( rDCEvt ); 1013 1014 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) ) 1015 { 1016 String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep(); 1017 String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep(); 1018 if ( IsDefaultLocale() ) 1019 ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() ); 1020 String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep(); 1021 String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep(); 1022 ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this ); 1023 ReformatAll(); 1024 } 1025 } 1026 1027 // ----------------------------------------------------------------------- 1028 1029 void NumericBox::Modify() 1030 { 1031 MarkToBeReformatted( sal_True ); 1032 ComboBox::Modify(); 1033 } 1034 1035 // ----------------------------------------------------------------------- 1036 1037 void NumericBox::ReformatAll() 1038 { 1039 double nValue; 1040 XubString aStr; 1041 SetUpdateMode( sal_False ); 1042 sal_uInt16 nEntryCount = GetEntryCount(); 1043 for ( sal_uInt16 i=0; i < nEntryCount; i++ ) 1044 { 1045 ImplNumericReformat( GetEntry( i ), nValue, aStr ); 1046 RemoveEntry( i ); 1047 InsertEntry( aStr, i ); 1048 } 1049 NumericFormatter::Reformat(); 1050 SetUpdateMode( sal_True ); 1051 } 1052 1053 // ----------------------------------------------------------------------- 1054 1055 void NumericBox::InsertValue( sal_Int64 nValue, sal_uInt16 nPos ) 1056 { 1057 ComboBox::InsertEntry( CreateFieldText( nValue ), nPos ); 1058 } 1059 1060 // ----------------------------------------------------------------------- 1061 1062 void NumericBox::RemoveValue( sal_Int64 nValue ) 1063 { 1064 ComboBox::RemoveEntry( CreateFieldText( nValue ) ); 1065 } 1066 1067 // ----------------------------------------------------------------------- 1068 1069 sal_Int64 NumericBox::GetValue( sal_uInt16 nPos ) const 1070 { 1071 double nValue = 0; 1072 ImplNumericGetValue( ComboBox::GetEntry( nPos ), nValue, GetDecimalDigits(), ImplGetLocaleDataWrapper() ); 1073 return (sal_Int64)nValue; 1074 } 1075 1076 // ----------------------------------------------------------------------- 1077 1078 sal_uInt16 NumericBox::GetValuePos( sal_Int64 nValue ) const 1079 { 1080 return ComboBox::GetEntryPos( CreateFieldText( nValue ) ); 1081 } 1082 1083 // ----------------------------------------------------------------------- 1084 1085 static sal_Bool ImplMetricProcessKeyInput( Edit* pEdit, const KeyEvent& rKEvt, 1086 sal_Bool, sal_Bool bUseThousandSep, const LocaleDataWrapper& rWrapper ) 1087 { 1088 // Es gibt hier kein sinnvolles StrictFormat, also alle 1089 // Zeichen erlauben 1090 return ImplNumericProcessKeyInput( pEdit, rKEvt, sal_False, bUseThousandSep, rWrapper ); 1091 } 1092 1093 // ----------------------------------------------------------------------- 1094 1095 static XubString ImplMetricGetUnitText( const XubString& rStr ) 1096 { 1097 // Einheitentext holen 1098 XubString aStr; 1099 for ( short i = rStr.Len()-1; i >= 0; i-- ) 1100 { 1101 xub_Unicode c = rStr.GetChar( i ); 1102 if ( unicode::isAlpha( c ) || 1103 (c == '\'') || (c == '\"') || (c == '%' ) ) 1104 aStr.Insert( c, 0 ); 1105 else 1106 { 1107 if ( aStr.Len() ) 1108 break; 1109 } 1110 } 1111 return aStr; 1112 1113 /* 1114 // MT: #90545# Preparation for translated strings... 1115 String aMetricText; 1116 for ( sal_uInt16 n = rStr.Len(); n; ) 1117 { 1118 sal_Unicode c = rStr.GetChar( --n ); 1119 sal_Int32 nType = xCharClass->getStringType( rStr, n, 1, rLocale ); 1120 1121 if ( CharClass::isLetterType( nType ) ) 1122 { 1123 aMetricText.Insert( c, 0 ); 1124 } 1125 else 1126 { 1127 if ( aMetricText.Len() ) 1128 break; 1129 } 1130 } 1131 */ 1132 } 1133 1134 // ----------------------------------------------------------------------- 1135 1136 // #104355# support localized mesaurements 1137 1138 static const String& ImplMetricToString( FieldUnit rUnit ) 1139 { 1140 FieldUnitStringList* pList = ImplGetFieldUnits(); 1141 if( pList ) 1142 { 1143 // return unit's default string (ie, the first one ) 1144 for( FieldUnitStringList::const_iterator it = pList->begin(); it != pList->end(); ++it ) 1145 { 1146 if ( it->second == rUnit ) 1147 return it->first; 1148 } 1149 } 1150 1151 return String::EmptyString(); 1152 } 1153 1154 static FieldUnit ImplStringToMetric( const String &rMetricString ) 1155 { 1156 FieldUnitStringList* pList = ImplGetCleanedFieldUnits(); 1157 if( pList ) 1158 { 1159 // return FieldUnit 1160 String aStr( rMetricString ); 1161 aStr.ToLowerAscii(); 1162 aStr.EraseAllChars( sal_Unicode( ' ' ) ); 1163 for( FieldUnitStringList::const_iterator it = pList->begin(); it != pList->end(); ++it ) 1164 { 1165 if ( it->first.Equals( aStr ) ) 1166 return it->second; 1167 } 1168 } 1169 1170 return FUNIT_NONE; 1171 } 1172 1173 // ----------------------------------------------------------------------- 1174 1175 static FieldUnit ImplMetricGetUnit( const XubString& rStr ) 1176 { 1177 XubString aStr = ImplMetricGetUnitText( rStr ); 1178 return ImplStringToMetric( aStr ); 1179 } 1180 1181 #define K *1000L 1182 #define M *1000000L 1183 #define X *5280L 1184 1185 static const sal_Int64 aImplFactor[FUNIT_MILE+1][FUNIT_MILE+1] = 1186 { /* 1187 mm/100 mm cm m km twip point pica inch foot mile */ 1188 { 1, 100, 1 K, 100 K, 100 M, 2540, 2540, 2540, 2540,2540*12,2540*12 X }, 1189 { 1, 1, 10, 1 K, 1 M, 2540, 2540, 2540, 2540,2540*12,2540*12 X }, 1190 { 1, 1, 1, 100, 100 K, 254, 254, 254, 254, 254*12, 254*12 X }, 1191 { 1, 1, 1, 1, 1 K, 254, 254, 254, 254, 254*12, 254*12 X }, 1192 { 1, 1, 1, 1, 1, 0, 254, 254, 254, 254*12, 254*12 X }, 1193 { 1440,144 K,144 K,14400 K, 0, 1, 20, 240, 1440,1440*12,1440*12 X }, 1194 { 72, 7200, 7200, 720 K, 720 M, 1, 1, 12, 72, 72*12, 72*12 X }, 1195 { 6, 600, 600, 60 K, 60 M, 1, 1, 1, 6, 6*12, 6*12 X }, 1196 { 1, 100, 100, 10 K, 10 M, 1, 1, 1, 1, 12, 12 X }, 1197 { 1, 100, 100, 10 K, 10 M, 1, 1, 1, 1, 1, 1 X }, 1198 { 1, 100, 100, 10 K, 10 M, 1, 1, 1, 1, 1, 1 } 1199 }; 1200 1201 #undef X 1202 #undef M 1203 #undef K 1204 // twip in km 254/14400 M 1205 1206 static FieldUnit eDefaultUnit = FUNIT_NONE; 1207 1208 FieldUnit MetricField::GetDefaultUnit() { return eDefaultUnit; } 1209 void MetricField::SetDefaultUnit( FieldUnit meUnit ) { eDefaultUnit = meUnit; } 1210 1211 static FieldUnit ImplMap2FieldUnit( MapUnit meUnit, long& nDecDigits ) 1212 { 1213 switch( meUnit ) 1214 { 1215 case MAP_100TH_MM : 1216 nDecDigits -= 2; 1217 return FUNIT_MM; 1218 case MAP_10TH_MM : 1219 nDecDigits -= 1; 1220 return FUNIT_MM; 1221 case MAP_MM : 1222 return FUNIT_MM; 1223 case MAP_CM : 1224 return FUNIT_CM; 1225 case MAP_1000TH_INCH : 1226 nDecDigits -= 3; 1227 return FUNIT_INCH; 1228 case MAP_100TH_INCH : 1229 nDecDigits -= 2; 1230 return FUNIT_INCH; 1231 case MAP_10TH_INCH : 1232 nDecDigits -= 1; 1233 return FUNIT_INCH; 1234 case MAP_INCH : 1235 return FUNIT_INCH; 1236 case MAP_POINT : 1237 return FUNIT_POINT; 1238 case MAP_TWIP : 1239 return FUNIT_TWIP; 1240 default: 1241 DBG_ERROR( "default eInUnit" ); 1242 break; 1243 } 1244 return FUNIT_NONE; 1245 } 1246 1247 // ----------------------------------------------------------------------- 1248 1249 static double nonValueDoubleToValueDouble( double nValue ) 1250 { 1251 return rtl::math::isFinite( nValue ) ? nValue : 0.0; 1252 } 1253 1254 sal_Int64 MetricField::ConvertValue( sal_Int64 nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits, 1255 FieldUnit eInUnit, FieldUnit eOutUnit ) 1256 { 1257 double nDouble = nonValueDoubleToValueDouble( ConvertDoubleValue( 1258 (double)nValue, mnBaseValue, nDecDigits, eInUnit, eOutUnit ) ); 1259 sal_Int64 nLong ; 1260 1261 // caution: precision loss in double cast 1262 if ( nDouble <= (double)SAL_MIN_INT64 ) 1263 nLong = SAL_MIN_INT64; 1264 else if ( nDouble >= (double)SAL_MAX_INT64 ) 1265 nLong = SAL_MAX_INT64; 1266 else 1267 nLong = static_cast<sal_Int64>( nDouble ); 1268 return ( nLong ); 1269 } 1270 1271 // ----------------------------------------------------------------------- 1272 1273 sal_Int64 MetricField::ConvertValue( sal_Int64 nValue, sal_uInt16 nDigits, 1274 MapUnit eInUnit, FieldUnit eOutUnit ) 1275 { 1276 return static_cast<sal_Int64>( 1277 nonValueDoubleToValueDouble( 1278 ConvertDoubleValue( nValue, nDigits, eInUnit, eOutUnit ) ) ); 1279 } 1280 1281 // ----------------------------------------------------------------------- 1282 1283 sal_Int64 MetricField::ConvertValue( sal_Int64 nValue, sal_uInt16 nDigits, 1284 FieldUnit eInUnit, MapUnit eOutUnit ) 1285 { 1286 return static_cast<sal_Int64>( 1287 // #150733# cast double to sal_Int64 can throw a 1288 // EXCEPTION_FLT_INVALID_OPERATION on Windows 1289 nonValueDoubleToValueDouble( 1290 ConvertDoubleValue( nValue, nDigits, eInUnit, eOutUnit ) ) ); 1291 } 1292 1293 // ----------------------------------------------------------------------- 1294 1295 double MetricField::ConvertDoubleValue( double nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits, 1296 FieldUnit eInUnit, FieldUnit eOutUnit ) 1297 { 1298 if ( eInUnit != eOutUnit ) 1299 { 1300 sal_Int64 nMult = 1, nDiv = 1; 1301 1302 if ( eInUnit == FUNIT_PERCENT ) 1303 { 1304 if ( (mnBaseValue <= 0) || (nValue <= 0) ) 1305 return nValue; 1306 nDiv = 100; 1307 for ( sal_uInt16 i=0; i < nDecDigits; i++ ) 1308 nDiv *= 10; 1309 1310 nMult = mnBaseValue; 1311 } 1312 else if ( eOutUnit == FUNIT_PERCENT || 1313 eOutUnit == FUNIT_CUSTOM || 1314 eOutUnit == FUNIT_NONE || 1315 eInUnit == FUNIT_CUSTOM || 1316 eInUnit == FUNIT_NONE ) 1317 return nValue; 1318 else 1319 { 1320 if ( eOutUnit == FUNIT_100TH_MM ) 1321 eOutUnit = FUNIT_NONE; 1322 if ( eInUnit == FUNIT_100TH_MM ) 1323 eInUnit = FUNIT_NONE; 1324 1325 nDiv = aImplFactor[eInUnit][eOutUnit]; 1326 nMult = aImplFactor[eOutUnit][eInUnit]; 1327 1328 DBG_ASSERT( nMult > 0, "illegal *" ); 1329 DBG_ASSERT( nDiv > 0, "illegal /" ); 1330 } 1331 1332 if ( nMult != 1 && nMult > 0 ) 1333 nValue *= nMult; 1334 if ( nDiv != 1 && nDiv > 0 ) 1335 { 1336 nValue += ( nValue < 0 ) ? (-nDiv/2) : (nDiv/2); 1337 nValue /= nDiv; 1338 } 1339 } 1340 1341 return nValue; 1342 } 1343 1344 // ----------------------------------------------------------------------- 1345 1346 double MetricField::ConvertDoubleValue( double nValue, sal_uInt16 nDigits, 1347 MapUnit eInUnit, FieldUnit eOutUnit ) 1348 { 1349 if ( eOutUnit == FUNIT_PERCENT || 1350 eOutUnit == FUNIT_CUSTOM || 1351 eOutUnit == FUNIT_NONE || 1352 eInUnit == MAP_PIXEL || 1353 eInUnit == MAP_SYSFONT || 1354 eInUnit == MAP_APPFONT || 1355 eInUnit == MAP_RELATIVE ) 1356 { 1357 DBG_ERROR( "invalid parameters" ); 1358 return nValue; 1359 } 1360 1361 long nDecDigits = nDigits; 1362 FieldUnit eFieldUnit = ImplMap2FieldUnit( eInUnit, nDecDigits ); 1363 1364 if ( nDecDigits < 0 ) 1365 { 1366 while ( nDecDigits ) 1367 { 1368 nValue += 5; 1369 nValue /= 10; 1370 nDecDigits++; 1371 } 1372 } 1373 else 1374 { 1375 while ( nDecDigits ) 1376 { 1377 nValue *= 10; 1378 nDecDigits--; 1379 } 1380 } 1381 1382 if ( eFieldUnit != eOutUnit ) 1383 { 1384 sal_Int64 nDiv = aImplFactor[eFieldUnit][eOutUnit]; 1385 sal_Int64 nMult = aImplFactor[eOutUnit][eFieldUnit]; 1386 1387 DBG_ASSERT( nMult > 0, "illegal *" ); 1388 DBG_ASSERT( nDiv > 0, "illegal /" ); 1389 1390 if ( nMult != 1 && nMult > 0) 1391 nValue *= nMult; 1392 if ( nDiv != 1 && nDiv > 0 ) 1393 { 1394 nValue += (nValue < 0) ? (-nDiv/2) : (nDiv/2); 1395 nValue /= nDiv; 1396 } 1397 } 1398 return nValue; 1399 } 1400 1401 // ----------------------------------------------------------------------- 1402 1403 double MetricField::ConvertDoubleValue( double nValue, sal_uInt16 nDigits, 1404 FieldUnit eInUnit, MapUnit eOutUnit ) 1405 { 1406 if ( eInUnit == FUNIT_PERCENT || 1407 eInUnit == FUNIT_CUSTOM || 1408 eInUnit == FUNIT_NONE || 1409 eOutUnit == MAP_PIXEL || 1410 eOutUnit == MAP_SYSFONT || 1411 eOutUnit == MAP_APPFONT || 1412 eOutUnit == MAP_RELATIVE ) 1413 { 1414 DBG_ERROR( "invalid parameters" ); 1415 return nValue; 1416 } 1417 1418 long nDecDigits = nDigits; 1419 FieldUnit eFieldUnit = ImplMap2FieldUnit( eOutUnit, nDecDigits ); 1420 1421 if ( nDecDigits < 0 ) 1422 { 1423 while ( nDecDigits ) 1424 { 1425 nValue *= 10; 1426 nDecDigits++; 1427 } 1428 } 1429 else 1430 { 1431 while ( nDecDigits ) 1432 { 1433 nValue += 5; 1434 nValue /= 10; 1435 nDecDigits--; 1436 } 1437 } 1438 1439 if ( eFieldUnit != eInUnit ) 1440 { 1441 sal_Int64 nDiv = aImplFactor[eInUnit][eFieldUnit]; 1442 sal_Int64 nMult = aImplFactor[eFieldUnit][eInUnit]; 1443 1444 DBG_ASSERT( nMult > 0, "illegal *" ); 1445 DBG_ASSERT( nDiv > 0, "illegal /" ); 1446 1447 if( nMult != 1 && nMult > 0 ) 1448 nValue *= nMult; 1449 if( nDiv != 1 && nDiv > 0 ) 1450 { 1451 nValue += (nValue < 0) ? (-nDiv/2) : (nDiv/2); 1452 nValue /= nDiv; 1453 } 1454 } 1455 return nValue; 1456 } 1457 1458 // ----------------------------------------------------------------------- 1459 1460 static sal_Bool ImplMetricGetValue( const XubString& rStr, double& rValue, sal_Int64 nBaseValue, 1461 sal_uInt16 nDecDigits, const LocaleDataWrapper& rLocaleDataWrapper, FieldUnit eUnit ) 1462 { 1463 // Zahlenwert holen 1464 if ( !ImplNumericGetValue( rStr, rValue, nDecDigits, rLocaleDataWrapper ) ) 1465 return sal_False; 1466 1467 // Einheit rausfinden 1468 FieldUnit eEntryUnit = ImplMetricGetUnit( rStr ); 1469 1470 // Einheiten umrechnen 1471 rValue = MetricField::ConvertDoubleValue( rValue, nBaseValue, nDecDigits, eEntryUnit, eUnit ); 1472 1473 return sal_True; 1474 } 1475 1476 // ----------------------------------------------------------------------- 1477 1478 sal_Bool MetricFormatter::ImplMetricReformat( const XubString& rStr, double& rValue, XubString& rOutStr ) 1479 { 1480 if ( !ImplMetricGetValue( rStr, rValue, mnBaseValue, GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit ) ) 1481 return sal_True; 1482 else 1483 { 1484 double nTempVal = rValue; 1485 // caution: precision loss in double cast 1486 if ( nTempVal > GetMax() ) 1487 nTempVal = (double)GetMax(); 1488 else if ( nTempVal < GetMin()) 1489 nTempVal = (double)GetMin(); 1490 1491 if ( GetErrorHdl().IsSet() && (rValue != nTempVal) ) 1492 { 1493 mnCorrectedValue = (sal_Int64)nTempVal; 1494 if ( !GetErrorHdl().Call( this ) ) 1495 { 1496 mnCorrectedValue = 0; 1497 return sal_False; 1498 } 1499 else 1500 mnCorrectedValue = 0; 1501 } 1502 1503 rOutStr = CreateFieldText( (sal_Int64)nTempVal ); 1504 return sal_True; 1505 } 1506 } 1507 1508 // ----------------------------------------------------------------------- 1509 1510 inline void MetricFormatter::ImplInit() 1511 { 1512 mnBaseValue = 0; 1513 meUnit = MetricField::GetDefaultUnit(); 1514 mnType = FORMAT_METRIC; 1515 } 1516 1517 // ----------------------------------------------------------------------- 1518 1519 MetricFormatter::MetricFormatter() 1520 { 1521 ImplInit(); 1522 } 1523 1524 // ----------------------------------------------------------------------- 1525 1526 void MetricFormatter::ImplLoadRes( const ResId& rResId ) 1527 { 1528 NumericFormatter::ImplLoadRes( rResId ); 1529 1530 ResMgr* pMgr = rResId.GetResMgr(); 1531 if( pMgr ) 1532 { 1533 sal_uLong nMask = pMgr->ReadLong(); 1534 1535 if ( METRICFORMATTER_UNIT & nMask ) 1536 meUnit = (FieldUnit)pMgr->ReadLong(); 1537 1538 if ( METRICFORMATTER_CUSTOMUNITTEXT & nMask ) 1539 maCustomUnitText = pMgr->ReadString(); 1540 } 1541 } 1542 1543 // ----------------------------------------------------------------------- 1544 1545 MetricFormatter::~MetricFormatter() 1546 { 1547 } 1548 1549 // ----------------------------------------------------------------------- 1550 1551 void MetricFormatter::SetUnit( FieldUnit eNewUnit ) 1552 { 1553 if ( eNewUnit == FUNIT_100TH_MM ) 1554 { 1555 SetDecimalDigits( GetDecimalDigits() + 2 ); 1556 meUnit = FUNIT_MM; 1557 } 1558 else 1559 meUnit = eNewUnit; 1560 ReformatAll(); 1561 } 1562 1563 // ----------------------------------------------------------------------- 1564 1565 void MetricFormatter::SetCustomUnitText( const XubString& rStr ) 1566 { 1567 maCustomUnitText = rStr; 1568 ReformatAll(); 1569 } 1570 1571 // ----------------------------------------------------------------------- 1572 1573 void MetricFormatter::SetValue( sal_Int64 nNewValue, FieldUnit eInUnit ) 1574 { 1575 SetUserValue( nNewValue, eInUnit ); 1576 mnFieldValue = mnLastValue; 1577 } 1578 1579 // ----------------------------------------------------------------------- 1580 1581 XubString MetricFormatter::CreateFieldText( sal_Int64 nValue ) const 1582 { 1583 XubString aStr = NumericFormatter::CreateFieldText( nValue ); 1584 1585 if( meUnit == FUNIT_CUSTOM ) 1586 aStr += maCustomUnitText; 1587 else 1588 aStr += ImplMetricToString( meUnit ); 1589 1590 return aStr; 1591 } 1592 1593 // ----------------------------------------------------------------------- 1594 1595 void MetricFormatter::SetUserValue( sal_Int64 nNewValue, FieldUnit eInUnit ) 1596 { 1597 // Umrechnen auf eingestellte Einheiten 1598 nNewValue = MetricField::ConvertValue( nNewValue, mnBaseValue, GetDecimalDigits(), eInUnit, meUnit ); 1599 NumericFormatter::SetUserValue( nNewValue ); 1600 } 1601 1602 // ----------------------------------------------------------------------- 1603 1604 sal_Int64 MetricFormatter::GetValue( FieldUnit eOutUnit ) const 1605 { 1606 if ( !GetField() ) 1607 return 0; 1608 1609 double nTempValue; 1610 // caution: precision loss in double cast 1611 if ( !ImplMetricGetValue( GetField()->GetText(), nTempValue, mnBaseValue, GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit ) ) 1612 nTempValue = (double)mnLastValue; 1613 1614 // caution: precision loss in double cast 1615 if ( nTempValue > mnMax ) 1616 nTempValue = (double)mnMax; 1617 else if ( nTempValue < mnMin ) 1618 nTempValue = (double)mnMin; 1619 1620 // Umrechnen auf gewuenschte Einheiten 1621 return MetricField::ConvertValue( (sal_Int64)nTempValue, mnBaseValue, GetDecimalDigits(), meUnit, eOutUnit ); 1622 } 1623 1624 // ----------------------------------------------------------------------- 1625 1626 void MetricFormatter::SetValue( sal_Int64 nValue ) 1627 { 1628 // Implementation not inline, because it is a virtual Function 1629 SetValue( nValue, FUNIT_NONE ); 1630 } 1631 1632 // ----------------------------------------------------------------------- 1633 1634 sal_Int64 MetricFormatter::GetValue() const 1635 { 1636 // Implementation not inline, because it is a virtual Function 1637 return GetValue( FUNIT_NONE ); 1638 } 1639 1640 // ----------------------------------------------------------------------- 1641 1642 void MetricFormatter::SetMin( sal_Int64 nNewMin, FieldUnit eInUnit ) 1643 { 1644 // Umrechnen auf gewuenschte Einheiten 1645 NumericFormatter::SetMin( MetricField::ConvertValue( nNewMin, mnBaseValue, GetDecimalDigits(), 1646 eInUnit, meUnit ) ); 1647 } 1648 1649 // ----------------------------------------------------------------------- 1650 1651 sal_Int64 MetricFormatter::GetMin( FieldUnit eOutUnit ) const 1652 { 1653 // Umrechnen auf gewuenschte Einheiten 1654 return MetricField::ConvertValue( NumericFormatter::GetMin(), mnBaseValue, 1655 GetDecimalDigits(), meUnit, eOutUnit ); 1656 } 1657 1658 // ----------------------------------------------------------------------- 1659 1660 void MetricFormatter::SetMax( sal_Int64 nNewMax, FieldUnit eInUnit ) 1661 { 1662 // Umrechnen auf gewuenschte Einheiten 1663 NumericFormatter::SetMax( MetricField::ConvertValue( nNewMax, mnBaseValue, GetDecimalDigits(), 1664 eInUnit, meUnit ) ); 1665 } 1666 1667 // ----------------------------------------------------------------------- 1668 1669 sal_Int64 MetricFormatter::GetMax( FieldUnit eOutUnit ) const 1670 { 1671 // Umrechnen auf gewuenschte Einheiten 1672 return MetricField::ConvertValue( NumericFormatter::GetMax(), mnBaseValue, 1673 GetDecimalDigits(), meUnit, eOutUnit ); 1674 } 1675 1676 // ----------------------------------------------------------------------- 1677 1678 void MetricFormatter::SetBaseValue( sal_Int64 nNewBase, FieldUnit eInUnit ) 1679 { 1680 mnBaseValue = MetricField::ConvertValue( nNewBase, mnBaseValue, GetDecimalDigits(), 1681 eInUnit, meUnit ); 1682 } 1683 1684 // ----------------------------------------------------------------------- 1685 1686 sal_Int64 MetricFormatter::GetBaseValue( FieldUnit eOutUnit ) const 1687 { 1688 // Umrechnen auf gewuenschte Einheiten 1689 return MetricField::ConvertValue( mnBaseValue, mnBaseValue, GetDecimalDigits(), 1690 meUnit, eOutUnit ); 1691 } 1692 1693 // ----------------------------------------------------------------------- 1694 1695 void MetricFormatter::Reformat() 1696 { 1697 if ( !GetField() ) 1698 return; 1699 1700 XubString aText = GetField()->GetText(); 1701 if ( meUnit == FUNIT_CUSTOM ) 1702 maCurUnitText = ImplMetricGetUnitText( aText ); 1703 1704 XubString aStr; 1705 // caution: precision loss in double cast 1706 double nTemp = (double)mnLastValue; 1707 sal_Bool bOK = ImplMetricReformat( aText, nTemp, aStr ); 1708 mnLastValue = (sal_Int64)nTemp; 1709 1710 if ( !bOK ) 1711 return; 1712 1713 if ( aStr.Len() ) 1714 { 1715 ImplSetText( aStr ); 1716 if ( meUnit == FUNIT_CUSTOM ) 1717 CustomConvert(); 1718 } 1719 else 1720 SetValue( mnLastValue ); 1721 maCurUnitText.Erase(); 1722 } 1723 1724 // ----------------------------------------------------------------------- 1725 1726 sal_Int64 MetricFormatter::GetCorrectedValue( FieldUnit eOutUnit ) const 1727 { 1728 // Umrechnen auf gewuenschte Einheiten 1729 return MetricField::ConvertValue( mnCorrectedValue, mnBaseValue, GetDecimalDigits(), 1730 meUnit, eOutUnit ); 1731 } 1732 1733 // ----------------------------------------------------------------------- 1734 1735 MetricField::MetricField( Window* pParent, WinBits nWinStyle ) : 1736 SpinField( pParent, nWinStyle ) 1737 { 1738 SetField( this ); 1739 Reformat(); 1740 } 1741 1742 // ----------------------------------------------------------------------- 1743 1744 MetricField::MetricField( Window* pParent, const ResId& rResId ) : 1745 SpinField( WINDOW_METRICFIELD ) 1746 { 1747 rResId.SetRT( RSC_METRICFIELD ); 1748 WinBits nStyle = ImplInitRes( rResId ) ; 1749 SpinField::ImplInit( pParent, nStyle ); 1750 SetField( this ); 1751 ImplLoadRes( rResId ); 1752 1753 if ( !(nStyle & WB_HIDE ) ) 1754 Show(); 1755 } 1756 1757 // ----------------------------------------------------------------------- 1758 1759 void MetricField::ImplLoadRes( const ResId& rResId ) 1760 { 1761 SpinField::ImplLoadRes( rResId ); 1762 MetricFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) ); 1763 1764 sal_uLong nMask = ReadLongRes(); 1765 1766 if ( METRICFIELD_FIRST & nMask ) 1767 mnFirst = ReadLongRes(); 1768 1769 if ( METRICFIELD_LAST & nMask ) 1770 mnLast = ReadLongRes(); 1771 1772 if ( METRICFIELD_SPINSIZE & nMask ) 1773 mnSpinSize = ReadLongRes(); 1774 1775 Reformat(); 1776 } 1777 1778 // ----------------------------------------------------------------------- 1779 1780 MetricField::~MetricField() 1781 { 1782 } 1783 1784 // ----------------------------------------------------------------------- 1785 1786 void MetricField::SetFirst( sal_Int64 nNewFirst, FieldUnit eInUnit ) 1787 { 1788 // convert 1789 nNewFirst = MetricField::ConvertValue( nNewFirst, mnBaseValue, GetDecimalDigits(), 1790 eInUnit, meUnit ); 1791 mnFirst = nNewFirst; 1792 } 1793 1794 // ----------------------------------------------------------------------- 1795 1796 sal_Int64 MetricField::GetFirst( FieldUnit eOutUnit ) const 1797 { 1798 // convert 1799 return MetricField::ConvertValue( mnFirst, mnBaseValue, GetDecimalDigits(), 1800 meUnit, eOutUnit ); 1801 } 1802 1803 // ----------------------------------------------------------------------- 1804 1805 void MetricField::SetLast( sal_Int64 nNewLast, FieldUnit eInUnit ) 1806 { 1807 // Umrechnen 1808 nNewLast = MetricField::ConvertValue( nNewLast, mnBaseValue, GetDecimalDigits(), 1809 eInUnit, meUnit ); 1810 mnLast = nNewLast; 1811 } 1812 1813 // ----------------------------------------------------------------------- 1814 1815 sal_Int64 MetricField::GetLast( FieldUnit eOutUnit ) const 1816 { 1817 // Umrechnen 1818 return MetricField::ConvertValue( mnLast, mnBaseValue, GetDecimalDigits(), 1819 meUnit, eOutUnit ); 1820 } 1821 1822 // ----------------------------------------------------------------------- 1823 1824 long MetricField::PreNotify( NotifyEvent& rNEvt ) 1825 { 1826 if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() ) 1827 { 1828 if ( ImplMetricProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) ) 1829 return 1; 1830 } 1831 1832 return SpinField::PreNotify( rNEvt ); 1833 } 1834 1835 // ----------------------------------------------------------------------- 1836 1837 long MetricField::Notify( NotifyEvent& rNEvt ) 1838 { 1839 if ( rNEvt.GetType() == EVENT_GETFOCUS ) 1840 MarkToBeReformatted( sal_False ); 1841 else if ( rNEvt.GetType() == EVENT_LOSEFOCUS ) 1842 { 1843 if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) ) 1844 Reformat(); 1845 } 1846 1847 return SpinField::Notify( rNEvt ); 1848 } 1849 1850 // ----------------------------------------------------------------------- 1851 1852 void MetricField::DataChanged( const DataChangedEvent& rDCEvt ) 1853 { 1854 SpinField::DataChanged( rDCEvt ); 1855 1856 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) ) 1857 { 1858 String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep(); 1859 String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep(); 1860 if ( IsDefaultLocale() ) 1861 ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() ); 1862 String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep(); 1863 String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep(); 1864 ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this ); 1865 ReformatAll(); 1866 } 1867 } 1868 1869 // ----------------------------------------------------------------------- 1870 1871 void MetricField::Modify() 1872 { 1873 MarkToBeReformatted( sal_True ); 1874 SpinField::Modify(); 1875 } 1876 1877 // ----------------------------------------------------------------------- 1878 1879 void MetricField::Up() 1880 { 1881 FieldUp(); 1882 SpinField::Up(); 1883 } 1884 1885 // ----------------------------------------------------------------------- 1886 1887 void MetricField::Down() 1888 { 1889 FieldDown(); 1890 SpinField::Down(); 1891 } 1892 1893 // ----------------------------------------------------------------------- 1894 1895 void MetricField::First() 1896 { 1897 FieldFirst(); 1898 SpinField::First(); 1899 } 1900 1901 // ----------------------------------------------------------------------- 1902 1903 void MetricField::Last() 1904 { 1905 FieldLast(); 1906 SpinField::Last(); 1907 } 1908 1909 // ----------------------------------------------------------------------- 1910 1911 void MetricField::CustomConvert() 1912 { 1913 maCustomConvertLink.Call( this ); 1914 } 1915 1916 // ----------------------------------------------------------------------- 1917 1918 MetricBox::MetricBox( Window* pParent, WinBits nWinStyle ) : 1919 ComboBox( pParent, nWinStyle ) 1920 { 1921 SetField( this ); 1922 Reformat(); 1923 } 1924 1925 // ----------------------------------------------------------------------- 1926 1927 MetricBox::MetricBox( Window* pParent, const ResId& rResId ) : 1928 ComboBox( WINDOW_METRICBOX ) 1929 { 1930 rResId.SetRT( RSC_METRICBOX ); 1931 WinBits nStyle = ImplInitRes( rResId ); 1932 ComboBox::ImplInit( pParent, nStyle ); 1933 SetField( this ); 1934 Reformat(); 1935 ComboBox::ImplLoadRes( rResId ); 1936 MetricFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) ); 1937 1938 if ( !(nStyle & WB_HIDE ) ) 1939 Show(); 1940 } 1941 1942 // ----------------------------------------------------------------------- 1943 1944 MetricBox::~MetricBox() 1945 { 1946 } 1947 1948 // ----------------------------------------------------------------------- 1949 1950 long MetricBox::PreNotify( NotifyEvent& rNEvt ) 1951 { 1952 if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() ) 1953 { 1954 if ( ImplMetricProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) ) 1955 return 1; 1956 } 1957 1958 return ComboBox::PreNotify( rNEvt ); 1959 } 1960 1961 // ----------------------------------------------------------------------- 1962 1963 long MetricBox::Notify( NotifyEvent& rNEvt ) 1964 { 1965 if ( rNEvt.GetType() == EVENT_GETFOCUS ) 1966 MarkToBeReformatted( sal_False ); 1967 else if ( rNEvt.GetType() == EVENT_LOSEFOCUS ) 1968 { 1969 if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) ) 1970 Reformat(); 1971 } 1972 1973 return ComboBox::Notify( rNEvt ); 1974 } 1975 1976 // ----------------------------------------------------------------------- 1977 1978 void MetricBox::DataChanged( const DataChangedEvent& rDCEvt ) 1979 { 1980 ComboBox::DataChanged( rDCEvt ); 1981 1982 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) ) 1983 { 1984 String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep(); 1985 String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep(); 1986 if ( IsDefaultLocale() ) 1987 ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() ); 1988 String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep(); 1989 String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep(); 1990 ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this ); 1991 ReformatAll(); 1992 } 1993 } 1994 1995 // ----------------------------------------------------------------------- 1996 1997 void MetricBox::Modify() 1998 { 1999 MarkToBeReformatted( sal_True ); 2000 ComboBox::Modify(); 2001 } 2002 2003 // ----------------------------------------------------------------------- 2004 2005 void MetricBox::ReformatAll() 2006 { 2007 double nValue; 2008 XubString aStr; 2009 SetUpdateMode( sal_False ); 2010 sal_uInt16 nEntryCount = GetEntryCount(); 2011 for ( sal_uInt16 i=0; i < nEntryCount; i++ ) 2012 { 2013 ImplMetricReformat( GetEntry( i ), nValue, aStr ); 2014 RemoveEntry( i ); 2015 InsertEntry( aStr, i ); 2016 } 2017 MetricFormatter::Reformat(); 2018 SetUpdateMode( sal_True ); 2019 } 2020 2021 // ----------------------------------------------------------------------- 2022 2023 void MetricBox::CustomConvert() 2024 { 2025 maCustomConvertLink.Call( this ); 2026 } 2027 2028 // ----------------------------------------------------------------------- 2029 2030 void MetricBox::InsertValue( sal_Int64 nValue, FieldUnit eInUnit, sal_uInt16 nPos ) 2031 { 2032 // Umrechnen auf eingestellte Einheiten 2033 nValue = MetricField::ConvertValue( nValue, mnBaseValue, GetDecimalDigits(), 2034 eInUnit, meUnit ); 2035 ComboBox::InsertEntry( CreateFieldText( nValue ), nPos ); 2036 } 2037 2038 // ----------------------------------------------------------------------- 2039 2040 void MetricBox::RemoveValue( sal_Int64 nValue, FieldUnit eInUnit ) 2041 { 2042 // Umrechnen auf eingestellte Einheiten 2043 nValue = MetricField::ConvertValue( nValue, mnBaseValue, GetDecimalDigits(), 2044 eInUnit, meUnit ); 2045 ComboBox::RemoveEntry( CreateFieldText( nValue ) ); 2046 } 2047 2048 // ----------------------------------------------------------------------- 2049 2050 sal_Int64 MetricBox::GetValue( sal_uInt16 nPos, FieldUnit eOutUnit ) const 2051 { 2052 double nValue = 0; 2053 ImplMetricGetValue( ComboBox::GetEntry( nPos ), nValue, mnBaseValue, 2054 GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit ); 2055 2056 // Umrechnen auf eingestellte Einheiten 2057 sal_Int64 nRetValue = MetricField::ConvertValue( (sal_Int64)nValue, mnBaseValue, GetDecimalDigits(), 2058 meUnit, eOutUnit ); 2059 2060 return nRetValue; 2061 } 2062 2063 // ----------------------------------------------------------------------- 2064 2065 sal_uInt16 MetricBox::GetValuePos( sal_Int64 nValue, FieldUnit eInUnit ) const 2066 { 2067 // Umrechnen auf eingestellte Einheiten 2068 nValue = MetricField::ConvertValue( nValue, mnBaseValue, GetDecimalDigits(), 2069 eInUnit, meUnit ); 2070 return ComboBox::GetEntryPos( CreateFieldText( nValue ) ); 2071 } 2072 2073 // ----------------------------------------------------------------------- 2074 2075 sal_Int64 MetricBox::GetValue( FieldUnit eOutUnit ) const 2076 { 2077 // Implementation not inline, because it is a virtual Function 2078 return MetricFormatter::GetValue( eOutUnit ); 2079 } 2080 2081 // ----------------------------------------------------------------------- 2082 2083 sal_Int64 MetricBox::GetValue() const 2084 { 2085 // Implementation not inline, because it is a virtual Function 2086 return GetValue( FUNIT_NONE ); 2087 } 2088 2089 // ----------------------------------------------------------------------- 2090 2091 static sal_Bool ImplCurrencyProcessKeyInput( Edit* pEdit, const KeyEvent& rKEvt, 2092 sal_Bool, sal_Bool bUseThousandSep, const LocaleDataWrapper& rWrapper ) 2093 { 2094 // Es gibt hier kein sinnvolles StrictFormat, also alle 2095 // Zeichen erlauben 2096 return ImplNumericProcessKeyInput( pEdit, rKEvt, sal_False, bUseThousandSep, rWrapper ); 2097 } 2098 2099 // ----------------------------------------------------------------------- 2100 2101 inline sal_Bool ImplCurrencyGetValue( const XubString& rStr, double& rValue, 2102 sal_uInt16 nDecDigits, const LocaleDataWrapper& rWrapper ) 2103 { 2104 // Zahlenwert holen 2105 return ImplNumericGetValue( rStr, rValue, nDecDigits, rWrapper, sal_True ); 2106 } 2107 2108 // ----------------------------------------------------------------------- 2109 2110 sal_Bool CurrencyFormatter::ImplCurrencyReformat( const XubString& rStr, 2111 XubString& rOutStr ) 2112 { 2113 double nValue; 2114 if ( !ImplNumericGetValue( rStr, nValue, GetDecimalDigits(), ImplGetLocaleDataWrapper(), sal_True ) ) 2115 return sal_True; 2116 else 2117 { 2118 double nTempVal = nValue; 2119 // caution: precision loss in double cast 2120 if ( nTempVal > GetMax() ) 2121 nTempVal = (double)GetMax(); 2122 else if ( nTempVal < GetMin()) 2123 nTempVal = (double)GetMin(); 2124 2125 if ( GetErrorHdl().IsSet() && (nValue != nTempVal) ) 2126 { 2127 mnCorrectedValue = (sal_Int64)nTempVal; 2128 if ( !GetErrorHdl().Call( this ) ) 2129 { 2130 mnCorrectedValue = 0; 2131 return sal_False; 2132 } 2133 else 2134 mnCorrectedValue = 0; 2135 } 2136 2137 rOutStr = CreateFieldText( (long)nTempVal ); 2138 return sal_True; 2139 } 2140 } 2141 2142 // ----------------------------------------------------------------------- 2143 2144 inline void CurrencyFormatter::ImplInit() 2145 { 2146 mnType = FORMAT_CURRENCY; 2147 } 2148 2149 // ----------------------------------------------------------------------- 2150 2151 CurrencyFormatter::CurrencyFormatter() 2152 { 2153 ImplInit(); 2154 } 2155 2156 // ----------------------------------------------------------------------- 2157 2158 CurrencyFormatter::~CurrencyFormatter() 2159 { 2160 } 2161 2162 // ----------------------------------------------------------------------- 2163 2164 void CurrencyFormatter::SetCurrencySymbol( const String& rStr ) 2165 { 2166 maCurrencySymbol= rStr; 2167 ReformatAll(); 2168 } 2169 2170 // ----------------------------------------------------------------------- 2171 2172 String CurrencyFormatter::GetCurrencySymbol() const 2173 { 2174 return maCurrencySymbol.Len() ? maCurrencySymbol : ImplGetLocaleDataWrapper().getCurrSymbol(); 2175 } 2176 2177 // ----------------------------------------------------------------------- 2178 2179 void CurrencyFormatter::SetValue( sal_Int64 nNewValue ) 2180 { 2181 SetUserValue( nNewValue ); 2182 mnFieldValue = mnLastValue; 2183 SetEmptyFieldValueData( sal_False ); 2184 } 2185 2186 // ----------------------------------------------------------------------- 2187 2188 XubString CurrencyFormatter::CreateFieldText( sal_Int64 nValue ) const 2189 { 2190 return ImplGetLocaleDataWrapper().getCurr( nValue, GetDecimalDigits(), GetCurrencySymbol(), IsUseThousandSep() ); 2191 } 2192 2193 // ----------------------------------------------------------------------- 2194 2195 sal_Int64 CurrencyFormatter::GetValue() const 2196 { 2197 if ( !GetField() ) 2198 return 0; 2199 2200 double nTempValue; 2201 if ( ImplCurrencyGetValue( GetField()->GetText(), nTempValue, GetDecimalDigits(), ImplGetLocaleDataWrapper() ) ) 2202 { 2203 // caution: precision loss in double cast 2204 if ( nTempValue > mnMax ) 2205 nTempValue = (double)mnMax; 2206 else if ( nTempValue < mnMin ) 2207 nTempValue = (double)mnMin; 2208 return (sal_Int64)nTempValue; 2209 } 2210 else 2211 return mnLastValue; 2212 } 2213 2214 // ----------------------------------------------------------------------- 2215 2216 void CurrencyFormatter::Reformat() 2217 { 2218 if ( !GetField() ) 2219 return; 2220 2221 XubString aStr; 2222 sal_Bool bOK = ImplCurrencyReformat( GetField()->GetText(), aStr ); 2223 if ( !bOK ) 2224 return; 2225 2226 if ( aStr.Len() ) 2227 { 2228 ImplSetText( aStr ); 2229 // caution: precision loss in double cast 2230 double nTemp = (double)mnLastValue; 2231 ImplCurrencyGetValue( aStr, nTemp, GetDecimalDigits(), ImplGetLocaleDataWrapper() ); 2232 mnLastValue = (sal_Int64)nTemp; 2233 } 2234 else 2235 SetValue( mnLastValue ); 2236 } 2237 2238 // ----------------------------------------------------------------------- 2239 2240 CurrencyField::CurrencyField( Window* pParent, WinBits nWinStyle ) : 2241 SpinField( pParent, nWinStyle ) 2242 { 2243 SetField( this ); 2244 Reformat(); 2245 } 2246 2247 // ----------------------------------------------------------------------- 2248 2249 CurrencyField::CurrencyField( Window* pParent, const ResId& rResId ) : 2250 SpinField( WINDOW_CURRENCYFIELD ) 2251 { 2252 rResId.SetRT( RSC_CURRENCYFIELD ); 2253 WinBits nStyle = ImplInitRes( rResId ); 2254 SpinField::ImplInit( pParent, nStyle); 2255 SetField( this ); 2256 ImplLoadRes( rResId ); 2257 2258 if ( !(nStyle & WB_HIDE ) ) 2259 Show(); 2260 } 2261 2262 // ----------------------------------------------------------------------- 2263 2264 void CurrencyField::ImplLoadRes( const ResId& rResId ) 2265 { 2266 SpinField::ImplLoadRes( rResId ); 2267 CurrencyFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) ); 2268 2269 sal_uLong nMask = ReadLongRes(); 2270 2271 if ( CURRENCYFIELD_FIRST & nMask ) 2272 mnFirst = ReadLongRes(); 2273 2274 if ( CURRENCYFIELD_LAST & nMask ) 2275 mnLast = ReadLongRes(); 2276 2277 if ( CURRENCYFIELD_SPINSIZE & nMask ) 2278 mnSpinSize = ReadLongRes(); 2279 2280 Reformat(); 2281 } 2282 2283 // ----------------------------------------------------------------------- 2284 2285 CurrencyField::~CurrencyField() 2286 { 2287 } 2288 2289 // ----------------------------------------------------------------------- 2290 2291 long CurrencyField::PreNotify( NotifyEvent& rNEvt ) 2292 { 2293 if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() ) 2294 { 2295 if ( ImplCurrencyProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) ) 2296 return 1; 2297 } 2298 2299 return SpinField::PreNotify( rNEvt ); 2300 } 2301 2302 // ----------------------------------------------------------------------- 2303 2304 long CurrencyField::Notify( NotifyEvent& rNEvt ) 2305 { 2306 if ( rNEvt.GetType() == EVENT_GETFOCUS ) 2307 MarkToBeReformatted( sal_False ); 2308 else if ( rNEvt.GetType() == EVENT_LOSEFOCUS ) 2309 { 2310 if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) ) 2311 Reformat(); 2312 } 2313 2314 return SpinField::Notify( rNEvt ); 2315 } 2316 2317 // ----------------------------------------------------------------------- 2318 2319 void CurrencyField::DataChanged( const DataChangedEvent& rDCEvt ) 2320 { 2321 SpinField::DataChanged( rDCEvt ); 2322 2323 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) ) 2324 { 2325 String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep(); 2326 String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep(); 2327 if ( IsDefaultLocale() ) 2328 ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() ); 2329 String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep(); 2330 String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep(); 2331 ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this ); 2332 ReformatAll(); 2333 } 2334 } 2335 2336 // ----------------------------------------------------------------------- 2337 2338 void CurrencyField::Modify() 2339 { 2340 MarkToBeReformatted( sal_True ); 2341 SpinField::Modify(); 2342 } 2343 2344 // ----------------------------------------------------------------------- 2345 2346 void CurrencyField::Up() 2347 { 2348 FieldUp(); 2349 SpinField::Up(); 2350 } 2351 2352 // ----------------------------------------------------------------------- 2353 2354 void CurrencyField::Down() 2355 { 2356 FieldDown(); 2357 SpinField::Down(); 2358 } 2359 2360 // ----------------------------------------------------------------------- 2361 2362 void CurrencyField::First() 2363 { 2364 FieldFirst(); 2365 SpinField::First(); 2366 } 2367 2368 // ----------------------------------------------------------------------- 2369 2370 void CurrencyField::Last() 2371 { 2372 FieldLast(); 2373 SpinField::Last(); 2374 } 2375 2376 // ----------------------------------------------------------------------- 2377 2378 CurrencyBox::CurrencyBox( Window* pParent, WinBits nWinStyle ) : 2379 ComboBox( pParent, nWinStyle ) 2380 { 2381 SetField( this ); 2382 Reformat(); 2383 } 2384 2385 // ----------------------------------------------------------------------- 2386 2387 CurrencyBox::CurrencyBox( Window* pParent, const ResId& rResId ) : 2388 ComboBox( WINDOW_CURRENCYBOX ) 2389 { 2390 rResId.SetRT( RSC_CURRENCYBOX ); 2391 WinBits nStyle = ImplInitRes( rResId ); 2392 ComboBox::ImplInit( pParent, nStyle ); 2393 CurrencyFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) ); 2394 SetField( this ); 2395 ComboBox::ImplLoadRes( rResId ); 2396 Reformat(); 2397 2398 if ( !(nStyle & WB_HIDE ) ) 2399 Show(); 2400 } 2401 2402 // ----------------------------------------------------------------------- 2403 2404 CurrencyBox::~CurrencyBox() 2405 { 2406 } 2407 2408 // ----------------------------------------------------------------------- 2409 2410 long CurrencyBox::PreNotify( NotifyEvent& rNEvt ) 2411 { 2412 if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() ) 2413 { 2414 if ( ImplCurrencyProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) ) 2415 return 1; 2416 } 2417 2418 return ComboBox::PreNotify( rNEvt ); 2419 } 2420 2421 // ----------------------------------------------------------------------- 2422 2423 long CurrencyBox::Notify( NotifyEvent& rNEvt ) 2424 { 2425 if ( rNEvt.GetType() == EVENT_GETFOCUS ) 2426 MarkToBeReformatted( sal_False ); 2427 else if ( rNEvt.GetType() == EVENT_LOSEFOCUS ) 2428 { 2429 if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) ) 2430 Reformat(); 2431 } 2432 2433 return ComboBox::Notify( rNEvt ); 2434 } 2435 2436 // ----------------------------------------------------------------------- 2437 2438 void CurrencyBox::DataChanged( const DataChangedEvent& rDCEvt ) 2439 { 2440 ComboBox::DataChanged( rDCEvt ); 2441 2442 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) ) 2443 { 2444 String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep(); 2445 String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep(); 2446 if ( IsDefaultLocale() ) 2447 ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() ); 2448 String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep(); 2449 String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep(); 2450 ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this ); 2451 ReformatAll(); 2452 } 2453 } 2454 2455 // ----------------------------------------------------------------------- 2456 2457 void CurrencyBox::Modify() 2458 { 2459 MarkToBeReformatted( sal_True ); 2460 ComboBox::Modify(); 2461 } 2462 2463 // ----------------------------------------------------------------------- 2464 2465 void CurrencyBox::ReformatAll() 2466 { 2467 XubString aStr; 2468 SetUpdateMode( sal_False ); 2469 sal_uInt16 nEntryCount = GetEntryCount(); 2470 for ( sal_uInt16 i=0; i < nEntryCount; i++ ) 2471 { 2472 ImplCurrencyReformat( GetEntry( i ), aStr ); 2473 RemoveEntry( i ); 2474 InsertEntry( aStr, i ); 2475 } 2476 CurrencyFormatter::Reformat(); 2477 SetUpdateMode( sal_True ); 2478 } 2479 2480 // ----------------------------------------------------------------------- 2481 2482 void CurrencyBox::InsertValue( sal_Int64 nValue, sal_uInt16 nPos ) 2483 { 2484 ComboBox::InsertEntry( CreateFieldText( nValue ), nPos ); 2485 } 2486 2487 // ----------------------------------------------------------------------- 2488 2489 void CurrencyBox::RemoveValue( sal_Int64 nValue ) 2490 { 2491 ComboBox::RemoveEntry( CreateFieldText( nValue ) ); 2492 } 2493 2494 // ----------------------------------------------------------------------- 2495 2496 sal_Int64 CurrencyBox::GetValue( sal_uInt16 nPos ) const 2497 { 2498 double nValue = 0; 2499 ImplCurrencyGetValue( ComboBox::GetEntry( nPos ), nValue, GetDecimalDigits(), ImplGetLocaleDataWrapper() ); 2500 return (sal_Int64)nValue; 2501 } 2502 2503 // ----------------------------------------------------------------------- 2504 2505 sal_uInt16 CurrencyBox::GetValuePos( sal_Int64 nValue ) const 2506 { 2507 return ComboBox::GetEntryPos( CreateFieldText( nValue ) ); 2508 } 2509 2510 // ----------------------------------------------------------------------- 2511 2512 sal_Int64 CurrencyBox::GetValue() const 2513 { 2514 // Implementation not inline, because it is a virtual Function 2515 return CurrencyFormatter::GetValue(); 2516 } 2517