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