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