xref: /AOO41X/main/forms/source/misc/limitedformats.cxx (revision 24acc54625a85f778a4f966495e8f4cd9d7b247c)
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