1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: longcurr.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include <sot/object.hxx>
36 #include <sot/factory.hxx>
37 #include <tools/debug.hxx>
38 #include <tools/bigint.hxx>
44 #include <vcl/event.hxx>
45 #include <vcl/svapp.hxx>
46 #include <vcl/svdata.hxx>
47 #include <vcl/longcurr.hxx>
50 #include <unotools/localedatawrapper.hxx>
53 // =======================================================================
55 #define FORMAT_LONGCURRENCY 4
57 // =======================================================================
59 static BigInt
ImplPower10( USHORT n
)
64 for ( i
=0; i
< n
; i
++ )
70 // -----------------------------------------------------------------------
72 static XubString
ImplGetCurr( const LocaleDataWrapper
& rLocaleDataWrapper
, const BigInt
&rNumber
, USHORT nDigits
, const String
& rCurrSymbol
, BOOL bShowThousandSep
)
74 DBG_ASSERT( nDigits
< 10, "LongCurrency duerfen nur maximal 9 Nachkommastellen haben" );
76 if ( rNumber
.IsZero() || (long)rNumber
)
77 return rLocaleDataWrapper
.getCurr( (long)rNumber
, nDigits
, rCurrSymbol
, bShowThousandSep
);
79 BigInt
aTmp( ImplPower10( nDigits
) );
80 BigInt
aInteger( rNumber
);
83 BigInt
aFraction( rNumber
);
86 if ( !aInteger
.IsZero() )
91 if ( rNumber
.IsNeg() )
94 XubString aTemplate
= rLocaleDataWrapper
.getCurr( (long)aFraction
, nDigits
, rCurrSymbol
, bShowThousandSep
);
95 while( !aInteger
.IsZero() )
100 if( !aInteger
.IsZero() )
103 XubString aFractionStr
= rLocaleDataWrapper
.getNum( (long)aFraction
, 0 );
105 xub_StrLen nSPos
= aTemplate
.Search( '1' );
106 if ( aFractionStr
.Len() == 1 )
107 aTemplate
.SetChar( nSPos
, aFractionStr
.GetChar( 0 ) );
110 aTemplate
.Erase( nSPos
, 1 );
111 aTemplate
.Insert( aFractionStr
, nSPos
);
118 // -----------------------------------------------------------------------
120 static BOOL
ImplNumericProcessKeyInput( Edit
*, const KeyEvent
& rKEvt
,
121 BOOL bStrictFormat
, BOOL bThousandSep
,
122 const LocaleDataWrapper
& rLocaleDataWrapper
)
124 if ( !bStrictFormat
)
128 sal_Unicode cChar
= rKEvt
.GetCharCode();
129 USHORT nGroup
= rKEvt
.GetKeyCode().GetGroup();
131 if ( (nGroup
== KEYGROUP_FKEYS
) || (nGroup
== KEYGROUP_CURSOR
) ||
132 (nGroup
== KEYGROUP_MISC
) ||
133 ((cChar
>= '0') && (cChar
<= '9')) ||
134 (bThousandSep
&& (cChar
== rLocaleDataWrapper
.getNumThousandSep())) ||
135 (cChar
== rLocaleDataWrapper
.getNumDecimalSep() ) ||
143 // -----------------------------------------------------------------------
145 static BOOL
ImplNumericGetValue( const XubString
& rStr
, BigInt
& rValue
,
146 USHORT nDecDigits
, const LocaleDataWrapper
& rLocaleDataWrapper
,
147 BOOL bCurrency
= FALSE
)
149 XubString aStr
= rStr
;
153 BOOL bNegative
= FALSE
;
156 // Reaktion auf leeren String
160 // Fuehrende und nachfolgende Leerzeichen entfernen
161 aStr
.EraseLeadingAndTrailingChars( ' ' );
163 // Position des Dezimalpunktes suchen
164 nDecPos
= aStr
.Search( rLocaleDataWrapper
.getNumDecimalSep() );
166 if ( nDecPos
!= STRING_NOTFOUND
)
168 aStr1
= aStr
.Copy( 0, nDecPos
);
169 aStr2
= aStr
.Copy( nDecPos
+1 );
177 if ( (aStr
.GetChar( 0 ) == '(') && (aStr
.GetChar( aStr
.Len()-1 ) == ')') )
181 for ( i
=0; i
< aStr
.Len(); i
++ )
183 if ( (aStr
.GetChar( i
) >= '0') && (aStr
.GetChar( i
) <= '9') )
185 else if ( aStr
.GetChar( i
) == '-' )
192 if ( !bNegative
&& bCurrency
&& aStr
.Len() )
194 USHORT nFormat
= rLocaleDataWrapper
.getCurrNegativeFormat();
195 if ( (nFormat
== 3) || (nFormat
== 6) ||
196 (nFormat
== 7) || (nFormat
== 10) )
198 for ( i
= (USHORT
)(aStr
.Len()-1); i
> 0; i
++ )
200 if ( (aStr
.GetChar( i
) >= '0') && (aStr
.GetChar( i
) <= '9') )
202 else if ( aStr
.GetChar( i
) == '-' )
213 if ( aStr1
.GetChar( 0 ) == '-' )
217 // Alle unerwuenschten Zeichen rauswerfen
218 for ( i
=0; i
< aStr1
.Len(); )
220 if ( (aStr1
.GetChar( i
) >= '0') && (aStr1
.GetChar( i
) <= '9') )
225 for ( i
=0; i
< aStr2
.Len(); )
227 if ( (aStr2
.GetChar( i
) >= '0') && (aStr2
.GetChar( i
) <= '9') )
233 if ( !aStr1
.Len() && !aStr2
.Len() )
239 aStr1
.Insert( '-', 0 );
241 // Nachkommateil zurechtstutzen und dabei runden
243 if ( aStr2
.Len() > nDecDigits
)
245 if ( aStr2
.GetChar( nDecDigits
) >= '5' )
247 aStr2
.Erase( nDecDigits
);
249 if ( aStr2
.Len() < nDecDigits
)
250 aStr2
.Expand( nDecDigits
, '0' );
255 // Bereichsueberpruefung
256 BigInt
nValue( aStr
);
270 // =======================================================================
272 static BOOL
ImplLongCurrencyProcessKeyInput( Edit
* pEdit
, const KeyEvent
& rKEvt
,
273 BOOL
, BOOL bUseThousandSep
, const LocaleDataWrapper
& rLocaleDataWrapper
)
275 // Es gibt hier kein sinnvolles StrictFormat, also alle
277 return ImplNumericProcessKeyInput( pEdit
, rKEvt
, FALSE
, bUseThousandSep
, rLocaleDataWrapper
);
280 // -----------------------------------------------------------------------
282 inline BOOL
ImplLongCurrencyGetValue( const XubString
& rStr
, BigInt
& rValue
,
283 USHORT nDecDigits
, const LocaleDataWrapper
& rLocaleDataWrapper
)
286 return ImplNumericGetValue( rStr
, rValue
, nDecDigits
, rLocaleDataWrapper
, TRUE
);
289 // -----------------------------------------------------------------------
291 BOOL
ImplLongCurrencyReformat( const XubString
& rStr
, BigInt nMin
, BigInt nMax
,
293 const LocaleDataWrapper
& rLocaleDataWrapper
, String
& rOutStr
,
294 LongCurrencyFormatter
& rFormatter
)
297 if ( !ImplNumericGetValue( rStr
, nValue
, nDecDigits
, rLocaleDataWrapper
, TRUE
) )
301 BigInt nTempVal
= nValue
;
302 if ( nTempVal
> nMax
)
304 else if ( nTempVal
< nMin
)
307 if ( rFormatter
.GetErrorHdl().IsSet() && (nValue
!= nTempVal
) )
309 rFormatter
.mnCorrectedValue
= nTempVal
;
310 if ( !rFormatter
.GetErrorHdl().Call( &rFormatter
) )
312 rFormatter
.mnCorrectedValue
= 0;
317 rFormatter
.mnCorrectedValue
= 0;
321 rOutStr
= ImplGetCurr( rLocaleDataWrapper
, nTempVal
, nDecDigits
, rFormatter
.GetCurrencySymbol(), rFormatter
.IsUseThousandSep() );
327 // =======================================================================
329 void LongCurrencyFormatter::ImpInit()
336 mnCorrectedValue
= 0;
338 mnType
= FORMAT_LONGCURRENCY
;
339 mbThousandSep
= TRUE
;
340 SetDecimalDigits( 0 );
343 // -----------------------------------------------------------------------
345 LongCurrencyFormatter::LongCurrencyFormatter()
350 // -----------------------------------------------------------------------
352 void LongCurrencyFormatter::ImplLoadRes( const ResId
& rResId
)
356 ResMgr
* pMgr
= rResId
.GetResMgr();
359 ULONG nMask
= pMgr
->ReadLong();
361 if ( NUMERICFORMATTER_MIN
& nMask
)
362 mnMin
= pMgr
->ReadLong();
364 if ( NUMERICFORMATTER_MAX
& nMask
)
365 mnMax
= pMgr
->ReadLong();
367 if ( NUMERICFORMATTER_STRICTFORMAT
& nMask
)
368 SetStrictFormat( (BOOL
)pMgr
->ReadShort() );
370 if ( NUMERICFORMATTER_DECIMALDIGITS
& nMask
)
371 SetDecimalDigits( pMgr
->ReadShort() );
373 if ( NUMERICFORMATTER_VALUE
& nMask
)
375 mnFieldValue
= pMgr
->ReadLong();
376 if ( mnFieldValue
> mnMax
)
377 mnFieldValue
= mnMax
;
378 else if ( mnFieldValue
< mnMin
)
379 mnFieldValue
= mnMin
;
380 mnLastValue
= mnFieldValue
;
385 // -----------------------------------------------------------------------
387 LongCurrencyFormatter::~LongCurrencyFormatter()
391 // -----------------------------------------------------------------------
393 void LongCurrencyFormatter::SetCurrencySymbol( const String
& rStr
)
395 maCurrencySymbol
= rStr
;
399 // -----------------------------------------------------------------------
401 String
LongCurrencyFormatter::GetCurrencySymbol() const
403 return maCurrencySymbol
.Len() ? maCurrencySymbol
: GetLocaleDataWrapper().getCurrSymbol();
406 // -----------------------------------------------------------------------
408 void LongCurrencyFormatter::SetValue( BigInt nNewValue
)
410 SetUserValue( nNewValue
);
411 mnFieldValue
= mnLastValue
;
412 SetEmptyFieldValueData( FALSE
);
415 // -----------------------------------------------------------------------
417 void LongCurrencyFormatter::SetUserValue( BigInt nNewValue
)
419 if ( nNewValue
> mnMax
)
421 else if ( nNewValue
< mnMin
)
423 mnLastValue
= nNewValue
;
428 XubString aStr
= ImplGetCurr( GetLocaleDataWrapper(), nNewValue
, GetDecimalDigits(), GetCurrencySymbol(), IsUseThousandSep() );
429 if ( GetField()->HasFocus() )
431 Selection aSelection
= GetField()->GetSelection();
432 GetField()->SetText( aStr
);
433 GetField()->SetSelection( aSelection
);
436 GetField()->SetText( aStr
);
437 MarkToBeReformatted( FALSE
);
440 // -----------------------------------------------------------------------
442 BigInt
LongCurrencyFormatter::GetValue() const
448 if ( ImplLongCurrencyGetValue( GetField()->GetText(), nTempValue
, GetDecimalDigits(), GetLocaleDataWrapper() ) )
450 if ( nTempValue
> mnMax
)
452 else if ( nTempValue
< mnMin
)
460 // -----------------------------------------------------------------------
462 void LongCurrencyFormatter::Reformat()
467 if ( !GetField()->GetText().Len() && ImplGetEmptyFieldValue() )
471 BOOL bOK
= ImplLongCurrencyReformat( GetField()->GetText(), mnMin
, mnMax
,
472 GetDecimalDigits(), GetLocaleDataWrapper(), aStr
, *this );
478 GetField()->SetText( aStr
);
479 MarkToBeReformatted( FALSE
);
480 ImplLongCurrencyGetValue( aStr
, mnLastValue
, GetDecimalDigits(), GetLocaleDataWrapper() );
483 SetValue( mnLastValue
);
486 // -----------------------------------------------------------------------
488 void LongCurrencyFormatter::ReformatAll()
493 // -----------------------------------------------------------------------
495 void LongCurrencyFormatter::SetMin( BigInt nNewMin
)
501 // -----------------------------------------------------------------------
503 void LongCurrencyFormatter::SetMax( BigInt nNewMax
)
509 // -----------------------------------------------------------------------
511 void LongCurrencyFormatter::SetUseThousandSep( BOOL b
)
518 // -----------------------------------------------------------------------
520 void LongCurrencyFormatter::SetDecimalDigits( USHORT nDigits
)
522 // DBG_ASSERT( nDigits < 10, "LongCurrency duerfen nur maximal 9 Nachkommastellen haben" );
527 mnDecimalDigits
= nDigits
;
531 // -----------------------------------------------------------------------
533 USHORT
LongCurrencyFormatter::GetDecimalDigits() const
535 return mnDecimalDigits
;
538 // -----------------------------------------------------------------------
540 BOOL
LongCurrencyFormatter::IsValueModified() const
542 if ( ImplGetEmptyFieldValue() )
543 return !IsEmptyValue();
544 else if ( GetValue() != mnFieldValue
)
550 // -----------------------------------------------------------------------
552 void LongCurrencyFormatter::SetEmptyValue()
554 GetField()->SetText( ImplGetSVEmptyStr() );
555 SetEmptyFieldValueData( TRUE
);
558 // -----------------------------------------------------------------------
560 BigInt
LongCurrencyFormatter::Normalize( BigInt nValue
) const
562 return (nValue
* ImplPower10( GetDecimalDigits() ) );
565 // -----------------------------------------------------------------------
567 BigInt
LongCurrencyFormatter::Denormalize( BigInt nValue
) const
569 BigInt nFactor
= ImplPower10( GetDecimalDigits() );
570 BigInt nTmp
= nFactor
;
577 // =======================================================================
579 void ImplNewLongCurrencyFieldValue( LongCurrencyField
* pField
, BigInt nNewValue
)
581 Selection aSelect
= pField
->GetSelection();
583 XubString aText
= pField
->GetText();
584 BOOL bLastSelected
= ((xub_StrLen
)aSelect
.Max() == aText
.Len()) ? TRUE
: FALSE
;
586 BigInt nOldLastValue
= pField
->mnLastValue
;
587 pField
->SetUserValue( nNewValue
);
588 pField
->mnLastValue
= nOldLastValue
;
592 if ( !aSelect
.Len() )
593 aSelect
.Min() = SELECTION_MAX
;
594 aSelect
.Max() = SELECTION_MAX
;
596 pField
->SetSelection( aSelect
);
597 pField
->SetModifyFlag();
601 // =======================================================================
603 LongCurrencyField::LongCurrencyField( Window
* pParent
, WinBits nWinStyle
) :
604 SpinField( pParent
, nWinStyle
)
614 // -----------------------------------------------------------------------
616 LongCurrencyField::LongCurrencyField( Window
* pParent
, const ResId
& rResId
) :
617 SpinField( WINDOW_NUMERICFIELD
)
619 rResId
.SetRT( RSC_NUMERICFIELD
);
620 WinBits nStyle
= ImplInitRes( rResId
) ;
621 SpinField::ImplInit( pParent
, nStyle
);
630 if ( !(nStyle
& WB_HIDE
) )
634 // -----------------------------------------------------------------------
636 void LongCurrencyField::ImplLoadRes( const ResId
& rResId
)
638 SpinField::ImplLoadRes( rResId
);
639 LongCurrencyFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE
*)GetClassRes(), *rResId
.GetResMgr() ) );
641 ULONG nMask
= ReadLongRes();
642 if ( CURRENCYFIELD_FIRST
& nMask
)
643 mnFirst
= ReadLongRes();
645 if ( CURRENCYFIELD_LAST
& nMask
)
646 mnLast
= ReadLongRes();
648 if ( CURRENCYFIELD_SPINSIZE
& nMask
)
649 mnSpinSize
= ReadLongRes();
652 // -----------------------------------------------------------------------
654 LongCurrencyField::~LongCurrencyField()
658 // -----------------------------------------------------------------------
660 long LongCurrencyField::PreNotify( NotifyEvent
& rNEvt
)
662 if( rNEvt
.GetType() == EVENT_KEYINPUT
)
664 if ( ImplLongCurrencyProcessKeyInput( GetField(), *rNEvt
.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), GetLocaleDataWrapper() ) )
667 return SpinField::PreNotify( rNEvt
);
670 // -----------------------------------------------------------------------
672 long LongCurrencyField::Notify( NotifyEvent
& rNEvt
)
674 if( rNEvt
.GetType() == EVENT_GETFOCUS
)
676 MarkToBeReformatted( FALSE
);
678 else if( rNEvt
.GetType() == EVENT_LOSEFOCUS
)
680 if ( MustBeReformatted() )
686 return SpinField::Notify( rNEvt
);
689 // -----------------------------------------------------------------------
691 void LongCurrencyField::Modify()
693 MarkToBeReformatted( TRUE
);
697 // -----------------------------------------------------------------------
699 void LongCurrencyField::Up()
701 BigInt nValue
= GetValue();
702 nValue
+= mnSpinSize
;
703 if ( nValue
> mnMax
)
706 ImplNewLongCurrencyFieldValue( this, nValue
);
710 // -----------------------------------------------------------------------
712 void LongCurrencyField::Down()
714 BigInt nValue
= GetValue();
715 nValue
-= mnSpinSize
;
716 if ( nValue
< mnMin
)
719 ImplNewLongCurrencyFieldValue( this, nValue
);
723 // -----------------------------------------------------------------------
725 void LongCurrencyField::First()
727 ImplNewLongCurrencyFieldValue( this, mnFirst
);
731 // -----------------------------------------------------------------------
733 void LongCurrencyField::Last()
735 ImplNewLongCurrencyFieldValue( this, mnLast
);
739 // =======================================================================
741 LongCurrencyBox::LongCurrencyBox( Window
* pParent
, WinBits nWinStyle
) :
742 ComboBox( pParent
, nWinStyle
)
748 // -----------------------------------------------------------------------
750 LongCurrencyBox::LongCurrencyBox( Window
* pParent
, const ResId
& rResId
) :
751 ComboBox( WINDOW_NUMERICFIELD
)
754 WinBits nStyle
= ImplInitRes( rResId
) ;
755 ComboBox::ImplLoadRes( rResId
);
756 ImplInit( pParent
, nStyle
);
757 LongCurrencyFormatter::ImplLoadRes( rResId
);
760 if ( !(nStyle
& WB_HIDE
) )
764 // -----------------------------------------------------------------------
766 LongCurrencyBox::~LongCurrencyBox()
770 // -----------------------------------------------------------------------
772 long LongCurrencyBox::PreNotify( NotifyEvent
& rNEvt
)
774 if( rNEvt
.GetType() == EVENT_KEYINPUT
)
776 if ( ImplLongCurrencyProcessKeyInput( GetField(), *rNEvt
.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), GetLocaleDataWrapper() ) )
779 return ComboBox::PreNotify( rNEvt
);
782 // -----------------------------------------------------------------------
784 long LongCurrencyBox::Notify( NotifyEvent
& rNEvt
)
786 if( rNEvt
.GetType() == EVENT_GETFOCUS
)
788 MarkToBeReformatted( FALSE
);
790 else if( rNEvt
.GetType() == EVENT_LOSEFOCUS
)
792 if ( MustBeReformatted() )
798 return ComboBox::Notify( rNEvt
);
801 // -----------------------------------------------------------------------
803 void LongCurrencyBox::Modify()
805 MarkToBeReformatted( TRUE
);
809 // -----------------------------------------------------------------------
811 void LongCurrencyBox::ReformatAll()
814 SetUpdateMode( FALSE
);
815 USHORT nEntryCount
= GetEntryCount();
816 for ( USHORT i
=0; i
< nEntryCount
; i
++ )
818 ImplLongCurrencyReformat( GetEntry( i
), mnMin
, mnMax
,
819 GetDecimalDigits(), GetLocaleDataWrapper(),
822 InsertEntry( aStr
, i
);
824 LongCurrencyFormatter::Reformat();
825 SetUpdateMode( TRUE
);
828 // -----------------------------------------------------------------------
830 void LongCurrencyBox::InsertValue( BigInt nValue
, USHORT nPos
)
832 XubString aStr
= ImplGetCurr( GetLocaleDataWrapper(), nValue
, GetDecimalDigits(), GetCurrencySymbol(), IsUseThousandSep() );
833 ComboBox::InsertEntry( aStr
, nPos
);
836 // -----------------------------------------------------------------------
838 void LongCurrencyBox::RemoveValue( BigInt nValue
)
840 XubString aStr
= ImplGetCurr( GetLocaleDataWrapper(), nValue
, GetDecimalDigits(), GetCurrencySymbol(), IsUseThousandSep() );
841 ComboBox::RemoveEntry( aStr
);
844 // -----------------------------------------------------------------------
846 BigInt
LongCurrencyBox::GetValue( USHORT nPos
) const
849 ImplLongCurrencyGetValue( ComboBox::GetEntry( nPos
), nValue
,
850 GetDecimalDigits(), GetLocaleDataWrapper() );
854 // -----------------------------------------------------------------------
856 USHORT
LongCurrencyBox::GetValuePos( BigInt nValue
) const
858 XubString aStr
= ImplGetCurr( GetLocaleDataWrapper(), nValue
, GetDecimalDigits(), GetCurrencySymbol(), IsUseThousandSep() );
859 return ComboBox::GetEntryPos( aStr
);
862 // =======================================================================