LCOV - code coverage report
Current view: top level - svtools/source/control - fmtfield.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 426 506 84.2 %
Date: 2015-06-13 12:38:46 Functions: 58 63 92.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : #include <tools/debug.hxx>
      21             : #include <comphelper/processfactory.hxx>
      22             : #include <comphelper/string.hxx>
      23             : #include <unotools/localedatawrapper.hxx>
      24             : #include <vcl/svapp.hxx>
      25             : #include <vcl/builderfactory.hxx>
      26             : #include <vcl/settings.hxx>
      27             : #include <svl/zformat.hxx>
      28             : #include <svtools/fmtfield.hxx>
      29             : #include <i18nlangtag/languagetag.hxx>
      30             : #include <com/sun/star/lang/Locale.hpp>
      31             : #include <com/sun/star/util/SearchOptions.hpp>
      32             : #include <com/sun/star/util/SearchAlgorithms.hpp>
      33             : #include <com/sun/star/util/SearchResult.hpp>
      34             : #include <com/sun/star/util/SearchFlags.hpp>
      35             : #include <unotools/syslocale.hxx>
      36             : #include <map>
      37             : #include <rtl/math.hxx>
      38             : #include <rtl/ustrbuf.hxx>
      39             : 
      40             : using namespace ::com::sun::star::lang;
      41             : using namespace ::com::sun::star::util;
      42             : 
      43             : // hmm. No support for regular expression. Well, I always (not really :) wanted to write a finite automat
      44             : // so here comes a finite automat ...
      45             : 
      46             : namespace validation
      47             : {
      48             :     // the states of our automat.
      49             :     enum State
      50             :     {
      51             :         START,              // at the very start of the string
      52             :         NUM_START,          // the very start of the number
      53             : 
      54             :         DIGIT_PRE_COMMA,    // some pre-comma digits are read, perhaps including some thousand separators
      55             : 
      56             :         DIGIT_POST_COMMA,   // reading digits after the comma
      57             :         EXPONENT_START,     // at the very start of the exponent value
      58             :                             //    (means: not including the "e" which denotes the exponent)
      59             :         EXPONENT_DIGIT,     // currently reading the digits of the exponent
      60             : 
      61             :         END                 // reached the end of the string
      62             :     };
      63             : 
      64             :     // a row in the transition table (means the set of states to be reached from a given state)
      65             :     typedef ::std::map< sal_Unicode, State >        StateTransitions;
      66             : 
      67             :     // a single transition
      68             :     typedef StateTransitions::value_type            Transition;
      69             : 
      70             :     // the complete transition table
      71             :     typedef ::std::map< State, StateTransitions >   TransitionTable;
      72             : 
      73             :     // the validator class
      74          74 :     class NumberValidator
      75             :     {
      76             :     private:
      77             :         TransitionTable     m_aTransitions;
      78             :         const sal_Unicode   m_cThSep;
      79             :         const sal_Unicode   m_cDecSep;
      80             : 
      81             :     public:
      82             :         NumberValidator( const sal_Unicode _cThSep, const sal_Unicode _cDecSep );
      83             : 
      84             :         bool isValidNumericFragment( const OUString& _rText );
      85             : 
      86             :     private:
      87             :         bool implValidateNormalized( const OUString& _rText );
      88             :     };
      89             : 
      90         296 :     static void lcl_insertStopTransition( StateTransitions& _rRow )
      91             :     {
      92         296 :         _rRow.insert( Transition( '_', END ) );
      93         296 :     }
      94             : 
      95         222 :     static void lcl_insertStartExponentTransition( StateTransitions& _rRow )
      96             :     {
      97         222 :         _rRow.insert( Transition( 'e', EXPONENT_START ) );
      98         222 :     }
      99             : 
     100         148 :     static void lcl_insertSignTransitions( StateTransitions& _rRow, const State eNextState )
     101             :     {
     102         148 :         _rRow.insert( Transition( '-', eNextState ) );
     103         148 :         _rRow.insert( Transition( '+', eNextState ) );
     104         148 :     }
     105             : 
     106         370 :     static void lcl_insertDigitTransitions( StateTransitions& _rRow, const State eNextState )
     107             :     {
     108        4070 :         for ( sal_Unicode aChar = '0'; aChar <= '9'; ++aChar )
     109        3700 :             _rRow.insert( Transition( aChar, eNextState ) );
     110         370 :     }
     111             : 
     112         148 :     static void lcl_insertCommonPreCommaTransitions( StateTransitions& _rRow, const sal_Unicode _cThSep, const sal_Unicode _cDecSep )
     113             :     {
     114             :         // digits are allowed
     115         148 :         lcl_insertDigitTransitions( _rRow, DIGIT_PRE_COMMA );
     116             : 
     117             :         // the thousand separator is allowed
     118         148 :         _rRow.insert( Transition( _cThSep, DIGIT_PRE_COMMA ) );
     119             : 
     120             :         // a comma is allowed
     121         148 :         _rRow.insert( Transition( _cDecSep, DIGIT_POST_COMMA ) );
     122         148 :     }
     123             : 
     124          74 :     NumberValidator::NumberValidator( const sal_Unicode _cThSep, const sal_Unicode _cDecSep )
     125             :         :m_cThSep( _cThSep )
     126          74 :         ,m_cDecSep( _cDecSep )
     127             :     {
     128             :         // build up our transition table
     129             : 
     130             :         // how to proceed from START
     131             :         {
     132          74 :             StateTransitions& rRow = m_aTransitions[ START ];
     133          74 :             rRow.insert( Transition( '_', NUM_START ) );
     134             :                 // if we encounter the normalizing character, we want to proceed with the number
     135             :         }
     136             : 
     137             :         // how to proceed from NUM_START
     138             :         {
     139          74 :             StateTransitions& rRow = m_aTransitions[ NUM_START ];
     140             : 
     141             :             // a sign is allowed
     142          74 :             lcl_insertSignTransitions( rRow, DIGIT_PRE_COMMA );
     143             : 
     144             :             // common transitions for the two pre-comma states
     145          74 :             lcl_insertCommonPreCommaTransitions( rRow, m_cThSep, m_cDecSep );
     146             : 
     147             :             // the exponent may start here
     148             :             // (this would mean string like "_+e10_", but this is a valid fragment, though no valid number)
     149          74 :             lcl_insertStartExponentTransition( rRow );
     150             :         }
     151             : 
     152             :         // how to proceed from DIGIT_PRE_COMMA
     153             :         {
     154          74 :             StateTransitions& rRow = m_aTransitions[ DIGIT_PRE_COMMA ];
     155             : 
     156             :             // common transitions for the two pre-comma states
     157          74 :             lcl_insertCommonPreCommaTransitions( rRow, m_cThSep, m_cDecSep );
     158             : 
     159             :             // the exponent may start here
     160          74 :             lcl_insertStartExponentTransition( rRow );
     161             : 
     162             :             // the final transition indicating the end of the string
     163             :             // (if there is no comma and no post-comma, then the string may end here)
     164          74 :             lcl_insertStopTransition( rRow );
     165             :         }
     166             : 
     167             :         // how to proceed from DIGIT_POST_COMMA
     168             :         {
     169          74 :             StateTransitions& rRow = m_aTransitions[ DIGIT_POST_COMMA ];
     170             : 
     171             :             // there might be digits, which would keep the state at DIGIT_POST_COMMA
     172          74 :             lcl_insertDigitTransitions( rRow, DIGIT_POST_COMMA );
     173             : 
     174             :             // the exponent may start here
     175          74 :             lcl_insertStartExponentTransition( rRow );
     176             : 
     177             :             // the string may end here
     178          74 :             lcl_insertStopTransition( rRow );
     179             :         }
     180             : 
     181             :         // how to proceed from EXPONENT_START
     182             :         {
     183          74 :             StateTransitions& rRow = m_aTransitions[ EXPONENT_START ];
     184             : 
     185             :             // there may be a sign
     186          74 :             lcl_insertSignTransitions( rRow, EXPONENT_DIGIT );
     187             : 
     188             :             // there may be digits
     189          74 :             lcl_insertDigitTransitions( rRow, EXPONENT_DIGIT );
     190             : 
     191             :             // the string may end here
     192          74 :             lcl_insertStopTransition( rRow );
     193             :         }
     194             : 
     195             :         // how to proceed from EXPONENT_DIGIT
     196             :         {
     197          74 :             StateTransitions& rRow = m_aTransitions[ EXPONENT_DIGIT ];
     198             : 
     199             :             // there may be digits
     200          74 :             lcl_insertDigitTransitions( rRow, EXPONENT_DIGIT );
     201             : 
     202             :             // the string may end here
     203          74 :             lcl_insertStopTransition( rRow );
     204             :         }
     205             : 
     206             :         // how to proceed from END
     207             :         {
     208          74 :             /*StateTransitions& rRow =*/ m_aTransitions[ EXPONENT_DIGIT ];
     209             :             // no valid transition to leave this state
     210             :             // (note that we, for consistency, nevertheless want to have a row in the table)
     211             :         }
     212          74 :     }
     213             : 
     214          28 :     bool NumberValidator::implValidateNormalized( const OUString& _rText )
     215             :     {
     216          28 :         const sal_Unicode* pCheckPos = _rText.getStr();
     217          28 :         State eCurrentState = START;
     218             : 
     219         212 :         while ( END != eCurrentState )
     220             :         {
     221             :             // look up the transition row for the current state
     222         164 :             TransitionTable::const_iterator aRow = m_aTransitions.find( eCurrentState );
     223             :             DBG_ASSERT( m_aTransitions.end() != aRow,
     224             :                 "NumberValidator::implValidateNormalized: invalid transition table (row not found)!" );
     225             : 
     226         164 :             if ( m_aTransitions.end() != aRow )
     227             :             {
     228             :                 // look up the current character in this row
     229         164 :                 StateTransitions::const_iterator aTransition = aRow->second.find( *pCheckPos );
     230         164 :                 if ( aRow->second.end() != aTransition )
     231             :                 {
     232             :                     // there is a valid transition for this character
     233         156 :                     eCurrentState = aTransition->second;
     234         156 :                     ++pCheckPos;
     235         156 :                     continue;
     236             :                 }
     237             :             }
     238             : 
     239             :             // if we're here, there is no valid transition
     240           8 :             break;
     241             :         }
     242             : 
     243             :         DBG_ASSERT( ( END != eCurrentState ) || ( 0 == *pCheckPos ),
     244             :             "NumberValidator::implValidateNormalized: inconsistency!" );
     245             :             // if we're at END, then the string should be done, too - the string should be normalized, means ending
     246             :             // a "_" and not containing any other "_" (except at the start), and "_" is the only possibility
     247             :             // to reach the END state
     248             : 
     249             :         // the string is valid if and only if we reached the final state
     250          28 :         return ( END == eCurrentState );
     251             :     }
     252             : 
     253          28 :     bool NumberValidator::isValidNumericFragment( const OUString& _rText )
     254             :     {
     255          28 :         if ( _rText.isEmpty() )
     256             :             // empty strings are always allowed
     257           0 :             return true;
     258             : 
     259             :         // normalize the string
     260          28 :         OUString sNormalized( "_" );
     261          28 :         sNormalized += _rText;
     262          28 :         sNormalized += "_";
     263             : 
     264          28 :         return implValidateNormalized( sNormalized );
     265             :     }
     266             : }
     267             : 
     268             : SvNumberFormatter* FormattedField::StaticFormatter::s_cFormatter = NULL;
     269             : sal_uLong FormattedField::StaticFormatter::s_nReferences = 0;
     270             : 
     271          35 : SvNumberFormatter* FormattedField::StaticFormatter::GetFormatter()
     272             : {
     273          35 :     if (!s_cFormatter)
     274             :     {
     275             :         // get the Office's locale and translate
     276          35 :         LanguageType eSysLanguage = SvtSysLocale().GetLanguageTag().getLanguageType( false);
     277             :         s_cFormatter = new SvNumberFormatter(
     278             :             ::comphelper::getProcessComponentContext(),
     279          35 :             eSysLanguage);
     280             :     }
     281          35 :     return s_cFormatter;
     282             : }
     283             : 
     284          63 : FormattedField::StaticFormatter::StaticFormatter()
     285             : {
     286          63 :     ++s_nReferences;
     287          63 : }
     288             : 
     289          63 : FormattedField::StaticFormatter::~StaticFormatter()
     290             : {
     291          63 :     if (--s_nReferences == 0)
     292             :     {
     293          36 :         delete s_cFormatter;
     294          36 :         s_cFormatter = NULL;
     295             :     }
     296          63 : }
     297             : 
     298             : 
     299          63 : FormattedField::FormattedField(vcl::Window* pParent, WinBits nStyle, SvNumberFormatter* pInitialFormatter, sal_Int32 nFormatKey)
     300             :     :SpinField(pParent, nStyle)
     301             :     ,m_aLastSelection(0,0)
     302             :     ,m_dMinValue(0)
     303             :     ,m_dMaxValue(0)
     304             :     ,m_bHasMin(false)
     305             :     ,m_bHasMax(false)
     306             :     ,m_bStrictFormat(true)
     307             :     ,m_bValueDirty(true)
     308             :     ,m_bEnableEmptyField(true)
     309             :     ,m_bAutoColor(false)
     310             :     ,m_bEnableNaN(false)
     311             :     ,m_dCurrentValue(0)
     312             :     ,m_dDefaultValue(0)
     313             :     ,m_nFormatKey(0)
     314             :     ,m_pFormatter(NULL)
     315             :     ,m_dSpinSize(1)
     316             :     ,m_dSpinFirst(-1000000)
     317             :     ,m_dSpinLast(1000000)
     318             :     ,m_bTreatAsNumber(true)
     319             :     ,m_pLastOutputColor(NULL)
     320          63 :     ,m_bUseInputStringForFormatting(false)
     321             : {
     322             : 
     323          63 :     if (pInitialFormatter)
     324             :     {
     325           0 :         m_pFormatter = pInitialFormatter;
     326           0 :         m_nFormatKey = nFormatKey;
     327             :     }
     328          63 : }
     329             : 
     330           0 : VCL_BUILDER_FACTORY_ARGS(FormattedField, WB_BORDER | WB_SPIN)
     331             : 
     332          78 : void FormattedField::SetText(const OUString& rStr)
     333             : {
     334             : 
     335          78 :     SpinField::SetText(rStr);
     336          78 :     m_bValueDirty = true;
     337          78 : }
     338             : 
     339           0 : void FormattedField::SetText( const OUString& rStr, const Selection& rNewSelection )
     340             : {
     341             : 
     342           0 :     SpinField::SetText( rStr, rNewSelection );
     343           0 :     m_bValueDirty = true;
     344           0 : }
     345             : 
     346          36 : void FormattedField::SetTextFormatted(const OUString& rStr)
     347             : {
     348             : 
     349             : #if defined DBG_UTIL
     350             :     if (ImplGetFormatter()->IsTextFormat(m_nFormatKey))
     351             :          DBG_WARNING("FormattedField::SetTextFormatted : valid only with text formats !");
     352             : #endif
     353             : 
     354          36 :     m_sCurrentTextValue = rStr;
     355             : 
     356          36 :     OUString sFormatted;
     357          36 :     double dNumber = 0.0;
     358             :     // IsNumberFormat changes the format key parameter
     359          36 :     sal_uInt32 nTempFormatKey = static_cast< sal_uInt32 >( m_nFormatKey );
     360          36 :     if( IsUsingInputStringForFormatting() &&
     361           0 :         ImplGetFormatter()->IsNumberFormat(m_sCurrentTextValue, nTempFormatKey, dNumber) )
     362             :     {
     363           0 :         ImplGetFormatter()->GetInputLineString(dNumber, m_nFormatKey, sFormatted);
     364             :     }
     365             :     else
     366             :     {
     367             :         ImplGetFormatter()->GetOutputString(m_sCurrentTextValue,
     368             :                                             m_nFormatKey,
     369             :                                             sFormatted,
     370          36 :                                             &m_pLastOutputColor);
     371             :     }
     372             : 
     373             :     // calculate the new selection
     374          36 :     Selection aSel(GetSelection());
     375          36 :     Selection aNewSel(aSel);
     376          36 :     aNewSel.Justify();
     377          36 :     sal_Int32 nNewLen = sFormatted.getLength();
     378          36 :     sal_Int32 nCurrentLen = GetText().getLength();
     379          36 :     if ((nNewLen > nCurrentLen) && (aNewSel.Max() == nCurrentLen))
     380             :     {   // the new text is longer and the cursor was behind the last char (of the old text)
     381           7 :         if (aNewSel.Min() == 0)
     382             :         {   // the whole text was selected -> select the new text on the whole, too
     383           7 :             aNewSel.Max() = nNewLen;
     384           7 :             if (!nCurrentLen)
     385             :             {   // there wasn't really a previous selection (as there was no previous text), we're setting a new one -> check the selection options
     386           7 :                 SelectionOptions nSelOptions = GetSettings().GetStyleSettings().GetSelectionOptions();
     387           7 :                 if (nSelOptions & SelectionOptions::ShowFirst)
     388             :                 {   // selection should be from right to left -> swap min and max
     389           5 :                     aNewSel.Min() = aNewSel.Max();
     390           5 :                     aNewSel.Max() = 0;
     391             :                 }
     392             :             }
     393             :         }
     394           0 :         else if (aNewSel.Max() == aNewSel.Min())
     395             :         {   // there was no selection -> set the cursor behind the new last char
     396           0 :             aNewSel.Max() = nNewLen;
     397           0 :             aNewSel.Min() = nNewLen;
     398             :         }
     399             :     }
     400          29 :     else if (aNewSel.Max() > nNewLen)
     401           0 :         aNewSel.Max() = nNewLen;
     402             :     else
     403          29 :         aNewSel = aSel; // don't use the justified version
     404          36 :     SpinField::SetText(sFormatted, aNewSel);
     405          36 :     m_bValueDirty = false;
     406          36 : }
     407             : 
     408           1 : OUString FormattedField::GetTextValue() const
     409             : {
     410           1 :     if (m_bValueDirty)
     411             :     {
     412           0 :         const_cast<FormattedField*>(this)->m_sCurrentTextValue = GetText();
     413           0 :         const_cast<FormattedField*>(this)->m_bValueDirty = false;
     414             :     }
     415           1 :     return m_sCurrentTextValue;
     416             : }
     417             : 
     418          53 : void FormattedField::EnableNotANumber( bool _bEnable )
     419             : {
     420          53 :     if ( m_bEnableNaN == _bEnable )
     421          80 :         return;
     422             : 
     423          26 :     m_bEnableNaN = _bEnable;
     424             : }
     425             : 
     426          70 : void FormattedField::SetAutoColor(bool _bAutomatic)
     427             : {
     428          70 :     if (_bAutomatic == m_bAutoColor)
     429         105 :         return;
     430             : 
     431          35 :     m_bAutoColor = _bAutomatic;
     432          35 :     if (m_bAutoColor)
     433             :     {   // if auto color is switched on, adjust the current text color, too
     434          35 :         if (m_pLastOutputColor)
     435           0 :             SetControlForeground(*m_pLastOutputColor);
     436             :         else
     437          35 :             SetControlForeground();
     438             :     }
     439             : }
     440             : 
     441          69 : void FormattedField::impl_Modify(bool makeValueDirty)
     442             : {
     443             : 
     444          69 :     if (!IsStrictFormat())
     445             :     {
     446           0 :         if(makeValueDirty)
     447           0 :             m_bValueDirty = true;
     448           0 :         SpinField::Modify();
     449          69 :         return;
     450             :     }
     451             : 
     452          69 :     OUString sCheck = GetText();
     453          69 :     if (CheckText(sCheck))
     454             :     {
     455          61 :         m_sLastValidText = sCheck;
     456          61 :         m_aLastSelection = GetSelection();
     457          61 :         if(makeValueDirty)
     458          61 :             m_bValueDirty = true;
     459             :     }
     460             :     else
     461             :     {
     462           8 :         ImplSetTextImpl(m_sLastValidText, &m_aLastSelection);
     463             :     }
     464             : 
     465          69 :     SpinField::Modify();
     466             : }
     467             : 
     468          69 : void FormattedField::Modify()
     469             : {
     470             : 
     471          69 :     impl_Modify();
     472          69 : }
     473             : 
     474          90 : void FormattedField::ImplSetTextImpl(const OUString& rNew, Selection* pNewSel)
     475             : {
     476             : 
     477          90 :     if (m_bAutoColor)
     478             :     {
     479          81 :         if (m_pLastOutputColor)
     480           0 :             SetControlForeground(*m_pLastOutputColor);
     481             :         else
     482          81 :             SetControlForeground();
     483             :     }
     484             : 
     485          90 :     if (pNewSel)
     486           8 :         SpinField::SetText(rNew, *pNewSel);
     487             :     else
     488             :     {
     489          82 :         Selection aSel(GetSelection());
     490          82 :         aSel.Justify();
     491             : 
     492          82 :         sal_Int32 nNewLen = rNew.getLength();
     493          82 :         sal_Int32 nCurrentLen = GetText().getLength();
     494             : 
     495          82 :         if ((nNewLen > nCurrentLen) && (aSel.Max() == nCurrentLen))
     496             :         {   // new new text is longer and the cursor is behind the last char
     497          34 :             if (aSel.Min() == 0)
     498             :             {   // the whole text was selected -> select the new text on the whole, too
     499          32 :                 aSel.Max() = nNewLen;
     500          32 :                 if (!nCurrentLen)
     501             :                 {   // there wasn't really a previous selection (as there was no previous text), we're setting a new one -> check the selection options
     502          20 :                     SelectionOptions nSelOptions = GetSettings().GetStyleSettings().GetSelectionOptions();
     503          20 :                     if (nSelOptions & SelectionOptions::ShowFirst)
     504             :                     {   // selection should be from right to left -> swap min and max
     505           9 :                         aSel.Min() = aSel.Max();
     506           9 :                         aSel.Max() = 0;
     507             :                     }
     508             :                 }
     509             :             }
     510           2 :             else if (aSel.Max() == aSel.Min())
     511             :             {   // there was no selection -> set the cursor behind the new last char
     512           0 :                 aSel.Max() = nNewLen;
     513           0 :                 aSel.Min() = nNewLen;
     514             :             }
     515             :         }
     516          48 :         else if (aSel.Max() > nNewLen)
     517           4 :             aSel.Max() = nNewLen;
     518          82 :         SpinField::SetText(rNew, aSel);
     519             :     }
     520             : 
     521          90 :     m_bValueDirty = true; // not always necessary, but better re-evaluate for safety reasons
     522          90 : }
     523             : 
     524           0 : bool FormattedField::PreNotify(NotifyEvent& rNEvt)
     525             : {
     526           0 :     if (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT)
     527           0 :         m_aLastSelection = GetSelection();
     528           0 :     return SpinField::PreNotify(rNEvt);
     529             : }
     530             : 
     531         203 : void FormattedField::ImplSetFormatKey(sal_uLong nFormatKey)
     532             : {
     533             : 
     534         203 :     m_nFormatKey = nFormatKey;
     535         203 :     bool bNeedFormatter = (m_pFormatter == NULL) && (nFormatKey != 0);
     536         203 :     if (bNeedFormatter)
     537             :     {
     538           0 :         ImplGetFormatter(); // this creates a standard formatter
     539             : 
     540             :         // It might happen that the standard formatter makes no sense here, but it takes a default
     541             :         // format. Thus, it is possible to set one of the other standard keys (which are spanning
     542             :         // across multiple formatters).
     543           0 :         m_nFormatKey = nFormatKey;
     544             :         // When calling SetFormatKey without a formatter, the key must be one of the standard values
     545             :         // that is available for all formatters (and, thus, also in this new one).
     546             :         DBG_ASSERT(m_pFormatter->GetEntry(nFormatKey) != NULL, "FormattedField::ImplSetFormatKey : invalid format key !");
     547             :     }
     548         203 : }
     549             : 
     550         123 : void FormattedField::SetFormatKey(sal_uLong nFormatKey)
     551             : {
     552         123 :     bool bNoFormatter = (m_pFormatter == NULL);
     553         123 :     ImplSetFormatKey(nFormatKey);
     554         123 :     FormatChanged((bNoFormatter && (m_pFormatter != NULL)) ? FORMAT_CHANGE_TYPE::FORMATTER : FORMAT_CHANGE_TYPE::KEYONLY);
     555         123 : }
     556             : 
     557          64 : void FormattedField::SetFormatter(SvNumberFormatter* pFormatter, bool bResetFormat)
     558             : {
     559             : 
     560          64 :     if (bResetFormat)
     561             :     {
     562          63 :         m_pFormatter = pFormatter;
     563             : 
     564             :         // calc the default format key from the Office's UI locale
     565          63 :         if ( m_pFormatter )
     566             :         {
     567             :             // get the Office's locale and translate
     568          63 :             LanguageType eSysLanguage = SvtSysLocale().GetLanguageTag().getLanguageType( false);
     569             :             // get the standard numeric format for this language
     570          63 :             m_nFormatKey = m_pFormatter->GetStandardFormat( css::util::NumberFormat::NUMBER, eSysLanguage );
     571             :         }
     572             :         else
     573           0 :             m_nFormatKey = 0;
     574             :     }
     575             :     else
     576             :     {
     577             :         LanguageType aOldLang;
     578           1 :         OUString sOldFormat = GetFormat(aOldLang);
     579             : 
     580           1 :         sal_uInt32 nDestKey = pFormatter->TestNewString(sOldFormat);
     581           1 :         if (nDestKey == NUMBERFORMAT_ENTRY_NOT_FOUND)
     582             :         {
     583             :             // language of the new formatter
     584           0 :             const SvNumberformat* pDefaultEntry = pFormatter->GetEntry(0);
     585           0 :             LanguageType aNewLang = pDefaultEntry ? pDefaultEntry->GetLanguage() : LANGUAGE_DONTKNOW;
     586             : 
     587             :             // convert the old format string into the new language
     588             :             sal_Int32 nCheckPos;
     589             :             short nType;
     590           0 :             pFormatter->PutandConvertEntry(sOldFormat, nCheckPos, nType, nDestKey, aOldLang, aNewLang);
     591           0 :             m_nFormatKey = nDestKey;
     592             :         }
     593           1 :         m_pFormatter = pFormatter;
     594             :     }
     595             : 
     596          64 :     FormatChanged(FORMAT_CHANGE_TYPE::FORMATTER);
     597          64 : }
     598             : 
     599         192 : OUString FormattedField::GetFormat(LanguageType& eLang) const
     600             : {
     601         192 :     const SvNumberformat* pFormatEntry = ImplGetFormatter()->GetEntry(m_nFormatKey);
     602             :     DBG_ASSERT(pFormatEntry != NULL, "FormattedField::GetFormat: no number format for the given format key.");
     603         192 :     OUString sFormatString = pFormatEntry ? pFormatEntry->GetFormatstring() : OUString();
     604         192 :     eLang = pFormatEntry ? pFormatEntry->GetLanguage() : LANGUAGE_DONTKNOW;
     605             : 
     606         192 :     return sFormatString;
     607             : }
     608             : 
     609         111 : bool FormattedField::SetFormat(const OUString& rFormatString, LanguageType eLang)
     610             : {
     611         111 :     sal_uInt32 nNewKey = ImplGetFormatter()->TestNewString(rFormatString, eLang);
     612         111 :     if (nNewKey == NUMBERFORMAT_ENTRY_NOT_FOUND)
     613             :     {
     614             :         sal_Int32 nCheckPos;
     615             :         short nType;
     616          94 :         OUString rFormat(rFormatString);
     617          94 :         if (!ImplGetFormatter()->PutEntry(rFormat, nCheckPos, nType, nNewKey, eLang))
     618           0 :             return false;
     619          94 :         DBG_ASSERT(nNewKey != NUMBERFORMAT_ENTRY_NOT_FOUND, "FormattedField::SetFormatString : PutEntry returned an invalid key !");
     620             :     }
     621             : 
     622         111 :     if (nNewKey != m_nFormatKey)
     623          94 :         SetFormatKey(nNewKey);
     624         111 :     return true;
     625             : }
     626             : 
     627         111 : bool FormattedField::GetThousandsSep() const
     628             : {
     629             :     DBG_ASSERT(!ImplGetFormatter()->IsTextFormat(m_nFormatKey),
     630             :         "FormattedField::GetThousandsSep : Are you sure what you are doing when setting the precision of a text format?");
     631             : 
     632             :     bool bThousand, IsRed;
     633             :     sal_uInt16 nPrecision, nAnzLeading;
     634         111 :     ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nAnzLeading);
     635             : 
     636         111 :     return bThousand;
     637             : }
     638             : 
     639          50 : void FormattedField::SetThousandsSep(bool _bUseSeparator)
     640             : {
     641             :     DBG_ASSERT(!ImplGetFormatter()->IsTextFormat(m_nFormatKey),
     642             :         "FormattedField::SetThousandsSep : Are you sure what you are doing when setting the precision of a text format?");
     643             : 
     644             :     // get the current settings
     645             :     bool bThousand, IsRed;
     646             :     sal_uInt16 nPrecision, nAnzLeading;
     647          50 :     ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nAnzLeading);
     648          50 :     if (bThousand == (bool)_bUseSeparator)
     649          74 :         return;
     650             : 
     651             :     // we need the language for the following
     652             :     LanguageType eLang;
     653          26 :     GetFormat(eLang);
     654             : 
     655             :     // generate a new format ...
     656          26 :     OUString sFmtDescription = ImplGetFormatter()->GenerateFormat(m_nFormatKey, eLang, _bUseSeparator, IsRed, nPrecision, nAnzLeading);
     657             :     // ... and introduce it to the formatter
     658          26 :     sal_Int32 nCheckPos = 0;
     659             :     sal_uInt32 nNewKey;
     660             :     short nType;
     661          26 :     ImplGetFormatter()->PutEntry(sFmtDescription, nCheckPos, nType, nNewKey, eLang);
     662             : 
     663             :     // set the new key
     664          26 :     ImplSetFormatKey(nNewKey);
     665          26 :     FormatChanged(FORMAT_CHANGE_TYPE::THOUSANDSSEP);
     666             : }
     667             : 
     668         111 : sal_uInt16 FormattedField::GetDecimalDigits() const
     669             : {
     670             :     DBG_ASSERT(!ImplGetFormatter()->IsTextFormat(m_nFormatKey),
     671             :         "FormattedField::GetDecimalDigits : Are you sure what you are doing when setting the precision of a text format?");
     672             : 
     673             :     bool bThousand, IsRed;
     674             :     sal_uInt16 nPrecision, nAnzLeading;
     675         111 :     ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nAnzLeading);
     676             : 
     677         111 :     return nPrecision;
     678             : }
     679             : 
     680          54 : void FormattedField::SetDecimalDigits(sal_uInt16 _nPrecision)
     681             : {
     682             :     DBG_ASSERT(!ImplGetFormatter()->IsTextFormat(m_nFormatKey),
     683             :         "FormattedField::SetDecimalDigits : Are you sure what you are doing when setting the precision of a text format?");
     684             : 
     685             :     // get the current settings
     686             :     bool bThousand, IsRed;
     687             :     sal_uInt16 nPrecision, nAnzLeading;
     688          54 :     ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nAnzLeading);
     689          54 :     if (nPrecision == _nPrecision)
     690          54 :         return;
     691             : 
     692             :     // we need the language for the following
     693             :     LanguageType eLang;
     694          54 :     GetFormat(eLang);
     695             : 
     696             :     // generate a new format ...
     697          54 :     OUString sFmtDescription = ImplGetFormatter()->GenerateFormat(m_nFormatKey, eLang, bThousand, IsRed, _nPrecision, nAnzLeading);
     698             :     // ... and introduce it to the formatter
     699          54 :     sal_Int32 nCheckPos = 0;
     700             :     sal_uInt32 nNewKey;
     701             :     short nType;
     702          54 :     ImplGetFormatter()->PutEntry(sFmtDescription, nCheckPos, nType, nNewKey, eLang);
     703             : 
     704             :     // set the new key
     705          54 :     ImplSetFormatKey(nNewKey);
     706          54 :     FormatChanged(FORMAT_CHANGE_TYPE::PRECISION);
     707             : }
     708             : 
     709         304 : void FormattedField::FormatChanged( FORMAT_CHANGE_TYPE _nWhat )
     710             : {
     711         304 :     m_pLastOutputColor = NULL;
     712             : 
     713         304 :     if ( (_nWhat == FORMAT_CHANGE_TYPE::FORMATTER) && m_pFormatter )
     714          64 :         m_pFormatter->SetEvalDateFormat( NF_EVALDATEFORMAT_INTL_FORMAT );
     715             : 
     716         304 :     ReFormat();
     717         304 : }
     718             : 
     719           1 : void FormattedField::Commit()
     720             : {
     721             :     // remember the old text
     722           1 :     OUString sOld( GetText() );
     723             : 
     724             :     // do the reformat
     725           1 :     ReFormat();
     726             : 
     727             :     // did the text change?
     728           1 :     if ( GetText() != sOld )
     729             :     {   // consider the field as modified,
     730             :         // but we already have the most recent value;
     731             :         // don't reparse it from the text
     732             :         // (can lead to data loss when the format is lossy,
     733             :         //  as is e.g. our default date format: 2-digit year!)
     734           0 :         impl_Modify(false);
     735           1 :     }
     736           1 : }
     737             : 
     738         421 : void FormattedField::ReFormat()
     739             : {
     740         421 :     if (!IsEmptyFieldEnabled() || !GetText().isEmpty())
     741             :     {
     742          47 :         if (TreatingAsNumber())
     743             :         {
     744          46 :             double dValue = GetValue();
     745          46 :             if ( m_bEnableNaN && ::rtl::math::isNan( dValue ) )
     746         421 :                 return;
     747          46 :             ImplSetValue( dValue, true );
     748             :         }
     749             :         else
     750           1 :             SetTextFormatted(GetTextValue());
     751             :     }
     752             : }
     753             : 
     754          36 : bool FormattedField::Notify(NotifyEvent& rNEvt)
     755             : {
     756             : 
     757          36 :     if ((rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) && !IsReadOnly())
     758             :     {
     759           0 :         const KeyEvent& rKEvt = *rNEvt.GetKeyEvent();
     760           0 :         sal_uInt16 nMod = rKEvt.GetKeyCode().GetModifier();
     761           0 :         switch ( rKEvt.GetKeyCode().GetCode() )
     762             :         {
     763             :             case KEY_UP:
     764             :             case KEY_DOWN:
     765             :             case KEY_PAGEUP:
     766             :             case KEY_PAGEDOWN:
     767           0 :                 if (!nMod && ImplGetFormatter()->IsTextFormat(m_nFormatKey))
     768             :                 {
     769             :                     // the base class would translate this into calls to Up/Down/First/Last,
     770             :                     // but we don't want this if we are text-formatted
     771           0 :                     return true;
     772             :                 }
     773             :         }
     774             :     }
     775             : 
     776          36 :     if ((rNEvt.GetType() == MouseNotifyEvent::COMMAND) && !IsReadOnly())
     777             :     {
     778           0 :         const CommandEvent* pCommand = rNEvt.GetCommandEvent();
     779           0 :         if (pCommand->GetCommand() == CommandEventId::Wheel)
     780             :         {
     781           0 :             const CommandWheelData* pData = rNEvt.GetCommandEvent()->GetWheelData();
     782           0 :             if ((pData->GetMode() == CommandWheelMode::SCROLL) && ImplGetFormatter()->IsTextFormat(m_nFormatKey))
     783             :             {
     784             :                 // same as above : prevent the base class from doing Up/Down-calls
     785             :                 // (normally I should put this test into the Up/Down methods itself, shouldn't I ?)
     786             :                 // FS - 71553 - 19.01.00
     787           0 :                 return true;
     788             :             }
     789             :         }
     790             :     }
     791             : 
     792          36 :     if (rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS)
     793             :     {
     794             :         // Sonderbehandlung fuer leere Texte
     795           0 :         if (GetText().isEmpty())
     796             :         {
     797           0 :             if (!IsEmptyFieldEnabled())
     798             :             {
     799           0 :                 if (TreatingAsNumber())
     800             :                 {
     801           0 :                     ImplSetValue(m_dCurrentValue, true);
     802           0 :                     Modify();
     803             :                 }
     804             :                 else
     805             :                 {
     806           0 :                     OUString sNew = GetTextValue();
     807           0 :                     if (!sNew.isEmpty())
     808           0 :                         SetTextFormatted(sNew);
     809             :                     else
     810           0 :                         SetTextFormatted(m_sDefaultText);
     811             :                 }
     812           0 :                 m_bValueDirty = false;
     813             :             }
     814             :         }
     815             :         else
     816             :         {
     817           0 :             Commit();
     818             :         }
     819             :     }
     820             : 
     821          36 :     return SpinField::Notify( rNEvt );
     822             : }
     823             : 
     824          58 : void FormattedField::SetMinValue(double dMin)
     825             : {
     826             :     DBG_ASSERT(m_bTreatAsNumber, "FormattedField::SetMinValue : only to be used in numeric mode !");
     827             : 
     828          58 :     m_dMinValue = dMin;
     829          58 :     m_bHasMin = true;
     830             :     // for checking the current value at the new border -> ImplSetValue
     831          58 :     ReFormat();
     832          58 : }
     833             : 
     834          58 : void FormattedField::SetMaxValue(double dMax)
     835             : {
     836             :     DBG_ASSERT(m_bTreatAsNumber, "FormattedField::SetMaxValue : only to be used in numeric mode !");
     837             : 
     838          58 :     m_dMaxValue = dMax;
     839          58 :     m_bHasMax = true;
     840             :     // for checking the current value at the new border -> ImplSetValue
     841          58 :     ReFormat();
     842          58 : }
     843             : 
     844           0 : void FormattedField::SetTextValue(const OUString& rText)
     845             : {
     846           0 :     SetText(rText);
     847           0 :     ReFormat();
     848           0 : }
     849             : 
     850           1 : void FormattedField::EnableEmptyField(bool bEnable)
     851             : {
     852           1 :     if (bEnable == m_bEnableEmptyField)
     853           2 :         return;
     854             : 
     855           0 :     m_bEnableEmptyField = bEnable;
     856           0 :     if (!m_bEnableEmptyField && GetText().isEmpty())
     857           0 :         ImplSetValue(m_dCurrentValue, true);
     858             : }
     859             : 
     860          88 : void FormattedField::ImplSetValue(double dVal, bool bForce)
     861             : {
     862             : 
     863          88 :     if (m_bHasMin && (dVal<m_dMinValue))
     864           0 :         dVal = m_dMinValue;
     865          88 :     if (m_bHasMax && (dVal>m_dMaxValue))
     866           6 :         dVal = m_dMaxValue;
     867          88 :     if (!bForce && (dVal == GetValue()))
     868          94 :         return;
     869             : 
     870             :     DBG_ASSERT(ImplGetFormatter() != NULL, "FormattedField::ImplSetValue : can't set a value without a formatter !");
     871             : 
     872          82 :     m_bValueDirty = false;
     873          82 :     m_dCurrentValue = dVal;
     874             : 
     875          82 :     OUString sNewText;
     876          82 :     if (ImplGetFormatter()->IsTextFormat(m_nFormatKey))
     877             :     {
     878             :         // first convert the number as string in standard format
     879           9 :         OUString sTemp;
     880           9 :         ImplGetFormatter()->GetOutputString(dVal, 0, sTemp, &m_pLastOutputColor);
     881             :         // then encode the string in the corresponding text format
     882           9 :         ImplGetFormatter()->GetOutputString(sTemp, m_nFormatKey, sNewText, &m_pLastOutputColor);
     883             :     }
     884             :     else
     885             :     {
     886          73 :         if( IsUsingInputStringForFormatting())
     887             :         {
     888           0 :             ImplGetFormatter()->GetInputLineString(dVal, m_nFormatKey, sNewText);
     889             :         }
     890             :         else
     891             :         {
     892          73 :             ImplGetFormatter()->GetOutputString(dVal, m_nFormatKey, sNewText, &m_pLastOutputColor);
     893             :         }
     894             :     }
     895             : 
     896          82 :     ImplSetTextImpl(sNewText, NULL);
     897          82 :     m_bValueDirty = false;
     898          82 :     DBG_ASSERT(CheckText(sNewText), "FormattedField::ImplSetValue : formatted string doesn't match the criteria !");
     899             : }
     900             : 
     901         290 : bool FormattedField::ImplGetValue(double& dNewVal)
     902             : {
     903             : 
     904         290 :     dNewVal = m_dCurrentValue;
     905         290 :     if (!m_bValueDirty)
     906         218 :         return true;
     907             : 
     908          72 :     dNewVal = m_dDefaultValue;
     909          72 :     OUString sText(GetText());
     910          72 :     if (sText.isEmpty())
     911           5 :         return true;
     912             : 
     913             :     DBG_ASSERT(ImplGetFormatter() != NULL, "FormattedField::ImplGetValue : can't give you a current value without a formatter !");
     914             : 
     915          67 :     sal_uInt32 nFormatKey = m_nFormatKey; // IsNumberFormat changes the FormatKey!
     916             : 
     917          67 :     if (ImplGetFormatter()->IsTextFormat(nFormatKey) && m_bTreatAsNumber)
     918             :         // for detection of values like "1,1" in fields that are formatted as text
     919           0 :         nFormatKey = 0;
     920             : 
     921             :     // special treatment for percentage formatting
     922          67 :     if (ImplGetFormatter()->GetType(m_nFormatKey) == css::util::NumberFormat::PERCENT)
     923             :     {
     924             :         // the language of our format
     925           0 :         LanguageType eLanguage = m_pFormatter->GetEntry(m_nFormatKey)->GetLanguage();
     926             :         // the default number format for this language
     927           0 :         sal_uLong nStandardNumericFormat = m_pFormatter->GetStandardFormat(css::util::NumberFormat::NUMBER, eLanguage);
     928             : 
     929           0 :         sal_uInt32 nTempFormat = nStandardNumericFormat;
     930             :         double dTemp;
     931           0 :         if (m_pFormatter->IsNumberFormat(sText, nTempFormat, dTemp) &&
     932           0 :             css::util::NumberFormat::NUMBER == m_pFormatter->GetType(nTempFormat))
     933             :             // the string is equivalent to a number formatted one (has no % sign) -> append it
     934           0 :             sText += "%";
     935             :         // (with this, a input of '3' becomes '3%', which then by the formatter is translated
     936             :         // into 0.03. Without this, the formatter would give us the double 3 for an input '3',
     937             :         // which equals 300 percent.
     938             :     }
     939          67 :     if (!ImplGetFormatter()->IsNumberFormat(sText, nFormatKey, dNewVal))
     940          13 :         return false;
     941             : 
     942          54 :     if (m_bHasMin && (dNewVal<m_dMinValue))
     943           0 :         dNewVal = m_dMinValue;
     944          54 :     if (m_bHasMax && (dNewVal>m_dMaxValue))
     945           0 :         dNewVal = m_dMaxValue;
     946          54 :     return true;
     947             : }
     948             : 
     949          42 : void FormattedField::SetValue(double dVal)
     950             : {
     951          42 :     ImplSetValue(dVal, m_bValueDirty);
     952          42 : }
     953             : 
     954         290 : double FormattedField::GetValue()
     955             : {
     956             : 
     957         290 :     if ( !ImplGetValue( m_dCurrentValue ) )
     958             :     {
     959          13 :         if ( m_bEnableNaN )
     960           0 :             ::rtl::math::setNan( &m_dCurrentValue );
     961             :         else
     962          13 :             m_dCurrentValue = m_dDefaultValue;
     963             :     }
     964             : 
     965         290 :     m_bValueDirty = false;
     966         290 :     return m_dCurrentValue;
     967             : }
     968             : 
     969          10 : void FormattedField::Up()
     970             : {
     971             :     // setValue handles under- and overflows (min/max) automatically
     972          10 :     SetValue(GetValue() + m_dSpinSize);
     973          10 :     SetModifyFlag();
     974          10 :     Modify();
     975             : 
     976          10 :     SpinField::Up();
     977          10 : }
     978             : 
     979           5 : void FormattedField::Down()
     980             : {
     981           5 :     SetValue(GetValue() - m_dSpinSize);
     982           5 :     SetModifyFlag();
     983           5 :     Modify();
     984             : 
     985           5 :     SpinField::Down();
     986           5 : }
     987             : 
     988           5 : void FormattedField::First()
     989             : {
     990           5 :     if (m_bHasMin)
     991             :     {
     992           4 :         SetValue(m_dMinValue);
     993           4 :         SetModifyFlag();
     994           4 :         Modify();
     995             :     }
     996             : 
     997           5 :     SpinField::First();
     998           5 : }
     999             : 
    1000           5 : void FormattedField::Last()
    1001             : {
    1002           5 :     if (m_bHasMax)
    1003             :     {
    1004           4 :         SetValue(m_dMaxValue);
    1005           4 :         SetModifyFlag();
    1006           4 :         Modify();
    1007             :     }
    1008             : 
    1009           5 :     SpinField::Last();
    1010           5 : }
    1011             : 
    1012           0 : void FormattedField::UseInputStringForFormatting( bool bUseInputStr /* = true */ )
    1013             : {
    1014           0 :     m_bUseInputStringForFormatting = bUseInputStr;
    1015           0 : }
    1016             : 
    1017             : 
    1018          51 : DoubleNumericField::~DoubleNumericField()
    1019             : {
    1020          17 :     disposeOnce();
    1021          34 : }
    1022             : 
    1023          17 : void DoubleNumericField::dispose()
    1024             : {
    1025          17 :     delete m_pNumberValidator;
    1026          17 :     FormattedField::dispose();
    1027          17 : }
    1028             : 
    1029          57 : void DoubleNumericField::FormatChanged(FORMAT_CHANGE_TYPE nWhat)
    1030             : {
    1031          57 :     ResetConformanceTester();
    1032          57 :     FormattedField::FormatChanged(nWhat);
    1033          57 : }
    1034             : 
    1035          28 : bool DoubleNumericField::CheckText(const OUString& sText) const
    1036             : {
    1037             :     // We'd like to implement this using the NumberFormatter::IsNumberFormat, but unfortunately, this doesn't
    1038             :     // recognize fragments of numbers (like, for instance "1e", which happens during entering e.g. "1e10")
    1039             :     // Thus, the roundabout way via a regular expression
    1040          28 :     return m_pNumberValidator->isValidNumericFragment( sText );
    1041             : }
    1042             : 
    1043          74 : void DoubleNumericField::ResetConformanceTester()
    1044             : {
    1045             :     // the thousands and the decimal separator are language dependent
    1046          74 :     const SvNumberformat* pFormatEntry = ImplGetFormatter()->GetEntry(m_nFormatKey);
    1047             : 
    1048          74 :     sal_Unicode cSeparatorThousand = ',';
    1049          74 :     sal_Unicode cSeparatorDecimal = '.';
    1050          74 :     if (pFormatEntry)
    1051             :     {
    1052          74 :         LocaleDataWrapper aLocaleInfo( LanguageTag( pFormatEntry->GetLanguage()) );
    1053             : 
    1054         148 :         OUString sSeparator = aLocaleInfo.getNumThousandSep();
    1055          74 :         if (!sSeparator.isEmpty())
    1056          74 :             cSeparatorThousand = sSeparator[0];
    1057             : 
    1058          74 :         sSeparator = aLocaleInfo.getNumDecimalSep();
    1059          74 :         if (!sSeparator.isEmpty())
    1060         148 :             cSeparatorDecimal = sSeparator[0];
    1061             :     }
    1062             : 
    1063          74 :     delete m_pNumberValidator;
    1064          74 :     m_pNumberValidator = new validation::NumberValidator( cSeparatorThousand, cSeparatorDecimal );
    1065          74 : }
    1066             : 
    1067          17 : DoubleCurrencyField::DoubleCurrencyField(vcl::Window* pParent, WinBits nStyle)
    1068             :     :FormattedField(pParent, nStyle)
    1069          17 :     ,m_bChangingFormat(false)
    1070             : {
    1071          17 :     m_bPrependCurrSym = false;
    1072             : 
    1073             :     // initialize with a system currency format
    1074          17 :     m_sCurrencySymbol = SvtSysLocale().GetLocaleData().getCurrSymbol();
    1075          17 :     UpdateCurrencyFormat();
    1076          17 : }
    1077             : 
    1078         188 : void DoubleCurrencyField::FormatChanged(FORMAT_CHANGE_TYPE nWhat)
    1079             : {
    1080         188 :     if (m_bChangingFormat)
    1081             :     {
    1082          94 :         FormattedField::FormatChanged(nWhat);
    1083         282 :         return;
    1084             :     }
    1085             : 
    1086          94 :     switch (nWhat)
    1087             :     {
    1088             :         case FORMAT_CHANGE_TYPE::FORMATTER:
    1089             :         case FORMAT_CHANGE_TYPE::PRECISION:
    1090             :         case FORMAT_CHANGE_TYPE::THOUSANDSSEP:
    1091             :             // the aspects which changed don't take our currency settings into account (in fact, they most probably
    1092             :             // destroyed them)
    1093          57 :             UpdateCurrencyFormat();
    1094          57 :             break;
    1095             :         case FORMAT_CHANGE_TYPE::KEYONLY:
    1096             :             OSL_FAIL("DoubleCurrencyField::FormatChanged : somebody modified my key !");
    1097             :             // We always build our own format from the settings we get via special methods (setCurrencySymbol etc.).
    1098             :             // Nobody but ourself should modifiy the format key directly !
    1099           0 :             break;
    1100          37 :         default: break;
    1101             :     }
    1102             : 
    1103          94 :     FormattedField::FormatChanged(nWhat);
    1104             : }
    1105             : 
    1106          25 : void DoubleCurrencyField::setCurrencySymbol(const OUString& rSymbol)
    1107             : {
    1108          25 :     if (m_sCurrencySymbol == rSymbol)
    1109          33 :         return;
    1110             : 
    1111          17 :     m_sCurrencySymbol = rSymbol;
    1112          17 :     UpdateCurrencyFormat();
    1113          17 :     FormatChanged(FORMAT_CHANGE_TYPE::CURRENCY_SYMBOL);
    1114             : }
    1115             : 
    1116          25 : void DoubleCurrencyField::setPrependCurrSym(bool _bPrepend)
    1117             : {
    1118          25 :     if (m_bPrependCurrSym == _bPrepend)
    1119          30 :          return;
    1120             : 
    1121          20 :     m_bPrependCurrSym = _bPrepend;
    1122          20 :     UpdateCurrencyFormat();
    1123          20 :     FormatChanged(FORMAT_CHANGE_TYPE::CURRSYM_POSITION);
    1124             : }
    1125             : 
    1126         111 : void DoubleCurrencyField::UpdateCurrencyFormat()
    1127             : {
    1128             :     // the old settings
    1129             :     LanguageType eLanguage;
    1130         111 :     GetFormat(eLanguage);
    1131         111 :     bool bThSep = GetThousandsSep();
    1132         111 :     sal_uInt16 nDigits = GetDecimalDigits();
    1133             : 
    1134             :     // build a new format string with the base class' and my own settings
    1135             : 
    1136             :     /* Strangely with gcc 4.6.3 this needs a temporary LanguageTag, otherwise
    1137             :      * there's
    1138             :      * error: request for member 'getNumThousandSep' in 'aLocaleInfo', which is
    1139             :      * of non-class type 'LocaleDataWrapper(LanguageTag)' */
    1140         111 :     LanguageTag aLanguageTag( eLanguage);
    1141         222 :     LocaleDataWrapper aLocaleInfo( aLanguageTag );
    1142             : 
    1143         222 :     OUStringBuffer sNewFormat;
    1144         111 :     if (bThSep)
    1145             :     {
    1146          19 :         sNewFormat.append('#');
    1147          19 :         sNewFormat.append(aLocaleInfo.getNumThousandSep());
    1148          19 :         sNewFormat.append("##0");
    1149             :     }
    1150             :     else
    1151          92 :         sNewFormat.append('0');
    1152             : 
    1153         111 :     if (nDigits)
    1154             :     {
    1155          68 :         sNewFormat.append(aLocaleInfo.getNumDecimalSep());
    1156             : 
    1157          68 :         OUStringBuffer sTemp;
    1158          68 :         comphelper::string::padToLength(sTemp, nDigits, '0');
    1159          68 :         sNewFormat.append(sTemp);
    1160             :     }
    1161             : 
    1162         111 :     if (getPrependCurrSym())
    1163             :     {
    1164          30 :         OUString sSymbol = getCurrencySymbol();
    1165          30 :         sSymbol = comphelper::string::stripStart(sSymbol, ' ');
    1166          30 :         sSymbol = comphelper::string::stripEnd(sSymbol, ' ');
    1167             : 
    1168          60 :         OUStringBuffer sTemp("[$");
    1169          30 :         sTemp.append(sSymbol);
    1170          30 :         sTemp.append("] ");
    1171          30 :         sTemp.append(sNewFormat);
    1172             : 
    1173             :         // for negative values : $ -0.00, not -$ 0.00 ...
    1174             :         // (the real solution would be a possibility to choose a "positive currency format" and a "negative currency format" ...
    1175             :         // But not now ... (and hey, you could take a formatted field for this ....))
    1176             :         // FS - 31.03.00 74642
    1177          30 :         sTemp.append(";[$");
    1178          30 :         sTemp.append(sSymbol);
    1179          30 :         sTemp.append("] -");
    1180          30 :         sTemp.append(sNewFormat);
    1181             : 
    1182          60 :         sNewFormat = sTemp;
    1183             :     }
    1184             :     else
    1185             :     {
    1186          81 :         OUString sTemp = getCurrencySymbol();
    1187          81 :         sTemp = comphelper::string::stripStart(sTemp, ' ');
    1188          81 :         sTemp = comphelper::string::stripEnd(sTemp, ' ');
    1189             : 
    1190          81 :         sNewFormat.append(" [$");
    1191          81 :         sNewFormat.append(sTemp);
    1192          81 :         sNewFormat.append(']');
    1193             :     }
    1194             : 
    1195             :     // set this new basic format
    1196         111 :     m_bChangingFormat = true;
    1197         111 :     SetFormat(sNewFormat.makeStringAndClear(), eLanguage);
    1198         222 :     m_bChangingFormat = false;
    1199         909 : }
    1200             : 
    1201             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11