1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_forms.hxx" 26 #include "limitedformats.hxx" 27 #include "services.hxx" 28 #include <osl/diagnose.h> 29 #include <comphelper/types.hxx> 30 #include <comphelper/extract.hxx> 31 #include <com/sun/star/form/FormComponentType.hpp> 32 33 //......................................................................... 34 namespace frm 35 { 36 //......................................................................... 37 38 using namespace ::com::sun::star::uno; 39 using namespace ::com::sun::star::util; 40 using namespace ::com::sun::star::lang; 41 using namespace ::com::sun::star::form; 42 using namespace ::com::sun::star::beans; 43 44 sal_Int32 OLimitedFormats::s_nInstanceCount(0); 45 ::osl::Mutex OLimitedFormats::s_aMutex; 46 Reference< XNumberFormatsSupplier > OLimitedFormats::s_xStandardFormats; 47 48 //===================================================================== 49 //= 50 //===================================================================== 51 //--------------------------------------------------------------------- 52 enum LocaleType 53 { 54 ltEnglishUS, 55 ltGerman, 56 ltSystem 57 }; 58 59 //--------------------------------------------------------------------- getLocale(LocaleType _eType)60 static const Locale& getLocale(LocaleType _eType) 61 { 62 static const Locale s_aEnglishUS( ::rtl::OUString::createFromAscii("en"), ::rtl::OUString::createFromAscii("us"), ::rtl::OUString() ); 63 static const Locale s_aGerman( ::rtl::OUString::createFromAscii("de"), ::rtl::OUString::createFromAscii("DE"), ::rtl::OUString() ); 64 static const ::rtl::OUString s_sEmptyString; 65 static const Locale s_aSystem( s_sEmptyString, s_sEmptyString, s_sEmptyString ); 66 67 switch (_eType) 68 { 69 case ltEnglishUS: 70 return s_aEnglishUS; 71 72 case ltGerman: 73 return s_aGerman; 74 75 case ltSystem: 76 return s_aSystem; 77 } 78 79 OSL_ENSURE(sal_False, "getLocale: invalid enum value!"); 80 return s_aSystem; 81 } 82 83 //--------------------------------------------------------------------- 84 struct FormatEntry 85 { 86 const sal_Char* pDescription; 87 sal_Int32 nKey; 88 LocaleType eLocale; 89 }; 90 91 //--------------------------------------------------------------------- lcl_getFormatTable(sal_Int16 nTableId)92 static const FormatEntry* lcl_getFormatTable(sal_Int16 nTableId) 93 { 94 switch (nTableId) 95 { 96 case FormComponentType::TIMEFIELD: 97 { 98 static FormatEntry s_aFormats[] = { 99 { "HH:MM", -1, ltEnglishUS }, 100 { "HH:MM:SS", -1, ltEnglishUS }, 101 { "HH:MM AM/PM", -1, ltEnglishUS }, 102 { "HH:MM:SS AM/PM", -1, ltEnglishUS }, 103 { NULL, -1, ltSystem } 104 }; 105 // don't switch this table here to const. The compiler could be tempted to really place this 106 // in a non-writeable segment, but we want to fill in the format keys later .... 107 return s_aFormats; 108 } 109 case FormComponentType::DATEFIELD: 110 { 111 static FormatEntry s_aFormats[] = { 112 { "T-M-JJ", -1, ltGerman }, 113 { "TT-MM-JJ", -1, ltGerman }, 114 { "TT-MM-JJJJ", -1, ltGerman }, 115 { "NNNNT. MMMM JJJJ", -1, ltGerman }, 116 117 { "DD/MM/YY", -1, ltEnglishUS }, 118 { "MM/DD/YY", -1, ltEnglishUS }, 119 { "YY/MM/DD", -1, ltEnglishUS }, 120 { "DD/MM/YYYY", -1, ltEnglishUS }, 121 { "MM/DD/YYYY", -1, ltEnglishUS }, 122 { "YYYY/MM/DD", -1, ltEnglishUS }, 123 124 { "JJ-MM-TT", -1, ltGerman }, 125 { "JJJJ-MM-TT", -1, ltGerman }, 126 127 { NULL, -1, ltSystem } 128 }; 129 return s_aFormats; 130 } 131 } 132 133 OSL_ENSURE(sal_False, "lcl_getFormatTable: invalid id!"); 134 return NULL; 135 } 136 137 //===================================================================== 138 //= OLimitedFormats 139 //===================================================================== 140 //--------------------------------------------------------------------- OLimitedFormats(const Reference<XMultiServiceFactory> & _rxORB,const sal_Int16 _nClassId)141 OLimitedFormats::OLimitedFormats(const Reference< XMultiServiceFactory >& _rxORB, const sal_Int16 _nClassId) 142 :m_nFormatEnumPropertyHandle(-1) 143 ,m_nTableId(_nClassId) 144 { 145 OSL_ENSURE(_rxORB.is(), "OLimitedFormats::OLimitedFormats: invalid service factory!"); 146 acquireSupplier(_rxORB); 147 ensureTableInitialized(m_nTableId); 148 } 149 150 //--------------------------------------------------------------------- ~OLimitedFormats()151 OLimitedFormats::~OLimitedFormats() 152 { 153 releaseSupplier(); 154 } 155 156 //--------------------------------------------------------------------- ensureTableInitialized(const sal_Int16 _nTableId)157 void OLimitedFormats::ensureTableInitialized(const sal_Int16 _nTableId) 158 { 159 const FormatEntry* pFormatTable = lcl_getFormatTable(_nTableId); 160 if (-1 == pFormatTable->nKey) 161 { 162 ::osl::MutexGuard aGuard(s_aMutex); 163 if (-1 == pFormatTable->nKey) 164 { 165 // initialize the keys 166 Reference<XNumberFormats> xStandardFormats; 167 if (s_xStandardFormats.is()) 168 xStandardFormats = s_xStandardFormats->getNumberFormats(); 169 OSL_ENSURE(xStandardFormats.is(), "OLimitedFormats::ensureTableInitialized: don't have a formats supplier!"); 170 171 if (xStandardFormats.is()) 172 { 173 // loop through the table 174 FormatEntry* pLoopFormats = const_cast<FormatEntry*>(pFormatTable); 175 while (pLoopFormats->pDescription) 176 { 177 // get the key for the description 178 pLoopFormats->nKey = xStandardFormats->queryKey( 179 ::rtl::OUString::createFromAscii(pLoopFormats->pDescription), 180 getLocale(pLoopFormats->eLocale), 181 sal_False 182 ); 183 184 if (-1 == pLoopFormats->nKey) 185 { 186 pLoopFormats->nKey = xStandardFormats->addNew( 187 ::rtl::OUString::createFromAscii(pLoopFormats->pDescription), 188 getLocale(pLoopFormats->eLocale) 189 ); 190 #ifdef DBG_UTIL 191 try 192 { 193 xStandardFormats->getByKey(pLoopFormats->nKey); 194 } 195 catch(const Exception&) 196 { 197 OSL_ENSURE(sal_False, "OLimitedFormats::ensureTableInitialized: adding the key to the formats collection failed!"); 198 } 199 #endif 200 } 201 202 // next 203 ++pLoopFormats; 204 } 205 } 206 } 207 } 208 } 209 210 //--------------------------------------------------------------------- clearTable(const sal_Int16 _nTableId)211 void OLimitedFormats::clearTable(const sal_Int16 _nTableId) 212 { 213 ::osl::MutexGuard aGuard(s_aMutex); 214 const FormatEntry* pFormats = lcl_getFormatTable(_nTableId); 215 FormatEntry* pResetLoop = const_cast<FormatEntry*>(pFormats); 216 while (pResetLoop->pDescription) 217 { 218 pResetLoop->nKey = -1; 219 ++pResetLoop; 220 } 221 } 222 223 //--------------------------------------------------------------------- setAggregateSet(const Reference<XFastPropertySet> & _rxAggregate,sal_Int32 _nOriginalPropertyHandle)224 void OLimitedFormats::setAggregateSet(const Reference< XFastPropertySet >& _rxAggregate, sal_Int32 _nOriginalPropertyHandle) 225 { 226 // changes (NULL -> not NULL) and (not NULL -> NULL) are allowed 227 OSL_ENSURE(!m_xAggregate.is() || !_rxAggregate.is(), "OLimitedFormats::setAggregateSet: already have an aggregate!"); 228 OSL_ENSURE(_rxAggregate.is() || m_xAggregate.is(), "OLimitedFormats::setAggregateSet: invalid new aggregate!"); 229 230 m_xAggregate = _rxAggregate; 231 m_nFormatEnumPropertyHandle = _nOriginalPropertyHandle; 232 #ifdef DBG_UTIL 233 if (m_xAggregate.is()) 234 { 235 try 236 { 237 m_xAggregate->getFastPropertyValue(m_nFormatEnumPropertyHandle); 238 } 239 catch(const Exception&) 240 { 241 OSL_ENSURE(sal_False, "OLimitedFormats::setAggregateSet: invalid handle!"); 242 } 243 } 244 #endif 245 } 246 247 //--------------------------------------------------------------------- getFormatKeyPropertyValue(Any & _rValue) const248 void OLimitedFormats::getFormatKeyPropertyValue( Any& _rValue ) const 249 { 250 _rValue.clear(); 251 252 OSL_ENSURE(m_xAggregate.is() && (-1 != m_nFormatEnumPropertyHandle), "OLimitedFormats::getFormatKeyPropertyValue: not initialized!"); 253 if (m_xAggregate.is()) 254 { 255 // get the aggregate's enum property value 256 Any aEnumPropertyValue = m_xAggregate->getFastPropertyValue(m_nFormatEnumPropertyHandle); 257 sal_Int32 nValue = -1; 258 ::cppu::enum2int(nValue, aEnumPropertyValue); 259 260 // get the translation table 261 const FormatEntry* pFormats = lcl_getFormatTable(m_nTableId); 262 263 // seek to the nValue'th entry 264 sal_Int32 nLookup = 0; 265 for ( ; 266 (NULL != pFormats->pDescription) && (nLookup < nValue); 267 ++pFormats, ++nLookup 268 ) 269 ; 270 OSL_ENSURE(NULL != pFormats->pDescription, "OLimitedFormats::getFormatKeyPropertyValue: did not find the value!"); 271 if (pFormats->pDescription) 272 _rValue <<= pFormats->nKey; 273 } 274 275 // TODO: should use a standard format for the control type we're working for 276 } 277 278 //--------------------------------------------------------------------- convertFormatKeyPropertyValue(Any & _rConvertedValue,Any & _rOldValue,const Any & _rNewValue)279 sal_Bool OLimitedFormats::convertFormatKeyPropertyValue(Any& _rConvertedValue, Any& _rOldValue, const Any& _rNewValue) 280 { 281 OSL_ENSURE(m_xAggregate.is() && (-1 != m_nFormatEnumPropertyHandle), "OLimitedFormats::convertFormatKeyPropertyValue: not initialized!"); 282 283 if (m_xAggregate.is()) 284 { 285 // the new format key to set 286 sal_Int32 nNewFormat = 0; 287 if (!(_rNewValue >>= nNewFormat)) 288 throw IllegalArgumentException(); 289 290 // get the old (enum) value from the aggregate 291 Any aEnumPropertyValue = m_xAggregate->getFastPropertyValue(m_nFormatEnumPropertyHandle); 292 sal_Int32 nOldEnumValue = -1; 293 ::cppu::enum2int(nOldEnumValue, aEnumPropertyValue); 294 295 // get the translation table 296 const FormatEntry* pFormats = lcl_getFormatTable(m_nTableId); 297 298 _rOldValue.clear(); 299 _rConvertedValue.clear(); 300 301 // look for the entry with the given format key 302 sal_Int32 nTablePosition = 0; 303 for ( ; 304 (NULL != pFormats->pDescription) && (nNewFormat != pFormats->nKey); 305 ++pFormats, ++nTablePosition 306 ) 307 { 308 if (nTablePosition == nOldEnumValue) 309 _rOldValue <<= pFormats->nKey; 310 } 311 312 sal_Bool bFoundIt = (NULL != pFormats->pDescription); 313 sal_Bool bModified = sal_False; 314 if (bFoundIt) 315 { 316 _rConvertedValue <<= (sal_Int16)nTablePosition; 317 bModified = nTablePosition != nOldEnumValue; 318 } 319 320 if (!_rOldValue.hasValue()) 321 { // did not reach the end of the table (means we found nNewFormat) 322 // -> go to the end to ensure that _rOldValue is set 323 while (pFormats->pDescription) 324 { 325 if (nTablePosition == nOldEnumValue) 326 { 327 _rOldValue <<= pFormats->nKey; 328 break; 329 } 330 331 ++pFormats; 332 ++nTablePosition; 333 } 334 } 335 336 OSL_ENSURE(_rOldValue.hasValue(), "OLimitedFormats::convertFormatKeyPropertyValue: did not find the old enum value in the table!"); 337 338 if (!bFoundIt) 339 { // somebody gave us an format which we can't translate 340 ::rtl::OUString sMessage = ::rtl::OUString::createFromAscii("This control supports only a very limited number of formats."); 341 throw IllegalArgumentException(sMessage, NULL, 2); 342 } 343 344 return bModified; 345 } 346 347 return sal_False; 348 } 349 350 //--------------------------------------------------------------------- setFormatKeyPropertyValue(const Any & _rNewValue)351 void OLimitedFormats::setFormatKeyPropertyValue( const Any& _rNewValue ) 352 { 353 OSL_ENSURE(m_xAggregate.is() && (-1 != m_nFormatEnumPropertyHandle), "OLimitedFormats::setFormatKeyPropertyValue: not initialized!"); 354 355 if (m_xAggregate.is()) 356 { // this is to be called after convertFormatKeyPropertyValue, where 357 // we translated the format key into a enum value. 358 // So now we can simply forward this enum value to our aggreate 359 m_xAggregate->setFastPropertyValue(m_nFormatEnumPropertyHandle, _rNewValue); 360 } 361 } 362 363 //--------------------------------------------------------------------- acquireSupplier(const Reference<XMultiServiceFactory> & _rxORB)364 void OLimitedFormats::acquireSupplier(const Reference< XMultiServiceFactory >& _rxORB) 365 { 366 ::osl::MutexGuard aGuard(s_aMutex); 367 if ((1 == ++s_nInstanceCount) && _rxORB.is()) 368 { // create the standard formatter 369 370 Sequence< Any > aInit(1); 371 aInit[0] <<= getLocale(ltEnglishUS); 372 373 Reference< XInterface > xSupplier = _rxORB->createInstanceWithArguments(FRM_NUMBER_FORMATS_SUPPLIER, aInit); 374 OSL_ENSURE(xSupplier.is(), "OLimitedFormats::OLimitedFormats: could not create a formats supplier!"); 375 376 s_xStandardFormats = Reference< XNumberFormatsSupplier >(xSupplier, UNO_QUERY); 377 OSL_ENSURE(s_xStandardFormats.is() || !xSupplier.is(), "OLimitedFormats::OLimitedFormats: missing an interface!"); 378 } 379 } 380 381 //--------------------------------------------------------------------- releaseSupplier()382 void OLimitedFormats::releaseSupplier() 383 { 384 ::osl::MutexGuard aGuard(s_aMutex); 385 if (0 == --s_nInstanceCount) 386 { 387 ::comphelper::disposeComponent(s_xStandardFormats); 388 s_xStandardFormats = NULL; 389 390 clearTable(FormComponentType::TIMEFIELD); 391 clearTable(FormComponentType::DATEFIELD); 392 } 393 } 394 395 //......................................................................... 396 } // namespace frm 397 //......................................................................... 398 399