1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "sal/config.h"
22 #include <comphelper/processfactory.hxx>
23 #include <comphelper/string.hxx>
25 #include "tools/debug.hxx"
29 #include "vcl/dialog.hxx"
30 #include "vcl/field.hxx"
31 #include "vcl/event.hxx"
32 #include "vcl/svapp.hxx"
37 #include "i18nutil/unicode.hxx"
39 #include "rtl/math.hxx"
41 #include <unotools/localedatawrapper.hxx>
43 using namespace ::com::sun::star
;
44 using namespace ::comphelper
;
46 // -----------------------------------------------------------------------
48 #define FORMAT_NUMERIC 1
49 #define FORMAT_METRIC 2
50 #define FORMAT_CURRENCY 3
52 // -----------------------------------------------------------------------
54 static sal_Int64
ImplPower10( sal_uInt16 n
)
59 for ( i
=0; i
< n
; i
++ )
65 // -----------------------------------------------------------------------
67 static bool ImplNumericProcessKeyInput( Edit
*, const KeyEvent
& rKEvt
,
68 bool bStrictFormat
, bool bThousandSep
,
69 const LocaleDataWrapper
& rLocaleDataWrappper
)
75 sal_Unicode cChar
= rKEvt
.GetCharCode();
76 sal_uInt16 nGroup
= rKEvt
.GetKeyCode().GetGroup();
78 if ( (nGroup
== KEYGROUP_FKEYS
) || (nGroup
== KEYGROUP_CURSOR
) ||
79 (nGroup
== KEYGROUP_MISC
) ||
80 ((cChar
>= '0') && (cChar
<= '9')) ||
81 string::equals(rLocaleDataWrappper
.getNumDecimalSep(), cChar
) ||
82 (bThousandSep
&& string::equals(rLocaleDataWrappper
.getNumThousandSep(), cChar
)) ||
90 // -----------------------------------------------------------------------
92 static bool ImplNumericGetValue( const OUString
& rStr
, sal_Int64
& rValue
,
93 sal_uInt16 nDecDigits
, const LocaleDataWrapper
& rLocaleDataWrappper
,
94 bool bCurrency
= false )
97 OUStringBuffer aStr1
, aStr2
;
98 bool bNegative
= false;
101 // react on empty string
102 if ( rStr
.isEmpty() )
105 // remove leading and trailing spaces
108 // find position of decimal point
109 nDecPos
= aStr
.indexOf( rLocaleDataWrappper
.getNumDecimalSep() );
112 aStr1
.append(aStr
.getStr(), nDecPos
);
113 aStr2
.append(aStr
.getStr()+nDecPos
+1);
121 if ( aStr
[0] == '(' && aStr
[aStr
.getLength()-1] == ')' )
125 for (sal_Int32 i
=0; i
< aStr
.getLength(); i
++ )
127 if ( (aStr
[i
] >= '0') && (aStr
[i
] <= '9') )
129 else if ( aStr
[i
] == '-' )
136 if ( !bNegative
&& bCurrency
&& !aStr
.isEmpty() )
138 sal_uInt16 nFormat
= rLocaleDataWrappper
.getCurrNegativeFormat();
139 if ( (nFormat
== 3) || (nFormat
== 6) || // $1- || 1-$
140 (nFormat
== 7) || (nFormat
== 10) ) // 1$- || 1 $-
142 for (sal_Int32 i
= aStr
.getLength()-1; i
> 0; --i
)
144 if ( (aStr
[i
] >= '0') && (aStr
[i
] <= '9') )
146 else if ( aStr
[i
] == '-' )
157 if ( !aStr1
.isEmpty() && aStr1
[0] == '-')
161 // remove all unwanted charaters
162 for (sal_Int32 i
=0; i
< aStr1
.getLength(); )
164 if ( (aStr1
[i
] >= '0') && (aStr1
[i
] <= '9') )
167 aStr1
.remove( i
, 1 );
169 for (sal_Int32 i
=0; i
< aStr2
.getLength(); )
171 if ((aStr2
[i
] >= '0') && (aStr2
[i
] <= '9'))
177 if ( aStr1
.isEmpty() && aStr2
.isEmpty() )
180 if ( aStr1
.isEmpty() )
185 // prune and round fraction
187 if (aStr2
.getLength() > nDecDigits
)
189 if (aStr2
[nDecDigits
] >= '5')
191 string::truncateToLength(aStr2
, nDecDigits
);
193 if (aStr2
.getLength() < nDecDigits
)
194 string::padToLength(aStr2
, nDecDigits
, '0');
196 aStr
= aStr1
.makeStringAndClear() + aStr2
.makeStringAndClear();
199 sal_Int64 nValue
= aStr
.toInt64();
202 // check if string is equivalent to zero
203 sal_Int16 nIndex
= bNegative
? 1 : 0;
204 while (nIndex
< aStr
.getLength() && aStr
[nIndex
] == '0')
206 if( nIndex
< aStr
.getLength() )
208 rValue
= bNegative
? SAL_MIN_INT64
: SAL_MAX_INT64
;
225 static void ImplUpdateSeparatorString( String
& io_rText
,
226 const String
& rOldDecSep
, const String
& rNewDecSep
,
227 const String
& rOldThSep
, const String
& rNewThSep
)
229 OUStringBuffer
aBuf( io_rText
.Len() );
230 xub_StrLen nIndexDec
= 0, nIndexTh
= 0, nIndex
= 0;
232 const sal_Unicode
* pBuffer
= io_rText
.GetBuffer();
233 while( nIndex
!= STRING_NOTFOUND
)
235 nIndexDec
= io_rText
.Search( rOldDecSep
, nIndex
);
236 nIndexTh
= io_rText
.Search( rOldThSep
, nIndex
);
237 if( (nIndexTh
!= STRING_NOTFOUND
&& nIndexDec
!= STRING_NOTFOUND
&& nIndexTh
< nIndexDec
)
238 || (nIndexTh
!= STRING_NOTFOUND
&& nIndexDec
== STRING_NOTFOUND
)
241 aBuf
.append( pBuffer
+ nIndex
, nIndexTh
- nIndex
);
242 aBuf
.append( rNewThSep
);
243 nIndex
= nIndexTh
+ rOldThSep
.Len();
245 else if( nIndexDec
!= STRING_NOTFOUND
)
247 aBuf
.append( pBuffer
+ nIndex
, nIndexDec
- nIndex
);
248 aBuf
.append( rNewDecSep
);
249 nIndex
= nIndexDec
+ rOldDecSep
.Len();
253 aBuf
.append( pBuffer
+ nIndex
);
254 nIndex
= STRING_NOTFOUND
;
258 io_rText
= aBuf
.makeStringAndClear();
261 static void ImplUpdateSeparators( const String
& rOldDecSep
, const String
& rNewDecSep
,
262 const String
& rOldThSep
, const String
& rNewThSep
,
265 bool bChangeDec
= (rOldDecSep
!= rNewDecSep
);
266 bool bChangeTh
= (rOldThSep
!= rNewThSep
);
268 if( bChangeDec
|| bChangeTh
)
270 sal_Bool bUpdateMode
= pEdit
->IsUpdateMode();
271 pEdit
->SetUpdateMode( sal_False
);
272 String aText
= pEdit
->GetText();
273 ImplUpdateSeparatorString( aText
, rOldDecSep
, rNewDecSep
, rOldThSep
, rNewThSep
);
274 pEdit
->SetText( aText
);
276 ComboBox
* pCombo
= dynamic_cast<ComboBox
*>(pEdit
);
279 // update box entries
280 sal_uInt16 nEntryCount
= pCombo
->GetEntryCount();
281 for ( sal_uInt16 i
=0; i
< nEntryCount
; i
++ )
283 aText
= pCombo
->GetEntry( i
);
284 void* pEntryData
= pCombo
->GetEntryData( i
);
285 ImplUpdateSeparatorString( aText
, rOldDecSep
, rNewDecSep
, rOldThSep
, rNewThSep
);
286 pCombo
->RemoveEntry( i
);
287 pCombo
->InsertEntry( aText
, i
);
288 pCombo
->SetEntryData( i
, pEntryData
);
292 pEdit
->SetUpdateMode( bUpdateMode
);
296 // -----------------------------------------------------------------------
298 FormatterBase::FormatterBase( Edit
* pField
)
301 mpLocaleDataWrapper
= NULL
;
302 mbReformat
= sal_False
;
303 mbStrictFormat
= sal_False
;
304 mbEmptyFieldValue
= sal_False
;
305 mbEmptyFieldValueEnabled
= sal_False
;
306 mbDefaultLocale
= sal_True
;
309 // -----------------------------------------------------------------------
311 FormatterBase::~FormatterBase()
313 delete mpLocaleDataWrapper
;
316 // -----------------------------------------------------------------------
318 LocaleDataWrapper
& FormatterBase::ImplGetLocaleDataWrapper() const
320 if ( !mpLocaleDataWrapper
)
322 ((FormatterBase
*)this)->mpLocaleDataWrapper
= new LocaleDataWrapper( GetLanguageTag() );
324 return *mpLocaleDataWrapper
;
327 const LocaleDataWrapper
& FormatterBase::GetLocaleDataWrapper() const
329 return ImplGetLocaleDataWrapper();
332 // -----------------------------------------------------------------------
334 void FormatterBase::Reformat()
338 // -----------------------------------------------------------------------
340 void FormatterBase::ReformatAll()
345 // -----------------------------------------------------------------------
347 void FormatterBase::SetStrictFormat( sal_Bool bStrict
)
349 if ( bStrict
!= mbStrictFormat
)
351 mbStrictFormat
= bStrict
;
352 if ( mbStrictFormat
)
357 // -----------------------------------------------------------------------
359 void FormatterBase::SetLocale( const lang::Locale
& rLocale
)
361 ImplGetLocaleDataWrapper().setLanguageTag( LanguageTag( rLocale
) );
362 mbDefaultLocale
= sal_False
;
366 // -----------------------------------------------------------------------
368 const lang::Locale
& FormatterBase::GetLocale() const
370 if ( !mpLocaleDataWrapper
|| mbDefaultLocale
)
373 return mpField
->GetSettings().GetLanguageTag().getLocale();
375 return Application::GetSettings().GetLanguageTag().getLocale();
378 return mpLocaleDataWrapper
->getLanguageTag().getLocale();
381 // -----------------------------------------------------------------------
383 const LanguageTag
& FormatterBase::GetLanguageTag() const
385 if ( !mpLocaleDataWrapper
|| mbDefaultLocale
)
388 return mpField
->GetSettings().GetLanguageTag();
390 return Application::GetSettings().GetLanguageTag();
393 return mpLocaleDataWrapper
->getLanguageTag();
396 // -----------------------------------------------------------------------
398 const AllSettings
& FormatterBase::GetFieldSettings() const
401 return mpField
->GetSettings();
403 return Application::GetSettings();
406 // -----------------------------------------------------------------------
408 void FormatterBase::ImplSetText( const OUString
& rText
, Selection
* pNewSelection
)
413 mpField
->SetText( rText
, *pNewSelection
);
416 Selection aSel
= mpField
->GetSelection();
417 aSel
.Min() = aSel
.Max();
418 mpField
->SetText( rText
, aSel
);
421 MarkToBeReformatted( sal_False
);
425 // -----------------------------------------------------------------------
427 void FormatterBase::SetEmptyFieldValue()
430 mpField
->SetText( ImplGetSVEmptyStr() );
431 mbEmptyFieldValue
= sal_True
;
434 // -----------------------------------------------------------------------
436 sal_Bool
FormatterBase::IsEmptyFieldValue() const
438 return (!mpField
|| mpField
->GetText().isEmpty());
441 // -----------------------------------------------------------------------
443 sal_Bool
NumericFormatter::ImplNumericReformat( const OUString
& rStr
, sal_Int64
& rValue
,
446 if ( !ImplNumericGetValue( rStr
, rValue
, GetDecimalDigits(), ImplGetLocaleDataWrapper() ) )
450 sal_Int64 nTempVal
= rValue
;
451 if ( nTempVal
> mnMax
)
453 else if ( nTempVal
< mnMin
)
456 if ( GetErrorHdl().IsSet() && (rValue
!= nTempVal
) )
458 mnCorrectedValue
= nTempVal
;
459 if ( !GetErrorHdl().Call( this ) )
461 mnCorrectedValue
= 0;
465 mnCorrectedValue
= 0;
468 rOutStr
= CreateFieldText( nTempVal
);
473 // -----------------------------------------------------------------------
475 void NumericFormatter::ImplInit()
480 mnMax
= 0x7FFFFFFFFFFFFFFFLL
;
481 mnCorrectedValue
= 0;
483 mnType
= FORMAT_NUMERIC
;
484 mbThousandSep
= sal_True
;
485 mbShowTrailingZeros
= sal_True
;
492 SetDecimalDigits( 0 );
495 // -----------------------------------------------------------------------
497 NumericFormatter::NumericFormatter()
502 // -----------------------------------------------------------------------
504 void NumericFormatter::ImplLoadRes( const ResId
& rResId
)
506 ResMgr
* pMgr
= rResId
.GetResMgr();
510 sal_uLong nMask
= pMgr
->ReadLong();
512 if ( NUMERICFORMATTER_MIN
& nMask
)
513 mnMin
= pMgr
->ReadLong();
515 if ( NUMERICFORMATTER_MAX
& nMask
)
516 mnMax
= pMgr
->ReadLong();
518 if ( NUMERICFORMATTER_STRICTFORMAT
& nMask
)
519 SetStrictFormat( (sal_Bool
)pMgr
->ReadShort() );
521 if ( NUMERICFORMATTER_DECIMALDIGITS
& nMask
)
522 SetDecimalDigits( pMgr
->ReadShort() );
524 if ( NUMERICFORMATTER_VALUE
& nMask
)
526 mnFieldValue
= pMgr
->ReadLong();
527 if ( mnFieldValue
> mnMax
)
528 mnFieldValue
= mnMax
;
529 else if ( mnFieldValue
< mnMin
)
530 mnFieldValue
= mnMin
;
531 mnLastValue
= mnFieldValue
;
534 if ( NUMERICFORMATTER_NOTHOUSANDSEP
& nMask
)
535 SetUseThousandSep( !(sal_Bool
)pMgr
->ReadShort() );
539 // -----------------------------------------------------------------------
541 NumericFormatter::~NumericFormatter()
545 // -----------------------------------------------------------------------
547 void NumericFormatter::SetMin( sal_Int64 nNewMin
)
550 if ( !IsEmptyFieldValue() )
554 // -----------------------------------------------------------------------
556 void NumericFormatter::SetMax( sal_Int64 nNewMax
)
559 if ( !IsEmptyFieldValue() )
563 // -----------------------------------------------------------------------
565 void NumericFormatter::SetUseThousandSep( sal_Bool b
)
571 // -----------------------------------------------------------------------
573 void NumericFormatter::SetDecimalDigits( sal_uInt16 nDigits
)
575 mnDecimalDigits
= nDigits
;
579 // -----------------------------------------------------------------------
581 void NumericFormatter::SetShowTrailingZeros( sal_Bool bShowTrailingZeros
)
583 if ( mbShowTrailingZeros
!= bShowTrailingZeros
)
585 mbShowTrailingZeros
= bShowTrailingZeros
;
590 // -----------------------------------------------------------------------
592 sal_uInt16
NumericFormatter::GetDecimalDigits() const
594 return mnDecimalDigits
;
597 // -----------------------------------------------------------------------
599 void NumericFormatter::SetValue( sal_Int64 nNewValue
)
601 SetUserValue( nNewValue
);
602 mnFieldValue
= mnLastValue
;
603 SetEmptyFieldValueData( sal_False
);
606 // -----------------------------------------------------------------------
608 OUString
NumericFormatter::CreateFieldText( sal_Int64 nValue
) const
610 return OUString(ImplGetLocaleDataWrapper().getNum( nValue
, GetDecimalDigits(), IsUseThousandSep(), IsShowTrailingZeros() ));
613 // -----------------------------------------------------------------------
615 void NumericFormatter::ImplSetUserValue( sal_Int64 nNewValue
, Selection
* pNewSelection
)
617 if ( nNewValue
> mnMax
)
619 else if ( nNewValue
< mnMin
)
621 mnLastValue
= nNewValue
;
624 ImplSetText( CreateFieldText( nNewValue
), pNewSelection
);
627 // -----------------------------------------------------------------------
629 void NumericFormatter::SetUserValue( sal_Int64 nNewValue
)
631 ImplSetUserValue( nNewValue
);
634 // -----------------------------------------------------------------------
636 sal_Int64
NumericFormatter::GetValue() const
641 sal_Int64 nTempValue
;
643 if ( ImplNumericGetValue( GetField()->GetText(), nTempValue
,
644 GetDecimalDigits(), ImplGetLocaleDataWrapper() ) )
646 if ( nTempValue
> mnMax
)
648 else if ( nTempValue
< mnMin
)
656 // -----------------------------------------------------------------------
658 sal_Bool
NumericFormatter::IsValueModified() const
660 if ( ImplGetEmptyFieldValue() )
661 return !IsEmptyFieldValue();
662 else if ( GetValue() != mnFieldValue
)
668 // -----------------------------------------------------------------------
670 sal_Int64
NumericFormatter::Normalize( sal_Int64 nValue
) const
672 return (nValue
* ImplPower10( GetDecimalDigits() ) );
675 // -----------------------------------------------------------------------
677 sal_Int64
NumericFormatter::Denormalize( sal_Int64 nValue
) const
679 sal_Int64 nFactor
= ImplPower10( GetDecimalDigits() );
682 sal_Int64 nHalf
= nValue
< ( SAL_MIN_INT64
+ nFactor
)? 0 : nFactor
/2;
683 return ((nValue
-nHalf
) / nFactor
);
687 sal_Int64 nHalf
= nValue
> ( SAL_MAX_INT64
- nFactor
)? 0 : nFactor
/2;
688 return ((nValue
+nHalf
) / nFactor
);
692 // -----------------------------------------------------------------------
694 void NumericFormatter::Reformat()
699 if ( GetField()->GetText().isEmpty() && ImplGetEmptyFieldValue() )
703 sal_Int64 nTemp
= mnLastValue
;
704 sal_Bool bOK
= ImplNumericReformat( GetField()->GetText(), nTemp
, aStr
);
709 if ( !aStr
.isEmpty() )
712 SetValue( mnLastValue
);
715 // -----------------------------------------------------------------------
717 void NumericFormatter::FieldUp()
719 sal_Int64 nValue
= GetValue();
720 nValue
+= mnSpinSize
;
721 if ( nValue
> mnMax
)
724 ImplNewFieldValue( nValue
);
727 // -----------------------------------------------------------------------
729 void NumericFormatter::FieldDown()
731 sal_Int64 nValue
= GetValue();
732 nValue
-= mnSpinSize
;
733 if ( nValue
< mnMin
)
736 ImplNewFieldValue( nValue
);
739 // -----------------------------------------------------------------------
741 void NumericFormatter::FieldFirst()
743 ImplNewFieldValue( mnFirst
);
746 // -----------------------------------------------------------------------
748 void NumericFormatter::FieldLast()
750 ImplNewFieldValue( mnLast
);
753 // -----------------------------------------------------------------------
755 void NumericFormatter::ImplNewFieldValue( sal_Int64 nNewValue
)
759 // !!! We should check why we do not validate in ImplSetUserValue() if the value was
760 // changed. This should be done there as well since otherwise the call to Modify would not
761 // be allowed. Anyway, the paths from ImplNewFieldValue, ImplSetUserValue, and ImplSetText
762 // should be checked and clearly traced (with comment) in order to find out what happens.
764 Selection aSelection
= GetField()->GetSelection();
765 aSelection
.Justify();
766 OUString aText
= GetField()->GetText();
767 // leave it as is if selected until end
768 if ( (sal_Int32
)aSelection
.Max() == aText
.getLength() )
770 if ( !aSelection
.Len() )
771 aSelection
.Min() = SELECTION_MAX
;
772 aSelection
.Max() = SELECTION_MAX
;
775 sal_Int64 nOldLastValue
= mnLastValue
;
776 ImplSetUserValue( nNewValue
, &aSelection
);
777 mnLastValue
= nOldLastValue
;
779 // Modify during Edit is only set during KeyInput
780 if ( GetField()->GetText() != aText
)
782 GetField()->SetModifyFlag();
783 GetField()->Modify();
788 // -----------------------------------------------------------------------
790 NumericField::NumericField( Window
* pParent
, WinBits nWinStyle
) :
791 SpinField( pParent
, nWinStyle
)
797 // -----------------------------------------------------------------------
799 NumericField::NumericField( Window
* pParent
, const ResId
& rResId
) :
800 SpinField( WINDOW_NUMERICFIELD
)
802 rResId
.SetRT( RSC_NUMERICFIELD
);
803 WinBits nStyle
= ImplInitRes( rResId
) ;
804 SpinField::ImplInit( pParent
, nStyle
);
806 ImplLoadRes( rResId
);
809 if ( !(nStyle
& WB_HIDE
) )
813 bool NumericField::set_property(const OString
&rKey
, const OString
&rValue
)
815 if (rKey
== "digits")
816 SetDecimalDigits(rValue
.toInt32());
818 return SpinField::set_property(rKey
, rValue
);
822 // -----------------------------------------------------------------------
824 void NumericField::ImplLoadRes( const ResId
& rResId
)
826 SpinField::ImplLoadRes( rResId
);
827 NumericFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE
*)GetClassRes(), *rResId
.GetResMgr() ) );
829 sal_uLong nMask
= ReadLongRes();
831 if ( NUMERICFIELD_FIRST
& nMask
)
832 mnFirst
= ReadLongRes();
834 if ( NUMERICFIELD_LAST
& nMask
)
835 mnLast
= ReadLongRes();
837 if ( NUMERICFIELD_SPINSIZE
& nMask
)
838 mnSpinSize
= ReadLongRes();
841 // -----------------------------------------------------------------------
843 NumericField::~NumericField()
847 // -----------------------------------------------------------------------
849 long NumericField::PreNotify( NotifyEvent
& rNEvt
)
851 if ( (rNEvt
.GetType() == EVENT_KEYINPUT
) && !rNEvt
.GetKeyEvent()->GetKeyCode().IsMod2() )
853 if ( ImplNumericProcessKeyInput( GetField(), *rNEvt
.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
857 return SpinField::PreNotify( rNEvt
);
860 // -----------------------------------------------------------------------
862 long NumericField::Notify( NotifyEvent
& rNEvt
)
864 if ( rNEvt
.GetType() == EVENT_GETFOCUS
)
865 MarkToBeReformatted( sal_False
);
866 else if ( rNEvt
.GetType() == EVENT_LOSEFOCUS
)
868 if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
872 return SpinField::Notify( rNEvt
);
875 // -----------------------------------------------------------------------
877 void NumericField::DataChanged( const DataChangedEvent
& rDCEvt
)
879 SpinField::DataChanged( rDCEvt
);
881 if ( (rDCEvt
.GetType() == DATACHANGED_SETTINGS
) && (rDCEvt
.GetFlags() & SETTINGS_LOCALE
) )
883 String sOldDecSep
= ImplGetLocaleDataWrapper().getNumDecimalSep();
884 String sOldThSep
= ImplGetLocaleDataWrapper().getNumThousandSep();
885 if ( IsDefaultLocale() )
886 ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
887 String sNewDecSep
= ImplGetLocaleDataWrapper().getNumDecimalSep();
888 String sNewThSep
= ImplGetLocaleDataWrapper().getNumThousandSep();
889 ImplUpdateSeparators( sOldDecSep
, sNewDecSep
, sOldThSep
, sNewThSep
, this );
894 // -----------------------------------------------------------------------
896 void NumericField::Modify()
898 MarkToBeReformatted( sal_True
);
902 // -----------------------------------------------------------------------
904 void NumericField::Up()
910 // -----------------------------------------------------------------------
912 void NumericField::Down()
918 // -----------------------------------------------------------------------
920 void NumericField::First()
926 // -----------------------------------------------------------------------
928 void NumericField::Last()
936 Size
calcMinimumSize(const SpinField
&rSpinField
, const NumericFormatter
&rFormatter
)
941 nTextLen
= OUString::valueOf(rFormatter
.GetMin()).getLength();
942 string::padToLength(aBuf
, nTextLen
, '9');
943 Size aMinTextSize
= rSpinField
.CalcMinimumSizeForText(
944 rFormatter
.CreateFieldText(aBuf
.makeStringAndClear().toInt64()));
946 nTextLen
= OUString::valueOf(rFormatter
.GetMax()).getLength();
947 string::padToLength(aBuf
, nTextLen
, '9');
948 Size aMaxTextSize
= rSpinField
.CalcMinimumSizeForText(
949 rFormatter
.CreateFieldText(aBuf
.makeStringAndClear().toInt64()));
951 Size
aRet(std::max(aMinTextSize
.Width(), aMaxTextSize
.Width()),
952 std::max(aMinTextSize
.Height(), aMaxTextSize
.Height()));
954 OUStringBuffer
sBuf("999999999");
955 sal_uInt16 nDigits
= rFormatter
.GetDecimalDigits();
959 string::padToLength(aBuf
, aBuf
.getLength() + nDigits
, '9');
961 aMaxTextSize
= rSpinField
.CalcMinimumSizeForText(sBuf
.makeStringAndClear());
962 aRet
.Width() = std::min(aRet
.Width(), aMaxTextSize
.Width());
968 Size
NumericField::CalcMinimumSize() const
970 return calcMinimumSize(*this, *this);
973 // -----------------------------------------------------------------------
975 NumericBox::NumericBox( Window
* pParent
, WinBits nWinStyle
) :
976 ComboBox( pParent
, nWinStyle
)
982 // -----------------------------------------------------------------------
984 NumericBox::NumericBox( Window
* pParent
, const ResId
& rResId
) :
985 ComboBox( WINDOW_NUMERICBOX
)
987 rResId
.SetRT( RSC_NUMERICBOX
);
988 WinBits nStyle
= ImplInitRes( rResId
);
989 ComboBox::ImplInit( pParent
, nStyle
);
991 ComboBox::ImplLoadRes( rResId
);
992 NumericFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE
*)GetClassRes(), *rResId
.GetResMgr() ) );
995 if ( !(nStyle
& WB_HIDE
) )
999 // -----------------------------------------------------------------------
1001 NumericBox::~NumericBox()
1005 // -----------------------------------------------------------------------
1007 long NumericBox::PreNotify( NotifyEvent
& rNEvt
)
1009 if ( (rNEvt
.GetType() == EVENT_KEYINPUT
) && !rNEvt
.GetKeyEvent()->GetKeyCode().IsMod2() )
1011 if ( ImplNumericProcessKeyInput( GetField(), *rNEvt
.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
1015 return ComboBox::PreNotify( rNEvt
);
1018 // -----------------------------------------------------------------------
1020 long NumericBox::Notify( NotifyEvent
& rNEvt
)
1022 if ( rNEvt
.GetType() == EVENT_GETFOCUS
)
1023 MarkToBeReformatted( sal_False
);
1024 else if ( rNEvt
.GetType() == EVENT_LOSEFOCUS
)
1026 if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
1030 return ComboBox::Notify( rNEvt
);
1033 // -----------------------------------------------------------------------
1035 void NumericBox::DataChanged( const DataChangedEvent
& rDCEvt
)
1037 ComboBox::DataChanged( rDCEvt
);
1039 if ( (rDCEvt
.GetType() == DATACHANGED_SETTINGS
) && (rDCEvt
.GetFlags() & SETTINGS_LOCALE
) )
1041 String sOldDecSep
= ImplGetLocaleDataWrapper().getNumDecimalSep();
1042 String sOldThSep
= ImplGetLocaleDataWrapper().getNumThousandSep();
1043 if ( IsDefaultLocale() )
1044 ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
1045 String sNewDecSep
= ImplGetLocaleDataWrapper().getNumDecimalSep();
1046 String sNewThSep
= ImplGetLocaleDataWrapper().getNumThousandSep();
1047 ImplUpdateSeparators( sOldDecSep
, sNewDecSep
, sOldThSep
, sNewThSep
, this );
1052 // -----------------------------------------------------------------------
1054 void NumericBox::Modify()
1056 MarkToBeReformatted( sal_True
);
1060 // -----------------------------------------------------------------------
1062 void NumericBox::ReformatAll()
1066 SetUpdateMode( sal_False
);
1067 sal_uInt16 nEntryCount
= GetEntryCount();
1068 for ( sal_uInt16 i
=0; i
< nEntryCount
; i
++ )
1070 ImplNumericReformat( GetEntry( i
), nValue
, aStr
);
1072 InsertEntry( aStr
, i
);
1074 NumericFormatter::Reformat();
1075 SetUpdateMode( sal_True
);
1078 // -----------------------------------------------------------------------
1080 void NumericBox::InsertValue( sal_Int64 nValue
, sal_uInt16 nPos
)
1082 ComboBox::InsertEntry( CreateFieldText( nValue
), nPos
);
1085 // -----------------------------------------------------------------------
1087 static bool ImplMetricProcessKeyInput( Edit
* pEdit
, const KeyEvent
& rKEvt
,
1088 bool, bool bUseThousandSep
, const LocaleDataWrapper
& rWrapper
)
1090 // no meaningfull strict format; therefore allow all characters
1091 return ImplNumericProcessKeyInput( pEdit
, rKEvt
, false, bUseThousandSep
, rWrapper
);
1094 // -----------------------------------------------------------------------
1096 static OUString
ImplMetricGetUnitText(const OUString
& rStr
)
1099 OUStringBuffer aStr
;
1100 for (sal_Int32 i
= rStr
.getLength()-1; i
>= 0; --i
)
1102 sal_Unicode c
= rStr
[i
];
1103 if ( (c
== '\'') || (c
== '\"') || (c
== '%' ) || unicode::isAlpha(c
) || unicode::isControl(c
) )
1107 if (aStr
.getLength())
1111 return aStr
.makeStringAndClear();
1114 // -----------------------------------------------------------------------
1116 // #104355# support localized mesaurements
1118 static const OUString
ImplMetricToString( FieldUnit rUnit
)
1120 FieldUnitStringList
* pList
= ImplGetFieldUnits();
1123 // return unit's default string (ie, the first one )
1124 for( FieldUnitStringList::const_iterator it
= pList
->begin(); it
!= pList
->end(); ++it
)
1126 if ( it
->second
== rUnit
)
1134 static FieldUnit
ImplStringToMetric(const OUString
&rMetricString
)
1136 FieldUnitStringList
* pList
= ImplGetCleanedFieldUnits();
1140 OUString
aStr(rMetricString
.toAsciiLowerCase());
1141 aStr
= string::remove(aStr
, ' ');
1142 for( FieldUnitStringList::const_iterator it
= pList
->begin(); it
!= pList
->end(); ++it
)
1144 if ( it
->first
== aStr
)
1152 // -----------------------------------------------------------------------
1154 static FieldUnit
ImplMetricGetUnit(const OUString
& rStr
)
1156 OUString aStr
= ImplMetricGetUnitText( rStr
);
1157 return ImplStringToMetric( aStr
);
1161 #define M *1000000LL
1164 // twip in km = 254 / 14 400 000 000
1165 // expressions too big for default size 32 bit need LL to avoid overflow
1167 static const sal_Int64 aImplFactor
[FUNIT_LINE
+1][FUNIT_LINE
+1] =
1169 mm/100 mm cm m km twip point pica inch foot mile char line */
1170 { 1, 100, 1 K
, 100 K
, 100 M
, 2540, 2540, 2540, 2540,2540*12,2540*12 X
, 53340, 396240},
1171 { 1, 1, 10, 1 K
, 1 M
, 2540, 2540, 2540, 2540,2540*12,2540*12 X
, 5334, 396240},
1172 { 1, 1, 1, 100, 100 K
, 254, 254, 254, 254, 254*12, 254*12 X
, 5334, 39624},
1173 { 1, 1, 1, 1, 1 K
, 254, 254, 254, 254, 254*12, 254*12 X
, 533400, 39624},
1174 { 1, 1, 1, 1, 1, 254, 254, 254, 254, 254*12, 254*12 X
,533400 K
, 39624},
1175 { 1440,144 K
,144 K
,14400 K
,14400LL M
, 1, 20, 240, 1440,1440*12,1440*12 X
, 210, 3120},
1176 { 72, 7200, 7200, 720 K
, 720 M
, 1, 1, 12, 72, 72*12, 72*12 X
, 210, 156},
1177 { 6, 600, 600, 60 K
, 60 M
, 1, 1, 1, 6, 6*12, 6*12 X
, 210, 10},
1178 { 1, 100, 100, 10 K
, 10 M
, 1, 1, 1, 1, 12, 12 X
, 210, 45},
1179 { 1, 100, 100, 10 K
, 10 M
, 1, 1, 1, 1, 1, 1 X
, 210, 45},
1180 { 1, 100, 100, 10 K
, 10 M
, 1, 1, 1, 1, 1, 1 , 210, 45},
1181 { 144, 1440,14400, 14400, 14400, 1, 20, 240, 1440,1440*12, 1440*12 X
, 1, 156 },
1182 { 720,72000,72000, 7200 K
,7200LL M
, 20, 10, 13, 11, 11*12, 11*12 X
, 105, 1 }
1188 static FieldUnit eDefaultUnit
= FUNIT_NONE
;
1190 FieldUnit
MetricField::GetDefaultUnit() { return eDefaultUnit
; }
1191 void MetricField::SetDefaultUnit( FieldUnit meUnit
) { eDefaultUnit
= meUnit
; }
1193 static FieldUnit
ImplMap2FieldUnit( MapUnit meUnit
, long& nDecDigits
)
1207 case MAP_1000TH_INCH
:
1210 case MAP_100TH_INCH
:
1213 case MAP_10TH_INCH
:
1223 OSL_FAIL( "default eInUnit" );
1229 // -----------------------------------------------------------------------
1231 static double nonValueDoubleToValueDouble( double nValue
)
1233 return rtl::math::isFinite( nValue
) ? nValue
: 0.0;
1236 sal_Int64
MetricField::ConvertValue( sal_Int64 nValue
, sal_Int64 mnBaseValue
, sal_uInt16 nDecDigits
,
1237 FieldUnit eInUnit
, FieldUnit eOutUnit
)
1239 double nDouble
= nonValueDoubleToValueDouble( ConvertDoubleValue(
1240 (double)nValue
, mnBaseValue
, nDecDigits
, eInUnit
, eOutUnit
) );
1242 // caution: precision loss in double cast
1243 sal_Int64 nLong
= static_cast<sal_Int64
>( nDouble
);
1245 if ( nDouble
>= (double)SAL_MAX_INT64
)
1246 nLong
= SAL_MAX_INT64
;
1247 else if ( nDouble
<= (double)SAL_MIN_INT64
)
1248 nLong
= SAL_MIN_INT64
;
1253 // -----------------------------------------------------------------------
1255 sal_Int64
MetricField::ConvertValue( sal_Int64 nValue
, sal_uInt16 nDigits
,
1256 MapUnit eInUnit
, FieldUnit eOutUnit
)
1258 return static_cast<sal_Int64
>(
1259 nonValueDoubleToValueDouble(
1260 ConvertDoubleValue( nValue
, nDigits
, eInUnit
, eOutUnit
) ) );
1263 // -----------------------------------------------------------------------
1265 double MetricField::ConvertDoubleValue( double nValue
, sal_Int64 mnBaseValue
, sal_uInt16 nDecDigits
,
1266 FieldUnit eInUnit
, FieldUnit eOutUnit
)
1268 if ( eInUnit
!= eOutUnit
)
1270 sal_Int64 nMult
= 1, nDiv
= 1;
1272 if ( eInUnit
== FUNIT_PERCENT
)
1274 if ( (mnBaseValue
<= 0) || (nValue
<= 0) )
1276 nDiv
= 100 * ImplPower10(nDecDigits
);
1278 nMult
= mnBaseValue
;
1280 else if ( eOutUnit
== FUNIT_PERCENT
||
1281 eOutUnit
== FUNIT_CUSTOM
||
1282 eOutUnit
== FUNIT_NONE
||
1283 eInUnit
== FUNIT_CUSTOM
||
1284 eInUnit
== FUNIT_NONE
)
1288 if ( eOutUnit
== FUNIT_100TH_MM
)
1289 eOutUnit
= FUNIT_NONE
;
1290 if ( eInUnit
== FUNIT_100TH_MM
)
1291 eInUnit
= FUNIT_NONE
;
1293 nDiv
= aImplFactor
[eInUnit
][eOutUnit
];
1294 nMult
= aImplFactor
[eOutUnit
][eInUnit
];
1296 DBG_ASSERT( nMult
> 0, "illegal *" );
1297 DBG_ASSERT( nDiv
> 0, "illegal /" );
1300 if ( nMult
!= 1 && nMult
> 0 )
1302 if ( nDiv
!= 1 && nDiv
> 0 )
1304 nValue
+= ( nValue
< 0 ) ? (-nDiv
/2) : (nDiv
/2);
1312 // -----------------------------------------------------------------------
1314 double MetricField::ConvertDoubleValue( double nValue
, sal_uInt16 nDigits
,
1315 MapUnit eInUnit
, FieldUnit eOutUnit
)
1317 if ( eOutUnit
== FUNIT_PERCENT
||
1318 eOutUnit
== FUNIT_CUSTOM
||
1319 eOutUnit
== FUNIT_NONE
||
1320 eInUnit
== MAP_PIXEL
||
1321 eInUnit
== MAP_SYSFONT
||
1322 eInUnit
== MAP_APPFONT
||
1323 eInUnit
== MAP_RELATIVE
)
1325 OSL_FAIL( "invalid parameters" );
1329 long nDecDigits
= nDigits
;
1330 FieldUnit eFieldUnit
= ImplMap2FieldUnit( eInUnit
, nDecDigits
);
1332 if ( nDecDigits
< 0 )
1334 while ( nDecDigits
)
1343 nValue
*= ImplPower10(nDecDigits
);
1346 if ( eFieldUnit
!= eOutUnit
)
1348 sal_Int64 nDiv
= aImplFactor
[eFieldUnit
][eOutUnit
];
1349 sal_Int64 nMult
= aImplFactor
[eOutUnit
][eFieldUnit
];
1351 DBG_ASSERT( nMult
> 0, "illegal *" );
1352 DBG_ASSERT( nDiv
> 0, "illegal /" );
1354 if ( nMult
!= 1 && nMult
> 0)
1356 if ( nDiv
!= 1 && nDiv
> 0 )
1358 nValue
+= (nValue
< 0) ? (-nDiv
/2) : (nDiv
/2);
1365 // -----------------------------------------------------------------------
1367 double MetricField::ConvertDoubleValue( double nValue
, sal_uInt16 nDigits
,
1368 FieldUnit eInUnit
, MapUnit eOutUnit
)
1370 if ( eInUnit
== FUNIT_PERCENT
||
1371 eInUnit
== FUNIT_CUSTOM
||
1372 eInUnit
== FUNIT_NONE
||
1373 eOutUnit
== MAP_PIXEL
||
1374 eOutUnit
== MAP_SYSFONT
||
1375 eOutUnit
== MAP_APPFONT
||
1376 eOutUnit
== MAP_RELATIVE
)
1378 OSL_FAIL( "invalid parameters" );
1382 long nDecDigits
= nDigits
;
1383 FieldUnit eFieldUnit
= ImplMap2FieldUnit( eOutUnit
, nDecDigits
);
1385 if ( nDecDigits
< 0 )
1387 nValue
*= ImplPower10(-nDecDigits
);
1391 nValue
/= ImplPower10(nDecDigits
);
1394 if ( eFieldUnit
!= eInUnit
)
1396 sal_Int64 nDiv
= aImplFactor
[eInUnit
][eFieldUnit
];
1397 sal_Int64 nMult
= aImplFactor
[eFieldUnit
][eInUnit
];
1399 DBG_ASSERT( nMult
> 0, "illegal *" );
1400 DBG_ASSERT( nDiv
> 0, "illegal /" );
1402 if( nMult
!= 1 && nMult
> 0 )
1404 if( nDiv
!= 1 && nDiv
> 0 )
1406 nValue
+= (nValue
< 0) ? (-nDiv
/2) : (nDiv
/2);
1413 // -----------------------------------------------------------------------
1415 static bool ImplMetricGetValue( const OUString
& rStr
, double& rValue
, sal_Int64 nBaseValue
,
1416 sal_uInt16 nDecDigits
, const LocaleDataWrapper
& rLocaleDataWrapper
, FieldUnit eUnit
)
1420 if ( !ImplNumericGetValue( rStr
, nValue
, nDecDigits
, rLocaleDataWrapper
) )
1423 // Einheit rausfinden
1424 FieldUnit eEntryUnit
= ImplMetricGetUnit( rStr
);
1426 // Einheiten umrechnen
1427 // caution: conversion to double loses precision
1428 rValue
= MetricField::ConvertDoubleValue( (double)nValue
, nBaseValue
, nDecDigits
, eEntryUnit
, eUnit
);
1433 // -----------------------------------------------------------------------
1435 sal_Bool
MetricFormatter::ImplMetricReformat( const OUString
& rStr
, double& rValue
, OUString
& rOutStr
)
1437 if ( !ImplMetricGetValue( rStr
, rValue
, mnBaseValue
, GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit
) )
1441 double nTempVal
= rValue
;
1442 // caution: precision loss in double cast
1443 if ( nTempVal
> GetMax() )
1444 nTempVal
= (double)GetMax();
1445 else if ( nTempVal
< GetMin())
1446 nTempVal
= (double)GetMin();
1448 if ( GetErrorHdl().IsSet() && (rValue
!= nTempVal
) )
1450 mnCorrectedValue
= (sal_Int64
)nTempVal
;
1451 if ( !GetErrorHdl().Call( this ) )
1453 mnCorrectedValue
= 0;
1457 mnCorrectedValue
= 0;
1460 rOutStr
= CreateFieldText( (sal_Int64
)nTempVal
);
1465 // -----------------------------------------------------------------------
1467 inline void MetricFormatter::ImplInit()
1470 meUnit
= MetricField::GetDefaultUnit();
1471 mnType
= FORMAT_METRIC
;
1474 // -----------------------------------------------------------------------
1476 MetricFormatter::MetricFormatter()
1481 // -----------------------------------------------------------------------
1483 void MetricFormatter::ImplLoadRes( const ResId
& rResId
)
1485 NumericFormatter::ImplLoadRes( rResId
);
1487 ResMgr
* pMgr
= rResId
.GetResMgr();
1490 sal_uLong nMask
= pMgr
->ReadLong();
1492 if ( METRICFORMATTER_UNIT
& nMask
)
1493 meUnit
= (FieldUnit
)pMgr
->ReadLong();
1495 if ( METRICFORMATTER_CUSTOMUNITTEXT
& nMask
)
1496 maCustomUnitText
= pMgr
->ReadString();
1500 // -----------------------------------------------------------------------
1502 MetricFormatter::~MetricFormatter()
1506 // -----------------------------------------------------------------------
1508 void MetricFormatter::SetUnit( FieldUnit eNewUnit
)
1510 if ( eNewUnit
== FUNIT_100TH_MM
)
1512 SetDecimalDigits( GetDecimalDigits() + 2 );
1520 // -----------------------------------------------------------------------
1522 void MetricFormatter::SetCustomUnitText( const OUString
& rStr
)
1524 maCustomUnitText
= rStr
;
1528 // -----------------------------------------------------------------------
1530 void MetricFormatter::SetValue( sal_Int64 nNewValue
, FieldUnit eInUnit
)
1532 SetUserValue( nNewValue
, eInUnit
);
1533 mnFieldValue
= mnLastValue
;
1536 // -----------------------------------------------------------------------
1538 OUString
MetricFormatter::CreateFieldText( sal_Int64 nValue
) const
1540 OUString aStr
= NumericFormatter::CreateFieldText( nValue
);
1542 if( meUnit
== FUNIT_CUSTOM
)
1543 aStr
+= maCustomUnitText
;
1545 aStr
+= ImplMetricToString( meUnit
);
1550 // -----------------------------------------------------------------------
1552 void MetricFormatter::SetUserValue( sal_Int64 nNewValue
, FieldUnit eInUnit
)
1554 // convert to previously configured units
1555 nNewValue
= MetricField::ConvertValue( nNewValue
, mnBaseValue
, GetDecimalDigits(), eInUnit
, meUnit
);
1556 NumericFormatter::SetUserValue( nNewValue
);
1559 // -----------------------------------------------------------------------
1561 sal_Int64
MetricFormatter::GetValue( FieldUnit eOutUnit
) const
1567 // caution: precision loss in double cast
1568 if ( !ImplMetricGetValue( GetField()->GetText(), nTempValue
, mnBaseValue
, GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit
) )
1569 nTempValue
= (double)mnLastValue
;
1571 // caution: precision loss in double cast
1572 if ( nTempValue
> mnMax
)
1573 nTempValue
= (double)mnMax
;
1574 else if ( nTempValue
< mnMin
)
1575 nTempValue
= (double)mnMin
;
1577 // convert to requested units
1578 return MetricField::ConvertValue( (sal_Int64
)nTempValue
, mnBaseValue
, GetDecimalDigits(), meUnit
, eOutUnit
);
1581 // -----------------------------------------------------------------------
1583 void MetricFormatter::SetValue( sal_Int64 nValue
)
1585 // Implementation not inline, because it is a virtual Function
1586 SetValue( nValue
, FUNIT_NONE
);
1589 // -----------------------------------------------------------------------
1591 sal_Int64
MetricFormatter::GetValue() const
1593 // Implementation not inline, because it is a virtual Function
1594 return GetValue( FUNIT_NONE
);
1597 // -----------------------------------------------------------------------
1599 void MetricFormatter::SetMin( sal_Int64 nNewMin
, FieldUnit eInUnit
)
1601 // convert to requested units
1602 NumericFormatter::SetMin( MetricField::ConvertValue( nNewMin
, mnBaseValue
, GetDecimalDigits(),
1603 eInUnit
, meUnit
) );
1606 // -----------------------------------------------------------------------
1608 sal_Int64
MetricFormatter::GetMin( FieldUnit eOutUnit
) const
1610 // convert to requested units
1611 return MetricField::ConvertValue( NumericFormatter::GetMin(), mnBaseValue
,
1612 GetDecimalDigits(), meUnit
, eOutUnit
);
1615 // -----------------------------------------------------------------------
1617 void MetricFormatter::SetMax( sal_Int64 nNewMax
, FieldUnit eInUnit
)
1619 // convert to requested units
1620 NumericFormatter::SetMax( MetricField::ConvertValue( nNewMax
, mnBaseValue
, GetDecimalDigits(),
1621 eInUnit
, meUnit
) );
1624 // -----------------------------------------------------------------------
1626 sal_Int64
MetricFormatter::GetMax( FieldUnit eOutUnit
) const
1628 // convert to requested units
1629 return MetricField::ConvertValue( NumericFormatter::GetMax(), mnBaseValue
,
1630 GetDecimalDigits(), meUnit
, eOutUnit
);
1633 // -----------------------------------------------------------------------
1635 void MetricFormatter::SetBaseValue( sal_Int64 nNewBase
, FieldUnit eInUnit
)
1637 mnBaseValue
= MetricField::ConvertValue( nNewBase
, mnBaseValue
, GetDecimalDigits(),
1641 // -----------------------------------------------------------------------
1643 sal_Int64
MetricFormatter::GetBaseValue( FieldUnit eOutUnit
) const
1645 // convert to requested units
1646 return MetricField::ConvertValue( mnBaseValue
, mnBaseValue
, GetDecimalDigits(),
1650 // -----------------------------------------------------------------------
1652 void MetricFormatter::Reformat()
1657 OUString aText
= GetField()->GetText();
1658 if ( meUnit
== FUNIT_CUSTOM
)
1659 maCurUnitText
= ImplMetricGetUnitText( aText
);
1662 // caution: precision loss in double cast
1663 double nTemp
= (double)mnLastValue
;
1664 sal_Bool bOK
= ImplMetricReformat( aText
, nTemp
, aStr
);
1665 mnLastValue
= (sal_Int64
)nTemp
;
1670 if ( !aStr
.isEmpty() )
1672 ImplSetText( aStr
);
1673 if ( meUnit
== FUNIT_CUSTOM
)
1677 SetValue( mnLastValue
);
1678 maCurUnitText
= OUString();
1681 // -----------------------------------------------------------------------
1683 sal_Int64
MetricFormatter::GetCorrectedValue( FieldUnit eOutUnit
) const
1685 // convert to requested units
1686 return MetricField::ConvertValue( mnCorrectedValue
, mnBaseValue
, GetDecimalDigits(),
1690 // -----------------------------------------------------------------------
1692 MetricField::MetricField( Window
* pParent
, WinBits nWinStyle
) :
1693 SpinField( pParent
, nWinStyle
)
1699 MetricField::MetricField( Window
* pParent
, const ResId
& rResId
) :
1700 SpinField( WINDOW_METRICFIELD
)
1702 rResId
.SetRT( RSC_METRICFIELD
);
1703 WinBits nStyle
= ImplInitRes( rResId
) ;
1704 SpinField::ImplInit( pParent
, nStyle
);
1706 ImplLoadRes( rResId
);
1708 if ( !(nStyle
& WB_HIDE
) )
1712 Size
MetricField::CalcMinimumSize() const
1714 return calcMinimumSize(*this, *this);
1717 bool MetricField::set_property(const OString
&rKey
, const OString
&rValue
)
1719 if (rKey
== "format")
1721 maCustomUnitText
= OStringToOUString(rValue
, RTL_TEXTENCODING_UTF8
);
1722 meUnit
= FUNIT_CUSTOM
;
1724 else if (rKey
== "digits")
1725 SetDecimalDigits(rValue
.toInt32());
1727 return SpinField::set_property(rKey
, rValue
);
1731 void MetricField::ImplLoadRes( const ResId
& rResId
)
1733 SpinField::ImplLoadRes( rResId
);
1734 MetricFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE
*)GetClassRes(), *rResId
.GetResMgr() ) );
1736 sal_uLong nMask
= ReadLongRes();
1738 if ( METRICFIELD_FIRST
& nMask
)
1739 mnFirst
= ReadLongRes();
1741 if ( METRICFIELD_LAST
& nMask
)
1742 mnLast
= ReadLongRes();
1744 if ( METRICFIELD_SPINSIZE
& nMask
)
1745 mnSpinSize
= ReadLongRes();
1750 // -----------------------------------------------------------------------
1752 MetricField::~MetricField()
1756 void MetricField::SetUnit( FieldUnit nNewUnit
)
1758 sal_Int64 nRawMax
= GetMax( nNewUnit
);
1759 sal_Int64 nMax
= Denormalize( nRawMax
);
1760 sal_Int64 nMin
= Denormalize( GetMin( nNewUnit
) );
1761 sal_Int64 nFirst
= Denormalize( GetFirst( nNewUnit
) );
1762 sal_Int64 nLast
= Denormalize( GetLast( nNewUnit
) );
1764 MetricFormatter::SetUnit( nNewUnit
);
1766 SetMax( Normalize( nMax
), nNewUnit
);
1767 SetMin( Normalize( nMin
), nNewUnit
);
1768 SetFirst( Normalize( nFirst
), nNewUnit
);
1769 SetLast( Normalize( nLast
), nNewUnit
);
1772 // -----------------------------------------------------------------------
1774 void MetricField::SetFirst( sal_Int64 nNewFirst
, FieldUnit eInUnit
)
1777 nNewFirst
= MetricField::ConvertValue( nNewFirst
, mnBaseValue
, GetDecimalDigits(),
1779 mnFirst
= nNewFirst
;
1782 // -----------------------------------------------------------------------
1784 sal_Int64
MetricField::GetFirst( FieldUnit eOutUnit
) const
1787 return MetricField::ConvertValue( mnFirst
, mnBaseValue
, GetDecimalDigits(),
1791 // -----------------------------------------------------------------------
1793 void MetricField::SetLast( sal_Int64 nNewLast
, FieldUnit eInUnit
)
1796 nNewLast
= MetricField::ConvertValue( nNewLast
, mnBaseValue
, GetDecimalDigits(),
1801 // -----------------------------------------------------------------------
1803 sal_Int64
MetricField::GetLast( FieldUnit eOutUnit
) const
1806 return MetricField::ConvertValue( mnLast
, mnBaseValue
, GetDecimalDigits(),
1810 // -----------------------------------------------------------------------
1812 long MetricField::PreNotify( NotifyEvent
& rNEvt
)
1814 if ( (rNEvt
.GetType() == EVENT_KEYINPUT
) && !rNEvt
.GetKeyEvent()->GetKeyCode().IsMod2() )
1816 if ( ImplMetricProcessKeyInput( GetField(), *rNEvt
.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
1820 return SpinField::PreNotify( rNEvt
);
1823 // -----------------------------------------------------------------------
1825 long MetricField::Notify( NotifyEvent
& rNEvt
)
1827 if ( rNEvt
.GetType() == EVENT_GETFOCUS
)
1828 MarkToBeReformatted( sal_False
);
1829 else if ( rNEvt
.GetType() == EVENT_LOSEFOCUS
)
1831 if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
1835 return SpinField::Notify( rNEvt
);
1838 // -----------------------------------------------------------------------
1840 void MetricField::DataChanged( const DataChangedEvent
& rDCEvt
)
1842 SpinField::DataChanged( rDCEvt
);
1844 if ( (rDCEvt
.GetType() == DATACHANGED_SETTINGS
) && (rDCEvt
.GetFlags() & SETTINGS_LOCALE
) )
1846 String sOldDecSep
= ImplGetLocaleDataWrapper().getNumDecimalSep();
1847 String sOldThSep
= ImplGetLocaleDataWrapper().getNumThousandSep();
1848 if ( IsDefaultLocale() )
1849 ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
1850 String sNewDecSep
= ImplGetLocaleDataWrapper().getNumDecimalSep();
1851 String sNewThSep
= ImplGetLocaleDataWrapper().getNumThousandSep();
1852 ImplUpdateSeparators( sOldDecSep
, sNewDecSep
, sOldThSep
, sNewThSep
, this );
1857 // -----------------------------------------------------------------------
1859 void MetricField::Modify()
1861 MarkToBeReformatted( sal_True
);
1862 SpinField::Modify();
1865 // -----------------------------------------------------------------------
1867 void MetricField::Up()
1873 // -----------------------------------------------------------------------
1875 void MetricField::Down()
1881 // -----------------------------------------------------------------------
1883 void MetricField::First()
1889 // -----------------------------------------------------------------------
1891 void MetricField::Last()
1897 // -----------------------------------------------------------------------
1899 void MetricField::CustomConvert()
1901 maCustomConvertLink
.Call( this );
1904 // -----------------------------------------------------------------------
1906 MetricBox::MetricBox( Window
* pParent
, WinBits nWinStyle
) :
1907 ComboBox( pParent
, nWinStyle
)
1913 // -----------------------------------------------------------------------
1915 MetricBox::MetricBox( Window
* pParent
, const ResId
& rResId
) :
1916 ComboBox( WINDOW_METRICBOX
)
1918 rResId
.SetRT( RSC_METRICBOX
);
1919 WinBits nStyle
= ImplInitRes( rResId
);
1920 ComboBox::ImplInit( pParent
, nStyle
);
1923 ComboBox::ImplLoadRes( rResId
);
1924 MetricFormatter::ImplLoadRes( ResId( (RSHEADER_TYPE
*)GetClassRes(), *rResId
.GetResMgr() ) );
1926 if ( !(nStyle
& WB_HIDE
) )
1930 // -----------------------------------------------------------------------
1932 MetricBox::~MetricBox()
1936 // -----------------------------------------------------------------------
1938 long MetricBox::PreNotify( NotifyEvent
& rNEvt
)
1940 if ( (rNEvt
.GetType() == EVENT_KEYINPUT
) && !rNEvt
.GetKeyEvent()->GetKeyCode().IsMod2() )
1942 if ( ImplMetricProcessKeyInput( GetField(), *rNEvt
.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
1946 return ComboBox::PreNotify( rNEvt
);
1949 // -----------------------------------------------------------------------
1951 long MetricBox::Notify( NotifyEvent
& rNEvt
)
1953 if ( rNEvt
.GetType() == EVENT_GETFOCUS
)
1954 MarkToBeReformatted( sal_False
);
1955 else if ( rNEvt
.GetType() == EVENT_LOSEFOCUS
)
1957 if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
1961 return ComboBox::Notify( rNEvt
);
1964 // -----------------------------------------------------------------------
1966 void MetricBox::DataChanged( const DataChangedEvent
& rDCEvt
)
1968 ComboBox::DataChanged( rDCEvt
);
1970 if ( (rDCEvt
.GetType() == DATACHANGED_SETTINGS
) && (rDCEvt
.GetFlags() & SETTINGS_LOCALE
) )
1972 String sOldDecSep
= ImplGetLocaleDataWrapper().getNumDecimalSep();
1973 String sOldThSep
= ImplGetLocaleDataWrapper().getNumThousandSep();
1974 if ( IsDefaultLocale() )
1975 ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
1976 String sNewDecSep
= ImplGetLocaleDataWrapper().getNumDecimalSep();
1977 String sNewThSep
= ImplGetLocaleDataWrapper().getNumThousandSep();
1978 ImplUpdateSeparators( sOldDecSep
, sNewDecSep
, sOldThSep
, sNewThSep
, this );
1983 // -----------------------------------------------------------------------
1985 void MetricBox::Modify()
1987 MarkToBeReformatted( sal_True
);
1991 // -----------------------------------------------------------------------
1993 void MetricBox::ReformatAll()
1997 SetUpdateMode( sal_False
);
1998 sal_uInt16 nEntryCount
= GetEntryCount();
1999 for ( sal_uInt16 i
=0; i
< nEntryCount
; i
++ )
2001 ImplMetricReformat( GetEntry( i
), nValue
, aStr
);
2003 InsertEntry( aStr
, i
);
2005 MetricFormatter::Reformat();
2006 SetUpdateMode( sal_True
);
2009 // -----------------------------------------------------------------------
2011 void MetricBox::CustomConvert()
2013 maCustomConvertLink
.Call( this );
2016 // -----------------------------------------------------------------------
2018 void MetricBox::InsertValue( sal_Int64 nValue
, FieldUnit eInUnit
, sal_uInt16 nPos
)
2020 // convert to previously configured units
2021 nValue
= MetricField::ConvertValue( nValue
, mnBaseValue
, GetDecimalDigits(),
2023 ComboBox::InsertEntry( CreateFieldText( nValue
), nPos
);
2026 // -----------------------------------------------------------------------
2028 sal_Int64
MetricBox::GetValue( sal_uInt16 nPos
, FieldUnit eOutUnit
) const
2031 ImplMetricGetValue( ComboBox::GetEntry( nPos
), nValue
, mnBaseValue
,
2032 GetDecimalDigits(), ImplGetLocaleDataWrapper(), meUnit
);
2034 // convert to previously configured units
2035 sal_Int64 nRetValue
= MetricField::ConvertValue( (sal_Int64
)nValue
, mnBaseValue
, GetDecimalDigits(),
2041 // -----------------------------------------------------------------------
2043 sal_uInt16
MetricBox::GetValuePos( sal_Int64 nValue
, FieldUnit eInUnit
) const
2045 // convert to previously configured units
2046 nValue
= MetricField::ConvertValue( nValue
, mnBaseValue
, GetDecimalDigits(),
2048 return ComboBox::GetEntryPos( CreateFieldText( nValue
) );
2051 // -----------------------------------------------------------------------
2053 sal_Int64
MetricBox::GetValue( FieldUnit eOutUnit
) const
2055 // Implementation not inline, because it is a virtual Function
2056 return MetricFormatter::GetValue( eOutUnit
);
2059 // -----------------------------------------------------------------------
2061 sal_Int64
MetricBox::GetValue() const
2063 // Implementation not inline, because it is a virtual Function
2064 return GetValue( FUNIT_NONE
);
2067 // -----------------------------------------------------------------------
2069 static bool ImplCurrencyProcessKeyInput( Edit
* pEdit
, const KeyEvent
& rKEvt
,
2070 bool, bool bUseThousandSep
, const LocaleDataWrapper
& rWrapper
)
2072 // no strict format set; therefore allow all characters
2073 return ImplNumericProcessKeyInput( pEdit
, rKEvt
, false, bUseThousandSep
, rWrapper
);
2076 // -----------------------------------------------------------------------
2078 inline bool ImplCurrencyGetValue( const OUString
& rStr
, sal_Int64
& rValue
,
2079 sal_uInt16 nDecDigits
, const LocaleDataWrapper
& rWrapper
)
2082 return ImplNumericGetValue( rStr
, rValue
, nDecDigits
, rWrapper
, true );
2085 // -----------------------------------------------------------------------
2087 sal_Bool
CurrencyFormatter::ImplCurrencyReformat( const OUString
& rStr
, OUString
& rOutStr
)
2090 if ( !ImplNumericGetValue( rStr
, nValue
, GetDecimalDigits(), ImplGetLocaleDataWrapper(), true ) )
2094 sal_Int64 nTempVal
= nValue
;
2095 if ( nTempVal
> GetMax() )
2096 nTempVal
= GetMax();
2097 else if ( nTempVal
< GetMin())
2098 nTempVal
= GetMin();
2100 if ( GetErrorHdl().IsSet() && (nValue
!= nTempVal
) )
2102 mnCorrectedValue
= nTempVal
;
2103 if ( !GetErrorHdl().Call( this ) )
2105 mnCorrectedValue
= 0;
2109 mnCorrectedValue
= 0;
2112 rOutStr
= CreateFieldText( nTempVal
);
2117 // -----------------------------------------------------------------------
2119 inline void CurrencyFormatter::ImplInit()
2121 mnType
= FORMAT_CURRENCY
;
2124 // -----------------------------------------------------------------------
2126 CurrencyFormatter::CurrencyFormatter()
2131 // -----------------------------------------------------------------------
2133 CurrencyFormatter::~CurrencyFormatter()
2137 // -----------------------------------------------------------------------
2139 String
CurrencyFormatter::GetCurrencySymbol() const
2141 return ImplGetLocaleDataWrapper().getCurrSymbol();
2144 // -----------------------------------------------------------------------
2146 void CurrencyFormatter::SetValue( sal_Int64 nNewValue
)
2148 SetUserValue( nNewValue
);
2149 mnFieldValue
= mnLastValue
;
2150 SetEmptyFieldValueData( sal_False
);
2153 // -----------------------------------------------------------------------
2155 OUString
CurrencyFormatter::CreateFieldText( sal_Int64 nValue
) const
2157 return ImplGetLocaleDataWrapper().getCurr( nValue
, GetDecimalDigits(), GetCurrencySymbol(), IsUseThousandSep() );
2160 // -----------------------------------------------------------------------
2162 sal_Int64
CurrencyFormatter::GetValue() const
2167 sal_Int64 nTempValue
;
2168 if ( ImplCurrencyGetValue( GetField()->GetText(), nTempValue
, GetDecimalDigits(), ImplGetLocaleDataWrapper() ) )
2170 if ( nTempValue
> mnMax
)
2172 else if ( nTempValue
< mnMin
)
2180 // -----------------------------------------------------------------------
2182 void CurrencyFormatter::Reformat()
2188 sal_Bool bOK
= ImplCurrencyReformat( GetField()->GetText(), aStr
);
2192 if ( !aStr
.isEmpty() )
2194 ImplSetText( aStr
);
2195 sal_Int64 nTemp
= mnLastValue
;
2196 ImplCurrencyGetValue( aStr
, nTemp
, GetDecimalDigits(), ImplGetLocaleDataWrapper() );
2197 mnLastValue
= nTemp
;
2200 SetValue( mnLastValue
);
2203 // -----------------------------------------------------------------------
2205 CurrencyField::CurrencyField( Window
* pParent
, WinBits nWinStyle
) :
2206 SpinField( pParent
, nWinStyle
)
2212 // -----------------------------------------------------------------------
2214 CurrencyField::~CurrencyField()
2218 // -----------------------------------------------------------------------
2220 long CurrencyField::PreNotify( NotifyEvent
& rNEvt
)
2222 if ( (rNEvt
.GetType() == EVENT_KEYINPUT
) && !rNEvt
.GetKeyEvent()->GetKeyCode().IsMod2() )
2224 if ( ImplCurrencyProcessKeyInput( GetField(), *rNEvt
.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
2228 return SpinField::PreNotify( rNEvt
);
2231 // -----------------------------------------------------------------------
2233 long CurrencyField::Notify( NotifyEvent
& rNEvt
)
2235 if ( rNEvt
.GetType() == EVENT_GETFOCUS
)
2236 MarkToBeReformatted( sal_False
);
2237 else if ( rNEvt
.GetType() == EVENT_LOSEFOCUS
)
2239 if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
2243 return SpinField::Notify( rNEvt
);
2246 // -----------------------------------------------------------------------
2248 void CurrencyField::DataChanged( const DataChangedEvent
& rDCEvt
)
2250 SpinField::DataChanged( rDCEvt
);
2252 if ( (rDCEvt
.GetType() == DATACHANGED_SETTINGS
) && (rDCEvt
.GetFlags() & SETTINGS_LOCALE
) )
2254 String sOldDecSep
= ImplGetLocaleDataWrapper().getNumDecimalSep();
2255 String sOldThSep
= ImplGetLocaleDataWrapper().getNumThousandSep();
2256 if ( IsDefaultLocale() )
2257 ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
2258 String sNewDecSep
= ImplGetLocaleDataWrapper().getNumDecimalSep();
2259 String sNewThSep
= ImplGetLocaleDataWrapper().getNumThousandSep();
2260 ImplUpdateSeparators( sOldDecSep
, sNewDecSep
, sOldThSep
, sNewThSep
, this );
2265 // -----------------------------------------------------------------------
2267 void CurrencyField::Modify()
2269 MarkToBeReformatted( sal_True
);
2270 SpinField::Modify();
2273 // -----------------------------------------------------------------------
2275 void CurrencyField::Up()
2281 // -----------------------------------------------------------------------
2283 void CurrencyField::Down()
2289 // -----------------------------------------------------------------------
2291 void CurrencyField::First()
2297 // -----------------------------------------------------------------------
2299 void CurrencyField::Last()
2305 // -----------------------------------------------------------------------
2307 CurrencyBox::CurrencyBox( Window
* pParent
, WinBits nWinStyle
) :
2308 ComboBox( pParent
, nWinStyle
)
2314 // -----------------------------------------------------------------------
2316 CurrencyBox::~CurrencyBox()
2320 // -----------------------------------------------------------------------
2322 long CurrencyBox::PreNotify( NotifyEvent
& rNEvt
)
2324 if ( (rNEvt
.GetType() == EVENT_KEYINPUT
) && !rNEvt
.GetKeyEvent()->GetKeyCode().IsMod2() )
2326 if ( ImplCurrencyProcessKeyInput( GetField(), *rNEvt
.GetKeyEvent(), IsStrictFormat(), IsUseThousandSep(), ImplGetLocaleDataWrapper() ) )
2330 return ComboBox::PreNotify( rNEvt
);
2333 // -----------------------------------------------------------------------
2335 long CurrencyBox::Notify( NotifyEvent
& rNEvt
)
2337 if ( rNEvt
.GetType() == EVENT_GETFOCUS
)
2338 MarkToBeReformatted( sal_False
);
2339 else if ( rNEvt
.GetType() == EVENT_LOSEFOCUS
)
2341 if ( MustBeReformatted() && (!GetText().isEmpty() || !IsEmptyFieldValueEnabled()) )
2345 return ComboBox::Notify( rNEvt
);
2348 // -----------------------------------------------------------------------
2350 void CurrencyBox::DataChanged( const DataChangedEvent
& rDCEvt
)
2352 ComboBox::DataChanged( rDCEvt
);
2354 if ( (rDCEvt
.GetType() == DATACHANGED_SETTINGS
) && (rDCEvt
.GetFlags() & SETTINGS_LOCALE
) )
2356 String sOldDecSep
= ImplGetLocaleDataWrapper().getNumDecimalSep();
2357 String sOldThSep
= ImplGetLocaleDataWrapper().getNumThousandSep();
2358 if ( IsDefaultLocale() )
2359 ImplGetLocaleDataWrapper().setLanguageTag( GetSettings().GetLanguageTag() );
2360 String sNewDecSep
= ImplGetLocaleDataWrapper().getNumDecimalSep();
2361 String sNewThSep
= ImplGetLocaleDataWrapper().getNumThousandSep();
2362 ImplUpdateSeparators( sOldDecSep
, sNewDecSep
, sOldThSep
, sNewThSep
, this );
2367 // -----------------------------------------------------------------------
2369 void CurrencyBox::Modify()
2371 MarkToBeReformatted( sal_True
);
2375 // -----------------------------------------------------------------------
2377 void CurrencyBox::ReformatAll()
2380 SetUpdateMode( sal_False
);
2381 sal_uInt16 nEntryCount
= GetEntryCount();
2382 for ( sal_uInt16 i
=0; i
< nEntryCount
; i
++ )
2384 ImplCurrencyReformat( GetEntry( i
), aStr
);
2386 InsertEntry( aStr
, i
);
2388 CurrencyFormatter::Reformat();
2389 SetUpdateMode( sal_True
);
2392 // -----------------------------------------------------------------------
2394 sal_Int64
CurrencyBox::GetValue() const
2396 // Implementation not inline, because it is a virtual Function
2397 return CurrencyFormatter::GetValue();
2400 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */