/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_forms.hxx" #include "limitedformats.hxx" #include "services.hxx" #include #include #include #include //......................................................................... namespace frm { //......................................................................... using namespace ::com::sun::star::uno; using namespace ::com::sun::star::util; using namespace ::com::sun::star::lang; using namespace ::com::sun::star::form; using namespace ::com::sun::star::beans; sal_Int32 OLimitedFormats::s_nInstanceCount(0); ::osl::Mutex OLimitedFormats::s_aMutex; Reference< XNumberFormatsSupplier > OLimitedFormats::s_xStandardFormats; //===================================================================== //= //===================================================================== //--------------------------------------------------------------------- enum LocaleType { ltEnglishUS, ltGerman, ltSystem }; //--------------------------------------------------------------------- static const Locale& getLocale(LocaleType _eType) { static const Locale s_aEnglishUS( ::rtl::OUString::createFromAscii("en"), ::rtl::OUString::createFromAscii("us"), ::rtl::OUString() ); static const Locale s_aGerman( ::rtl::OUString::createFromAscii("de"), ::rtl::OUString::createFromAscii("DE"), ::rtl::OUString() ); static const ::rtl::OUString s_sEmptyString; static const Locale s_aSystem( s_sEmptyString, s_sEmptyString, s_sEmptyString ); switch (_eType) { case ltEnglishUS: return s_aEnglishUS; case ltGerman: return s_aGerman; case ltSystem: return s_aSystem; } OSL_ENSURE(sal_False, "getLocale: invalid enum value!"); return s_aSystem; } //--------------------------------------------------------------------- struct FormatEntry { const sal_Char* pDescription; sal_Int32 nKey; LocaleType eLocale; }; //--------------------------------------------------------------------- static const FormatEntry* lcl_getFormatTable(sal_Int16 nTableId) { switch (nTableId) { case FormComponentType::TIMEFIELD: { static FormatEntry s_aFormats[] = { { "HH:MM", -1, ltEnglishUS }, { "HH:MM:SS", -1, ltEnglishUS }, { "HH:MM AM/PM", -1, ltEnglishUS }, { "HH:MM:SS AM/PM", -1, ltEnglishUS }, { NULL, -1, ltSystem } }; // don't switch this table here to const. The compiler could be tempted to really place this // in a non-writeable segment, but we want to fill in the format keys later .... return s_aFormats; } case FormComponentType::DATEFIELD: { static FormatEntry s_aFormats[] = { { "T-M-JJ", -1, ltGerman }, { "TT-MM-JJ", -1, ltGerman }, { "TT-MM-JJJJ", -1, ltGerman }, { "NNNNT. MMMM JJJJ", -1, ltGerman }, { "DD/MM/YY", -1, ltEnglishUS }, { "MM/DD/YY", -1, ltEnglishUS }, { "YY/MM/DD", -1, ltEnglishUS }, { "DD/MM/YYYY", -1, ltEnglishUS }, { "MM/DD/YYYY", -1, ltEnglishUS }, { "YYYY/MM/DD", -1, ltEnglishUS }, { "JJ-MM-TT", -1, ltGerman }, { "JJJJ-MM-TT", -1, ltGerman }, { NULL, -1, ltSystem } }; return s_aFormats; } } OSL_ENSURE(sal_False, "lcl_getFormatTable: invalid id!"); return NULL; } //===================================================================== //= OLimitedFormats //===================================================================== //--------------------------------------------------------------------- OLimitedFormats::OLimitedFormats(const Reference< XMultiServiceFactory >& _rxORB, const sal_Int16 _nClassId) :m_nFormatEnumPropertyHandle(-1) ,m_nTableId(_nClassId) { OSL_ENSURE(_rxORB.is(), "OLimitedFormats::OLimitedFormats: invalid service factory!"); acquireSupplier(_rxORB); ensureTableInitialized(m_nTableId); } //--------------------------------------------------------------------- OLimitedFormats::~OLimitedFormats() { releaseSupplier(); } //--------------------------------------------------------------------- void OLimitedFormats::ensureTableInitialized(const sal_Int16 _nTableId) { const FormatEntry* pFormatTable = lcl_getFormatTable(_nTableId); if (-1 == pFormatTable->nKey) { ::osl::MutexGuard aGuard(s_aMutex); if (-1 == pFormatTable->nKey) { // initialize the keys Reference xStandardFormats; if (s_xStandardFormats.is()) xStandardFormats = s_xStandardFormats->getNumberFormats(); OSL_ENSURE(xStandardFormats.is(), "OLimitedFormats::ensureTableInitialized: don't have a formats supplier!"); if (xStandardFormats.is()) { // loop through the table FormatEntry* pLoopFormats = const_cast(pFormatTable); while (pLoopFormats->pDescription) { // get the key for the description pLoopFormats->nKey = xStandardFormats->queryKey( ::rtl::OUString::createFromAscii(pLoopFormats->pDescription), getLocale(pLoopFormats->eLocale), sal_False ); if (-1 == pLoopFormats->nKey) { pLoopFormats->nKey = xStandardFormats->addNew( ::rtl::OUString::createFromAscii(pLoopFormats->pDescription), getLocale(pLoopFormats->eLocale) ); #ifdef DBG_UTIL try { xStandardFormats->getByKey(pLoopFormats->nKey); } catch(const Exception&) { OSL_ENSURE(sal_False, "OLimitedFormats::ensureTableInitialized: adding the key to the formats collection failed!"); } #endif } // next ++pLoopFormats; } } } } } //--------------------------------------------------------------------- void OLimitedFormats::clearTable(const sal_Int16 _nTableId) { ::osl::MutexGuard aGuard(s_aMutex); const FormatEntry* pFormats = lcl_getFormatTable(_nTableId); FormatEntry* pResetLoop = const_cast(pFormats); while (pResetLoop->pDescription) { pResetLoop->nKey = -1; ++pResetLoop; } } //--------------------------------------------------------------------- void OLimitedFormats::setAggregateSet(const Reference< XFastPropertySet >& _rxAggregate, sal_Int32 _nOriginalPropertyHandle) { // changes (NULL -> not NULL) and (not NULL -> NULL) are allowed OSL_ENSURE(!m_xAggregate.is() || !_rxAggregate.is(), "OLimitedFormats::setAggregateSet: already have an aggregate!"); OSL_ENSURE(_rxAggregate.is() || m_xAggregate.is(), "OLimitedFormats::setAggregateSet: invalid new aggregate!"); m_xAggregate = _rxAggregate; m_nFormatEnumPropertyHandle = _nOriginalPropertyHandle; #ifdef DBG_UTIL if (m_xAggregate.is()) { try { m_xAggregate->getFastPropertyValue(m_nFormatEnumPropertyHandle); } catch(const Exception&) { OSL_ENSURE(sal_False, "OLimitedFormats::setAggregateSet: invalid handle!"); } } #endif } //--------------------------------------------------------------------- void OLimitedFormats::getFormatKeyPropertyValue( Any& _rValue ) const { _rValue.clear(); OSL_ENSURE(m_xAggregate.is() && (-1 != m_nFormatEnumPropertyHandle), "OLimitedFormats::getFormatKeyPropertyValue: not initialized!"); if (m_xAggregate.is()) { // get the aggregate's enum property value Any aEnumPropertyValue = m_xAggregate->getFastPropertyValue(m_nFormatEnumPropertyHandle); sal_Int32 nValue = -1; ::cppu::enum2int(nValue, aEnumPropertyValue); // get the translation table const FormatEntry* pFormats = lcl_getFormatTable(m_nTableId); // seek to the nValue'th entry sal_Int32 nLookup = 0; for ( ; (NULL != pFormats->pDescription) && (nLookup < nValue); ++pFormats, ++nLookup ) ; OSL_ENSURE(NULL != pFormats->pDescription, "OLimitedFormats::getFormatKeyPropertyValue: did not find the value!"); if (pFormats->pDescription) _rValue <<= pFormats->nKey; } // TODO: should use a standard format for the control type we're working for } //--------------------------------------------------------------------- sal_Bool OLimitedFormats::convertFormatKeyPropertyValue(Any& _rConvertedValue, Any& _rOldValue, const Any& _rNewValue) { OSL_ENSURE(m_xAggregate.is() && (-1 != m_nFormatEnumPropertyHandle), "OLimitedFormats::convertFormatKeyPropertyValue: not initialized!"); if (m_xAggregate.is()) { // the new format key to set sal_Int32 nNewFormat = 0; if (!(_rNewValue >>= nNewFormat)) throw IllegalArgumentException(); // get the old (enum) value from the aggregate Any aEnumPropertyValue = m_xAggregate->getFastPropertyValue(m_nFormatEnumPropertyHandle); sal_Int32 nOldEnumValue = -1; ::cppu::enum2int(nOldEnumValue, aEnumPropertyValue); // get the translation table const FormatEntry* pFormats = lcl_getFormatTable(m_nTableId); _rOldValue.clear(); _rConvertedValue.clear(); // look for the entry with the given format key sal_Int32 nTablePosition = 0; for ( ; (NULL != pFormats->pDescription) && (nNewFormat != pFormats->nKey); ++pFormats, ++nTablePosition ) { if (nTablePosition == nOldEnumValue) _rOldValue <<= pFormats->nKey; } sal_Bool bFoundIt = (NULL != pFormats->pDescription); sal_Bool bModified = sal_False; if (bFoundIt) { _rConvertedValue <<= (sal_Int16)nTablePosition; bModified = nTablePosition != nOldEnumValue; } if (!_rOldValue.hasValue()) { // did not reach the end of the table (means we found nNewFormat) // -> go to the end to ensure that _rOldValue is set while (pFormats->pDescription) { if (nTablePosition == nOldEnumValue) { _rOldValue <<= pFormats->nKey; break; } ++pFormats; ++nTablePosition; } } OSL_ENSURE(_rOldValue.hasValue(), "OLimitedFormats::convertFormatKeyPropertyValue: did not find the old enum value in the table!"); if (!bFoundIt) { // somebody gave us an format which we can't translate ::rtl::OUString sMessage = ::rtl::OUString::createFromAscii("This control supports only a very limited number of formats."); throw IllegalArgumentException(sMessage, NULL, 2); } return bModified; } return sal_False; } //--------------------------------------------------------------------- void OLimitedFormats::setFormatKeyPropertyValue( const Any& _rNewValue ) { OSL_ENSURE(m_xAggregate.is() && (-1 != m_nFormatEnumPropertyHandle), "OLimitedFormats::setFormatKeyPropertyValue: not initialized!"); if (m_xAggregate.is()) { // this is to be called after convertFormatKeyPropertyValue, where // we translated the format key into a enum value. // So now we can simply forward this enum value to our aggregate m_xAggregate->setFastPropertyValue(m_nFormatEnumPropertyHandle, _rNewValue); } } //--------------------------------------------------------------------- void OLimitedFormats::acquireSupplier(const Reference< XMultiServiceFactory >& _rxORB) { ::osl::MutexGuard aGuard(s_aMutex); if ((1 == ++s_nInstanceCount) && _rxORB.is()) { // create the standard formatter Sequence< Any > aInit(1); aInit[0] <<= getLocale(ltEnglishUS); Reference< XInterface > xSupplier = _rxORB->createInstanceWithArguments(FRM_NUMBER_FORMATS_SUPPLIER, aInit); OSL_ENSURE(xSupplier.is(), "OLimitedFormats::OLimitedFormats: could not create a formats supplier!"); s_xStandardFormats = Reference< XNumberFormatsSupplier >(xSupplier, UNO_QUERY); OSL_ENSURE(s_xStandardFormats.is() || !xSupplier.is(), "OLimitedFormats::OLimitedFormats: missing an interface!"); } } //--------------------------------------------------------------------- void OLimitedFormats::releaseSupplier() { ::osl::MutexGuard aGuard(s_aMutex); if (0 == --s_nInstanceCount) { ::comphelper::disposeComponent(s_xStandardFormats); s_xStandardFormats = NULL; clearTable(FormComponentType::TIMEFIELD); clearTable(FormComponentType::DATEFIELD); } } //......................................................................... } // namespace frm //.........................................................................