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 mnCorrectedValue = 0; 481 mnDecimalDigits = 2; 482 mnType = FORMAT_NUMERIC; 483 mbThousandSep = sal_True; 484 mbShowTrailingZeros = sal_True; 485 486 // for fields 487 mnSpinSize = 1; 488 mnFirst = mnMin; 489 mnLast = mnMax; 490 491 SetDecimalDigits( 0 ); 492 } 493 494 // ----------------------------------------------------------------------- 495 496 NumericFormatter::NumericFormatter() 497 { 498 ImplInit(); 499 } 500 501 // ----------------------------------------------------------------------- 502 503 void NumericFormatter::ImplLoadRes( const ResId& rResId ) 504 { 505 ResMgr* pMgr = rResId.GetResMgr(); 506 507 if( pMgr ) 508 { 509 sal_uLong nMask = pMgr->ReadLong(); 510 511 if ( NUMERICFORMATTER_MIN & nMask ) 512 mnMin = pMgr->ReadLong(); 513 514 if ( NUMERICFORMATTER_MAX & nMask ) 515 mnMax = pMgr->ReadLong(); 516 517 if ( NUMERICFORMATTER_STRICTFORMAT & nMask ) 518 SetStrictFormat( (sal_Bool)pMgr->ReadShort() ); 519 520 if ( NUMERICFORMATTER_DECIMALDIGITS & nMask ) 521 SetDecimalDigits( pMgr->ReadShort() ); 522 523 if ( NUMERICFORMATTER_VALUE & nMask ) 524 { 525 mnFieldValue = pMgr->ReadLong(); 526 if ( mnFieldValue > mnMax ) 527 mnFieldValue = mnMax; 528 else if ( mnFieldValue < mnMin ) 529 mnFieldValue = mnMin; 530 mnLastValue = mnFieldValue; 531 } 532 533 if ( NUMERICFORMATTER_NOTHOUSANDSEP & nMask ) 534 SetUseThousandSep( !(sal_Bool)pMgr->ReadShort() ); 535 } 536 } 537 538 // ----------------------------------------------------------------------- 539 540 NumericFormatter::~NumericFormatter() 541 { 542 } 543 544 // ----------------------------------------------------------------------- 545 546 void NumericFormatter::SetMin( sal_Int64 nNewMin ) 547 { 548 mnMin = nNewMin; 549 if ( !IsEmptyFieldValue() ) 550 ReformatAll(); 551 } 552 553 // ----------------------------------------------------------------------- 554 555 void NumericFormatter::SetMax( sal_Int64 nNewMax ) 556 { 557 mnMax = nNewMax; 558 if ( !IsEmptyFieldValue() ) 559 ReformatAll(); 560 } 561 562 // ----------------------------------------------------------------------- 563 564 void NumericFormatter::SetUseThousandSep( sal_Bool b ) 565 { 566 mbThousandSep = b; 567 ReformatAll(); 568 } 569 570 // ----------------------------------------------------------------------- 571 572 void NumericFormatter::SetDecimalDigits( sal_uInt16 nDigits ) 573 { 574 mnDecimalDigits = nDigits; 575 ReformatAll(); 576 } 577 578 // ----------------------------------------------------------------------- 579 580 void NumericFormatter::SetShowTrailingZeros( sal_Bool bShowTrailingZeros ) 581 { 582 if ( mbShowTrailingZeros != bShowTrailingZeros ) 583 { 584 mbShowTrailingZeros = bShowTrailingZeros; 585 ReformatAll(); 586 } 587 } 588 589 // ----------------------------------------------------------------------- 590 591 sal_uInt16 NumericFormatter::GetDecimalDigits() const 592 { 593 return mnDecimalDigits; 594 } 595 596 // ----------------------------------------------------------------------- 597 598 void NumericFormatter::SetValue( sal_Int64 nNewValue ) 599 { 600 SetUserValue( nNewValue ); 601 mnFieldValue = mnLastValue; 602 SetEmptyFieldValueData( sal_False ); 603 } 604 605 // ----------------------------------------------------------------------- 606 607 XubString NumericFormatter::CreateFieldText( sal_Int64 nValue ) const 608 { 609 return ImplGetLocaleDataWrapper().getNum( nValue, GetDecimalDigits(), IsUseThousandSep(), IsShowTrailingZeros() ); 610 } 611 612 // ----------------------------------------------------------------------- 613 614 void NumericFormatter::ImplSetUserValue( sal_Int64 nNewValue, Selection* pNewSelection ) 615 { 616 if ( nNewValue > mnMax ) 617 nNewValue = mnMax; 618 else if ( nNewValue < mnMin ) 619 nNewValue = mnMin; 620 mnLastValue = nNewValue; 621 622 if ( GetField() ) 623 ImplSetText( CreateFieldText( nNewValue ), pNewSelection ); 624 } 625 626 // ----------------------------------------------------------------------- 627 628 void NumericFormatter::SetUserValue( sal_Int64 nNewValue ) 629 { 630 ImplSetUserValue( nNewValue ); 631 } 632 633 // ----------------------------------------------------------------------- 634 635 sal_Int64 NumericFormatter::GetValue() const 636 { 637 if ( !GetField() ) 638 return 0; 639 640 double nTempValue; 641 642 if ( ImplNumericGetValue( GetField()->GetText(), nTempValue, 643 GetDecimalDigits(), ImplGetLocaleDataWrapper() ) ) 644 { 645 // caution: precision loss in double cast 646 if ( nTempValue > mnMax ) 647 nTempValue = (double)mnMax; 648 else if ( nTempValue < mnMin ) 649 nTempValue = (double)mnMin; 650 return (sal_Int64)nTempValue; 651 } 652 else 653 return mnLastValue; 654 } 655 656 // ----------------------------------------------------------------------- 657 658 sal_Bool NumericFormatter::IsValueModified() const 659 { 660 if ( ImplGetEmptyFieldValue() ) 661 return !IsEmptyFieldValue(); 662 else if ( GetValue() != mnFieldValue ) 663 return sal_True; 664 else 665 return sal_False; 666 } 667 668 // ----------------------------------------------------------------------- 669 670 Fraction NumericFormatter::ConvertToFraction( sal_Int64 nValue ) 671 { 672 // caution: precision loss in double cast (and in fraction anyhow) 673 return Fraction( (double)nValue/(double)ImplPower10( GetDecimalDigits() ) ); 674 } 675 676 // ----------------------------------------------------------------------- 677 678 sal_Int64 NumericFormatter::ConvertToLong( const Fraction& rValue ) 679 { 680 Fraction aFract = rValue; 681 aFract *= Fraction( (long)ImplPower10( GetDecimalDigits() ), 1 ); 682 return (sal_Int64)(double)aFract; 683 } 684 685 // ----------------------------------------------------------------------- 686 687 sal_Int64 NumericFormatter::Normalize( sal_Int64 nValue ) const 688 { 689 return (nValue * ImplPower10( GetDecimalDigits() ) ); 690 } 691 692 // ----------------------------------------------------------------------- 693 694 sal_Int64 NumericFormatter::Denormalize( sal_Int64 nValue ) const 695 { 696 sal_Int64 nFactor = ImplPower10( GetDecimalDigits() ); 697 if( nValue < 0 ) 698 return ((nValue-(nFactor/2)) / nFactor ); 699 else 700 return ((nValue+(nFactor/2)) / nFactor ); 701 } 702 703 // ----------------------------------------------------------------------- 704 705 void NumericFormatter::Reformat() 706 { 707 if ( !GetField() ) 708 return; 709 710 if ( !GetField()->GetText().Len() && ImplGetEmptyFieldValue() ) 711 return; 712 713 XubString aStr; 714 // caution: precision loss in double cast 715 double nTemp = (double)mnLastValue; 716 sal_Bool bOK = ImplNumericReformat( GetField()->GetText(), nTemp, aStr ); 717 mnLastValue = (sal_Int64)nTemp; 718 if ( !bOK ) 719 return; 720 721 if ( aStr.Len() ) 722 ImplSetText( aStr ); 723 else 724 SetValue( mnLastValue ); 725 } 726 727 // ----------------------------------------------------------------------- 728 729 void NumericFormatter::FieldUp() 730 { 731 sal_Int64 nValue = GetValue(); 732 nValue += mnSpinSize; 733 if ( nValue > mnMax ) 734 nValue = mnMax; 735 736 ImplNewFieldValue( nValue ); 737 } 738 739 // ----------------------------------------------------------------------- 740 741 void NumericFormatter::FieldDown() 742 { 743 sal_Int64 nValue = GetValue(); 744 nValue -= mnSpinSize; 745 if ( nValue < mnMin ) 746 nValue = mnMin; 747 748 ImplNewFieldValue( nValue ); 749 } 750 751 // ----------------------------------------------------------------------- 752 753 void NumericFormatter::FieldFirst() 754 { 755 ImplNewFieldValue( mnFirst ); 756 } 757 758 // ----------------------------------------------------------------------- 759 760 void NumericFormatter::FieldLast() 761 { 762 ImplNewFieldValue( mnLast ); 763 } 764 765 // ----------------------------------------------------------------------- 766 767 void NumericFormatter::ImplNewFieldValue( sal_Int64 nNewValue ) 768 { 769 if ( GetField() ) 770 { 771 // !!! TH-18.2.99: Wenn wir Zeit haben sollte mal geklaert werden, 772 // !!! warum nicht bei ImplSetUserValue() geprueft wird, ob 773 // !!! sich der Wert aendert. Denn auch hier muesste dieses 774 // !!! gemacht werden, da ansonsten der Modify-Aufruf 775 // !!! nicht gemacht werden duerfte. Jedenfalls sollten die 776 // !!! Wege von ImplNewFieldValue, ImplSetUserValue und 777 // !!! ImplSetText ueberprueft und klarer gestalltet (mit Kommentar) 778 // !!! werden, damit wir mal wissen, was dort ablaeuft!!! 779 780 Selection aSelection = GetField()->GetSelection(); 781 aSelection.Justify(); 782 XubString aText = GetField()->GetText(); 783 // Wenn bis ans Ende selektiert war, soll das auch so bleiben... 784 if ( (xub_StrLen)aSelection.Max() == aText.Len() ) 785 { 786 if ( !aSelection.Len() ) 787 aSelection.Min() = SELECTION_MAX; 788 aSelection.Max() = SELECTION_MAX; 789 } 790 791 sal_Int64 nOldLastValue = mnLastValue; 792 ImplSetUserValue( nNewValue, &aSelection ); 793 mnLastValue = nOldLastValue; 794 795 // Modify am Edit wird nur bei KeyInput gesetzt... 796 if ( GetField()->GetText() != aText ) 797 { 798 GetField()->SetModifyFlag(); 799 GetField()->Modify(); 800 } 801 } 802 } 803 804 // ----------------------------------------------------------------------- 805 806 NumericField::NumericField( Window* pParent, WinBits nWinStyle ) : 807 SpinField( pParent, nWinStyle ) 808 { 809 SetField( this ); 810 Reformat(); 811 } 812 813 // ----------------------------------------------------------------------- 814 815 NumericField::NumericField( Window* pParent, const ResId& rResId ) : 816 SpinField( WINDOW_NUMERICFIELD ) 817 { 818 rResId.SetRT( RSC_NUMERICFIELD ); 819 WinBits nStyle = ImplInitRes( rResId ) ; 820 SpinField::ImplInit( pParent, nStyle ); 821 SetField( this ); 822 ImplLoadRes( rResId ); 823 Reformat(); 824 825 if ( !(nStyle & WB_HIDE ) ) 826 Show(); 827 } 828 829 // ----------------------------------------------------------------------- 830 831 void NumericField::ImplLoadRes( const ResId& rResId ) 832 { 833 SpinField::ImplLoadRes( rResId ); 834 NumericFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) ); 835 836 sal_uLong nMask = ReadLongRes(); 837 838 if ( NUMERICFIELD_FIRST & nMask ) 839 mnFirst = ReadLongRes(); 840 841 if ( NUMERICFIELD_LAST & nMask ) 842 mnLast = ReadLongRes(); 843 844 if ( NUMERICFIELD_SPINSIZE & nMask ) 845 mnSpinSize = ReadLongRes(); 846 } 847 848 // ----------------------------------------------------------------------- 849 850 NumericField::~NumericField() 851 { 852 } 853 854 // ----------------------------------------------------------------------- 855 856 long NumericField::PreNotify( NotifyEvent& rNEvt ) 857 { 858 if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() ) 859 { 860 if ( ImplNumericProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) ) 861 return 1; 862 } 863 864 return SpinField::PreNotify( rNEvt ); 865 } 866 867 // ----------------------------------------------------------------------- 868 869 long NumericField::Notify( NotifyEvent& rNEvt ) 870 { 871 if ( rNEvt.GetType() == EVENT_GETFOCUS ) 872 MarkToBeReformatted( sal_False ); 873 else if ( rNEvt.GetType() == EVENT_LOSEFOCUS ) 874 { 875 if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) ) 876 Reformat(); 877 } 878 879 return SpinField::Notify( rNEvt ); 880 } 881 882 // ----------------------------------------------------------------------- 883 884 void NumericField::DataChanged( const DataChangedEvent& rDCEvt ) 885 { 886 SpinField::DataChanged( rDCEvt ); 887 888 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) ) 889 { 890 String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep(); 891 String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep(); 892 if ( IsDefaultLocale() ) 893 ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() ); 894 String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep(); 895 String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep(); 896 ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this ); 897 ReformatAll(); 898 } 899 } 900 901 // ----------------------------------------------------------------------- 902 903 void NumericField::Modify() 904 { 905 MarkToBeReformatted( sal_True ); 906 SpinField::Modify(); 907 } 908 909 // ----------------------------------------------------------------------- 910 911 void NumericField::Up() 912 { 913 FieldUp(); 914 SpinField::Up(); 915 } 916 917 // ----------------------------------------------------------------------- 918 919 void NumericField::Down() 920 { 921 FieldDown(); 922 SpinField::Down(); 923 } 924 925 // ----------------------------------------------------------------------- 926 927 void NumericField::First() 928 { 929 FieldFirst(); 930 SpinField::First(); 931 } 932 933 // ----------------------------------------------------------------------- 934 935 void NumericField::Last() 936 { 937 FieldLast(); 938 SpinField::Last(); 939 } 940 941 // ----------------------------------------------------------------------- 942 943 NumericBox::NumericBox( Window* pParent, WinBits nWinStyle ) : 944 ComboBox( pParent, nWinStyle ) 945 { 946 SetField( this ); 947 Reformat(); 948 } 949 950 // ----------------------------------------------------------------------- 951 952 NumericBox::NumericBox( Window* pParent, const ResId& rResId ) : 953 ComboBox( WINDOW_NUMERICBOX ) 954 { 955 rResId.SetRT( RSC_NUMERICBOX ); 956 WinBits nStyle = ImplInitRes( rResId ); 957 ComboBox::ImplInit( pParent, nStyle ); 958 SetField( this ); 959 ComboBox::ImplLoadRes( rResId ); 960 NumericFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) ); 961 Reformat(); 962 963 if ( !(nStyle & WB_HIDE ) ) 964 Show(); 965 } 966 967 // ----------------------------------------------------------------------- 968 969 NumericBox::~NumericBox() 970 { 971 } 972 973 // ----------------------------------------------------------------------- 974 975 long NumericBox::PreNotify( NotifyEvent& rNEvt ) 976 { 977 if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() ) 978 { 979 if ( ImplNumericProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) ) 980 return 1; 981 } 982 983 return ComboBox::PreNotify( rNEvt ); 984 } 985 986 // ----------------------------------------------------------------------- 987 988 long NumericBox::Notify( NotifyEvent& rNEvt ) 989 { 990 if ( rNEvt.GetType() == EVENT_GETFOCUS ) 991 MarkToBeReformatted( sal_False ); 992 else if ( rNEvt.GetType() == EVENT_LOSEFOCUS ) 993 { 994 if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) ) 995 Reformat(); 996 } 997 998 return ComboBox::Notify( rNEvt ); 999 } 1000 1001 // ----------------------------------------------------------------------- 1002 1003 void NumericBox::DataChanged( const DataChangedEvent& rDCEvt ) 1004 { 1005 ComboBox::DataChanged( rDCEvt ); 1006 1007 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) ) 1008 { 1009 String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep(); 1010 String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep(); 1011 if ( IsDefaultLocale() ) 1012 ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() ); 1013 String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep(); 1014 String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep(); 1015 ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this ); 1016 ReformatAll(); 1017 } 1018 } 1019 1020 // ----------------------------------------------------------------------- 1021 1022 void NumericBox::Modify() 1023 { 1024 MarkToBeReformatted( sal_True ); 1025 ComboBox::Modify(); 1026 } 1027 1028 // ----------------------------------------------------------------------- 1029 1030 void NumericBox::ReformatAll() 1031 { 1032 double nValue; 1033 XubString aStr; 1034 SetUpdateMode( sal_False ); 1035 sal_uInt16 nEntryCount = GetEntryCount(); 1036 for ( sal_uInt16 i=0; i < nEntryCount; i++ ) 1037 { 1038 ImplNumericReformat( GetEntry( i ), nValue, aStr ); 1039 RemoveEntry( i ); 1040 InsertEntry( aStr, i ); 1041 } 1042 NumericFormatter::Reformat(); 1043 SetUpdateMode( sal_True ); 1044 } 1045 1046 // ----------------------------------------------------------------------- 1047 1048 void NumericBox::InsertValue( sal_Int64 nValue, sal_uInt16 nPos ) 1049 { 1050 ComboBox::InsertEntry( CreateFieldText( nValue ), nPos ); 1051 } 1052 1053 // ----------------------------------------------------------------------- 1054 1055 void NumericBox::RemoveValue( sal_Int64 nValue ) 1056 { 1057 ComboBox::RemoveEntry( CreateFieldText( nValue ) ); 1058 } 1059 1060 // ----------------------------------------------------------------------- 1061 1062 sal_Int64 NumericBox::GetValue( sal_uInt16 nPos ) const 1063 { 1064 double nValue = 0; 1065 ImplNumericGetValue( ComboBox::GetEntry( nPos ), nValue, GetDecimalDigits(), ImplGetLocaleDataWrapper() ); 1066 return (sal_Int64)nValue; 1067 } 1068 1069 // ----------------------------------------------------------------------- 1070 1071 sal_uInt16 NumericBox::GetValuePos( sal_Int64 nValue ) const 1072 { 1073 return ComboBox::GetEntryPos( CreateFieldText( nValue ) ); 1074 } 1075 1076 // ----------------------------------------------------------------------- 1077 1078 static sal_Bool ImplMetricProcessKeyInput( Edit* pEdit, const KeyEvent& rKEvt, 1079 sal_Bool, sal_Bool bUseThousandSep, const LocaleDataWrapper& rWrapper ) 1080 { 1081 // Es gibt hier kein sinnvolles StrictFormat, also alle 1082 // Zeichen erlauben 1083 return ImplNumericProcessKeyInput( pEdit, rKEvt, sal_False, bUseThousandSep, rWrapper ); 1084 } 1085 1086 // ----------------------------------------------------------------------- 1087 1088 static XubString ImplMetricGetUnitText( const XubString& rStr ) 1089 { 1090 // Einheitentext holen 1091 XubString aStr; 1092 for ( short i = rStr.Len()-1; i >= 0; i-- ) 1093 { 1094 xub_Unicode c = rStr.GetChar( i ); 1095 if ( unicode::isAlpha( c ) || 1096 (c == '\'') || (c == '\"') || (c == '%' ) ) 1097 aStr.Insert( c, 0 ); 1098 else 1099 { 1100 if ( aStr.Len() ) 1101 break; 1102 } 1103 } 1104 return aStr; 1105 1106 /* 1107 // MT: #90545# Preparation for translated strings... 1108 String aMetricText; 1109 for ( sal_uInt16 n = rStr.Len(); n; ) 1110 { 1111 sal_Unicode c = rStr.GetChar( --n ); 1112 sal_Int32 nType = xCharClass->getStringType( rStr, n, 1, rLocale ); 1113 1114 if ( CharClass::isLetterType( nType ) ) 1115 { 1116 aMetricText.Insert( c, 0 ); 1117 } 1118 else 1119 { 1120 if ( aMetricText.Len() ) 1121 break; 1122 } 1123 } 1124 */ 1125 } 1126 1127 // ----------------------------------------------------------------------- 1128 1129 // #104355# support localized mesaurements 1130 1131 static const String& ImplMetricToString( FieldUnit rUnit ) 1132 { 1133 FieldUnitStringList* pList = ImplGetFieldUnits(); 1134 if( pList ) 1135 { 1136 // return unit's default string (ie, the first one ) 1137 for( FieldUnitStringList::const_iterator it = pList->begin(); it != pList->end(); ++it ) 1138 { 1139 if ( it->second == rUnit ) 1140 return it->first; 1141 } 1142 } 1143 1144 return String::EmptyString(); 1145 } 1146 1147 static FieldUnit ImplStringToMetric( const String &rMetricString ) 1148 { 1149 FieldUnitStringList* pList = ImplGetCleanedFieldUnits(); 1150 if( pList ) 1151 { 1152 // return FieldUnit 1153 String aStr( rMetricString ); 1154 aStr.ToLowerAscii(); 1155 aStr.EraseAllChars( sal_Unicode( ' ' ) ); 1156 for( FieldUnitStringList::const_iterator it = pList->begin(); it != pList->end(); ++it ) 1157 { 1158 if ( it->first.Equals( aStr ) ) 1159 return it->second; 1160 } 1161 } 1162 1163 return FUNIT_NONE; 1164 } 1165 1166 // ----------------------------------------------------------------------- 1167 1168 static FieldUnit ImplMetricGetUnit( const XubString& rStr ) 1169 { 1170 XubString aStr = ImplMetricGetUnitText( rStr ); 1171 return ImplStringToMetric( aStr ); 1172 } 1173 1174 #define K *1000L 1175 #define M *1000000L 1176 #define X *5280L 1177 1178 static const sal_Int64 aImplFactor[FUNIT_MILE+1][FUNIT_MILE+1] = 1179 { /* 1180 mm/100 mm cm m km twip point pica inch foot mile */ 1181 { 1, 100, 1 K, 100 K, 100 M, 2540, 2540, 2540, 2540,2540*12,2540*12 X }, 1182 { 1, 1, 10, 1 K, 1 M, 2540, 2540, 2540, 2540,2540*12,2540*12 X }, 1183 { 1, 1, 1, 100, 100 K, 254, 254, 254, 254, 254*12, 254*12 X }, 1184 { 1, 1, 1, 1, 1 K, 254, 254, 254, 254, 254*12, 254*12 X }, 1185 { 1, 1, 1, 1, 1, 0, 254, 254, 254, 254*12, 254*12 X }, 1186 { 1440,144 K,144 K,14400 K, 0, 1, 20, 240, 1440,1440*12,1440*12 X }, 1187 { 72, 7200, 7200, 720 K, 720 M, 1, 1, 12, 72, 72*12, 72*12 X }, 1188 { 6, 600, 600, 60 K, 60 M, 1, 1, 1, 6, 6*12, 6*12 X }, 1189 { 1, 100, 100, 10 K, 10 M, 1, 1, 1, 1, 12, 12 X }, 1190 { 1, 100, 100, 10 K, 10 M, 1, 1, 1, 1, 1, 1 X }, 1191 { 1, 100, 100, 10 K, 10 M, 1, 1, 1, 1, 1, 1 } 1192 }; 1193 1194 #undef X 1195 #undef M 1196 #undef K 1197 // twip in km 254/14400 M 1198 1199 static FieldUnit eDefaultUnit = FUNIT_NONE; 1200 1201 FieldUnit MetricField::GetDefaultUnit() { return eDefaultUnit; } 1202 void MetricField::SetDefaultUnit( FieldUnit meUnit ) { eDefaultUnit = meUnit; } 1203 1204 static FieldUnit ImplMap2FieldUnit( MapUnit meUnit, long& nDecDigits ) 1205 { 1206 switch( meUnit ) 1207 { 1208 case MAP_100TH_MM : 1209 nDecDigits -= 2; 1210 return FUNIT_MM; 1211 case MAP_10TH_MM : 1212 nDecDigits -= 1; 1213 return FUNIT_MM; 1214 case MAP_MM : 1215 return FUNIT_MM; 1216 case MAP_CM : 1217 return FUNIT_CM; 1218 case MAP_1000TH_INCH : 1219 nDecDigits -= 3; 1220 return FUNIT_INCH; 1221 case MAP_100TH_INCH : 1222 nDecDigits -= 2; 1223 return FUNIT_INCH; 1224 case MAP_10TH_INCH : 1225 nDecDigits -= 1; 1226 return FUNIT_INCH; 1227 case MAP_INCH : 1228 return FUNIT_INCH; 1229 case MAP_POINT : 1230 return FUNIT_POINT; 1231 case MAP_TWIP : 1232 return FUNIT_TWIP; 1233 default: 1234 DBG_ERROR( "default eInUnit" ); 1235 break; 1236 } 1237 return FUNIT_NONE; 1238 } 1239 1240 // ----------------------------------------------------------------------- 1241 1242 static double nonValueDoubleToValueDouble( double nValue ) 1243 { 1244 return rtl::math::isFinite( nValue ) ? nValue : 0.0; 1245 } 1246 1247 sal_Int64 MetricField::ConvertValue( sal_Int64 nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits, 1248 FieldUnit eInUnit, FieldUnit eOutUnit ) 1249 { 1250 // caution: precision loss in double cast 1251 return static_cast<sal_Int64>( 1252 // #150733# cast double to sal_Int64 can throw a 1253 // EXCEPTION_FLT_INVALID_OPERATION on Windows 1254 nonValueDoubleToValueDouble( 1255 ConvertDoubleValue( (double)nValue, mnBaseValue, nDecDigits, 1256 eInUnit, eOutUnit ) ) ); 1257 } 1258 1259 // ----------------------------------------------------------------------- 1260 1261 sal_Int64 MetricField::ConvertValue( sal_Int64 nValue, sal_uInt16 nDigits, 1262 MapUnit eInUnit, FieldUnit eOutUnit ) 1263 { 1264 return static_cast<sal_Int64>( 1265 // #150733# cast double to sal_Int64 can throw a 1266 // EXCEPTION_FLT_INVALID_OPERATION on Windows 1267 nonValueDoubleToValueDouble( 1268 ConvertDoubleValue( nValue, nDigits, eInUnit, eOutUnit ) ) ); 1269 } 1270 1271 // ----------------------------------------------------------------------- 1272 1273 sal_Int64 MetricField::ConvertValue( sal_Int64 nValue, sal_uInt16 nDigits, 1274 FieldUnit eInUnit, MapUnit eOutUnit ) 1275 { 1276 return static_cast<sal_Int64>( 1277 // #150733# cast double to sal_Int64 can throw a 1278 // EXCEPTION_FLT_INVALID_OPERATION on Windows 1279 nonValueDoubleToValueDouble( 1280 ConvertDoubleValue( nValue, nDigits, eInUnit, eOutUnit ) ) ); 1281 } 1282 1283 // ----------------------------------------------------------------------- 1284 1285 double MetricField::ConvertDoubleValue( double nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits, 1286 FieldUnit eInUnit, FieldUnit eOutUnit ) 1287 { 1288 if ( eInUnit != eOutUnit ) 1289 { 1290 sal_Int64 nMult = 1, nDiv = 1; 1291 1292 if ( eInUnit == FUNIT_PERCENT ) 1293 { 1294 if ( (mnBaseValue <= 0) || (nValue <= 0) ) 1295 return nValue; 1296 nDiv = 100; 1297 for ( sal_uInt16 i=0; i < nDecDigits; i++ ) 1298 nDiv *= 10; 1299 1300 nMult = mnBaseValue; 1301 } 1302 else if ( eOutUnit == FUNIT_PERCENT || 1303 eOutUnit == FUNIT_CUSTOM || 1304 eOutUnit == FUNIT_NONE || 1305 eInUnit == FUNIT_CUSTOM || 1306 eInUnit == FUNIT_NONE ) 1307 return nValue; 1308 else 1309 { 1310 if ( eOutUnit == FUNIT_100TH_MM ) 1311 eOutUnit = FUNIT_NONE; 1312 if ( eInUnit == FUNIT_100TH_MM ) 1313 eInUnit = FUNIT_NONE; 1314 1315 nDiv = aImplFactor[eInUnit][eOutUnit]; 1316 nMult = aImplFactor[eOutUnit][eInUnit]; 1317 1318 DBG_ASSERT( nMult > 0, "illegal *" ); 1319 DBG_ASSERT( nDiv > 0, "illegal /" ); 1320 } 1321 1322 if ( nMult != 1 && nMult > 0 ) 1323 nValue *= nMult; 1324 if ( nDiv != 1 && nDiv > 0 ) 1325 { 1326 nValue += ( nValue < 0 ) ? (-nDiv/2) : (nDiv/2); 1327 nValue /= nDiv; 1328 } 1329 } 1330 1331 return nValue; 1332 } 1333 1334 // ----------------------------------------------------------------------- 1335 1336 double MetricField::ConvertDoubleValue( double nValue, sal_uInt16 nDigits, 1337 MapUnit eInUnit, FieldUnit eOutUnit ) 1338 { 1339 if ( eOutUnit == FUNIT_PERCENT || 1340 eOutUnit == FUNIT_CUSTOM || 1341 eOutUnit == FUNIT_NONE || 1342 eInUnit == MAP_PIXEL || 1343 eInUnit == MAP_SYSFONT || 1344 eInUnit == MAP_APPFONT || 1345 eInUnit == MAP_RELATIVE ) 1346 { 1347 DBG_ERROR( "invalid parameters" ); 1348 return nValue; 1349 } 1350 1351 long nDecDigits = nDigits; 1352 FieldUnit eFieldUnit = ImplMap2FieldUnit( eInUnit, nDecDigits ); 1353 1354 if ( nDecDigits < 0 ) 1355 { 1356 while ( nDecDigits ) 1357 { 1358 nValue += 5; 1359 nValue /= 10; 1360 nDecDigits++; 1361 } 1362 } 1363 else 1364 { 1365 while ( nDecDigits ) 1366 { 1367 nValue *= 10; 1368 nDecDigits--; 1369 } 1370 } 1371 1372 if ( eFieldUnit != eOutUnit ) 1373 { 1374 sal_Int64 nDiv = aImplFactor[eFieldUnit][eOutUnit]; 1375 sal_Int64 nMult = aImplFactor[eOutUnit][eFieldUnit]; 1376 1377 DBG_ASSERT( nMult > 0, "illegal *" ); 1378 DBG_ASSERT( nDiv > 0, "illegal /" ); 1379 1380 if ( nMult != 1 && nMult > 0) 1381 nValue *= nMult; 1382 if ( nDiv != 1 && nDiv > 0 ) 1383 { 1384 nValue += (nValue < 0) ? (-nDiv/2) : (nDiv/2); 1385 nValue /= nDiv; 1386 } 1387 } 1388 return nValue; 1389 } 1390 1391 // ----------------------------------------------------------------------- 1392 1393 double MetricField::ConvertDoubleValue( double nValue, sal_uInt16 nDigits, 1394 FieldUnit eInUnit, MapUnit eOutUnit ) 1395 { 1396 if ( eInUnit == FUNIT_PERCENT || 1397 eInUnit == FUNIT_CUSTOM || 1398 eInUnit == FUNIT_NONE || 1399 eOutUnit == MAP_PIXEL || 1400 eOutUnit == MAP_SYSFONT || 1401 eOutUnit == MAP_APPFONT || 1402 eOutUnit == MAP_RELATIVE ) 1403 { 1404 DBG_ERROR( "invalid parameters" ); 1405 return nValue; 1406 } 1407 1408 long nDecDigits = nDigits; 1409 FieldUnit eFieldUnit = ImplMap2FieldUnit( eOutUnit, nDecDigits ); 1410 1411 if ( nDecDigits < 0 ) 1412 { 1413 while ( nDecDigits ) 1414 { 1415 nValue *= 10; 1416 nDecDigits++; 1417 } 1418 } 1419 else 1420 { 1421 while ( nDecDigits ) 1422 { 1423 nValue += 5; 1424 nValue /= 10; 1425 nDecDigits--; 1426 } 1427 } 1428 1429 if ( eFieldUnit != eInUnit ) 1430 { 1431 sal_Int64 nDiv = aImplFactor[eInUnit][eFieldUnit]; 1432 sal_Int64 nMult = aImplFactor[eFieldUnit][eInUnit]; 1433 1434 DBG_ASSERT( nMult > 0, "illegal *" ); 1435 DBG_ASSERT( nDiv > 0, "illegal /" ); 1436 1437 if( nMult != 1 && nMult > 0 ) 1438 nValue *= nMult; 1439 if( nDiv != 1 && nDiv > 0 ) 1440 { 1441 nValue += (nValue < 0) ? (-nDiv/2) : (nDiv/2); 1442 nValue /= nDiv; 1443 } 1444 } 1445 return nValue; 1446 } 1447 1448 // ----------------------------------------------------------------------- 1449 1450 static sal_Bool ImplMetricGetValue( const XubString& rStr, double& rValue, sal_Int64 nBaseValue, 1451 sal_uInt16 nDecDigits, const LocaleDataWrapper& rLocaleDataWrapper, FieldUnit eUnit ) 1452 { 1453 // Zahlenwert holen 1454 if ( !ImplNumericGetValue( rStr, rValue, nDecDigits, rLocaleDataWrapper ) ) 1455 return sal_False; 1456 1457 // Einheit rausfinden 1458 FieldUnit eEntryUnit = ImplMetricGetUnit( rStr ); 1459 1460 // Einheiten umrechnen 1461 rValue = MetricField::ConvertDoubleValue( rValue, nBaseValue, nDecDigits, eEntryUnit, eUnit ); 1462 1463 return sal_True; 1464 } 1465 1466 // ----------------------------------------------------------------------- 1467 1468 sal_Bool MetricFormatter::ImplMetricReformat( const XubString& rStr, double& rValue, XubString& rOutStr ) 1469 { 1470 if ( !ImplMetricGetValue( rStr, rValue, mnBaseValue, GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit ) ) 1471 return sal_True; 1472 else 1473 { 1474 double nTempVal = rValue; 1475 // caution: precision loss in double cast 1476 if ( nTempVal > GetMax() ) 1477 nTempVal = (double)GetMax(); 1478 else if ( nTempVal < GetMin()) 1479 nTempVal = (double)GetMin(); 1480 1481 if ( GetErrorHdl().IsSet() && (rValue != nTempVal) ) 1482 { 1483 mnCorrectedValue = (sal_Int64)nTempVal; 1484 if ( !GetErrorHdl().Call( this ) ) 1485 { 1486 mnCorrectedValue = 0; 1487 return sal_False; 1488 } 1489 else 1490 mnCorrectedValue = 0; 1491 } 1492 1493 rOutStr = CreateFieldText( (sal_Int64)nTempVal ); 1494 return sal_True; 1495 } 1496 } 1497 1498 // ----------------------------------------------------------------------- 1499 1500 inline void MetricFormatter::ImplInit() 1501 { 1502 mnBaseValue = 0; 1503 meUnit = MetricField::GetDefaultUnit(); 1504 mnType = FORMAT_METRIC; 1505 } 1506 1507 // ----------------------------------------------------------------------- 1508 1509 MetricFormatter::MetricFormatter() 1510 { 1511 ImplInit(); 1512 } 1513 1514 // ----------------------------------------------------------------------- 1515 1516 void MetricFormatter::ImplLoadRes( const ResId& rResId ) 1517 { 1518 NumericFormatter::ImplLoadRes( rResId ); 1519 1520 ResMgr* pMgr = rResId.GetResMgr(); 1521 if( pMgr ) 1522 { 1523 sal_uLong nMask = pMgr->ReadLong(); 1524 1525 if ( METRICFORMATTER_UNIT & nMask ) 1526 meUnit = (FieldUnit)pMgr->ReadLong(); 1527 1528 if ( METRICFORMATTER_CUSTOMUNITTEXT & nMask ) 1529 maCustomUnitText = pMgr->ReadString(); 1530 } 1531 } 1532 1533 // ----------------------------------------------------------------------- 1534 1535 MetricFormatter::~MetricFormatter() 1536 { 1537 } 1538 1539 // ----------------------------------------------------------------------- 1540 1541 void MetricFormatter::SetUnit( FieldUnit eNewUnit ) 1542 { 1543 if ( eNewUnit == FUNIT_100TH_MM ) 1544 { 1545 SetDecimalDigits( GetDecimalDigits() + 2 ); 1546 meUnit = FUNIT_MM; 1547 } 1548 else 1549 meUnit = eNewUnit; 1550 ReformatAll(); 1551 } 1552 1553 // ----------------------------------------------------------------------- 1554 1555 void MetricFormatter::SetCustomUnitText( const XubString& rStr ) 1556 { 1557 maCustomUnitText = rStr; 1558 ReformatAll(); 1559 } 1560 1561 // ----------------------------------------------------------------------- 1562 1563 void MetricFormatter::SetValue( sal_Int64 nNewValue, FieldUnit eInUnit ) 1564 { 1565 SetUserValue( nNewValue, eInUnit ); 1566 mnFieldValue = mnLastValue; 1567 } 1568 1569 // ----------------------------------------------------------------------- 1570 1571 XubString MetricFormatter::CreateFieldText( sal_Int64 nValue ) const 1572 { 1573 XubString aStr = NumericFormatter::CreateFieldText( nValue ); 1574 1575 if( meUnit == FUNIT_CUSTOM ) 1576 aStr += maCustomUnitText; 1577 else 1578 aStr += ImplMetricToString( meUnit ); 1579 1580 return aStr; 1581 } 1582 1583 // ----------------------------------------------------------------------- 1584 1585 void MetricFormatter::SetUserValue( sal_Int64 nNewValue, FieldUnit eInUnit ) 1586 { 1587 // Umrechnen auf eingestellte Einheiten 1588 nNewValue = MetricField::ConvertValue( nNewValue, mnBaseValue, GetDecimalDigits(), eInUnit, meUnit ); 1589 NumericFormatter::SetUserValue( nNewValue ); 1590 } 1591 1592 // ----------------------------------------------------------------------- 1593 1594 sal_Int64 MetricFormatter::GetValue( FieldUnit eOutUnit ) const 1595 { 1596 if ( !GetField() ) 1597 return 0; 1598 1599 double nTempValue; 1600 // caution: precision loss in double cast 1601 if ( !ImplMetricGetValue( GetField()->GetText(), nTempValue, mnBaseValue, GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit ) ) 1602 nTempValue = (double)mnLastValue; 1603 1604 // caution: precision loss in double cast 1605 if ( nTempValue > mnMax ) 1606 nTempValue = (double)mnMax; 1607 else if ( nTempValue < mnMin ) 1608 nTempValue = (double)mnMin; 1609 1610 // Umrechnen auf gewuenschte Einheiten 1611 return MetricField::ConvertValue( (sal_Int64)nTempValue, mnBaseValue, GetDecimalDigits(), meUnit, eOutUnit ); 1612 } 1613 1614 // ----------------------------------------------------------------------- 1615 1616 void MetricFormatter::SetValue( sal_Int64 nValue ) 1617 { 1618 // Implementation not inline, because it is a virtual Function 1619 SetValue( nValue, FUNIT_NONE ); 1620 } 1621 1622 // ----------------------------------------------------------------------- 1623 1624 sal_Int64 MetricFormatter::GetValue() const 1625 { 1626 // Implementation not inline, because it is a virtual Function 1627 return GetValue( FUNIT_NONE ); 1628 } 1629 1630 // ----------------------------------------------------------------------- 1631 1632 void MetricFormatter::SetMin( sal_Int64 nNewMin, FieldUnit eInUnit ) 1633 { 1634 // Umrechnen auf gewuenschte Einheiten 1635 NumericFormatter::SetMin( MetricField::ConvertValue( nNewMin, mnBaseValue, GetDecimalDigits(), 1636 eInUnit, meUnit ) ); 1637 } 1638 1639 // ----------------------------------------------------------------------- 1640 1641 sal_Int64 MetricFormatter::GetMin( FieldUnit eOutUnit ) const 1642 { 1643 // Umrechnen auf gewuenschte Einheiten 1644 return MetricField::ConvertValue( NumericFormatter::GetMin(), mnBaseValue, 1645 GetDecimalDigits(), meUnit, eOutUnit ); 1646 } 1647 1648 // ----------------------------------------------------------------------- 1649 1650 void MetricFormatter::SetMax( sal_Int64 nNewMax, FieldUnit eInUnit ) 1651 { 1652 // Umrechnen auf gewuenschte Einheiten 1653 NumericFormatter::SetMax( MetricField::ConvertValue( nNewMax, mnBaseValue, GetDecimalDigits(), 1654 eInUnit, meUnit ) ); 1655 } 1656 1657 // ----------------------------------------------------------------------- 1658 1659 sal_Int64 MetricFormatter::GetMax( FieldUnit eOutUnit ) const 1660 { 1661 // Umrechnen auf gewuenschte Einheiten 1662 return MetricField::ConvertValue( NumericFormatter::GetMax(), mnBaseValue, 1663 GetDecimalDigits(), meUnit, eOutUnit ); 1664 } 1665 1666 // ----------------------------------------------------------------------- 1667 1668 void MetricFormatter::SetBaseValue( sal_Int64 nNewBase, FieldUnit eInUnit ) 1669 { 1670 mnBaseValue = MetricField::ConvertValue( nNewBase, mnBaseValue, GetDecimalDigits(), 1671 eInUnit, meUnit ); 1672 } 1673 1674 // ----------------------------------------------------------------------- 1675 1676 sal_Int64 MetricFormatter::GetBaseValue( FieldUnit eOutUnit ) const 1677 { 1678 // Umrechnen auf gewuenschte Einheiten 1679 return MetricField::ConvertValue( mnBaseValue, mnBaseValue, GetDecimalDigits(), 1680 meUnit, eOutUnit ); 1681 } 1682 1683 // ----------------------------------------------------------------------- 1684 1685 void MetricFormatter::Reformat() 1686 { 1687 if ( !GetField() ) 1688 return; 1689 1690 XubString aText = GetField()->GetText(); 1691 if ( meUnit == FUNIT_CUSTOM ) 1692 maCurUnitText = ImplMetricGetUnitText( aText ); 1693 1694 XubString aStr; 1695 // caution: precision loss in double cast 1696 double nTemp = (double)mnLastValue; 1697 sal_Bool bOK = ImplMetricReformat( aText, nTemp, aStr ); 1698 mnLastValue = (sal_Int64)nTemp; 1699 1700 if ( !bOK ) 1701 return; 1702 1703 if ( aStr.Len() ) 1704 { 1705 ImplSetText( aStr ); 1706 if ( meUnit == FUNIT_CUSTOM ) 1707 CustomConvert(); 1708 } 1709 else 1710 SetValue( mnLastValue ); 1711 maCurUnitText.Erase(); 1712 } 1713 1714 // ----------------------------------------------------------------------- 1715 1716 sal_Int64 MetricFormatter::GetCorrectedValue( FieldUnit eOutUnit ) const 1717 { 1718 // Umrechnen auf gewuenschte Einheiten 1719 return MetricField::ConvertValue( mnCorrectedValue, mnBaseValue, GetDecimalDigits(), 1720 meUnit, eOutUnit ); 1721 } 1722 1723 // ----------------------------------------------------------------------- 1724 1725 MetricField::MetricField( Window* pParent, WinBits nWinStyle ) : 1726 SpinField( pParent, nWinStyle ) 1727 { 1728 SetField( this ); 1729 Reformat(); 1730 } 1731 1732 // ----------------------------------------------------------------------- 1733 1734 MetricField::MetricField( Window* pParent, const ResId& rResId ) : 1735 SpinField( WINDOW_METRICFIELD ) 1736 { 1737 rResId.SetRT( RSC_METRICFIELD ); 1738 WinBits nStyle = ImplInitRes( rResId ) ; 1739 SpinField::ImplInit( pParent, nStyle ); 1740 SetField( this ); 1741 ImplLoadRes( rResId ); 1742 1743 if ( !(nStyle & WB_HIDE ) ) 1744 Show(); 1745 } 1746 1747 // ----------------------------------------------------------------------- 1748 1749 void MetricField::ImplLoadRes( const ResId& rResId ) 1750 { 1751 SpinField::ImplLoadRes( rResId ); 1752 MetricFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) ); 1753 1754 sal_uLong nMask = ReadLongRes(); 1755 1756 if ( METRICFIELD_FIRST & nMask ) 1757 mnFirst = ReadLongRes(); 1758 1759 if ( METRICFIELD_LAST & nMask ) 1760 mnLast = ReadLongRes(); 1761 1762 if ( METRICFIELD_SPINSIZE & nMask ) 1763 mnSpinSize = ReadLongRes(); 1764 1765 Reformat(); 1766 } 1767 1768 // ----------------------------------------------------------------------- 1769 1770 MetricField::~MetricField() 1771 { 1772 } 1773 1774 // ----------------------------------------------------------------------- 1775 1776 void MetricField::SetFirst( sal_Int64 nNewFirst, FieldUnit eInUnit ) 1777 { 1778 // convert 1779 nNewFirst = MetricField::ConvertValue( nNewFirst, mnBaseValue, GetDecimalDigits(), 1780 eInUnit, meUnit ); 1781 mnFirst = nNewFirst; 1782 } 1783 1784 // ----------------------------------------------------------------------- 1785 1786 sal_Int64 MetricField::GetFirst( FieldUnit eOutUnit ) const 1787 { 1788 // convert 1789 return MetricField::ConvertValue( mnFirst, mnBaseValue, GetDecimalDigits(), 1790 meUnit, eOutUnit ); 1791 } 1792 1793 // ----------------------------------------------------------------------- 1794 1795 void MetricField::SetLast( sal_Int64 nNewLast, FieldUnit eInUnit ) 1796 { 1797 // Umrechnen 1798 nNewLast = MetricField::ConvertValue( nNewLast, mnBaseValue, GetDecimalDigits(), 1799 eInUnit, meUnit ); 1800 mnLast = nNewLast; 1801 } 1802 1803 // ----------------------------------------------------------------------- 1804 1805 sal_Int64 MetricField::GetLast( FieldUnit eOutUnit ) const 1806 { 1807 // Umrechnen 1808 return MetricField::ConvertValue( mnLast, mnBaseValue, GetDecimalDigits(), 1809 meUnit, eOutUnit ); 1810 } 1811 1812 // ----------------------------------------------------------------------- 1813 1814 long MetricField::PreNotify( NotifyEvent& rNEvt ) 1815 { 1816 if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() ) 1817 { 1818 if ( ImplMetricProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) ) 1819 return 1; 1820 } 1821 1822 return SpinField::PreNotify( rNEvt ); 1823 } 1824 1825 // ----------------------------------------------------------------------- 1826 1827 long MetricField::Notify( NotifyEvent& rNEvt ) 1828 { 1829 if ( rNEvt.GetType() == EVENT_GETFOCUS ) 1830 MarkToBeReformatted( sal_False ); 1831 else if ( rNEvt.GetType() == EVENT_LOSEFOCUS ) 1832 { 1833 if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) ) 1834 Reformat(); 1835 } 1836 1837 return SpinField::Notify( rNEvt ); 1838 } 1839 1840 // ----------------------------------------------------------------------- 1841 1842 void MetricField::DataChanged( const DataChangedEvent& rDCEvt ) 1843 { 1844 SpinField::DataChanged( rDCEvt ); 1845 1846 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) ) 1847 { 1848 String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep(); 1849 String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep(); 1850 if ( IsDefaultLocale() ) 1851 ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() ); 1852 String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep(); 1853 String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep(); 1854 ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this ); 1855 ReformatAll(); 1856 } 1857 } 1858 1859 // ----------------------------------------------------------------------- 1860 1861 void MetricField::Modify() 1862 { 1863 MarkToBeReformatted( sal_True ); 1864 SpinField::Modify(); 1865 } 1866 1867 // ----------------------------------------------------------------------- 1868 1869 void MetricField::Up() 1870 { 1871 FieldUp(); 1872 SpinField::Up(); 1873 } 1874 1875 // ----------------------------------------------------------------------- 1876 1877 void MetricField::Down() 1878 { 1879 FieldDown(); 1880 SpinField::Down(); 1881 } 1882 1883 // ----------------------------------------------------------------------- 1884 1885 void MetricField::First() 1886 { 1887 FieldFirst(); 1888 SpinField::First(); 1889 } 1890 1891 // ----------------------------------------------------------------------- 1892 1893 void MetricField::Last() 1894 { 1895 FieldLast(); 1896 SpinField::Last(); 1897 } 1898 1899 // ----------------------------------------------------------------------- 1900 1901 void MetricField::CustomConvert() 1902 { 1903 maCustomConvertLink.Call( this ); 1904 } 1905 1906 // ----------------------------------------------------------------------- 1907 1908 MetricBox::MetricBox( Window* pParent, WinBits nWinStyle ) : 1909 ComboBox( pParent, nWinStyle ) 1910 { 1911 SetField( this ); 1912 Reformat(); 1913 } 1914 1915 // ----------------------------------------------------------------------- 1916 1917 MetricBox::MetricBox( Window* pParent, const ResId& rResId ) : 1918 ComboBox( WINDOW_METRICBOX ) 1919 { 1920 rResId.SetRT( RSC_METRICBOX ); 1921 WinBits nStyle = ImplInitRes( rResId ); 1922 ComboBox::ImplInit( pParent, nStyle ); 1923 SetField( this ); 1924 Reformat(); 1925 ComboBox::ImplLoadRes( rResId ); 1926 MetricFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) ); 1927 1928 if ( !(nStyle & WB_HIDE ) ) 1929 Show(); 1930 } 1931 1932 // ----------------------------------------------------------------------- 1933 1934 MetricBox::~MetricBox() 1935 { 1936 } 1937 1938 // ----------------------------------------------------------------------- 1939 1940 long MetricBox::PreNotify( NotifyEvent& rNEvt ) 1941 { 1942 if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() ) 1943 { 1944 if ( ImplMetricProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) ) 1945 return 1; 1946 } 1947 1948 return ComboBox::PreNotify( rNEvt ); 1949 } 1950 1951 // ----------------------------------------------------------------------- 1952 1953 long MetricBox::Notify( NotifyEvent& rNEvt ) 1954 { 1955 if ( rNEvt.GetType() == EVENT_GETFOCUS ) 1956 MarkToBeReformatted( sal_False ); 1957 else if ( rNEvt.GetType() == EVENT_LOSEFOCUS ) 1958 { 1959 if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) ) 1960 Reformat(); 1961 } 1962 1963 return ComboBox::Notify( rNEvt ); 1964 } 1965 1966 // ----------------------------------------------------------------------- 1967 1968 void MetricBox::DataChanged( const DataChangedEvent& rDCEvt ) 1969 { 1970 ComboBox::DataChanged( rDCEvt ); 1971 1972 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) ) 1973 { 1974 String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep(); 1975 String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep(); 1976 if ( IsDefaultLocale() ) 1977 ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() ); 1978 String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep(); 1979 String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep(); 1980 ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this ); 1981 ReformatAll(); 1982 } 1983 } 1984 1985 // ----------------------------------------------------------------------- 1986 1987 void MetricBox::Modify() 1988 { 1989 MarkToBeReformatted( sal_True ); 1990 ComboBox::Modify(); 1991 } 1992 1993 // ----------------------------------------------------------------------- 1994 1995 void MetricBox::ReformatAll() 1996 { 1997 double nValue; 1998 XubString aStr; 1999 SetUpdateMode( sal_False ); 2000 sal_uInt16 nEntryCount = GetEntryCount(); 2001 for ( sal_uInt16 i=0; i < nEntryCount; i++ ) 2002 { 2003 ImplMetricReformat( GetEntry( i ), nValue, aStr ); 2004 RemoveEntry( i ); 2005 InsertEntry( aStr, i ); 2006 } 2007 MetricFormatter::Reformat(); 2008 SetUpdateMode( sal_True ); 2009 } 2010 2011 // ----------------------------------------------------------------------- 2012 2013 void MetricBox::CustomConvert() 2014 { 2015 maCustomConvertLink.Call( this ); 2016 } 2017 2018 // ----------------------------------------------------------------------- 2019 2020 void MetricBox::InsertValue( sal_Int64 nValue, FieldUnit eInUnit, sal_uInt16 nPos ) 2021 { 2022 // Umrechnen auf eingestellte Einheiten 2023 nValue = MetricField::ConvertValue( nValue, mnBaseValue, GetDecimalDigits(), 2024 eInUnit, meUnit ); 2025 ComboBox::InsertEntry( CreateFieldText( nValue ), nPos ); 2026 } 2027 2028 // ----------------------------------------------------------------------- 2029 2030 void MetricBox::RemoveValue( sal_Int64 nValue, FieldUnit eInUnit ) 2031 { 2032 // Umrechnen auf eingestellte Einheiten 2033 nValue = MetricField::ConvertValue( nValue, mnBaseValue, GetDecimalDigits(), 2034 eInUnit, meUnit ); 2035 ComboBox::RemoveEntry( CreateFieldText( nValue ) ); 2036 } 2037 2038 // ----------------------------------------------------------------------- 2039 2040 sal_Int64 MetricBox::GetValue( sal_uInt16 nPos, FieldUnit eOutUnit ) const 2041 { 2042 double nValue = 0; 2043 ImplMetricGetValue( ComboBox::GetEntry( nPos ), nValue, mnBaseValue, 2044 GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit ); 2045 2046 // Umrechnen auf eingestellte Einheiten 2047 sal_Int64 nRetValue = MetricField::ConvertValue( (sal_Int64)nValue, mnBaseValue, GetDecimalDigits(), 2048 meUnit, eOutUnit ); 2049 2050 return nRetValue; 2051 } 2052 2053 // ----------------------------------------------------------------------- 2054 2055 sal_uInt16 MetricBox::GetValuePos( sal_Int64 nValue, FieldUnit eInUnit ) const 2056 { 2057 // Umrechnen auf eingestellte Einheiten 2058 nValue = MetricField::ConvertValue( nValue, mnBaseValue, GetDecimalDigits(), 2059 eInUnit, meUnit ); 2060 return ComboBox::GetEntryPos( CreateFieldText( nValue ) ); 2061 } 2062 2063 // ----------------------------------------------------------------------- 2064 2065 sal_Int64 MetricBox::GetValue( FieldUnit eOutUnit ) const 2066 { 2067 // Implementation not inline, because it is a virtual Function 2068 return MetricFormatter::GetValue( eOutUnit ); 2069 } 2070 2071 // ----------------------------------------------------------------------- 2072 2073 sal_Int64 MetricBox::GetValue() const 2074 { 2075 // Implementation not inline, because it is a virtual Function 2076 return GetValue( FUNIT_NONE ); 2077 } 2078 2079 // ----------------------------------------------------------------------- 2080 2081 static sal_Bool ImplCurrencyProcessKeyInput( Edit* pEdit, const KeyEvent& rKEvt, 2082 sal_Bool, sal_Bool bUseThousandSep, const LocaleDataWrapper& rWrapper ) 2083 { 2084 // Es gibt hier kein sinnvolles StrictFormat, also alle 2085 // Zeichen erlauben 2086 return ImplNumericProcessKeyInput( pEdit, rKEvt, sal_False, bUseThousandSep, rWrapper ); 2087 } 2088 2089 // ----------------------------------------------------------------------- 2090 2091 inline sal_Bool ImplCurrencyGetValue( const XubString& rStr, double& rValue, 2092 sal_uInt16 nDecDigits, const LocaleDataWrapper& rWrapper ) 2093 { 2094 // Zahlenwert holen 2095 return ImplNumericGetValue( rStr, rValue, nDecDigits, rWrapper, sal_True ); 2096 } 2097 2098 // ----------------------------------------------------------------------- 2099 2100 sal_Bool CurrencyFormatter::ImplCurrencyReformat( const XubString& rStr, 2101 XubString& rOutStr ) 2102 { 2103 double nValue; 2104 if ( !ImplNumericGetValue( rStr, nValue, GetDecimalDigits(), ImplGetLocaleDataWrapper(), sal_True ) ) 2105 return sal_True; 2106 else 2107 { 2108 double nTempVal = nValue; 2109 // caution: precision loss in double cast 2110 if ( nTempVal > GetMax() ) 2111 nTempVal = (double)GetMax(); 2112 else if ( nTempVal < GetMin()) 2113 nTempVal = (double)GetMin(); 2114 2115 if ( GetErrorHdl().IsSet() && (nValue != nTempVal) ) 2116 { 2117 mnCorrectedValue = (sal_Int64)nTempVal; 2118 if ( !GetErrorHdl().Call( this ) ) 2119 { 2120 mnCorrectedValue = 0; 2121 return sal_False; 2122 } 2123 else 2124 mnCorrectedValue = 0; 2125 } 2126 2127 rOutStr = CreateFieldText( (long)nTempVal ); 2128 return sal_True; 2129 } 2130 } 2131 2132 // ----------------------------------------------------------------------- 2133 2134 inline void CurrencyFormatter::ImplInit() 2135 { 2136 mnType = FORMAT_CURRENCY; 2137 } 2138 2139 // ----------------------------------------------------------------------- 2140 2141 CurrencyFormatter::CurrencyFormatter() 2142 { 2143 ImplInit(); 2144 } 2145 2146 // ----------------------------------------------------------------------- 2147 2148 CurrencyFormatter::~CurrencyFormatter() 2149 { 2150 } 2151 2152 // ----------------------------------------------------------------------- 2153 2154 void CurrencyFormatter::SetCurrencySymbol( const String& rStr ) 2155 { 2156 maCurrencySymbol= rStr; 2157 ReformatAll(); 2158 } 2159 2160 // ----------------------------------------------------------------------- 2161 2162 String CurrencyFormatter::GetCurrencySymbol() const 2163 { 2164 return maCurrencySymbol.Len() ? maCurrencySymbol : ImplGetLocaleDataWrapper().getCurrSymbol(); 2165 } 2166 2167 // ----------------------------------------------------------------------- 2168 2169 void CurrencyFormatter::SetValue( sal_Int64 nNewValue ) 2170 { 2171 SetUserValue( nNewValue ); 2172 mnFieldValue = mnLastValue; 2173 SetEmptyFieldValueData( sal_False ); 2174 } 2175 2176 // ----------------------------------------------------------------------- 2177 2178 XubString CurrencyFormatter::CreateFieldText( sal_Int64 nValue ) const 2179 { 2180 return ImplGetLocaleDataWrapper().getCurr( nValue, GetDecimalDigits(), GetCurrencySymbol(), IsUseThousandSep() ); 2181 } 2182 2183 // ----------------------------------------------------------------------- 2184 2185 sal_Int64 CurrencyFormatter::GetValue() const 2186 { 2187 if ( !GetField() ) 2188 return 0; 2189 2190 double nTempValue; 2191 if ( ImplCurrencyGetValue( GetField()->GetText(), nTempValue, GetDecimalDigits(), ImplGetLocaleDataWrapper() ) ) 2192 { 2193 // caution: precision loss in double cast 2194 if ( nTempValue > mnMax ) 2195 nTempValue = (double)mnMax; 2196 else if ( nTempValue < mnMin ) 2197 nTempValue = (double)mnMin; 2198 return (sal_Int64)nTempValue; 2199 } 2200 else 2201 return mnLastValue; 2202 } 2203 2204 // ----------------------------------------------------------------------- 2205 2206 void CurrencyFormatter::Reformat() 2207 { 2208 if ( !GetField() ) 2209 return; 2210 2211 XubString aStr; 2212 sal_Bool bOK = ImplCurrencyReformat( GetField()->GetText(), aStr ); 2213 if ( !bOK ) 2214 return; 2215 2216 if ( aStr.Len() ) 2217 { 2218 ImplSetText( aStr ); 2219 // caution: precision loss in double cast 2220 double nTemp = (double)mnLastValue; 2221 ImplCurrencyGetValue( aStr, nTemp, GetDecimalDigits(), ImplGetLocaleDataWrapper() ); 2222 mnLastValue = (sal_Int64)nTemp; 2223 } 2224 else 2225 SetValue( mnLastValue ); 2226 } 2227 2228 // ----------------------------------------------------------------------- 2229 2230 CurrencyField::CurrencyField( Window* pParent, WinBits nWinStyle ) : 2231 SpinField( pParent, nWinStyle ) 2232 { 2233 SetField( this ); 2234 Reformat(); 2235 } 2236 2237 // ----------------------------------------------------------------------- 2238 2239 CurrencyField::CurrencyField( Window* pParent, const ResId& rResId ) : 2240 SpinField( WINDOW_CURRENCYFIELD ) 2241 { 2242 rResId.SetRT( RSC_CURRENCYFIELD ); 2243 WinBits nStyle = ImplInitRes( rResId ); 2244 SpinField::ImplInit( pParent, nStyle); 2245 SetField( this ); 2246 ImplLoadRes( rResId ); 2247 2248 if ( !(nStyle & WB_HIDE ) ) 2249 Show(); 2250 } 2251 2252 // ----------------------------------------------------------------------- 2253 2254 void CurrencyField::ImplLoadRes( const ResId& rResId ) 2255 { 2256 SpinField::ImplLoadRes( rResId ); 2257 CurrencyFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) ); 2258 2259 sal_uLong nMask = ReadLongRes(); 2260 2261 if ( CURRENCYFIELD_FIRST & nMask ) 2262 mnFirst = ReadLongRes(); 2263 2264 if ( CURRENCYFIELD_LAST & nMask ) 2265 mnLast = ReadLongRes(); 2266 2267 if ( CURRENCYFIELD_SPINSIZE & nMask ) 2268 mnSpinSize = ReadLongRes(); 2269 2270 Reformat(); 2271 } 2272 2273 // ----------------------------------------------------------------------- 2274 2275 CurrencyField::~CurrencyField() 2276 { 2277 } 2278 2279 // ----------------------------------------------------------------------- 2280 2281 long CurrencyField::PreNotify( NotifyEvent& rNEvt ) 2282 { 2283 if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() ) 2284 { 2285 if ( ImplCurrencyProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) ) 2286 return 1; 2287 } 2288 2289 return SpinField::PreNotify( rNEvt ); 2290 } 2291 2292 // ----------------------------------------------------------------------- 2293 2294 long CurrencyField::Notify( NotifyEvent& rNEvt ) 2295 { 2296 if ( rNEvt.GetType() == EVENT_GETFOCUS ) 2297 MarkToBeReformatted( sal_False ); 2298 else if ( rNEvt.GetType() == EVENT_LOSEFOCUS ) 2299 { 2300 if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) ) 2301 Reformat(); 2302 } 2303 2304 return SpinField::Notify( rNEvt ); 2305 } 2306 2307 // ----------------------------------------------------------------------- 2308 2309 void CurrencyField::DataChanged( const DataChangedEvent& rDCEvt ) 2310 { 2311 SpinField::DataChanged( rDCEvt ); 2312 2313 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) ) 2314 { 2315 String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep(); 2316 String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep(); 2317 if ( IsDefaultLocale() ) 2318 ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() ); 2319 String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep(); 2320 String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep(); 2321 ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this ); 2322 ReformatAll(); 2323 } 2324 } 2325 2326 // ----------------------------------------------------------------------- 2327 2328 void CurrencyField::Modify() 2329 { 2330 MarkToBeReformatted( sal_True ); 2331 SpinField::Modify(); 2332 } 2333 2334 // ----------------------------------------------------------------------- 2335 2336 void CurrencyField::Up() 2337 { 2338 FieldUp(); 2339 SpinField::Up(); 2340 } 2341 2342 // ----------------------------------------------------------------------- 2343 2344 void CurrencyField::Down() 2345 { 2346 FieldDown(); 2347 SpinField::Down(); 2348 } 2349 2350 // ----------------------------------------------------------------------- 2351 2352 void CurrencyField::First() 2353 { 2354 FieldFirst(); 2355 SpinField::First(); 2356 } 2357 2358 // ----------------------------------------------------------------------- 2359 2360 void CurrencyField::Last() 2361 { 2362 FieldLast(); 2363 SpinField::Last(); 2364 } 2365 2366 // ----------------------------------------------------------------------- 2367 2368 CurrencyBox::CurrencyBox( Window* pParent, WinBits nWinStyle ) : 2369 ComboBox( pParent, nWinStyle ) 2370 { 2371 SetField( this ); 2372 Reformat(); 2373 } 2374 2375 // ----------------------------------------------------------------------- 2376 2377 CurrencyBox::CurrencyBox( Window* pParent, const ResId& rResId ) : 2378 ComboBox( WINDOW_CURRENCYBOX ) 2379 { 2380 rResId.SetRT( RSC_CURRENCYBOX ); 2381 WinBits nStyle = ImplInitRes( rResId ); 2382 ComboBox::ImplInit( pParent, nStyle ); 2383 CurrencyFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE *)GetClassRes(), *rResId.GetResMgr() ) ); 2384 SetField( this ); 2385 ComboBox::ImplLoadRes( rResId ); 2386 Reformat(); 2387 2388 if ( !(nStyle & WB_HIDE ) ) 2389 Show(); 2390 } 2391 2392 // ----------------------------------------------------------------------- 2393 2394 CurrencyBox::~CurrencyBox() 2395 { 2396 } 2397 2398 // ----------------------------------------------------------------------- 2399 2400 long CurrencyBox::PreNotify( NotifyEvent& rNEvt ) 2401 { 2402 if ( (rNEvt.GetType() == EVENT_KEYINPUT) && !rNEvt.GetKeyEvent()->GetKeyCode().IsMod2() ) 2403 { 2404 if ( ImplCurrencyProcessKeyInput( GetField(), *rNEvt.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) ) 2405 return 1; 2406 } 2407 2408 return ComboBox::PreNotify( rNEvt ); 2409 } 2410 2411 // ----------------------------------------------------------------------- 2412 2413 long CurrencyBox::Notify( NotifyEvent& rNEvt ) 2414 { 2415 if ( rNEvt.GetType() == EVENT_GETFOCUS ) 2416 MarkToBeReformatted( sal_False ); 2417 else if ( rNEvt.GetType() == EVENT_LOSEFOCUS ) 2418 { 2419 if ( MustBeReformatted() && (GetText().Len() || !IsEmptyFieldValueEnabled()) ) 2420 Reformat(); 2421 } 2422 2423 return ComboBox::Notify( rNEvt ); 2424 } 2425 2426 // ----------------------------------------------------------------------- 2427 2428 void CurrencyBox::DataChanged( const DataChangedEvent& rDCEvt ) 2429 { 2430 ComboBox::DataChanged( rDCEvt ); 2431 2432 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_LOCALE) ) 2433 { 2434 String sOldDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep(); 2435 String sOldThSep = ImplGetLocaleDataWrapper().getNumThousandSep(); 2436 if ( IsDefaultLocale() ) 2437 ImplGetLocaleDataWrapper().setLocale( GetSettings().GetLocale() ); 2438 String sNewDecSep = ImplGetLocaleDataWrapper().getNumDecimalSep(); 2439 String sNewThSep = ImplGetLocaleDataWrapper().getNumThousandSep(); 2440 ImplUpdateSeparators( sOldDecSep, sNewDecSep, sOldThSep, sNewThSep, this ); 2441 ReformatAll(); 2442 } 2443 } 2444 2445 // ----------------------------------------------------------------------- 2446 2447 void CurrencyBox::Modify() 2448 { 2449 MarkToBeReformatted( sal_True ); 2450 ComboBox::Modify(); 2451 } 2452 2453 // ----------------------------------------------------------------------- 2454 2455 void CurrencyBox::ReformatAll() 2456 { 2457 XubString aStr; 2458 SetUpdateMode( sal_False ); 2459 sal_uInt16 nEntryCount = GetEntryCount(); 2460 for ( sal_uInt16 i=0; i < nEntryCount; i++ ) 2461 { 2462 ImplCurrencyReformat( GetEntry( i ), aStr ); 2463 RemoveEntry( i ); 2464 InsertEntry( aStr, i ); 2465 } 2466 CurrencyFormatter::Reformat(); 2467 SetUpdateMode( sal_True ); 2468 } 2469 2470 // ----------------------------------------------------------------------- 2471 2472 void CurrencyBox::InsertValue( sal_Int64 nValue, sal_uInt16 nPos ) 2473 { 2474 ComboBox::InsertEntry( CreateFieldText( nValue ), nPos ); 2475 } 2476 2477 // ----------------------------------------------------------------------- 2478 2479 void CurrencyBox::RemoveValue( sal_Int64 nValue ) 2480 { 2481 ComboBox::RemoveEntry( CreateFieldText( nValue ) ); 2482 } 2483 2484 // ----------------------------------------------------------------------- 2485 2486 sal_Int64 CurrencyBox::GetValue( sal_uInt16 nPos ) const 2487 { 2488 double nValue = 0; 2489 ImplCurrencyGetValue( ComboBox::GetEntry( nPos ), nValue, GetDecimalDigits(), ImplGetLocaleDataWrapper() ); 2490 return (sal_Int64)nValue; 2491 } 2492 2493 // ----------------------------------------------------------------------- 2494 2495 sal_uInt16 CurrencyBox::GetValuePos( sal_Int64 nValue ) const 2496 { 2497 return ComboBox::GetEntryPos( CreateFieldText( nValue ) ); 2498 } 2499 2500 // ----------------------------------------------------------------------- 2501 2502 sal_Int64 CurrencyBox::GetValue() const 2503 { 2504 // Implementation not inline, because it is a virtual Function 2505 return CurrencyFormatter::GetValue(); 2506 } 2507