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